Skip to content

Commit 995b0f1

Browse files
authored
[SPIRV] Handle inttoptr constant expressions in global initialisers (llvm#166494)
`inttoptr` usage in global initialisers is valid, and rather common when it comes to the machinery around vtables (construction vtables are particularly fond). This was not handled by the BE, even though SPIR-V allows forming `SpecConstantOp`s with the `OpConvertUToPtr` opcode, which is what these would map to. We augment instruction selection to address this.
1 parent 32ebf63 commit 995b0f1

File tree

5 files changed

+68
-6
lines changed

5 files changed

+68
-6
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,8 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
767767
Type *RefTy = deduceElementTypeHelper(Ref->getPointerOperand(), Visited,
768768
UnknownElemTypeI8);
769769
maybeAssignPtrType(Ty, I, RefTy, UnknownElemTypeI8);
770+
} else if (auto *Ref = dyn_cast<IntToPtrInst>(I)) {
771+
maybeAssignPtrType(Ty, I, Ref->getDestTy(), UnknownElemTypeI8);
770772
} else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
771773
if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy();
772774
isPointerTy(Src) && isPointerTy(Dest))
@@ -2149,7 +2151,9 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
21492151
for (const auto &Op : I->operands()) {
21502152
if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
21512153
// Check GetElementPtrConstantExpr case.
2152-
(isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
2154+
(isa<ConstantExpr>(Op) &&
2155+
(isa<GEPOperator>(Op) ||
2156+
(cast<ConstantExpr>(Op)->getOpcode() == CastInst::IntToPtr)))) {
21532157
setInsertPointSkippingPhis(B, I);
21542158
Type *OpTy = Op->getType();
21552159
if (isa<UndefValue>(Op) && OpTy->isAggregateType()) {

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,16 @@ bool SPIRVInstructionSelector::selectUnOp(Register ResVReg,
12101210
for (MachineRegisterInfo::def_instr_iterator DefIt =
12111211
MRI->def_instr_begin(SrcReg);
12121212
DefIt != MRI->def_instr_end(); DefIt = std::next(DefIt)) {
1213-
if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
1214-
(*DefIt).getOpcode() == SPIRV::OpVariable) {
1213+
unsigned DefOpCode = DefIt->getOpcode();
1214+
if (DefOpCode == SPIRV::ASSIGN_TYPE) {
1215+
// We need special handling to look through the type assignment and see
1216+
// if this is a constant or a global
1217+
if (auto *VRD = getVRegDef(*MRI, DefIt->getOperand(1).getReg()))
1218+
DefOpCode = VRD->getOpcode();
1219+
}
1220+
if (DefOpCode == TargetOpcode::G_GLOBAL_VALUE ||
1221+
DefOpCode == TargetOpcode::G_CONSTANT ||
1222+
DefOpCode == SPIRV::OpVariable || DefOpCode == SPIRV::OpConstantI) {
12151223
IsGV = true;
12161224
break;
12171225
}
@@ -3099,9 +3107,10 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
30993107
SmallPtrSet<SPIRVType *, 4> Visited;
31003108
if (!OpDefine || !OpType || isConstReg(MRI, OpDefine, Visited) ||
31013109
OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
3110+
OpDefine->getOpcode() == TargetOpcode::G_INTTOPTR ||
31023111
GR.isAggregateType(OpType)) {
31033112
// The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed
3104-
// by selectAddrSpaceCast()
3113+
// by selectAddrSpaceCast(), and G_INTTOPTR is processed by selectUnOp()
31053114
CompositeArgs.push_back(OpReg);
31063115
continue;
31073116
}

llvm/test/CodeGen/SPIRV/ComparePointers.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
;; return;
1313
;; }
1414

15-
; CHECK-SPIRV: OpConvertPtrToU
15+
; CHECK-SPIRV: OpSpecConstantOp %[[#]] ConvertPtrToU
1616
; CHECK-SPIRV: OpConvertPtrToU
1717
; CHECK-SPIRV: OpINotEqual
1818
; CHECK-SPIRV: OpConvertPtrToU

llvm/test/CodeGen/SPIRV/complex-constexpr.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
define linkonce_odr hidden spir_func void @test() {
77
entry:
88
; CHECK: %[[#MinusOne:]] = OpConstant %[[#]] 18446744073709551615
9-
; CHECK: %[[#Ptr:]] = OpConvertUToPtr %[[#]] %[[#MinusOne]]
9+
; CHECK: %[[#Ptr:]] = OpSpecConstantOp %[[#]] ConvertUToPtr %[[#MinusOne]]
1010
; CHECK: %[[#PtrCast:]] = OpPtrCastToGeneric %[[#]] %[[#]]
1111
; CHECK: %[[#]] = OpFunctionCall %[[#]] %[[#]] %[[#PtrCast]] %[[#Ptr]]
1212

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: %[[Int8Ty:[0-9]+]] = OpTypeInt 8 0
5+
; CHECK: %[[Int8PtrTy:[0-9]+]] = OpTypePointer Generic %[[Int8Ty]]
6+
; CHECK-DAG: %[[GlobInt8PtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[Int8Ty]]
7+
; CHECK: %[[GlobInt8PtrPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[GlobInt8PtrTy]]
8+
; CHECK: %[[Int8PtrGlobPtrPtrTy:[0-9]+]] = OpTypePointer Generic %[[GlobInt8PtrPtrTy]]
9+
; CHECK: %[[Int32Ty:[0-9]+]] = OpTypeInt 32 0
10+
; CHECK: %[[Const5:[0-9]+]] = OpConstant %[[Int32Ty]] 5
11+
; CHECK: %[[ArrTy:[0-9]+]] = OpTypeArray %[[GlobInt8PtrTy]] %[[Const5]]
12+
; CHECK: %[[VtblTy:[0-9]+]] = OpTypeStruct %[[ArrTy]] %[[ArrTy]] %[[ArrTy]] %[[ArrTy]] %[[ArrTy]]
13+
; CHECK: %[[Int64Ty:[0-9]+]] = OpTypeInt 64 0
14+
; CHECK: %[[GlobVtblPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[VtblTy]]
15+
; CHECK: %[[ConstMinus184:[0-9]+]] = OpConstant %[[Int64Ty]] 18446744073709551432
16+
; CHECK: %[[ConstMinus16:[0-9]+]] = OpConstant %[[Int64Ty]] 18446744073709551600
17+
; CHECK: %[[Const168:[0-9]+]] = OpConstant %[[Int64Ty]] 168
18+
; CHECK: %[[Nullptr:[0-9]+]] = OpConstantNull %[[GlobInt8PtrTy]]
19+
; CHECK: %[[Const184:[0-9]+]] = OpConstant %[[Int64Ty]] 184
20+
; CHECK: %[[Const184toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[Const184]]
21+
; CHECK: %[[Const168toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[Const168]]
22+
; CHECK: %[[ConstMinus16toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[ConstMinus16]]
23+
; CHECK: %[[ConstMinus184toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[ConstMinus184]]
24+
; CHECK: %[[Vtbl012:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[Const184toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
25+
; CHECK: %[[Vtbl3:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[Const168toPtr]] %[[ConstMinus16toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
26+
; CHECK: %[[Vtbl4:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[ConstMinus184toPtr]] %[[ConstMinus184toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
27+
; CHECK: %[[Vtbl:[0-9]+]] = OpConstantComposite %[[VtblTy]] %[[Vtbl012]] %[[Vtbl012]] %[[Vtbl012]] %[[Vtbl3]] %[[Vtbl4]]
28+
; CHECK: %[[#]] = OpVariable %[[GlobVtblPtrTy]] CrossWorkgroup %[[Vtbl]]
29+
30+
@vtable = linkonce_odr unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }
31+
{ [5 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 184 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null],
32+
[5 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 184 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null],
33+
[5 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 184 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null],
34+
[5 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 168 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -16 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null],
35+
[5 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -184 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -184 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) null] }
36+
37+
define linkonce_odr spir_func void @foo(ptr addrspace(4) %this) {
38+
entry:
39+
%0 = getelementptr inbounds i8, ptr addrspace(4) %this, i64 184
40+
store ptr addrspace(1) getelementptr inbounds inrange(-24, 16) ({ [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }, ptr addrspace(1) @vtable, i32 0, i32 0, i32 3), ptr addrspace(4) %this
41+
store ptr addrspace(1) getelementptr inbounds inrange(-24, 16) ({ [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }, ptr addrspace(1) @vtable, i32 0, i32 1, i32 3), ptr addrspace(4) %this
42+
store ptr addrspace(1) getelementptr inbounds inrange(-24, 16) ({ [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }, ptr addrspace(1) @vtable, i32 0, i32 2, i32 3), ptr addrspace(4) %this
43+
%add.ptr = getelementptr inbounds i8, ptr addrspace(4) %this, i64 184
44+
store ptr addrspace(1) getelementptr inbounds inrange(-24, 16) ({ [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }, ptr addrspace(1) @vtable, i32 0, i32 4, i32 3), ptr addrspace(4) %add.ptr
45+
%add.ptr2 = getelementptr inbounds i8, ptr addrspace(4) %this, i64 16
46+
store ptr addrspace(1) getelementptr inbounds inrange(-24, 16) ({ [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)], [5 x ptr addrspace(1)] }, ptr addrspace(1) @vtable, i32 0, i32 3, i32 3), ptr addrspace(4) %add.ptr2
47+
48+
ret void
49+
}

0 commit comments

Comments
 (0)