diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index f7d00b59ac..7bf8f8cb73 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -2893,6 +2893,15 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) { // assuming llvm.memset is supported by the device compiler. If this // assumption is not safe, we should have a command line option to control // this behavior. + if (FuncNameRef.startswith("spirv.llvm_memset_p")) { + // We can't guarantee that the name is correctly mangled due to opaque + // pointers. Derive the correct name from the function type. + FuncName = + Intrinsic::getDeclaration(M, Intrinsic::memset, + {FT->getParamType(0), FT->getParamType(2)}) + ->getName() + .str(); + } if (FuncNameRef.consume_front("spirv.")) { FuncNameRef.consume_back(".volatile"); FuncName = FuncNameRef.str(); diff --git a/test/llvm-intrinsics/memset-opaque.spt b/test/llvm-intrinsics/memset-opaque.spt new file mode 100644 index 0000000000..50655a5082 --- /dev/null +++ b/test/llvm-intrinsics/memset-opaque.spt @@ -0,0 +1,238 @@ +; RUN: llvm-spirv %s -to-binary -o %t.spv +; RUN: llvm-spirv -r %t.spv -o %t.bc +; RUN: llvm-dis < %t.bc | FileCheck %s --check-prefix=CHECK-LLVM + +; Verify that the reverse translation works correctly and converts opaque-type generated intrinsics +; (like 'spirv.llvm_memset_p0_i32') to the typed-pointer signatures (like to '@llvm.memset.p0i8.i32'). + +; CHECK-LLVM: call void @llvm.memcpy.p4i8.p2i8.i32(i8 addrspace(4)* align 4 %1, i8 addrspace(2)* align 4 %2, i32 12, i1 false) +; CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %3, i8 addrspace(2)* align 4 %4, i32 4, i1 false) +; CHECK-LLVM: call void @llvm.memset.p0a4i8.i32([4 x i8]* %x, i8 %v, i32 3, i1 false) +; CHECK-LLVM: call void @llvm.memset.p0a4i8.i32([4 x i8]* %x, i8 %v, i32 %s1, i1 false) +; CHECK-LLVM: call void @llvm.memset.p3s_struct.S1s.i32(%struct.S1 addrspace(3)* %a, i8 %v, i32 %s1, i1 false) +; CHECK-LLVM: call void @llvm.memset.p1s_struct.S1s.i64(%struct.S1 addrspace(1)* %b, i8 %v, i64 %s2, i1 false) +; CHECK-LLVM: call void @llvm.memset.p1s_struct.S1s.i64(%struct.S1 addrspace(1)* %b, i8 %v, i64 %s2, i1 true) + +119734787 65536 393230 117 0 +2 Capability Addresses +2 Capability Linkage +2 Capability Kernel +2 Capability Int64 +2 Capability GenericPointer +2 Capability Int8 +5 ExtInstImport 1 "OpenCL.std" +3 MemoryModel 1 2 +3 Source 4 202000 +5 Name 3 "struct.S1" +5 Name 9 "_Z5foo11v" +5 Name 10 "agg.result" +3 Name 11 "s1" +3 Name 12 "s2" +3 Name 13 "v" +3 Name 18 "x" +9 Name 39 "spirv.llvm_memset_p0_i32" +4 Name 40 "dest" +3 Name 41 "val" +3 Name 42 "len" +5 Name 43 "isvolatile" +3 Name 47 "a" +9 Name 49 "spirv.llvm_memset_p3_i32" +4 Name 50 "dest" +3 Name 51 "val" +3 Name 52 "len" +5 Name 53 "isvolatile" +3 Name 56 "b" +9 Name 58 "spirv.llvm_memset_p1_i64" +4 Name 59 "dest" +3 Name 60 "val" +3 Name 61 "len" +5 Name 62 "isvolatile" +11 Name 65 "spirv.llvm_memset_p1_i64.volatile" +4 Name 66 "dest" +3 Name 67 "val" +3 Name 68 "len" +5 Name 69 "isvolatile" +4 Name 71 "entry" +6 Name 72 "loadstoreloop" +4 Name 73 "split" +4 Name 83 "entry" +6 Name 84 "loadstoreloop" +4 Name 85 "split" +4 Name 94 "entry" +6 Name 95 "loadstoreloop" +4 Name 96 "split" +4 Name 107 "entry" +6 Name 108 "loadstoreloop" +4 Name 109 "split" +7 Decorate 9 LinkageAttributes "_Z5foo11v" Export +4 Decorate 10 FuncParamAttr 4 +4 Decorate 10 FuncParamAttr 5 +4 Decorate 10 FuncParamAttr 3 +4 Decorate 18 Alignment 1 +3 Decorate 25 Constant +3 Decorate 33 Constant +11 Decorate 39 LinkageAttributes "spirv.llvm_memset_p0_i32" Export +11 Decorate 49 LinkageAttributes "spirv.llvm_memset_p3_i32" Export +11 Decorate 58 LinkageAttributes "spirv.llvm_memset_p1_i64" Export +13 Decorate 65 LinkageAttributes "spirv.llvm_memset_p1_i64.volatile" Export +4 TypeInt 4 32 0 +4 TypeInt 6 64 0 +4 TypeInt 7 8 0 +4 Constant 4 15 4 +4 Constant 4 21 12 +4 Constant 7 30 21 +4 Constant 4 35 3 +4 Constant 4 74 0 +4 Constant 4 80 1 +5 Constant 6 97 0 0 +5 Constant 6 104 1 0 +2 TypeVoid 2 +5 TypeStruct 3 4 4 4 + +4 TypePointer 5 8 3 +7 TypeFunction 8 2 5 4 6 7 +4 TypeArray 16 7 15 +4 TypePointer 17 7 16 +4 TypePointer 19 8 7 +4 TypeArray 22 7 21 +4 TypePointer 24 0 22 +4 TypePointer 26 0 7 +4 TypePointer 28 7 7 +4 TypePointer 32 0 16 +2 TypeBool 36 +7 TypeFunction 38 2 17 7 4 36 +4 TypePointer 46 4 3 +7 TypeFunction 48 2 46 7 4 36 +4 TypePointer 55 5 3 +7 TypeFunction 57 2 55 7 6 36 +4 TypePointer 89 4 7 +4 TypePointer 101 5 7 +3 ConstantNull 22 23 +5 Variable 24 25 0 23 +7 ConstantComposite 16 31 30 30 30 30 + +5 Variable 32 33 0 31 +3 ConstantFalse 36 37 +3 ConstantTrue 36 64 + + +5 Function 2 9 0 8 +3 FunctionParameter 5 10 +3 FunctionParameter 4 11 +3 FunctionParameter 6 12 +3 FunctionParameter 7 13 + +2 Label 14 +4 Variable 17 18 7 +4 Bitcast 19 20 10 +4 Bitcast 26 27 25 +6 CopyMemorySized 20 27 21 2 4 +4 Bitcast 28 29 18 +4 Bitcast 26 34 33 +6 CopyMemorySized 29 34 15 2 4 +8 FunctionCall 2 44 39 18 13 35 37 +8 FunctionCall 2 45 39 18 13 11 37 +4 GenericCastToPtr 46 47 10 +8 FunctionCall 2 54 49 47 13 11 37 +4 GenericCastToPtr 55 56 10 +8 FunctionCall 2 63 58 56 13 12 37 +8 FunctionCall 2 70 65 56 13 12 64 +1 Return + +1 FunctionEnd + +5 Function 2 39 0 38 +3 FunctionParameter 17 40 +3 FunctionParameter 7 41 +3 FunctionParameter 4 42 +3 FunctionParameter 36 43 + +2 Label 71 +5 IEqual 36 75 74 42 +4 BranchConditional 75 73 72 + +2 Label 72 +7 Phi 4 77 74 71 76 72 +4 Bitcast 28 78 40 +5 InBoundsPtrAccessChain 28 79 78 77 +5 Store 79 41 2 1 +5 IAdd 4 76 77 80 +5 ULessThan 36 82 76 42 +4 BranchConditional 82 72 73 + +2 Label 73 +1 Return + +1 FunctionEnd + +5 Function 2 49 0 48 +3 FunctionParameter 46 50 +3 FunctionParameter 7 51 +3 FunctionParameter 4 52 +3 FunctionParameter 36 53 + +2 Label 83 +5 IEqual 36 86 74 52 +4 BranchConditional 86 85 84 + +2 Label 84 +7 Phi 4 88 74 83 87 84 +4 Bitcast 89 90 50 +5 InBoundsPtrAccessChain 89 91 90 88 +5 Store 91 51 2 1 +5 IAdd 4 87 88 80 +5 ULessThan 36 93 87 52 +4 BranchConditional 93 84 85 + +2 Label 85 +1 Return + +1 FunctionEnd + +5 Function 2 58 0 57 +3 FunctionParameter 55 59 +3 FunctionParameter 7 60 +3 FunctionParameter 6 61 +3 FunctionParameter 36 62 + +2 Label 94 +5 IEqual 36 98 97 61 +4 BranchConditional 98 96 95 + +2 Label 95 +7 Phi 6 100 97 94 99 95 +4 Bitcast 101 102 59 +5 InBoundsPtrAccessChain 101 103 102 100 +5 Store 103 60 2 1 +5 IAdd 6 99 100 104 +5 ULessThan 36 106 99 61 +4 BranchConditional 106 95 96 + +2 Label 96 +1 Return + +1 FunctionEnd + +5 Function 2 65 0 57 +3 FunctionParameter 55 66 +3 FunctionParameter 7 67 +3 FunctionParameter 6 68 +3 FunctionParameter 36 69 + +2 Label 107 +5 IEqual 36 110 97 68 +4 BranchConditional 110 109 108 + +2 Label 108 +7 Phi 6 112 97 107 111 108 +4 Bitcast 101 113 66 +5 InBoundsPtrAccessChain 101 114 113 112 +5 Store 114 67 3 1 +5 IAdd 6 111 112 104 +5 ULessThan 36 116 111 68 +4 BranchConditional 116 108 109 + +2 Label 109 +1 Return + +1 FunctionEnd diff --git a/test/llvm-intrinsics/memset.ll b/test/llvm-intrinsics/memset.ll index 183f53931d..a4030971e0 100644 --- a/test/llvm-intrinsics/memset.ll +++ b/test/llvm-intrinsics/memset.ll @@ -5,6 +5,7 @@ ; RUN: llvm-spirv -r %t.spv -o %t.rev.bc ; RUN: spirv-val %t.spv ; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM +; RUN: llvm-spirv -r %t.spv -o - --opaque-pointers=1 | llvm-dis -opaque-pointers=1 | FileCheck %s --check-prefix=CHECK-LLVM-OPAQUE ; CHECK-SPIRV: Decorate [[#NonConstMemset:]] LinkageAttributes "spirv.llvm_memset_p3i8_i32" ; CHECK-SPIRV: TypeInt [[Int8:[0-9]+]] 8 0 @@ -69,28 +70,35 @@ define spir_func void @_Z5foo11v(%struct.S1 addrspace(4)* noalias nocapture sret %1 = bitcast %struct.S1 addrspace(4)* %agg.result to i8 addrspace(4)* tail call void @llvm.memset.p4i8.i32(i8 addrspace(4)* align 4 %1, i8 0, i32 12, i1 false) ; CHECK-LLVM: call void @llvm.memcpy.p4i8.p2i8.i32(i8 addrspace(4)* align 4 %1, i8 addrspace(2)* align 4 %2, i32 12, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memcpy.p4.p2.i32(ptr addrspace(4) align 4 %1, ptr addrspace(2) align 4 %2, i32 12, i1 false) tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 21, i32 4, i1 false) ; CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %x.bc, i8 addrspace(2)* align 4 %3, i32 4, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memcpy.p0.p2.i32(ptr align 4 %x.bc, ptr addrspace(2) align 4 %3, i32 4, i1 false) ; non-const value tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 %v, i32 3, i1 false) ; CHECK-LLVM: call void @llvm.memset.p0i8.i32(i8* %x.bc, i8 %v, i32 3, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memset.p0.i32(ptr %x.bc, i8 %v, i32 3, i1 false) ; non-const value and size tail call void @llvm.memset.p0i8.i32(i8* align 4 %x.bc, i8 %v, i32 %s1, i1 false) ; CHECK-LLVM: call void @llvm.memset.p0i8.i32(i8* %x.bc, i8 %v, i32 %s1, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memset.p0.i32(ptr %x.bc, i8 %v, i32 %s1, i1 false) ; Address spaces, non-const value and size %a = addrspacecast i8 addrspace(4)* %1 to i8 addrspace(3)* tail call void @llvm.memset.p3i8.i32(i8 addrspace(3)* align 4 %a, i8 %v, i32 %s1, i1 false) ; CHECK-LLVM: call void @llvm.memset.p3i8.i32(i8 addrspace(3)* %a, i8 %v, i32 %s1, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memset.p3.i32(ptr addrspace(3) %a, i8 %v, i32 %s1, i1 false) %b = addrspacecast i8 addrspace(4)* %1 to i8 addrspace(1)* tail call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 %v, i64 %s2, i1 false) ; CHECK-LLVM: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %b, i8 %v, i64 %s2, i1 false) +; CHECK-LLVM-OPAQUE: call void @llvm.memset.p1.i64(ptr addrspace(1) %b, i8 %v, i64 %s2, i1 false) ; Volatile tail call void @llvm.memset.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 %v, i64 %s2, i1 true) ; CHECK-LLVM: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %b, i8 %v, i64 %s2, i1 true) +; CHECK-LLVM-OPAQUE: call void @llvm.memset.p1.i64(ptr addrspace(1) %b, i8 %v, i64 %s2, i1 true) ret void }