Skip to content

Commit cda4820

Browse files
authored
[SPIRV] Do not use OpTypeRuntimeArray in Kernel env. (#149522)
Prior to this patch, when `NumElems` was 0, `OpTypeRuntimeArray` was directly generated, but it requires `Shader` capability, so it can only be generated if `Shader` env is being used. We have observed a pattern of using unbound arrays that translate into `[0 x ...]` types in OpenCL, which implies `Kernel` capability, so `OpTypeRuntimeArray` should not be used. To prevent this scenario, this patch simplifies GEP instructions where type is a 0-length array and the first index is also 0. In such scenario, we effectively drop the 0-length array and the first index. Additionally, the newly added test prior to this patch was generating a module with both `Shader` and `Kernel` capabilities at the same time, but they're incompatible. This patch also fixes that. Finally, prior to this patch, the newly added test was adding `Shader` capability to the module even with the command line flag `--avoid-spirv-capabilities=Shader`. This patch also has a fix for that.
1 parent 7587a32 commit cda4820

18 files changed

+252
-76
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
#include "llvm/IR/InstIterator.h"
2222
#include "llvm/IR/InstVisitor.h"
2323
#include "llvm/IR/IntrinsicsSPIRV.h"
24+
#include "llvm/IR/PatternMatch.h"
2425
#include "llvm/IR/TypedPointerType.h"
26+
#include "llvm/Transforms/Utils/Local.h"
2527

2628
#include <queue>
2729
#include <unordered_set>
@@ -187,6 +189,8 @@ class SPIRVEmitIntrinsics
187189

188190
void applyDemangledPtrArgTypes(IRBuilder<> &B);
189191

192+
GetElementPtrInst *simplifyZeroLengthArrayGepInst(GetElementPtrInst *GEP);
193+
190194
bool runOnFunction(Function &F);
191195
bool postprocessTypes(Module &M);
192196
bool processFunctionPointers(Module &M);
@@ -2561,6 +2565,30 @@ void SPIRVEmitIntrinsics::applyDemangledPtrArgTypes(IRBuilder<> &B) {
25612565
}
25622566
}
25632567

2568+
GetElementPtrInst *
2569+
SPIRVEmitIntrinsics::simplifyZeroLengthArrayGepInst(GetElementPtrInst *GEP) {
2570+
// getelementptr [0 x T], P, 0 (zero), I -> getelementptr T, P, I.
2571+
// If type is 0-length array and first index is 0 (zero), drop both the
2572+
// 0-length array type and the first index. This is a common pattern in the
2573+
// IR, e.g. when using a zero-length array as a placeholder for a flexible
2574+
// array such as unbound arrays.
2575+
assert(GEP && "GEP is null");
2576+
Type *SrcTy = GEP->getSourceElementType();
2577+
SmallVector<Value *, 8> Indices(GEP->indices());
2578+
ArrayType *ArrTy = dyn_cast<ArrayType>(SrcTy);
2579+
if (ArrTy && ArrTy->getNumElements() == 0 &&
2580+
PatternMatch::match(Indices[0], PatternMatch::m_Zero())) {
2581+
IRBuilder<> Builder(GEP);
2582+
Indices.erase(Indices.begin());
2583+
SrcTy = ArrTy->getElementType();
2584+
Value *NewGEP = Builder.CreateGEP(SrcTy, GEP->getPointerOperand(), Indices,
2585+
"", GEP->getNoWrapFlags());
2586+
assert(llvm::isa<GetElementPtrInst>(NewGEP) && "NewGEP should be a GEP");
2587+
return cast<GetElementPtrInst>(NewGEP);
2588+
}
2589+
return nullptr;
2590+
}
2591+
25642592
bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
25652593
if (Func.isDeclaration())
25662594
return false;
@@ -2578,14 +2606,30 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
25782606
AggrConstTypes.clear();
25792607
AggrStores.clear();
25802608

2581-
// fix GEP result types ahead of inference
2609+
// Fix GEP result types ahead of inference, and simplify if possible.
2610+
// Data structure for dead instructions that were simplified and replaced.
2611+
SmallPtrSet<Instruction *, 4> DeadInsts;
25822612
for (auto &I : instructions(Func)) {
25832613
auto *Ref = dyn_cast<GetElementPtrInst>(&I);
25842614
if (!Ref || GR->findDeducedElementType(Ref))
25852615
continue;
2616+
2617+
GetElementPtrInst *NewGEP = simplifyZeroLengthArrayGepInst(Ref);
2618+
if (NewGEP) {
2619+
Ref->replaceAllUsesWith(NewGEP);
2620+
if (isInstructionTriviallyDead(Ref))
2621+
DeadInsts.insert(Ref);
2622+
2623+
Ref = NewGEP;
2624+
}
25862625
if (Type *GepTy = getGEPType(Ref))
25872626
GR->addDeducedElementType(Ref, normalizeType(GepTy));
25882627
}
2628+
// Remove dead instructions that were simplified and replaced.
2629+
for (auto *I : DeadInsts) {
2630+
assert(I->use_empty() && "Dead instruction should not have any uses left");
2631+
I->eraseFromParent();
2632+
}
25892633

25902634
processParamTypesByFunHeader(CurrF, B);
25912635

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,8 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
828828
"Invalid array element type");
829829
SPIRVType *SpvTypeInt32 = getOrCreateSPIRVIntegerType(32, MIRBuilder);
830830
SPIRVType *ArrayType = nullptr;
831+
const SPIRVSubtarget &ST =
832+
cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
831833
if (NumElems != 0) {
832834
Register NumElementsVReg =
833835
buildConstantInt(NumElems, MIRBuilder, SpvTypeInt32, EmitIR);
@@ -838,6 +840,8 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeArray(uint32_t NumElems,
838840
.addUse(NumElementsVReg);
839841
});
840842
} else {
843+
if (!ST.isShader())
844+
return nullptr;
841845
ArrayType = createOpType(MIRBuilder, [&](MachineIRBuilder &MIRBuilder) {
842846
return MIRBuilder.buildInstr(SPIRV::OpTypeRuntimeArray)
843847
.addDef(createTypeVReg(MIRBuilder))

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -744,8 +744,14 @@ void SPIRV::RequirementHandler::checkSatisfiable(
744744
IsSatisfiable = false;
745745
}
746746

747+
AvoidCapabilitiesSet AvoidCaps;
748+
if (!ST.isShader())
749+
AvoidCaps.S.insert(SPIRV::Capability::Shader);
750+
else
751+
AvoidCaps.S.insert(SPIRV::Capability::Kernel);
752+
747753
for (auto Cap : MinimalCaps) {
748-
if (AvailableCaps.contains(Cap))
754+
if (AvailableCaps.contains(Cap) && !AvoidCaps.S.contains(Cap))
749755
continue;
750756
LLVM_DEBUG(dbgs() << "Capability not supported: "
751757
<< getSymbolicOperandMnemonic(
@@ -1865,6 +1871,10 @@ void addInstrRequirements(const MachineInstr &MI,
18651871
Reqs.addCapability(SPIRV::Capability::TernaryBitwiseFunctionINTEL);
18661872
break;
18671873
}
1874+
case SPIRV::OpCopyMemorySized: {
1875+
Reqs.addCapability(SPIRV::Capability::Addresses);
1876+
// TODO: Add UntypedPointersKHR when implemented.
1877+
}
18681878

18691879
default:
18701880
break;

llvm/test/CodeGen/SPIRV/array_type.ll

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.2-unknown-unknown %s -o - -filetype=obj | spirv-val --target-env opencl2.2 %}
3+
4+
; CHECK: OpCapability Kernel
5+
; CHECK-NOT: OpCapability Shader
6+
; CHECK-DAG: %[[#float16:]] = OpTypeFloat 16
7+
; CHECK-DAG: %[[#SyclHalfTy:]] = OpTypeStruct %[[#float16]]
8+
; CHECK-DAG: %[[#i16:]] = OpTypeInt 16
9+
; CHECK-DAG: %[[#i32:]] = OpTypeInt 32
10+
; CHECK-DAG: %[[#i64:]] = OpTypeInt 64
11+
; CHECK-DAG: %[[#ConstNull:]] = OpConstantNull %[[#i64]]
12+
; CHECK-DAG: %[[#ConstOne:]] = OpConstant %[[#i64]] 1
13+
; CHECK-DAG: %[[#ConstFive:]] = OpConstant %[[#i16]] 5
14+
; CHECK-DAG: %[[#SyclHalfTyPtr:]] = OpTypePointer Function %[[#SyclHalfTy]]
15+
; CHECK-DAG: %[[#i32Ptr:]] = OpTypePointer Function %[[#i32]]
16+
; CHECK-DAG: %[[#StorePtrTy:]] = OpTypePointer Function %[[#i16]]
17+
18+
%"class.sycl::_V1::detail::half_impl::half" = type { half }
19+
20+
; Function Attrs: mustprogress norecurse nounwind
21+
define spir_kernel void @foo(ptr %p){
22+
; CHECK: OpFunction
23+
; CHECK: %[[#Ptr:]] = OpFunctionParameter
24+
; CHECK: OpLabel
25+
; CHECK: %[[#BitcastOp:]] = OpInBoundsPtrAccessChain %[[#SyclHalfTyPtr]] %[[#Ptr]] %[[#ConstNull]] %[[#ConstNull]]
26+
; CHECK: %[[#StorePtr:]] = OpBitcast %[[#StorePtrTy]] %[[#BitcastOp]]
27+
; CHECK: OpStore %[[#StorePtr]] %[[#ConstFive]]
28+
; CHECK: OpReturn
29+
entry:
30+
%0 = getelementptr inbounds [0 x [32 x %"class.sycl::_V1::detail::half_impl::half"]], ptr %p, i64 0, i64 0, i64 0
31+
store i16 5, ptr %0
32+
ret void
33+
}
34+
35+
; Function Attrs: mustprogress norecurse nounwind
36+
define spir_kernel void @foo2(ptr %p){
37+
; CHECK: OpFunction
38+
; CHECK: %[[#Ptr:]] = OpFunctionParameter
39+
; CHECK: OpLabel
40+
; CHECK: %[[#BitcastOp:]] = OpInBoundsPtrAccessChain %[[#SyclHalfTyPtr]] %[[#Ptr]] %[[#ConstOne]] %[[#ConstOne]]
41+
; CHECK: %[[#StorePtr:]] = OpBitcast %[[#StorePtrTy]] %[[#BitcastOp]]
42+
; CHECK: OpStore %[[#StorePtr]] %[[#ConstFive]]
43+
; CHECK: OpReturn
44+
entry:
45+
%0 = getelementptr inbounds [0 x [32 x %"class.sycl::_V1::detail::half_impl::half"]], ptr %p, i64 0, i64 1, i64 1
46+
store i16 5, ptr %0
47+
ret void
48+
}
49+
50+
; Function Attrs: mustprogress norecurse nounwind
51+
define spir_kernel void @foo3(ptr %p){
52+
; CHECK: OpFunction
53+
; CHECK: %[[#Ptr:]] = OpFunctionParameter
54+
; CHECK: OpLabel
55+
; CHECK: %[[#BitcastOp:]] = OpInBoundsPtrAccessChain %[[#i32Ptr]] %[[#Ptr]] %[[#ConstNull]] %[[#ConstNull]]
56+
; CHECK: %[[#StorePtr:]] = OpBitcast %[[#StorePtrTy]] %[[#BitcastOp]]
57+
; CHECK: OpStore %[[#StorePtr]] %[[#ConstFive]]
58+
; CHECK: OpReturn
59+
entry:
60+
%0 = getelementptr inbounds [0 x [32 x i32]], ptr %p, i64 0, i64 0, i64 0
61+
store i16 5, ptr %0
62+
ret void
63+
}
64+
65+
; Function Attrs: mustprogress norecurse nounwind
66+
define spir_kernel void @foo4(ptr %p){
67+
; CHECK: OpFunction
68+
; CHECK: %[[#Ptr:]] = OpFunctionParameter
69+
; CHECK: OpLabel
70+
; CHECK: %[[#BitcastOp:]] = OpInBoundsPtrAccessChain %[[#i32Ptr]] %[[#Ptr]] %[[#ConstOne]] %[[#ConstOne]]
71+
; CHECK: %[[#StorePtr:]] = OpBitcast %[[#StorePtrTy]] %[[#BitcastOp]]
72+
; CHECK: OpStore %[[#StorePtr]] %[[#ConstFive]]
73+
; CHECK: OpReturn
74+
entry:
75+
%0 = getelementptr inbounds [0 x [32 x i32]], ptr %p, i64 0, i64 1, i64 1
76+
store i16 5, ptr %0
77+
ret void
78+
}

llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions.ll

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - | FileCheck %s --check-prefix=CHECK-EXTENSION
2-
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.2-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - -filetype=obj | spirv-val --target-env opencl2.2 %}
33

44
; CHECK-EXTENSION: OpCapability BitInstructions
55
; CHECK-EXTENSION-NEXT: OpExtension "SPV_KHR_bit_instructions"
66
; CHECK-EXTENSION-NOT: OpCabilitity Shader
7-
; CHECK-NO-EXTENSION: OpCapability Shader
8-
; CHECK-NO-EXTENSION-NOT: OpCabilitity BitInstructions
9-
; CHECK-NO-EXTENSION-NOT: OpExtension "SPV_KHR_bit_instructions"
10-
11-
127
; CHECK-EXTENSION: %[[#int:]] = OpTypeInt 32
138
; CHECK-EXTENSION: OpBitReverse %[[#int]]
14-
; CHECK-NO-EXTENSION: %[[#int:]] = OpTypeInt 32
15-
; CHECK-NO-EXTENSION: OpBitReverse %[[#int]]
169

1710
define spir_kernel void @testBitRev(i32 %a, i32 %b, i32 %c, i32 addrspace(1)* nocapture %res) local_unnamed_addr {
1811
entry:
Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - | FileCheck %s --check-prefix=CHECK-EXTENSION
2-
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION
3-
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - -filetype=obj | spirv-val %}
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.2-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - -filetype=obj | spirv-val --target-env opencl2.2 %}
43
;
54
; CHECK-EXTENSION: Capability BitInstructions
65
; CHECK-EXTENSION: Extension "SPV_KHR_bit_instructions"
7-
; CHECK-NO-EXTENSION-NOT: Capability BitInstructions
8-
; CHECK-NO-EXTENSION-NOT: Extension "SPV_KHR_bit_instructions"
9-
; CHECK-NO-EXTENSION: Capability Shader
106
;
117
; CHECK-EXTENSION: %[[#]] = OpFunction %[[#]] None %[[#]]
128
; CHECK-EXTENSION: %[[#reversebase:]] = OpFunctionParameter %[[#]]
@@ -15,24 +11,11 @@
1511
; kernel void testBitReverse_SPIRVFriendly(long4 b, global long4 *res) {
1612
; *res = bit_reverse(b);
1713
; }
18-
define spir_kernel void @testBitReverse_SPIRVFriendly(<4 x i64> %b, ptr addrspace(1) nocapture align 32 %res) #3 {
14+
define spir_kernel void @testBitReverse_SPIRVFriendly(<4 x i64> %b, ptr addrspace(1) %res) {
1915
entry:
2016
%call = call <4 x i64> @llvm.bitreverse.v4i64(<4 x i64> %b)
21-
store <4 x i64> %call, ptr addrspace(1) %res, align 32
17+
store <4 x i64> %call, ptr addrspace(1) %res
2218
ret void
2319
}
2420

25-
declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>) #4
26-
27-
28-
attributes #3 = { nounwind }
29-
attributes #4 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
30-
31-
!llvm.module.flags = !{!0}
32-
!opencl.ocl.version = !{!1}
33-
!opencl.spir.version = !{!1}
34-
!llvm.ident = !{!2}
35-
36-
!0 = !{i32 1, !"wchar_size", i32 4}
37-
!1 = !{i32 2, i32 0}
38-
!2 = !{!"clang version 20.0.0git (https://github.com/llvm/llvm-project.git cc61409d353a40f62d3a137f3c7436aa00df779d)"}
21+
declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
;
4+
; CHECK-NO-EXTENSION-NOT: Capability BitInstructions
5+
; CHECK-NO-EXTENSION-NOT: Extension "SPV_KHR_bit_instructions"
6+
; CHECK-NO-EXTENSION: Capability Shader
7+
8+
define internal spir_func void @testBitReverse_SPIRVFriendly() #3 {
9+
entry:
10+
%call = call <4 x i64> @llvm.bitreverse.v4i64(<4 x i64> <i64 1, i64 2, i64 3, i64 4>)
11+
ret void
12+
}
13+
14+
declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>)
15+
16+
attributes #3 = { nounwind "hlsl.shader"="compute" }
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
3+
4+
5+
; CHECK-NO-EXTENSION: OpCapability Shader
6+
; CHECK-NO-EXTENSION-NOT: OpCabilitity BitInstructions
7+
; CHECK-NO-EXTENSION-NOT: OpExtension "SPV_KHR_bit_instructions"
8+
; CHECK-NO-EXTENSION: %[[#int:]] = OpTypeInt 32
9+
; CHECK-NO-EXTENSION: OpBitReverse %[[#int]]
10+
11+
define hidden spir_func void @testBitRev(i32 %a, i32 %b, i32 %c, ptr %res) local_unnamed_addr {
12+
entry:
13+
%call = tail call i32 @llvm.bitreverse.i32(i32 %b)
14+
store i32 %call, ptr %res, align 4
15+
ret void
16+
}
17+
18+
define void @main() #1 {
19+
ret void
20+
}
21+
22+
declare i32 @llvm.bitreverse.i32(i32)
23+
attributes #1 = { "hlsl.numthreads"="8,1,1" "hlsl.shader"="compute" }

llvm/test/CodeGen/SPIRV/llvm-intrinsics/bitreverse_small_type.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
;; Check that llvm.bitreverse.* intrinsics are lowered for
22
;; 2/4-bit scalar and vector types.
33

4-
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s
5-
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers %s -o - -filetype=obj | spirv-val %}
4+
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers,+SPV_KHR_bit_instructions %s -o - | FileCheck %s
5+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers,+SPV_KHR_bit_instructions %s -o - -filetype=obj | spirv-val %}
66

77
; CHECK: OpCapability ArbitraryPrecisionIntegersINTEL
88
; CHECK: OpExtension "SPV_INTEL_arbitrary_precision_integers"

llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,18 @@
1818
; CL: %[[#FooVar:]] = OpVariable
1919
; CL-NEXT: %[[#Casted1:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
2020
; CL-NEXT: OpLifetimeStart %[[#Casted1]], 72
21-
; CL-NEXT: OpCopyMemorySized
2221
; CL-NEXT: OpBitcast
2322
; CL-NEXT: OpInBoundsPtrAccessChain
2423
; CL-NEXT: %[[#Casted2:]] = OpBitcast %[[#PtrChar]] %[[#FooVar]]
2524
; CL-NEXT: OpLifetimeStop %[[#Casted2]], 72
2625

2726
; VK: OpFunction
2827
; VK: %[[#FooVar:]] = OpVariable
29-
; VK-NEXT: OpCopyMemorySized
3028
; VK-NEXT: OpInBoundsAccessChain
3129
; VK-NEXT: OpReturn
3230
define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
3331
%RoundedRangeKernel = alloca %tprange, align 8
3432
call void @llvm.lifetime.start.p0(i64 72, ptr nonnull %RoundedRangeKernel)
35-
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %RoundedRangeKernel, ptr align 8 %_arg_UserRange, i64 16, i1 false)
3633
%KernelFunc = getelementptr inbounds i8, ptr %RoundedRangeKernel, i64 8
3734
call void @llvm.lifetime.end.p0(i64 72, ptr nonnull %RoundedRangeKernel)
3835
ret void
@@ -41,20 +38,17 @@ define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange)
4138
; CL: OpFunction
4239
; CL: %[[#BarVar:]] = OpVariable
4340
; CL-NEXT: OpLifetimeStart %[[#BarVar]], 0
44-
; CL-NEXT: OpCopyMemorySized
4541
; CL-NEXT: OpBitcast
4642
; CL-NEXT: OpInBoundsPtrAccessChain
4743
; CL-NEXT: OpLifetimeStop %[[#BarVar]], 0
4844

4945
; VK: OpFunction
5046
; VK: %[[#BarVar:]] = OpVariable
51-
; VK-NEXT: OpCopyMemorySized
5247
; VK-NEXT: OpInBoundsAccessChain
5348
; VK-NEXT: OpReturn
5449
define spir_func void @bar(ptr noundef byval(%tprange) align 8 %_arg_UserRange) {
5550
%RoundedRangeKernel = alloca %tprange, align 8
5651
call void @llvm.lifetime.start.p0(i64 -1, ptr nonnull %RoundedRangeKernel)
57-
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %RoundedRangeKernel, ptr align 8 %_arg_UserRange, i64 16, i1 false)
5852
%KernelFunc = getelementptr inbounds i8, ptr %RoundedRangeKernel, i64 8
5953
call void @llvm.lifetime.end.p0(i64 -1, ptr nonnull %RoundedRangeKernel)
6054
ret void
@@ -63,20 +57,17 @@ define spir_func void @bar(ptr noundef byval(%tprange) align 8 %_arg_UserRange)
6357
; CL: OpFunction
6458
; CL: %[[#TestVar:]] = OpVariable
6559
; CL-NEXT: OpLifetimeStart %[[#TestVar]], 1
66-
; CL-NEXT: OpCopyMemorySized
6760
; CL-NEXT: OpInBoundsPtrAccessChain
6861
; CL-NEXT: OpLifetimeStop %[[#TestVar]], 1
6962

7063
; VK: OpFunction
7164
; VK: %[[#Test:]] = OpVariable
72-
; VK-NEXT: OpCopyMemorySized
7365
; VK-NEXT: OpInBoundsAccessChain
7466
; VK-NEXT: OpReturn
7567
define spir_func void @test(ptr noundef align 8 %_arg) {
7668
%var = alloca i8, align 8
7769
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %var)
78-
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %var, ptr align 8 %_arg, i64 1, i1 false)
79-
%KernelFunc = getelementptr inbounds i8, ptr %var, i64 0
70+
%KernelFunc = getelementptr inbounds i8, ptr %var, i64 1
8071
call void @llvm.lifetime.end.p0(i64 1, ptr nonnull %var)
8172
ret void
8273
}

0 commit comments

Comments
 (0)