Skip to content

Commit a4fe52d

Browse files
vmaksimosys-ce-bb
authored andcommitted
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. Original commit: KhronosGroup/SPIRV-LLVM-Translator@a384e036501551e
1 parent 9e365c8 commit a4fe52d

File tree

4 files changed

+70
-18
lines changed

4 files changed

+70
-18
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 3 additions & 1 deletion
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);

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4012,19 +4012,30 @@ bool allowDecorateWithLatencyControlINTEL(IntrinsicInst *II) {
40124012

40134013
SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
40144014
SPIRVBasicBlock *BB) {
4015-
auto GetMemoryAccess = [](MemIntrinsic *MI) -> std::vector<SPIRVWord> {
4015+
auto GetMemoryAccess =
4016+
[](MemIntrinsic *MI,
4017+
bool AllowTwoMemAccessMasks) -> std::vector<SPIRVWord> {
40164018
std::vector<SPIRVWord> MemoryAccess(1, MemoryAccessMaskNone);
40174019
MaybeAlign DestAlignVal = MI->getDestAlign();
40184020
if (DestAlignVal) {
40194021
Align AlignVal = *DestAlignVal;
40204022
MemoryAccess[0] |= MemoryAccessAlignedMask;
4021-
if (auto *MTI = dyn_cast<MemTransferInst>(MI)) {
4023+
if (auto *MTI = dyn_cast<MemCpyInst>(MI)) {
40224024
MaybeAlign SourceAlignVal = MTI->getSourceAlign();
40234025
assert(SourceAlignVal && "Missed Source alignment!");
40244026

40254027
// In a case when alignment of source differs from dest one
4026-
// least value is guaranteed anyway.
4027-
AlignVal = std::min(*DestAlignVal, *SourceAlignVal);
4028+
// we either preserve both (allowed since SPIR-V 1.4), or the least
4029+
// value is guaranteed anyway.
4030+
if (AllowTwoMemAccessMasks) {
4031+
if (*DestAlignVal != *SourceAlignVal) {
4032+
MemoryAccess.push_back(DestAlignVal.valueOrOne().value());
4033+
MemoryAccess.push_back(MemoryAccessAlignedMask);
4034+
AlignVal = *SourceAlignVal;
4035+
}
4036+
} else {
4037+
AlignVal = std::min(*DestAlignVal, *SourceAlignVal);
4038+
}
40284039
}
40294040
MemoryAccess.push_back(AlignVal.value());
40304041
}
@@ -4519,14 +4530,19 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
45194530
transPointerType(Val->getType(), SPIRV::SPIRAS_Constant);
45204531
SPIRVValue *Source = BM->addUnaryInst(OpBitcast, SourceTy, Var, BB);
45214532
SPIRVValue *Target = transValue(MSI->getRawDest(), BB);
4522-
return BM->addCopyMemorySizedInst(Target, Source, CompositeTy->getLength(),
4523-
GetMemoryAccess(MSI), BB);
4533+
return BM->addCopyMemorySizedInst(
4534+
Target, Source, CompositeTy->getLength(),
4535+
GetMemoryAccess(MSI,
4536+
BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)),
4537+
BB);
45244538
} break;
45254539
case Intrinsic::memcpy:
45264540
return BM->addCopyMemorySizedInst(
45274541
transValue(II->getOperand(0), BB), transValue(II->getOperand(1), BB),
45284542
transValue(II->getOperand(2), BB),
4529-
GetMemoryAccess(cast<MemIntrinsic>(II)), BB);
4543+
GetMemoryAccess(cast<MemIntrinsic>(II),
4544+
BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_4)),
4545+
BB);
45304546
case Intrinsic::lifetime_start:
45314547
case Intrinsic::lifetime_end: {
45324548
Op OC = (II->getIntrinsicID() == Intrinsic::lifetime_start)

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,14 +381,14 @@ class SPIRVInstTemplate : public BT {
381381
class SPIRVMemoryAccess {
382382
public:
383383
SPIRVMemoryAccess(const std::vector<SPIRVWord> &TheMemoryAccess)
384-
: TheMemoryAccessMask(0), Alignment(0), AliasScopeInstID(0),
385-
NoAliasInstID(0) {
384+
: TheMemoryAccessMask(0), Alignment(0), SrcAlignment(0),
385+
AliasScopeInstID(0), NoAliasInstID(0) {
386386
memoryAccessUpdate(TheMemoryAccess);
387387
}
388388

389389
SPIRVMemoryAccess()
390-
: TheMemoryAccessMask(0), Alignment(0), AliasScopeInstID(0),
391-
NoAliasInstID(0) {}
390+
: TheMemoryAccessMask(0), Alignment(0), SrcAlignment(0),
391+
AliasScopeInstID(0), NoAliasInstID(0) {}
392392

393393
void memoryAccessUpdate(const std::vector<SPIRVWord> &MemoryAccess) {
394394
if (!MemoryAccess.size())
@@ -409,7 +409,18 @@ class SPIRVMemoryAccess {
409409
if (MemoryAccess[0] & MemoryAccessNoAliasINTELMaskMask) {
410410
assert(MemoryAccess.size() > MemAccessNumParam &&
411411
"Aliasing operand is missing");
412-
NoAliasInstID = MemoryAccess[MemAccessNumParam];
412+
NoAliasInstID = MemoryAccess[MemAccessNumParam++];
413+
}
414+
415+
// Exit if there is no second memory operand mask
416+
if (MemoryAccess.size() == MemAccessNumParam)
417+
return;
418+
419+
size_t SecondMaskId = MemAccessNumParam++;
420+
if (MemoryAccess[SecondMaskId] & MemoryAccessAlignedMask) {
421+
assert(MemoryAccess.size() > MemAccessNumParam &&
422+
"Alignment operand is missing");
423+
SrcAlignment = MemoryAccess[MemAccessNumParam];
413424
}
414425
}
415426
SPIRVWord isVolatile() const {
@@ -426,12 +437,14 @@ class SPIRVMemoryAccess {
426437
}
427438
SPIRVWord getMemoryAccessMask() const { return TheMemoryAccessMask; }
428439
SPIRVWord getAlignment() const { return Alignment; }
440+
SPIRVWord getSrcAlignment() const { return SrcAlignment; }
429441
SPIRVWord getAliasScopeInstID() const { return AliasScopeInstID; }
430442
SPIRVWord getNoAliasInstID() const { return NoAliasInstID; }
431443

432444
protected:
433445
SPIRVWord TheMemoryAccessMask;
434446
SPIRVWord Alignment;
447+
SPIRVWord SrcAlignment;
435448
SPIRVId AliasScopeInstID;
436449
SPIRVId NoAliasInstID;
437450
};
@@ -2091,13 +2104,21 @@ class SPIRVCopyMemorySized : public SPIRVInstruction, public SPIRVMemoryAccess {
20912104
Size(TheSize->getId()) {
20922105
validate();
20932106
assert(TheBB && "Invalid BB");
2107+
updateModuleVersion();
20942108
}
20952109
// Incomplete constructor
20962110
SPIRVCopyMemorySized()
20972111
: SPIRVInstruction(OC), SPIRVMemoryAccess(), Target(SPIRVID_INVALID),
20982112
Source(SPIRVID_INVALID), Size(0) {
20992113
setHasNoId();
21002114
setHasNoType();
2115+
updateModuleVersion();
2116+
}
2117+
2118+
VersionNumber getRequiredSPIRVVersion() const override {
2119+
if (getSrcAlignment())
2120+
return VersionNumber::SPIRV_1_4;
2121+
return VersionNumber::SPIRV_1_0;
21012122
}
21022123

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

llvm-spirv/test/llvm-intrinsics/memcpy.align.ll

Lines changed: 18 additions & 5 deletions
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)