Skip to content

Commit 50be0b1

Browse files
[SPIR-V] Ensure that internal intrinsic functions "ptrcast" for PHI's operand are inserted at the correct positions (#92536)
The goal of the PR is to ensure that newly inserted `ptrcast` internal intrinsic functions are inserted at the correct positions, and don't break rules of instruction domination and PHI nodes grouping at top of basic block.
1 parent 0047df9 commit 50be0b1

File tree

2 files changed

+107
-4
lines changed

2 files changed

+107
-4
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,17 +489,15 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) {
489489
Type *Ty = GR->findDeducedElementType(Op);
490490
if (Ty == KnownElemTy)
491491
continue;
492-
if (Instruction *User = dyn_cast<Instruction>(Op->use_begin()->get()))
493-
setInsertPointSkippingPhis(B, User->getNextNode());
494-
else
495-
setInsertPointSkippingPhis(B, I);
496492
Value *OpTyVal = Constant::getNullValue(KnownElemTy);
497493
Type *OpTy = Op->getType();
498494
if (!Ty) {
499495
GR->addDeducedElementType(Op, KnownElemTy);
500496
// check if there is existing Intrinsic::spv_assign_ptr_type instruction
501497
auto It = AssignPtrTypeInstr.find(Op);
502498
if (It == AssignPtrTypeInstr.end()) {
499+
Instruction *User = dyn_cast<Instruction>(Op->use_begin()->get());
500+
setInsertPointSkippingPhis(B, User ? User->getNextNode() : I);
503501
CallInst *CI =
504502
buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op,
505503
{B.getInt32(getPointerAddressSpace(OpTy))}, B);
@@ -511,6 +509,17 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) {
511509
Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal))));
512510
}
513511
} else {
512+
if (auto *OpI = dyn_cast<Instruction>(Op)) {
513+
// spv_ptrcast's argument Op denotes an instruction that generates
514+
// a value, and we may use getInsertionPointAfterDef()
515+
B.SetInsertPoint(*OpI->getInsertionPointAfterDef());
516+
B.SetCurrentDebugLocation(OpI->getDebugLoc());
517+
} else if (auto *OpA = dyn_cast<Argument>(Op)) {
518+
B.SetInsertPointPastAllocas(OpA->getParent());
519+
B.SetCurrentDebugLocation(DebugLoc());
520+
} else {
521+
B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
522+
}
514523
SmallVector<Type *, 2> Types = {OpTy, OpTy};
515524
MetadataAsValue *VMD = MetadataAsValue::get(
516525
Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal)));
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
; The goal of the test is to check that newly inserted `ptrcast` internal
2+
; intrinsic functions for PHI's operands are inserted at the correct
3+
; positions, and don't break rules of instruction domination and PHI nodes
4+
; grouping at top of basic block.
5+
6+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
7+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
8+
9+
; CHECK-DAG: OpName %[[#Case1:]] "case1"
10+
; CHECK-DAG: OpName %[[#Case2:]] "case2"
11+
; CHECK-DAG: OpName %[[#Case3:]] "case3"
12+
; CHECK: %[[#Case1]] = OpFunction
13+
; CHECK: OpBranchConditional
14+
; CHECK: OpPhi
15+
; CHECK: OpBranch
16+
; CHECK-COUNT-2: OpBranchConditional
17+
; CHECK: OpFunctionEnd
18+
; CHECK: %[[#Case2]] = OpFunction
19+
; CHECK: OpBranchConditional
20+
; CHECK: OpPhi
21+
; CHECK: OpBranch
22+
; CHECK-COUNT-2: OpBranchConditional
23+
; CHECK: OpFunctionEnd
24+
; CHECK: %[[#Case3]] = OpFunction
25+
; CHECK: OpBranchConditional
26+
; CHECK: OpPhi
27+
; CHECK: OpBranch
28+
; CHECK: OpInBoundsPtrAccessChain
29+
; CHECK: OpBranchConditional
30+
; CHECK: OpInBoundsPtrAccessChain
31+
; CHECK: OpBranchConditional
32+
; CHECK: OpFunctionEnd
33+
34+
%struct1 = type { i64 }
35+
%struct2 = type { i64, i64 }
36+
37+
@.str.1 = private unnamed_addr addrspace(1) constant [3 x i8] c"OK\00", align 1
38+
@.str.2 = private unnamed_addr addrspace(1) constant [6 x i8] c"WRONG\00", align 1
39+
40+
define spir_func void @case1(i1 %b1, i1 %b2, i1 %b3) {
41+
entry:
42+
br i1 %b1, label %l1, label %l2
43+
44+
l1:
45+
%str = phi ptr addrspace(1) [ @.str.1, %entry ], [ @.str.2, %l2 ], [ @.str.2, %l3 ]
46+
br label %exit
47+
48+
l2:
49+
br i1 %b2, label %l1, label %l3
50+
51+
l3:
52+
br i1 %b3, label %l1, label %exit
53+
54+
exit:
55+
ret void
56+
}
57+
58+
define spir_func void @case2(i1 %b1, i1 %b2, i1 %b3, ptr addrspace(1) byval(%struct1) %str1, ptr addrspace(1) byval(%struct2) %str2) {
59+
entry:
60+
br i1 %b1, label %l1, label %l2
61+
62+
l1:
63+
%str = phi ptr addrspace(1) [ %str1, %entry ], [ %str2, %l2 ], [ %str2, %l3 ]
64+
br label %exit
65+
66+
l2:
67+
br i1 %b2, label %l1, label %l3
68+
69+
l3:
70+
br i1 %b3, label %l1, label %exit
71+
72+
exit:
73+
ret void
74+
}
75+
76+
define spir_func void @case3(i1 %b1, i1 %b2, i1 %b3, ptr addrspace(1) byval(%struct1) %_arg_str1, ptr addrspace(1) byval(%struct2) %_arg_str2) {
77+
entry:
78+
br i1 %b1, label %l1, label %l2
79+
80+
l1:
81+
%str = phi ptr addrspace(1) [ %_arg_str1, %entry ], [ %str2, %l2 ], [ %str3, %l3 ]
82+
br label %exit
83+
84+
l2:
85+
%str2 = getelementptr inbounds %struct2, ptr addrspace(1) %_arg_str2, i32 1
86+
br i1 %b2, label %l1, label %l3
87+
88+
l3:
89+
%str3 = getelementptr inbounds %struct2, ptr addrspace(1) %_arg_str2, i32 2
90+
br i1 %b3, label %l1, label %exit
91+
92+
exit:
93+
ret void
94+
}

0 commit comments

Comments
 (0)