Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,8 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
Type *RefTy = deduceElementTypeHelper(Ref->getPointerOperand(), Visited,
UnknownElemTypeI8);
maybeAssignPtrType(Ty, I, RefTy, UnknownElemTypeI8);
} else if (auto *Ref = dyn_cast<IntToPtrInst>(I)) {
maybeAssignPtrType(Ty, I, Ref->getDestTy(), UnknownElemTypeI8);
} else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy();
isPointerTy(Src) && isPointerTy(Dest))
Expand Down Expand Up @@ -2149,7 +2151,9 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
for (const auto &Op : I->operands()) {
if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
// Check GetElementPtrConstantExpr case.
(isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
(isa<ConstantExpr>(Op) &&
(isa<GEPOperator>(Op) ||
(cast<ConstantExpr>(Op)->getOpcode() == CastInst::IntToPtr)))) {
setInsertPointSkippingPhis(B, I);
Type *OpTy = Op->getType();
if (isa<UndefValue>(Op) && OpTy->isAggregateType()) {
Expand Down
15 changes: 12 additions & 3 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1210,8 +1210,16 @@ bool SPIRVInstructionSelector::selectUnOp(Register ResVReg,
for (MachineRegisterInfo::def_instr_iterator DefIt =
MRI->def_instr_begin(SrcReg);
DefIt != MRI->def_instr_end(); DefIt = std::next(DefIt)) {
if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
(*DefIt).getOpcode() == SPIRV::OpVariable) {
unsigned DefOpCode = DefIt->getOpcode();
if (DefOpCode == SPIRV::ASSIGN_TYPE) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this loop only iterating on register definitions and not uses?
I thought spv.assign.type as spv.assign.ptr.type were intrinsics registering as having a side-effect, but returning no values?

Copy link
Contributor Author

@AlexVlx AlexVlx Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intrinsics get lowered to a pseudo (ASSIGN_TYPE) which defines a destination vreg, which is what gets used by subsequent instructions, rather than the global whose type we assigned; hence the need to have a peek through the type assignment. The sequence looks something like so:

%60:iid(s64) = G_CONSTANT i64 184
%9:iid(s64) = ASSIGN_TYPE %60:iid(s64), %49:type(s64)
%8:_(p1) = G_INTTOPTR %9:iid(s64)

I will note that we cannot use the result of the type assignment, as that assigns the from integer's type, and not the to pointer's type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AH I see thanks! Was looking at the wrong level of IR.
Should you add an assert(DefOpCode != ASSIGN_TYPE) after this to make sure no ASSIGN_TYPE are ever chained? (Seems like this shouldn't happen)

// We need special handling to look through the type assignment and see
// if this is a constant or a global
if (auto *VRD = getVRegDef(*MRI, DefIt->getOperand(1).getReg()))
DefOpCode = VRD->getOpcode();
}
if (DefOpCode == TargetOpcode::G_GLOBAL_VALUE ||
DefOpCode == TargetOpcode::G_CONSTANT ||
DefOpCode == SPIRV::OpVariable || DefOpCode == SPIRV::OpConstantI) {
IsGV = true;
break;
}
Expand Down Expand Up @@ -3099,9 +3107,10 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
SmallPtrSet<SPIRVType *, 4> Visited;
if (!OpDefine || !OpType || isConstReg(MRI, OpDefine, Visited) ||
OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
OpDefine->getOpcode() == TargetOpcode::G_INTTOPTR ||
GR.isAggregateType(OpType)) {
// The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed
// by selectAddrSpaceCast()
// by selectAddrSpaceCast(), and G_INTTOPTR is processed by selectUnOp()
CompositeArgs.push_back(OpReg);
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/SPIRV/ComparePointers.ll
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
;; return;
;; }

; CHECK-SPIRV: OpConvertPtrToU
; CHECK-SPIRV: OpSpecConstantOp %[[#]] ConvertPtrToU
; CHECK-SPIRV: OpConvertPtrToU
; CHECK-SPIRV: OpINotEqual
; CHECK-SPIRV: OpConvertPtrToU
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/SPIRV/complex-constexpr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
define linkonce_odr hidden spir_func void @test() {
entry:
; CHECK: %[[#MinusOne:]] = OpConstant %[[#]] 18446744073709551615
; CHECK: %[[#Ptr:]] = OpConvertUToPtr %[[#]] %[[#MinusOne]]
; CHECK: %[[#Ptr:]] = OpSpecConstantOp %[[#]] ConvertUToPtr %[[#MinusOne]]
; CHECK: %[[#PtrCast:]] = OpPtrCastToGeneric %[[#]] %[[#]]
; CHECK: %[[#]] = OpFunctionCall %[[#]] %[[#]] %[[#PtrCast]] %[[#Ptr]]

Expand Down
49 changes: 49 additions & 0 deletions llvm/test/CodeGen/SPIRV/transcoding/ConvertPtrInGlobalInit.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}

; CHECK: %[[Int8Ty:[0-9]+]] = OpTypeInt 8 0
; CHECK: %[[Int8PtrTy:[0-9]+]] = OpTypePointer Generic %[[Int8Ty]]
; CHECK-DAG: %[[GlobInt8PtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[Int8Ty]]
; CHECK: %[[GlobInt8PtrPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[GlobInt8PtrTy]]
; CHECK: %[[Int8PtrGlobPtrPtrTy:[0-9]+]] = OpTypePointer Generic %[[GlobInt8PtrPtrTy]]
; CHECK: %[[Int32Ty:[0-9]+]] = OpTypeInt 32 0
; CHECK: %[[Const5:[0-9]+]] = OpConstant %[[Int32Ty]] 5
; CHECK: %[[ArrTy:[0-9]+]] = OpTypeArray %[[GlobInt8PtrTy]] %[[Const5]]
; CHECK: %[[VtblTy:[0-9]+]] = OpTypeStruct %[[ArrTy]] %[[ArrTy]] %[[ArrTy]] %[[ArrTy]] %[[ArrTy]]
; CHECK: %[[Int64Ty:[0-9]+]] = OpTypeInt 64 0
; CHECK: %[[GlobVtblPtrTy:[0-9]+]] = OpTypePointer CrossWorkgroup %[[VtblTy]]
; CHECK: %[[ConstMinus184:[0-9]+]] = OpConstant %[[Int64Ty]] 18446744073709551432
; CHECK: %[[ConstMinus16:[0-9]+]] = OpConstant %[[Int64Ty]] 18446744073709551600
; CHECK: %[[Const168:[0-9]+]] = OpConstant %[[Int64Ty]] 168
; CHECK: %[[Nullptr:[0-9]+]] = OpConstantNull %[[GlobInt8PtrTy]]
; CHECK: %[[Const184:[0-9]+]] = OpConstant %[[Int64Ty]] 184
; CHECK: %[[Const184toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[Const184]]
; CHECK: %[[Const168toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[Const168]]
; CHECK: %[[ConstMinus16toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[ConstMinus16]]
; CHECK: %[[ConstMinus184toPtr:[0-9]+]] = OpSpecConstantOp %[[GlobInt8PtrTy]] ConvertUToPtr %[[ConstMinus184]]
; CHECK: %[[Vtbl012:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[Const184toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
; CHECK: %[[Vtbl3:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[Const168toPtr]] %[[ConstMinus16toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
; CHECK: %[[Vtbl4:[0-9]+]] = OpConstantComposite %[[ArrTy]] %[[ConstMinus184toPtr]] %[[ConstMinus184toPtr]] %[[Nullptr]] %[[Nullptr]] %[[Nullptr]]
; CHECK: %[[Vtbl:[0-9]+]] = OpConstantComposite %[[VtblTy]] %[[Vtbl012]] %[[Vtbl012]] %[[Vtbl012]] %[[Vtbl3]] %[[Vtbl4]]
; CHECK: %[[#]] = OpVariable %[[GlobVtblPtrTy]] CrossWorkgroup %[[Vtbl]]

@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)] }
{ [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],
[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],
[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],
[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],
[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] }

define linkonce_odr spir_func void @foo(ptr addrspace(4) %this) {
entry:
%0 = getelementptr inbounds i8, ptr addrspace(4) %this, i64 184
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
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
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
%add.ptr = getelementptr inbounds i8, ptr addrspace(4) %this, i64 184
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
%add.ptr2 = getelementptr inbounds i8, ptr addrspace(4) %this, i64 16
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

ret void
}