Skip to content

Commit a384e03

Browse files
authored
[SPIR-V 1.4] Allow OpCopyMemorySized to have Memory Operands for both Source and Target (#2470)
This change addresses p.4 of #2460. No changes for OpCopyMemory as we currently don't use it in translation.
1 parent a3dea91 commit a384e03

File tree

4 files changed

+70
-18
lines changed

4 files changed

+70
-18
lines changed

lib/SPIRV/SPIRVReader.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1778,13 +1778,15 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
17781778
CallInst *CI = nullptr;
17791779
llvm::Value *Dst = transValue(BC->getTarget(), F, BB);
17801780
MaybeAlign Align(BC->getAlignment());
1781+
MaybeAlign SrcAlign =
1782+
BC->getSrcAlignment() ? MaybeAlign(BC->getSrcAlignment()) : Align;
17811783
llvm::Value *Size = transValue(BC->getSize(), F, BB);
17821784
bool IsVolatile = BC->SPIRVMemoryAccess::isVolatile();
17831785
IRBuilder<> Builder(BB);
17841786

17851787
if (!CI) {
17861788
llvm::Value *Src = transValue(BC->getSource(), F, BB);
1787-
CI = Builder.CreateMemCpy(Dst, Align, Src, Align, Size, IsVolatile);
1789+
CI = Builder.CreateMemCpy(Dst, Align, Src, SrcAlign, Size, IsVolatile);
17881790
}
17891791
if (isFuncNoUnwind())
17901792
CI->getFunction()->addFnAttr(Attribute::NoUnwind);

lib/SPIRV/SPIRVWriter.cpp

+23-7
Original file line numberDiff line numberDiff line change
@@ -3947,19 +3947,30 @@ bool allowDecorateWithLatencyControlINTEL(IntrinsicInst *II) {
39473947

39483948
SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
39493949
SPIRVBasicBlock *BB) {
3950-
auto GetMemoryAccess = [](MemIntrinsic *MI) -> std::vector<SPIRVWord> {
3950+
auto GetMemoryAccess =
3951+
[](MemIntrinsic *MI,
3952+
bool AllowTwoMemAccessMasks) -> std::vector<SPIRVWord> {
39513953
std::vector<SPIRVWord> MemoryAccess(1, MemoryAccessMaskNone);
39523954
MaybeAlign DestAlignVal = MI->getDestAlign();
39533955
if (DestAlignVal) {
39543956
Align AlignVal = *DestAlignVal;
39553957
MemoryAccess[0] |= MemoryAccessAlignedMask;
3956-
if (auto *MTI = dyn_cast<MemTransferInst>(MI)) {
3958+
if (auto *MTI = dyn_cast<MemCpyInst>(MI)) {
39573959
MaybeAlign SourceAlignVal = MTI->getSourceAlign();
39583960
assert(SourceAlignVal && "Missed Source alignment!");
39593961

39603962
// In a case when alignment of source differs from dest one
3961-
// least value is guaranteed anyway.
3962-
AlignVal = std::min(*DestAlignVal, *SourceAlignVal);
3963+
// we either preserve both (allowed since SPIR-V 1.4), or the least
3964+
// value is guaranteed anyway.
3965+
if (AllowTwoMemAccessMasks) {
3966+
if (*DestAlignVal != *SourceAlignVal) {
3967+
MemoryAccess.push_back(DestAlignVal.valueOrOne().value());
3968+
MemoryAccess.push_back(MemoryAccessAlignedMask);
3969+
AlignVal = *SourceAlignVal;
3970+
}
3971+
} else {
3972+
AlignVal = std::min(*DestAlignVal, *SourceAlignVal);
3973+
}
39633974
}
39643975
MemoryAccess.push_back(AlignVal.value());
39653976
}
@@ -4454,14 +4465,19 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
44544465
transPointerType(Val->getType(), SPIRV::SPIRAS_Constant);
44554466
SPIRVValue *Source = BM->addUnaryInst(OpBitcast, SourceTy, Var, BB);
44564467
SPIRVValue *Target = transValue(MSI->getRawDest(), BB);
4457-
return BM->addCopyMemorySizedInst(Target, Source, CompositeTy->getLength(),
4458-
GetMemoryAccess(MSI), BB);
4468+
return BM->addCopyMemorySizedInst(
4469+
Target, Source, CompositeTy->getLength(),
4470+
GetMemoryAccess(MSI,
4471+
BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)),
4472+
BB);
44594473
} break;
44604474
case Intrinsic::memcpy:
44614475
return BM->addCopyMemorySizedInst(
44624476
transValue(II->getOperand(0), BB), transValue(II->getOperand(1), BB),
44634477
transValue(II->getOperand(2), BB),
4464-
GetMemoryAccess(cast<MemIntrinsic>(II)), BB);
4478+
GetMemoryAccess(cast<MemIntrinsic>(II),
4479+
BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)),
4480+
BB);
44654481
case Intrinsic::lifetime_start:
44664482
case Intrinsic::lifetime_end: {
44674483
Op OC = (II->getIntrinsicID() == Intrinsic::lifetime_start)

lib/SPIRV/libSPIRV/SPIRVInstruction.h

+26-5
Original file line numberDiff line numberDiff line change
@@ -393,14 +393,14 @@ class SPIRVInstTemplate : public BT {
393393
class SPIRVMemoryAccess {
394394
public:
395395
SPIRVMemoryAccess(const std::vector<SPIRVWord> &TheMemoryAccess)
396-
: TheMemoryAccessMask(0), Alignment(0), AliasScopeInstID(0),
397-
NoAliasInstID(0) {
396+
: TheMemoryAccessMask(0), Alignment(0), SrcAlignment(0),
397+
AliasScopeInstID(0), NoAliasInstID(0) {
398398
memoryAccessUpdate(TheMemoryAccess);
399399
}
400400

401401
SPIRVMemoryAccess()
402-
: TheMemoryAccessMask(0), Alignment(0), AliasScopeInstID(0),
403-
NoAliasInstID(0) {}
402+
: TheMemoryAccessMask(0), Alignment(0), SrcAlignment(0),
403+
AliasScopeInstID(0), NoAliasInstID(0) {}
404404

405405
void memoryAccessUpdate(const std::vector<SPIRVWord> &MemoryAccess) {
406406
if (!MemoryAccess.size())
@@ -421,7 +421,18 @@ class SPIRVMemoryAccess {
421421
if (MemoryAccess[0] & MemoryAccessNoAliasINTELMaskMask) {
422422
assert(MemoryAccess.size() > MemAccessNumParam &&
423423
"Aliasing operand is missing");
424-
NoAliasInstID = MemoryAccess[MemAccessNumParam];
424+
NoAliasInstID = MemoryAccess[MemAccessNumParam++];
425+
}
426+
427+
// Exit if there is no second memory operand mask
428+
if (MemoryAccess.size() == MemAccessNumParam)
429+
return;
430+
431+
size_t SecondMaskId = MemAccessNumParam++;
432+
if (MemoryAccess[SecondMaskId] & MemoryAccessAlignedMask) {
433+
assert(MemoryAccess.size() > MemAccessNumParam &&
434+
"Alignment operand is missing");
435+
SrcAlignment = MemoryAccess[MemAccessNumParam];
425436
}
426437
}
427438
SPIRVWord isVolatile() const {
@@ -438,12 +449,14 @@ class SPIRVMemoryAccess {
438449
}
439450
SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; }
440451
SPIRVWord getAlignment() const { return Alignment; }
452+
SPIRVWord getSrcAlignment() const { return SrcAlignment; }
441453
SPIRVWord getAliasScopeInstID() const { return AliasScopeInstID; }
442454
SPIRVWord getNoAliasInstID() const { return NoAliasInstID; }
443455

444456
protected:
445457
SPIRVWord TheMemoryAccessMask;
446458
SPIRVWord Alignment;
459+
SPIRVWord SrcAlignment;
447460
SPIRVId AliasScopeInstID;
448461
SPIRVId NoAliasInstID;
449462
};
@@ -2103,13 +2116,21 @@ class SPIRVCopyMemorySized : public SPIRVInstruction, public SPIRVMemoryAccess {
21032116
Size(TheSize->getId()) {
21042117
validate();
21052118
assert(TheBB && "Invalid BB");
2119+
updateModuleVersion();
21062120
}
21072121
// Incomplete constructor
21082122
SPIRVCopyMemorySized()
21092123
: SPIRVInstruction(OC), SPIRVMemoryAccess(), Target(SPIRVID_INVALID),
21102124
Source(SPIRVID_INVALID), Size(0) {
21112125
setHasNoId();
21122126
setHasNoType();
2127+
updateModuleVersion();
2128+
}
2129+
2130+
VersionNumber getRequiredSPIRVVersion() const override {
2131+
if (getSrcAlignment())
2132+
return VersionNumber::SPIRV_1_4;
2133+
return VersionNumber::SPIRV_1_0;
21132134
}
21142135

21152136
SPIRVValue *getSource() { return getValue(Source); }

test/llvm-intrinsics/memcpy.align.ll

+18-5
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,21 @@
2525
; clang -cc1 -triple spir -disable-llvm-passes t.cl -emit-llvm -o t.ll
2626

2727
; RUN: llvm-as %s -o %t.bc
28-
; RUN: llvm-spirv %t.bc -spirv-text -o %t.txt
28+
; RUN: llvm-spirv %t.bc --spirv-max-version=1.3 -spirv-text -o %t.txt
2929
; RUN: FileCheck < %t.txt %s --check-prefix=CHECK-SPIRV
30-
; RUN: llvm-spirv %t.bc -o %t.spv
30+
; RUN: llvm-spirv %t.bc --spirv-max-version=1.3 -o %t.spv
3131
; RUN: spirv-val %t.spv
3232
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
33-
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
33+
; RUN: llvm-dis %t.rev.bc
34+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
35+
36+
; RUN: llvm-spirv %t.bc --spirv-max-version=1.4 -spirv-text -o %t.txt
37+
; RUN: FileCheck < %t.txt %s --check-prefix=ALIGN-MATCH-SPIRV
38+
; RUN: llvm-spirv %t.bc --spirv-max-version=1.4 -o %t.spv
39+
; RUN: spirv-val %t.spv
40+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
41+
; RUN: llvm-dis %t.rev.bc
42+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=ALIGN-MATCH-LLVM
3443

3544
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
3645
target triple = "spir"
@@ -53,8 +62,10 @@ entry:
5362
%b1 = getelementptr inbounds %struct.A, %struct.A* %agg.result, i32 0, i32 1
5463
%2 = bitcast %struct.B* %b1 to i8*
5564
%3 = bitcast %struct.B* %b to i8*
56-
; CHECK-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 4
65+
; CHECK-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 2 4
5766
; CHECK-LLVM: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{%[0-9]+}}, ptr align 4 {{%[0-9]+}}, i32 8, i1 false)
67+
; ALIGN-MATCH-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 2 8 2 4
68+
; ALIGN-MATCH-LLVM: call void @llvm.memcpy.p0.p0.i32(ptr align 8 {{%[0-9]+}}, ptr align 4 {{%[0-9]+}}, i32 8, i1 false)
5869
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %2, i8* align 4 %3, i32 8, i1 false), !tbaa.struct !4
5970
%4 = bitcast %struct.B* %b to i8*
6071
call void @llvm.lifetime.end.p0i8(i64 8, i8* %4) #2
@@ -85,8 +96,10 @@ entry:
8596
%b = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 1
8697
%2 = bitcast %struct.B* %agg.result to i8*
8798
%3 = bitcast %struct.B* %b to i8*
88-
; CHECK-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 4
99+
; CHECK-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 2 4
89100
; CHECK-LLVM: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{%[0-9]+}}, ptr align 4 {{%[0-9]+}}, i32 8, i1 false)
101+
; ALIGN-MATCH-SPIRV: CopyMemorySized {{[0-9]+}} {{[0-9]+}} {{[0-9]+}} 2 4 2 8
102+
; ALIGN-MATCH-LLVM: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{%[0-9]+}}, ptr align 8 {{%[0-9]+}}, i32 8, i1 false)
90103
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %2, i8* align 8 %3, i32 8, i1 false), !tbaa.struct !4
91104
%4 = bitcast %struct.A* %a to i8*
92105
call void @llvm.lifetime.end.p0i8(i64 16, i8* %4) #2

0 commit comments

Comments
 (0)