Skip to content

Commit b4cfb50

Browse files
[SPIR-V] Emit SPIR-V bitcasts between source/expected pointer type (#69621)
This patch introduces a new spv_ptrcast intrinsic for tracking expected pointer types. The change fixes multiple OpenCL CTS regressions due the switch to opaque pointers (e.g. basic/hiloeo).
1 parent f686479 commit b4cfb50

19 files changed

+264
-66
lines changed

llvm/include/llvm/IR/IntrinsicsSPIRV.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ let TargetPrefix = "spv" in {
2828
def int_spv_insertelt : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_any_ty, llvm_anyint_ty]>;
2929
def int_spv_const_composite : Intrinsic<[llvm_i32_ty], [llvm_vararg_ty]>;
3030
def int_spv_bitcast : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
31+
def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
3132
def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
3233
def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>;
3334
def int_spv_unreachable : Intrinsic<[], []>;

llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx,
211211

212212
MDString *MDKernelArgType =
213213
getKernelArgAttribute(F, ArgIdx, "kernel_arg_type");
214-
if (!MDKernelArgType || (MDKernelArgType->getString().ends_with("*") &&
215-
MDKernelArgType->getString().ends_with("_t")))
214+
if (!MDKernelArgType || (!MDKernelArgType->getString().ends_with("*") &&
215+
!MDKernelArgType->getString().ends_with("_t")))
216216
return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
217217

218218
if (MDKernelArgType->getString().ends_with("*"))
@@ -438,7 +438,8 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
438438
assert(Arg.Regs.size() == 1 && "Call arg has multiple VRegs");
439439
ArgVRegs.push_back(Arg.Regs[0]);
440440
SPIRVType *SPIRVTy = GR->getOrCreateSPIRVType(Arg.Ty, MIRBuilder);
441-
GR->assignSPIRVTypeToVReg(SPIRVTy, Arg.Regs[0], MIRBuilder.getMF());
441+
if (!GR->getSPIRVTypeForVReg(Arg.Regs[0]))
442+
GR->assignSPIRVTypeToVReg(SPIRVTy, Arg.Regs[0], MIRBuilder.getMF());
442443
}
443444
if (auto Res = SPIRV::lowerBuiltin(
444445
DemangledName, SPIRV::InstructionSet::OpenCL_std, MIRBuilder,

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class SPIRVEmitIntrinsics
7474
void processInstrAfterVisit(Instruction *I);
7575
void insertAssignPtrTypeIntrs(Instruction *I);
7676
void insertAssignTypeIntrs(Instruction *I);
77+
void insertPtrCastInstr(Instruction *I);
7778
void processGlobalValue(GlobalVariable &GV);
7879

7980
public:
@@ -255,7 +256,19 @@ Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
255256
}
256257

257258
Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
258-
SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
259+
Value *Source = I.getOperand(0);
260+
261+
// SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of
262+
// varying element types. In case of IR coming from older versions of LLVM
263+
// such bitcasts do not provide sufficient information, should be just skipped
264+
// here, and handled in insertPtrCastInstr.
265+
if (I.getType()->isPointerTy()) {
266+
I.replaceAllUsesWith(Source);
267+
I.eraseFromParent();
268+
return nullptr;
269+
}
270+
271+
SmallVector<Type *, 2> Types = {I.getType(), Source->getType()};
259272
SmallVector<Value *> Args(I.op_begin(), I.op_end());
260273
auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args});
261274
std::string InstName = I.hasName() ? I.getName().str() : "";
@@ -265,6 +278,111 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
265278
return NewI;
266279
}
267280

281+
void SPIRVEmitIntrinsics::insertPtrCastInstr(Instruction *I) {
282+
Value *Pointer;
283+
Type *ExpectedElementType;
284+
unsigned OperandToReplace;
285+
if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
286+
Pointer = SI->getPointerOperand();
287+
ExpectedElementType = SI->getValueOperand()->getType();
288+
OperandToReplace = 1;
289+
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
290+
Pointer = LI->getPointerOperand();
291+
ExpectedElementType = LI->getType();
292+
OperandToReplace = 0;
293+
} else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
294+
Pointer = GEPI->getPointerOperand();
295+
ExpectedElementType = GEPI->getSourceElementType();
296+
OperandToReplace = 0;
297+
} else {
298+
return;
299+
}
300+
301+
// If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source
302+
// pointer instead. The BitCastInst should be later removed when visited.
303+
while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer))
304+
Pointer = BC->getOperand(0);
305+
306+
// Do not emit spv_ptrcast if Pointer is a GlobalValue of expected type.
307+
GlobalValue *GV = dyn_cast<GlobalValue>(Pointer);
308+
if (GV && GV->getValueType() == ExpectedElementType)
309+
return;
310+
311+
// Do not emit spv_ptrcast if Pointer is a result of alloca with expected
312+
// type.
313+
AllocaInst *A = dyn_cast<AllocaInst>(Pointer);
314+
if (A && A->getAllocatedType() == ExpectedElementType)
315+
return;
316+
317+
if (dyn_cast<GetElementPtrInst>(Pointer))
318+
return;
319+
320+
setInsertPointSkippingPhis(*IRB, I);
321+
Constant *ExpectedElementTypeConst =
322+
Constant::getNullValue(ExpectedElementType);
323+
ConstantAsMetadata *CM =
324+
ValueAsMetadata::getConstant(ExpectedElementTypeConst);
325+
MDTuple *TyMD = MDNode::get(F->getContext(), CM);
326+
MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD);
327+
unsigned AddressSpace = Pointer->getType()->getPointerAddressSpace();
328+
bool FirstPtrCastOrAssignPtrType = true;
329+
330+
// Do not emit new spv_ptrcast if equivalent one already exists or when
331+
// spv_assign_ptr_type already targets this pointer with the same element
332+
// type.
333+
for (auto User : Pointer->users()) {
334+
auto *II = dyn_cast<IntrinsicInst>(User);
335+
if (!II ||
336+
(II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type &&
337+
II->getIntrinsicID() != Intrinsic::spv_ptrcast) ||
338+
II->getOperand(0) != Pointer)
339+
continue;
340+
341+
// There is some spv_ptrcast/spv_assign_ptr_type already targeting this
342+
// pointer.
343+
FirstPtrCastOrAssignPtrType = false;
344+
if (II->getOperand(1) != VMD ||
345+
dyn_cast<ConstantInt>(II->getOperand(2))->getSExtValue() !=
346+
AddressSpace)
347+
continue;
348+
349+
// The spv_ptrcast/spv_assign_ptr_type targeting this pointer is of the same
350+
// element type and address space.
351+
if (II->getIntrinsicID() != Intrinsic::spv_ptrcast)
352+
return;
353+
354+
// This must be a spv_ptrcast, do not emit new if this one has the same BB
355+
// as I. Otherwise, search for other spv_ptrcast/spv_assign_ptr_type.
356+
if (II->getParent() != I->getParent())
357+
continue;
358+
359+
I->setOperand(OperandToReplace, II);
360+
return;
361+
}
362+
363+
// Do not emit spv_ptrcast if it would cast to the default pointer element
364+
// type (i8) of the same address space.
365+
if (ExpectedElementType->isIntegerTy(8))
366+
return;
367+
368+
// If this would be the first spv_ptrcast and there is no spv_assign_ptr_type
369+
// for this pointer before, do not emit spv_ptrcast but emit
370+
// spv_assign_ptr_type instead.
371+
if (FirstPtrCastOrAssignPtrType && isa<Instruction>(Pointer)) {
372+
buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {Pointer->getType()},
373+
ExpectedElementTypeConst, Pointer,
374+
{IRB->getInt32(AddressSpace)});
375+
return;
376+
} else {
377+
SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
378+
SmallVector<Value *, 2> Args = {Pointer, VMD, IRB->getInt32(AddressSpace)};
379+
auto *PtrCastI =
380+
IRB->CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
381+
I->setOperand(OperandToReplace, PtrCastI);
382+
return;
383+
}
384+
}
385+
268386
Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
269387
SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
270388
I.getOperand(1)->getType(),
@@ -522,13 +640,18 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
522640
for (auto &I : Worklist) {
523641
insertAssignPtrTypeIntrs(I);
524642
insertAssignTypeIntrs(I);
643+
insertPtrCastInstr(I);
525644
}
526645

527646
for (auto *I : Worklist) {
528647
TrackConstants = true;
529648
if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
530649
IRB->SetInsertPoint(I->getNextNode());
650+
// Visitors return either the original/newly created instruction for further
651+
// processing, nullptr otherwise.
531652
I = visit(*I);
653+
if (!I)
654+
continue;
532655
processInstrAfterVisit(I);
533656
}
534657
return true;

llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,32 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
125125
SmallVector<MachineInstr *, 10> ToErase;
126126
for (MachineBasicBlock &MBB : MF) {
127127
for (MachineInstr &MI : MBB) {
128-
if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast))
128+
if (!isSpvIntrinsic(MI, Intrinsic::spv_bitcast) &&
129+
!isSpvIntrinsic(MI, Intrinsic::spv_ptrcast))
129130
continue;
130131
assert(MI.getOperand(2).isReg());
131132
MIB.setInsertPt(*MI.getParent(), MI);
132-
MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
133133
ToErase.push_back(&MI);
134+
if (isSpvIntrinsic(MI, Intrinsic::spv_bitcast)) {
135+
MIB.buildBitcast(MI.getOperand(0).getReg(), MI.getOperand(2).getReg());
136+
continue;
137+
}
138+
Register Def = MI.getOperand(0).getReg();
139+
Register Source = MI.getOperand(2).getReg();
140+
SPIRVType *BaseTy = GR->getOrCreateSPIRVType(
141+
getMDOperandAsType(MI.getOperand(3).getMetadata(), 0), MIB);
142+
SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
143+
BaseTy, MI, *MF.getSubtarget<SPIRVSubtarget>().getInstrInfo(),
144+
addressSpaceToStorageClass(MI.getOperand(4).getImm()));
145+
146+
// If the bitcast would be redundant, replace all uses with the source
147+
// register.
148+
if (GR->getSPIRVTypeForVReg(Source) == AssignedPtrType) {
149+
MIB.getMRI()->replaceRegWith(Def, Source);
150+
} else {
151+
GR->assignSPIRVTypeToVReg(AssignedPtrType, Def, MF);
152+
MIB.buildBitcast(Def, Source);
153+
}
134154
}
135155
}
136156
for (MachineInstr *MI : ToErase)

llvm/test/CodeGen/SPIRV/AtomicCompareExchange.ll

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,47 +10,40 @@
1010
; CHECK-SPIRV-DAG: %[[#Struct:]] = OpTypeStruct %[[#Int]] %[[#Bool]]
1111
; CHECK-SPIRV-DAG: %[[#UndefStruct:]] = OpUndef %[[#Struct]]
1212

13-
; CHECK-SPIRV: %[[#Pointer:]] = OpFunctionParameter %[[#]]
14-
; CHECK-SPIRV: %[[#Value_ptr:]] = OpFunctionParameter %[[#]]
15-
; CHECK-SPIRV: %[[#Comparator:]] = OpFunctionParameter %[[#]]
16-
17-
; CHECK-SPIRV: %[[#Value:]] = OpLoad %[[#Int]] %[[#Value_ptr]]
18-
; CHECK-SPIRV: %[[#Res:]] = OpAtomicCompareExchange %[[#Int]] %[[#Pointer]] %[[#MemScope_Device]]
19-
; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Value]] %[[#Comparator]]
13+
; CHECK-SPIRV: %[[#Value:]] = OpLoad %[[#Int]] %[[#Value_ptr:]]
14+
; CHECK-SPIRV: %[[#Res:]] = OpAtomicCompareExchange %[[#Int]] %[[#Pointer:]] %[[#MemScope_Device]]
15+
; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Value]] %[[#Comparator:]]
2016
; CHECK-SPIRV: %[[#Success:]] = OpIEqual %[[#]] %[[#Res]] %[[#Comparator]]
2117
; CHECK-SPIRV: %[[#Composite_0:]] = OpCompositeInsert %[[#Struct]] %[[#Res]] %[[#UndefStruct]] 0
2218
; CHECK-SPIRV: %[[#Composite_1:]] = OpCompositeInsert %[[#Struct]] %[[#Success]] %[[#Composite_0]] 1
2319
; CHECK-SPIRV: %[[#]] = OpCompositeExtract %[[#Bool]] %[[#Composite_1]] 1
2420

25-
define dso_local spir_func void @test(i32* %ptr, i32* %value_ptr, i32 %comparator) local_unnamed_addr {
21+
define dso_local spir_func void @test(ptr %ptr, ptr %value_ptr, i32 %comparator) local_unnamed_addr {
2622
entry:
27-
%0 = load i32, i32* %value_ptr, align 4
28-
%1 = cmpxchg i32* %ptr, i32 %comparator, i32 %0 seq_cst acquire
23+
%0 = load i32, ptr %value_ptr, align 4
24+
%1 = cmpxchg ptr %ptr, i32 %comparator, i32 %0 seq_cst acquire
2925
%2 = extractvalue { i32, i1 } %1, 1
3026
br i1 %2, label %cmpxchg.continue, label %cmpxchg.store_expected
3127

3228
cmpxchg.store_expected: ; preds = %entry
3329
%3 = extractvalue { i32, i1 } %1, 0
34-
store i32 %3, i32* %value_ptr, align 4
30+
store i32 %3, ptr %value_ptr, align 4
3531
br label %cmpxchg.continue
3632

3733
cmpxchg.continue: ; preds = %cmpxchg.store_expected, %entry
3834
ret void
3935
}
4036

41-
; CHECK-SPIRV: %[[#Ptr:]] = OpFunctionParameter %[[#]]
42-
; CHECK-SPIRV: %[[#Store_ptr:]] = OpFunctionParameter %[[#]]
43-
44-
; CHECK-SPIRV: %[[#Res_1:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr]] %[[#MemScope_Device]]
37+
; CHECK-SPIRV: %[[#Res_1:]] = OpAtomicCompareExchange %[[#Int]] %[[#Ptr:]] %[[#MemScope_Device]]
4538
; CHECK-SPIRV-SAME: %[[#MemSemEqual_SeqCst]] %[[#MemSemUnequal_Acquire]] %[[#Constant_456]] %[[#Constant_128]]
4639
; CHECK-SPIRV: %[[#Success_1:]] = OpIEqual %[[#]] %[[#Res_1]] %[[#Constant_128]]
4740
; CHECK-SPIRV: %[[#Composite:]] = OpCompositeInsert %[[#Struct]] %[[#Res_1]] %[[#UndefStruct]] 0
4841
; CHECK-SPIRV: %[[#Composite_1:]] = OpCompositeInsert %[[#Struct]] %[[#Success_1]] %[[#Composite]] 1
49-
; CHECK-SPIRV: OpStore %[[#Store_ptr]] %[[#Composite_1]]
42+
; CHECK-SPIRV: OpStore %[[#Store_ptr:]] %[[#Composite_1]]
5043

51-
define dso_local spir_func void @test2(i32* %ptr, {i32, i1}* %store_ptr) local_unnamed_addr {
44+
define dso_local spir_func void @test2(ptr %ptr, ptr %store_ptr) local_unnamed_addr {
5245
entry:
53-
%0 = cmpxchg i32* %ptr, i32 128, i32 456 seq_cst acquire
54-
store { i32, i1 } %0, { i32, i1 }* %store_ptr, align 4
46+
%0 = cmpxchg ptr %ptr, i32 128, i32 456 seq_cst acquire
47+
store { i32, i1 } %0, ptr %store_ptr, align 4
5548
ret void
5649
}

llvm/test/CodeGen/SPIRV/function/alloca-load-store.ll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
22

3-
target triple = "spirv32-unknown-unknown"
4-
53
; CHECK-DAG: OpName %[[#BAR:]] "bar"
64
; CHECK-DAG: OpName %[[#FOO:]] "foo"
75
; CHECK-DAG: OpName %[[#GOO:]] "goo"
86

97
; CHECK-DAG: %[[#CHAR:]] = OpTypeInt 8
108
; CHECK-DAG: %[[#INT:]] = OpTypeInt 32
11-
; CHECK-DAG: %[[#STACK_PTR:]] = OpTypePointer Function %[[#INT]]
12-
; CHECK-DAG: %[[#GLOBAL_PTR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]]
9+
; CHECK-DAG: %[[#STACK_PTR_INT:]] = OpTypePointer Function %[[#INT]]
10+
; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]]
11+
; CHECK-DAG: %[[#GLOBAL_PTR_CHAR:]] = OpTypePointer CrossWorkgroup %[[#CHAR]]
1312
; CHECK-DAG: %[[#FN1:]] = OpTypeFunction %[[#INT]] %[[#INT]]
14-
; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR]]
13+
; CHECK-DAG: %[[#FN2:]] = OpTypeFunction %[[#INT]] %[[#INT]] %[[#GLOBAL_PTR_CHAR]]
1514

1615
define i32 @bar(i32 %a) {
1716
%p = alloca i32
@@ -23,7 +22,7 @@ define i32 @bar(i32 %a) {
2322
; CHECK: %[[#BAR]] = OpFunction %[[#INT]] None %[[#FN1]]
2423
; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]]
2524
; CHECK: OpLabel
26-
; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR]] Function
25+
; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR_INT]] Function
2726
; CHECK: OpStore %[[#P]] %[[#A]]
2827
; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]]
2928
; CHECK: OpReturnValue %[[#B]]
@@ -40,25 +39,26 @@ define i32 @foo(i32 %a) {
4039
; CHECK: %[[#FOO]] = OpFunction %[[#INT]] None %[[#FN1]]
4140
; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]]
4241
; CHECK: OpLabel
43-
; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR]] Function
42+
; CHECK: %[[#P:]] = OpVariable %[[#STACK_PTR_INT]] Function
4443
; CHECK: OpStore %[[#P]] %[[#A]] Volatile
4544
; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]] Volatile
4645
; CHECK: OpReturnValue %[[#B]]
4746
; CHECK: OpFunctionEnd
4847

4948

5049
;; Test load and store in global address space.
51-
define i32 @goo(i32 %a, i32 addrspace(1)* %p) {
50+
define i32 @goo(i32 %a, ptr addrspace(1) %p) {
5251
store i32 %a, i32 addrspace(1)* %p
5352
%b = load i32, i32 addrspace(1)* %p
5453
ret i32 %b
5554
}
5655

5756
; CHECK: %[[#GOO]] = OpFunction %[[#INT]] None %[[#FN2]]
5857
; CHECK: %[[#A:]] = OpFunctionParameter %[[#INT]]
59-
; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR]]
58+
; CHECK: %[[#P:]] = OpFunctionParameter %[[#GLOBAL_PTR_CHAR]]
6059
; CHECK: OpLabel
61-
; CHECK: OpStore %[[#P]] %[[#A]]
62-
; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#P]]
60+
; CHECK: %[[#C:]] = OpBitcast %[[#GLOBAL_PTR_INT]] %[[#P]]
61+
; CHECK: OpStore %[[#C]] %[[#A]]
62+
; CHECK: %[[#B:]] = OpLoad %[[#INT]] %[[#C]]
6363
; CHECK: OpReturnValue %[[#B]]
6464
; CHECK: OpFunctionEnd

llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
1010
; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
1111
; CHECK-NEXT: %[[#]] = OpLabel
12-
; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4
12+
; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]]
13+
; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4
1314
; CHECK-NEXT: OpReturn
1415
; CHECK-NEXT: OpFunctionEnd
1516

llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
99
; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
1010
; CHECK-NEXT: %[[#]] = OpLabel
11-
; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4
11+
; CHECK-NEXT: %[[#BC:]] = OpBitcast %[[#]] %[[#PTR]]
12+
; CHECK-NEXT: OpStore %[[#BC]] %[[#UNDEF]] Aligned 4
1213
; CHECK-NEXT: OpReturn
1314
; CHECK-NEXT: OpFunctionEnd
1415

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
; CHECK: %[[#VarNull:]] = OpVariable %[[#]] UniformConstant %[[#ConstNull]]
2626

2727
; CHECK-DAG: %[[#Int8PtrConst:]] = OpTypePointer UniformConstant %[[#Int8]]
28-
; CHECK: %[[#Target:]] = OpBitcast %[[#Int8Ptr]] %[[#]]
29-
; CHECK: %[[#Source:]] = OpBitcast %[[#Int8PtrConst]] %[[#VarNull]]
30-
; CHECK: OpCopyMemorySized %[[#Target]] %[[#Source]] %[[#Const12]] Aligned 4
28+
; CHECK: OpCopyMemorySized %[[#Target:]] %[[#Source:]] %[[#Const12]] Aligned 4
3129

3230
; CHECK: %[[#SourceComp:]] = OpBitcast %[[#Int8PtrConst]] %[[#VarComp]]
3331
; CHECK: OpCopyMemorySized %[[#]] %[[#SourceComp]] %[[#Const4]] Aligned 4

0 commit comments

Comments
 (0)