Skip to content

Commit 36d69c7

Browse files
svenvhvladimirlaz
authored andcommitted
Handle non-zero values for llvm.memset
Relax a limitation of the SPIR-V writer. The memset intrinsic is mapped to `OpCopyMemorySized`, causing it to be converted to memcpy when converting back from SPIR-V to LLVM. Fixes KhronosGroup/SPIRV-LLVM-Translator#357
1 parent e85a959 commit 36d69c7

File tree

2 files changed

+33
-23
lines changed

2 files changed

+33
-23
lines changed

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,20 +1566,16 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
15661566
transValue(II->getArgOperand(2), BB), BB);
15671567
}
15681568
case Intrinsic::memset: {
1569-
// Generally memset can't be translated with current version of SPIRV spec.
1570-
// But in most cases it turns out that memset is emited by Clang to do
1571-
// zero-initializtion in default constructors.
1572-
// The code below handles only cases with val = 0 and constant len.
1569+
// Generally there is no direct mapping of memset to SPIR-V. But it turns
1570+
// out that memset is emitted by Clang for initialization in default
1571+
// constructors so we need some basic support. The code below only handles
1572+
// cases with constant value and constant length.
15731573
MemSetInst *MSI = cast<MemSetInst>(II);
15741574
Value *Val = MSI->getValue();
15751575
if (!isa<Constant>(Val)) {
15761576
assert(!"Can't translate llvm.memset with non-const `value` argument");
15771577
return nullptr;
15781578
}
1579-
if (!cast<Constant>(Val)->isZeroValue()) {
1580-
assert(!"Can't translate llvm.memset with non-zero `value` argument");
1581-
return nullptr;
1582-
}
15831579
Value *Len = MSI->getLength();
15841580
if (!isa<ConstantInt>(Len)) {
15851581
assert(!"Can't translate llvm.memset with non-const `length` argument");
@@ -1588,7 +1584,13 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
15881584
uint64_t NumElements = static_cast<ConstantInt *>(Len)->getZExtValue();
15891585
auto *AT = ArrayType::get(Val->getType(), NumElements);
15901586
SPIRVTypeArray *CompositeTy = static_cast<SPIRVTypeArray *>(transType(AT));
1591-
SPIRVValue *Init = BM->addNullConstant(CompositeTy);
1587+
SPIRVValue *Init;
1588+
if (cast<Constant>(Val)->isZeroValue()) {
1589+
Init = BM->addNullConstant(CompositeTy);
1590+
} else {
1591+
std::vector<SPIRVValue *> Elts{NumElements, transValue(Val, BB)};
1592+
Init = BM->addCompositeConstant(CompositeTy, Elts);
1593+
}
15921594
SPIRVType *VarTy = transType(PointerType::get(AT, SPIRV::SPIRAS_Constant));
15931595
SPIRVValue *Var =
15941596
BM->addVariable(VarTy, /*isConstant*/ true, spv::LinkageTypeInternal,

llvm-spirv/test/transcoding/llvm.memset.ll

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,58 @@
1-
;; struct S1
2-
;; {
3-
;; int x;
4-
;; int y;
5-
;; int z;
6-
;; };
7-
;; S1 foo11()
8-
;; {
9-
;; return S1();
10-
;; }
11-
121
; RUN: llvm-as %s -o %t.bc
132
; RUN: llvm-spirv %t.bc -spirv-text -o %t.spt
143
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
154
; RUN: llvm-spirv %t.bc -o %t.spv
165
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
6+
; RUN: spirv-val %t.spv
177
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
188

199
; CHECK-SPIRV: TypeInt [[Int8:[0-9]+]] 8 0
20-
; CHECK-SPIRV: Constant {{[0-9]+}} [[Len:[0-9]+]] 12
10+
; CHECK-SPIRV: Constant {{[0-9]+}} [[Lenmemset21:[0-9]+]] 4
11+
; CHECK-SPIRV: Constant {{[0-9]+}} [[Lenmemset0:[0-9]+]] 12
12+
; CHECK-SPIRV: Constant {{[0-9]+}} [[Const21:[0-9]+]] 21
13+
; CHECK-SPIRV: TypeArray [[Int8x4:[0-9]+]] [[Int8]] [[Lenmemset21]]
2114
; CHECK-SPIRV: TypePointer [[Int8Ptr:[0-9]+]] 8 [[Int8]]
22-
; CHECK-SPIRV: TypeArray [[Int8x12:[0-9]+]] [[Int8]] [[Len]]
15+
; CHECK-SPIRV: TypeArray [[Int8x12:[0-9]+]] [[Int8]] [[Lenmemset0]]
2316
; CHECK-SPIRV: TypePointer [[Int8PtrConst:[0-9]+]] 0 [[Int8]]
17+
2418
; CHECK-SPIRV: ConstantNull [[Int8x12]] [[Init:[0-9]+]]
2519
; CHECK-SPIRV: Variable {{[0-9]+}} [[Val:[0-9]+]] 0 [[Init]]
20+
; CHECK-SPIRV: 7 ConstantComposite [[Int8x4]] [[InitComp:[0-9]+]] [[Const21]] [[Const21]] [[Const21]] [[Const21]]
21+
; CHECK-SPIRV: Variable {{[0-9]+}} [[ValComp:[0-9]+]] 0 [[InitComp]]
2622

2723
; CHECK-SPIRV: Bitcast [[Int8Ptr]] [[Target:[0-9]+]] {{[0-9]+}}
2824
; CHECK-SPIRV: Bitcast [[Int8PtrConst]] [[Source:[0-9]+]] [[Val]]
29-
; CHECK-SPIRV: CopyMemorySized [[Target]] [[Source]] [[Len]] 2 4
25+
; CHECK-SPIRV: CopyMemorySized [[Target]] [[Source]] [[Lenmemset0]] 2 4
3026

27+
; CHECK-SPIRV: Bitcast [[Int8PtrConst]] [[SourceComp:[0-9]+]] [[ValComp]]
28+
; CHECK-SPIRV: CopyMemorySized {{[0-9]+}} [[SourceComp]] [[Lenmemset21]] 2 4
3129

3230
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-n8:16:32:64"
3331
target triple = "spir"
3432

3533
%struct.S1 = type { i32, i32, i32 }
3634

35+
; CHECK-LLVM: internal unnamed_addr addrspace(2) constant [12 x i8] zeroinitializer
36+
; CHECK-LLVM: internal unnamed_addr addrspace(2) constant [4 x i8] c"\15\15\15\15"
37+
3738
; Function Attrs: nounwind
3839
define spir_func void @_Z5foo11v(%struct.S1 addrspace(4)* noalias nocapture sret %agg.result) #0 {
40+
%x = alloca [4 x i8]
41+
%x.bc = bitcast [4 x i8]* %x to i8*
3942
%1 = bitcast %struct.S1 addrspace(4)* %agg.result to i8 addrspace(4)*
4043
tail call void @llvm.memset.p4i8.i32(i8 addrspace(4)* align 4 %1, i8 0, i32 12, i1 false)
4144
; CHECK-LLVM: call void @llvm.memset.p4i8.i32(i8 addrspace(4)* align 4 %1, i8 0, i32 12, i1 false)
45+
tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 21, i32 4, i1 false)
46+
; CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %x.bc, i8 addrspace(2)* align 4 %3, i32 4, i1 false)
4247
ret void
4348
}
4449

4550
; Function Attrs: nounwind
4651
declare void @llvm.memset.p4i8.i32(i8 addrspace(4)* nocapture, i8, i32, i1) #1
4752

53+
; Function Attrs: nounwind
54+
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) #1
55+
4856
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
4957
attributes #1 = { nounwind }
5058

0 commit comments

Comments
 (0)