mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-01 12:43:47 +00:00
[SPIR-V] Preserve pointer address space for load/gep instructions
Differential Revision: https://reviews.llvm.org/D158761
This commit is contained in:
parent
86ddbdd3e7
commit
2616c279d5
@ -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<ArgIndex<2>>]>;
|
||||
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]>;
|
||||
|
@ -58,11 +58,17 @@ class SPIRVEmitIntrinsics
|
||||
void preprocessCompositeConstants();
|
||||
void preprocessUndefs();
|
||||
CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
|
||||
Value *Arg, Value *Arg2) {
|
||||
Value *Arg, Value *Arg2,
|
||||
ArrayRef<Constant *> 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<Value *, 4> 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 @@ static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I) {
|
||||
B.SetInsertPoint(I);
|
||||
}
|
||||
|
||||
static bool requireAssignPtrType(Instruction *I) {
|
||||
if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool requireAssignType(Instruction *I) {
|
||||
IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
|
||||
if (Intr) {
|
||||
@ -389,20 +402,30 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV) {
|
||||
}
|
||||
|
||||
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<AllocaInst>(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<GetElementPtrInst>(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<IntrinsicInst>(I)) {
|
||||
@ -414,7 +437,7 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
|
||||
}
|
||||
}
|
||||
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<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
|
||||
@ -423,9 +446,10 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
|
||||
setInsertPointSkippingPhis(*IRB, I);
|
||||
if (isa<UndefValue>(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 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I) {
|
||||
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 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,8 @@ static void generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
|
||||
SPIRVType *BaseTy = GR->getOrCreateSPIRVType(
|
||||
getMDOperandAsType(MI.getOperand(2).getMetadata(), 0), MIB);
|
||||
SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
|
||||
BaseTy, MI, *MF.getSubtarget<SPIRVSubtarget>().getInstrInfo());
|
||||
BaseTy, MI, *MF.getSubtarget<SPIRVSubtarget>().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,
|
||||
|
@ -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
|
||||
}
|
16
llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll
Normal file
16
llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user