diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -12,7 +12,7 @@ let TargetPrefix = "spv" in { def int_spv_assign_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>; - def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>; + def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg>]>; def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>; def int_spv_track_constant : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty]>; diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -58,11 +58,17 @@ void preprocessCompositeConstants(); void preprocessUndefs(); CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef Types, - Value *Arg, Value *Arg2) { + Value *Arg, Value *Arg2, + ArrayRef Imms) { ConstantAsMetadata *CM = ValueAsMetadata::getConstant(Arg); MDTuple *TyMD = MDNode::get(F->getContext(), CM); MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); - return IRB->CreateIntrinsic(IntrID, {Types}, {Arg2, VMD}); + SmallVector Args; + Args.push_back(Arg2); + Args.push_back(VMD); + for (auto *Imm : Imms) + Args.push_back(Imm); + return IRB->CreateIntrinsic(IntrID, {Types}, Args); } void replaceMemInstrUses(Instruction *Old, Instruction *New); void processInstrAfterVisit(Instruction *I); @@ -122,6 +128,13 @@ B.SetInsertPoint(I); } +static bool requireAssignPtrType(Instruction *I) { + if (isa(I) || isa(I)) + return true; + + return false; +} + static bool requireAssignType(Instruction *I) { IntrinsicInst *Intr = dyn_cast(I); if (Intr) { @@ -389,20 +402,30 @@ } void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) { - if (I->getType()->isVoidTy() || !requireAssignType(I)) + if (I->getType()->isVoidTy() || !requireAssignPtrType(I)) return; setInsertPointSkippingPhis(*IRB, I->getNextNode()); + + Constant *EltTyConst; + unsigned AddressSpace = 0; if (auto *AI = dyn_cast(I)) { - Constant *Const = Constant::getNullValue(AI->getAllocatedType()); - buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, Const, I); + EltTyConst = Constant::getNullValue(AI->getAllocatedType()); + AddressSpace = AI->getAddressSpace(); + } else if (auto *GEP = dyn_cast(I)) { + EltTyConst = Constant::getNullValue(GEP->getSourceElementType()); + AddressSpace = GEP->getPointerAddressSpace(); + } else { + llvm_unreachable("Unexpected instruction!"); } + + buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I, + {IRB->getInt32(AddressSpace)}); } void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) { Type *Ty = I->getType(); - if (!Ty->isVoidTy() && requireAssignType(I) && - I->getOpcode() != Instruction::Alloca) { + if (!Ty->isVoidTy() && requireAssignType(I) && !requireAssignPtrType(I)) { setInsertPointSkippingPhis(*IRB, I->getNextNode()); Type *TypeToAssign = Ty; if (auto *II = dyn_cast(I)) { @@ -414,7 +437,7 @@ } } Constant *Const = Constant::getNullValue(TypeToAssign); - buildIntrWithMD(Intrinsic::spv_assign_type, {Ty}, Const, I); + buildIntrWithMD(Intrinsic::spv_assign_type, {Ty}, Const, I, {}); } for (const auto &Op : I->operands()) { if (isa(Op) || isa(Op) || @@ -423,9 +446,10 @@ setInsertPointSkippingPhis(*IRB, I); if (isa(Op) && Op->getType()->isAggregateType()) buildIntrWithMD(Intrinsic::spv_assign_type, {IRB->getInt32Ty()}, Op, - UndefValue::get(IRB->getInt32Ty())); + UndefValue::get(IRB->getInt32Ty()), {}); else - buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op); + buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op, + {}); } } } @@ -438,8 +462,8 @@ Type *Ty = IRB->getInt32Ty(); auto t = AggrConsts.find(I); assert(t != AggrConsts.end()); - auto *NewOp = - buildIntrWithMD(Intrinsic::spv_track_constant, {Ty, Ty}, t->second, I); + auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant, {Ty, Ty}, + t->second, I, {}); I->replaceAllUsesWith(NewOp); NewOp->setArgOperand(0, I); } @@ -454,7 +478,7 @@ continue; IRB->SetInsertPoint(I); auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant, - {Op->getType(), Op->getType()}, Op, Op); + {Op->getType(), Op->getType()}, Op, Op, {}); I->setOperand(OpNo, NewOp); } } diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -248,7 +248,8 @@ SPIRVType *BaseTy = GR->getOrCreateSPIRVType( getMDOperandAsType(MI.getOperand(2).getMetadata(), 0), MIB); SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType( - BaseTy, MI, *MF.getSubtarget().getInstrInfo()); + BaseTy, MI, *MF.getSubtarget().getInstrInfo(), + addressSpaceToStorageClass(MI.getOperand(3).getImm())); MachineInstr *Def = MRI.getVRegDef(Reg); assert(Def && "Expecting an instruction that defines the register"); insertAssignInstr(Reg, nullptr, AssignedPtrType, GR, MIB, diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll @@ -0,0 +1,14 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s + +; CHECK: %[[#INT8:]] = OpTypeInt 8 0 +; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] +; CHECK: %[[#PTR2:]] = OpTypePointer UniformConstant %[[#INT8]] +; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTR1]] %[[#]] %[[#]] +; CHECK: %[[#]] = OpInBoundsPtrAccessChain %[[#PTR2]] %[[#]] %[[#]] + +define spir_kernel void @foo(ptr addrspace(1) %a, ptr addrspace(2) %b) { +entry: + %c = getelementptr inbounds i8, ptr addrspace(1) %a, i32 1 + %d = getelementptr inbounds i8, ptr addrspace(2) %b, i32 2 + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll @@ -0,0 +1,16 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s + +; CHECK: %[[#INT8:]] = OpTypeInt 8 0 +; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] +; CHECK: %[[#PTR2:]] = OpTypePointer UniformConstant %[[#INT8]] +; CHECK: %[[#FNP1:]] = OpFunctionParameter %[[#PTR1]] +; CHECK: %[[#FNP2:]] = OpFunctionParameter %[[#PTR2]] +; CHECK: %[[#]] = OpLoad %[[#INT8]] %[[#FNP1]] Aligned 1 +; CHECK: %[[#]] = OpLoad %[[#INT8]] %[[#FNP2]] Aligned 1 + +define spir_kernel void @foo(ptr addrspace(1) %a, ptr addrspace(2) %b) { +entry: + %c = load i8, ptr addrspace(1) %a + %d = load i8, ptr addrspace(2) %b + ret void +}