[llvm] 9a73710 - [SPIR-V] Improve type inference, addrspacecast and dependencies between SPIR-V entities and required capability/extensions (#94626)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 7 12:12:37 PDT 2024
Author: Vyacheslav Levytskyy
Date: 2024-06-07T21:12:33+02:00
New Revision: 9a737109a07c0c29176e617eed34e91b523b7e9b
URL: https://github.com/llvm/llvm-project/commit/9a737109a07c0c29176e617eed34e91b523b7e9b
DIFF: https://github.com/llvm/llvm-project/commit/9a737109a07c0c29176e617eed34e91b523b7e9b.diff
LOG: [SPIR-V] Improve type inference, addrspacecast and dependencies between SPIR-V entities and required capability/extensions (#94626)
This PR continues https://github.com/llvm/llvm-project/pull/94467 and
contains fixes in emission of type intrinsics, constant recording and
corresponding test cases:
* type-deduce-global-dup.ll -- fix of integer constant emission on
32-bit platforms and correct type deduction for globals
* type-deduce-simple-for.ll -- fix of GEP translation (there was an
issue previously that led to incorrect translation/broken logic of
for-range implementation)
This PR also:
* fixes a cast between identical storage classes and updates the test
case to include validation run by spirv-val,
* ensures that Bitcast for pointers satisfies the requirement that the
address spaces must match and adds the corresponding test case,
* improve encode in Tablegen and decode in code of dependencies between
SPIR-V entities and required capability/extensions,
* prevent emission of identical OpTypePointer instructions.
Added:
llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll
llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll
llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll
llvm/test/CodeGen/SPIRV/transcoding/bitcast-diff-addrspace.ll
Modified:
llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
llvm/lib/Target/SPIRV/SPIRVUtils.cpp
llvm/lib/Target/SPIRV/SPIRVUtils.h
llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll
llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index f4daab7d06eb5..de0b97fbea0c1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -243,11 +243,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx,
continue;
MetadataAsValue *VMD = cast<MetadataAsValue>(II->getOperand(1));
- Type *ElementTy = cast<ConstantAsMetadata>(VMD->getMetadata())->getType();
- if (isUntypedPointerTy(ElementTy))
- ElementTy =
- TypedPointerType::get(IntegerType::getInt8Ty(II->getContext()),
- getPointerAddressSpace(ElementTy));
+ Type *ElementTy =
+ toTypedPointer(cast<ConstantAsMetadata>(VMD->getMetadata())->getType());
SPIRVType *ElementType = GR->getOrCreateSPIRVType(ElementTy, MIRBuilder);
return GR->getOrCreateSPIRVPointerType(
ElementType, MIRBuilder,
@@ -257,12 +254,8 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx,
// Replace PointerType with TypedPointerType to be able to map SPIR-V types to
// LLVM types in a consistent manner
- if (isUntypedPointerTy(OriginalArgType)) {
- OriginalArgType =
- TypedPointerType::get(Type::getInt8Ty(F.getContext()),
- getPointerAddressSpace(OriginalArgType));
- }
- return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual);
+ return GR->getOrCreateSPIRVType(toTypedPointer(OriginalArgType), MIRBuilder,
+ ArgAccessQual);
}
static SPIRV::ExecutionModel::ExecutionModel
@@ -386,8 +379,8 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
Type *FRetTy = FTy->getReturnType();
if (isUntypedPointerTy(FRetTy)) {
if (Type *FRetElemTy = GR->findDeducedElementType(&F)) {
- TypedPointerType *DerivedTy =
- TypedPointerType::get(FRetElemTy, getPointerAddressSpace(FRetTy));
+ TypedPointerType *DerivedTy = TypedPointerType::get(
+ toTypedPointer(FRetElemTy), getPointerAddressSpace(FRetTy));
GR->addReturnType(&F, DerivedTy);
FRetTy = DerivedTy;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index bbd25dc85f52b..7b8e3230bf553 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -50,6 +50,13 @@ void initializeSPIRVEmitIntrinsicsPass(PassRegistry &);
} // namespace llvm
namespace {
+
+inline MetadataAsValue *buildMD(Value *Arg) {
+ LLVMContext &Ctx = Arg->getContext();
+ return MetadataAsValue::get(
+ Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(Arg)));
+}
+
class SPIRVEmitIntrinsics
: public ModulePass,
public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
@@ -84,12 +91,9 @@ class SPIRVEmitIntrinsics
CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
IRBuilder<> &B) {
- ConstantAsMetadata *CM = ValueAsMetadata::getConstant(Arg);
- MDTuple *TyMD = MDNode::get(F->getContext(), CM);
- MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD);
SmallVector<Value *, 4> Args;
Args.push_back(Arg2);
- Args.push_back(VMD);
+ Args.push_back(buildMD(Arg));
for (auto *Imm : Imms)
Args.push_back(Imm);
return B.CreateIntrinsic(IntrID, {Types}, Args);
@@ -228,20 +232,23 @@ void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
void SPIRVEmitIntrinsics::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,
Value *Arg) {
Value *OfType = PoisonValue::get(ElemTy);
- CallInst *AssignPtrTyCI = buildIntrWithMD(
- Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
- {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
- GR->addDeducedElementType(AssignPtrTyCI, ElemTy);
- GR->addDeducedElementType(Arg, ElemTy);
- GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
+ CallInst *AssignPtrTyCI = GR->findAssignPtrTypeInstr(Arg);
+ if (AssignPtrTyCI == nullptr ||
+ AssignPtrTyCI->getParent()->getParent() != F) {
+ AssignPtrTyCI = buildIntrWithMD(
+ Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
+ {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
+ GR->addDeducedElementType(AssignPtrTyCI, ElemTy);
+ GR->addDeducedElementType(Arg, ElemTy);
+ GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
+ } else {
+ updateAssignType(AssignPtrTyCI, Arg, OfType);
+ }
}
void SPIRVEmitIntrinsics::updateAssignType(CallInst *AssignCI, Value *Arg,
Value *OfType) {
- LLVMContext &Ctx = Arg->getContext();
- AssignCI->setArgOperand(
- 1, MetadataAsValue::get(
- Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType))));
+ AssignCI->setArgOperand(1, buildMD(OfType));
if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=
Intrinsic::spv_assign_ptr_type)
return;
@@ -560,9 +567,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I) {
B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
}
SmallVector<Type *, 2> Types = {OpTy, OpTy};
- MetadataAsValue *VMD = MetadataAsValue::get(
- Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(OpTyVal)));
- SmallVector<Value *, 2> Args = {Op, VMD,
+ SmallVector<Value *, 2> Args = {Op, buildMD(OpTyVal),
B.getInt32(getPointerAddressSpace(OpTy))};
CallInst *PtrCastI =
B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
@@ -689,8 +694,7 @@ Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
Constant *TyC = UndefValue::get(IA->getFunctionType());
MDString *ConstraintString = MDString::get(Ctx, IA->getConstraintString());
SmallVector<Value *> Args = {
- MetadataAsValue::get(Ctx,
- MDNode::get(Ctx, ValueAsMetadata::getConstant(TyC))),
+ buildMD(TyC),
MetadataAsValue::get(Ctx, MDNode::get(Ctx, ConstraintString))};
for (unsigned OpIdx = 0; OpIdx < Call.arg_size(); OpIdx++)
Args.push_back(Call.getArgOperand(OpIdx));
@@ -822,12 +826,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
return;
setInsertPointSkippingPhis(B, I);
- Constant *ExpectedElementTypeConst =
- Constant::getNullValue(ExpectedElementType);
- ConstantAsMetadata *CM =
- ValueAsMetadata::getConstant(ExpectedElementTypeConst);
- MDTuple *TyMD = MDNode::get(F->getContext(), CM);
- MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD);
+ MetadataAsValue *VMD = buildMD(PoisonValue::get(ExpectedElementType));
unsigned AddressSpace = getPointerAddressSpace(Pointer->getType());
bool FirstPtrCastOrAssignPtrType = true;
@@ -873,12 +872,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
// spv_assign_ptr_type instead.
if (FirstPtrCastOrAssignPtrType &&
(isa<Instruction>(Pointer) || isa<Argument>(Pointer))) {
- CallInst *CI = buildIntrWithMD(
- Intrinsic::spv_assign_ptr_type, {Pointer->getType()},
- ExpectedElementTypeConst, Pointer, {B.getInt32(AddressSpace)}, B);
- GR->addDeducedElementType(CI, ExpectedElementType);
- GR->addDeducedElementType(Pointer, ExpectedElementType);
- GR->addAssignPtrTypeInstr(Pointer, CI);
+ buildAssignPtr(B, ExpectedElementType, Pointer);
return;
}
@@ -1167,12 +1161,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
setInsertPointAfterDef(B, I);
Type *ElemTy = deduceElementType(I);
- Constant *EltTyConst = UndefValue::get(ElemTy);
- unsigned AddressSpace = getPointerAddressSpace(I->getType());
- CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()},
- EltTyConst, I, {B.getInt32(AddressSpace)}, B);
- GR->addDeducedElementType(CI, ElemTy);
- GR->addAssignPtrTypeInstr(I, CI);
+ buildAssignPtr(B, ElemTy, I);
}
void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
@@ -1407,12 +1396,14 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
continue;
insertAssignPtrTypeIntrs(I, B);
- deduceOperandElementType(I);
insertAssignTypeIntrs(I, B);
insertPtrCastOrAssignTypeInstr(I, B);
insertSpirvDecorations(I, B);
}
+ for (auto &I : instructions(Func))
+ deduceOperandElementType(&I);
+
for (auto *I : Worklist) {
TrackConstants = true;
if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index f96c3a2b0a770..d434e0b5efbcc 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -742,8 +742,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(const StructType *Ty,
bool EmitIR) {
SmallVector<Register, 4> FieldTypes;
for (const auto &Elem : Ty->elements()) {
- SPIRVType *ElemTy =
- findSPIRVType(toTypedPointer(Elem, Ty->getContext()), MIRBuilder);
+ SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder);
assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
"Invalid struct element type");
FieldTypes.push_back(getSPIRVTypeID(ElemTy));
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 517a9b490ebad..db83172f7fa9c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1086,7 +1086,11 @@ bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg,
// don't generate a cast between identical storage classes
if (SrcSC == DstSC)
- return true;
+ return BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(TargetOpcode::COPY))
+ .addDef(ResVReg)
+ .addUse(SrcPtr)
+ .constrainAllUses(TII, TRI, RBI);
// Casting from an eligible pointer to Generic.
if (DstSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(SrcSC))
@@ -1121,10 +1125,13 @@ bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg,
if (SrcSC == SPIRV::StorageClass::CrossWorkgroup && isUSMStorageClass(DstSC))
return selectUnOp(ResVReg, ResType, I,
SPIRV::OpCrossWorkgroupCastToPtrINTEL);
+ if (isUSMStorageClass(SrcSC) && DstSC == SPIRV::StorageClass::Generic)
+ return selectUnOp(ResVReg, ResType, I, SPIRV::OpPtrCastToGeneric);
+ if (SrcSC == SPIRV::StorageClass::Generic && isUSMStorageClass(DstSC))
+ return selectUnOp(ResVReg, ResType, I, SPIRV::OpGenericCastToPtr);
- // TODO Should this case just be disallowed completely?
- // We're casting 2 other arbitrary address spaces, so have to bitcast.
- return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
+ // Bitcast for pointers requires that the address spaces must match
+ return false;
}
static unsigned getFCmpOpcode(unsigned PredNum) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 61f99f8d85269..30a6c474f467a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -95,7 +95,7 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
if (ReqCaps.size() == 1) {
auto Cap = ReqCaps[0];
if (Reqs.isCapabilityAvailable(Cap))
- return {true, {Cap}, {}, ReqMinVer, ReqMaxVer};
+ return {true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
} else {
// By SPIR-V specification: "If an instruction, enumerant, or other
// feature specifies multiple enabling capabilities, only one such
@@ -110,7 +110,7 @@ getSymbolicOperandRequirements(SPIRV::OperandCategory::OperandCategory Category,
for (size_t i = 0, Sz = UseCaps.size(); i < Sz; ++i) {
auto Cap = UseCaps[i];
if (i == Sz - 1 || !AvoidCaps.S.contains(Cap))
- return {true, {Cap}, {}, ReqMinVer, ReqMaxVer};
+ return {true, {Cap}, ReqExts, ReqMinVer, ReqMaxVer};
}
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index a0a253c23b1e8..adc5b36af6f18 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -166,8 +166,8 @@ static void insertBitcasts(MachineFunction &MF, SPIRVGlobalRegistry *GR,
}
Register Def = MI.getOperand(0).getReg();
Register Source = MI.getOperand(2).getReg();
- SPIRVType *BaseTy = GR->getOrCreateSPIRVType(
- getMDOperandAsType(MI.getOperand(3).getMetadata(), 0), MIB);
+ Type *ElemTy = getMDOperandAsType(MI.getOperand(3).getMetadata(), 0);
+ SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElemTy, MIB);
SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
BaseTy, MI, *MF.getSubtarget<SPIRVSubtarget>().getInstrInfo(),
addressSpaceToStorageClass(MI.getOperand(4).getImm(), *ST));
@@ -220,7 +220,7 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR,
MIB.setInsertPt(*MI->getParent(), MI);
const GlobalValue *Global = MI->getOperand(1).getGlobal();
Type *ElementTy = GR->getDeducedGlobalValueType(Global);
- auto *Ty = TypedPointerType::get(ElementTy,
+ auto *Ty = TypedPointerType::get(toTypedPointer(ElementTy),
Global->getType()->getAddressSpace());
SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB);
break;
@@ -409,8 +409,8 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_ptr_type)) {
Register Reg = MI.getOperand(1).getReg();
MIB.setInsertPt(*MI.getParent(), MI.getIterator());
- SPIRVType *BaseTy = GR->getOrCreateSPIRVType(
- getMDOperandAsType(MI.getOperand(2).getMetadata(), 0), MIB);
+ Type *ElementTy = getMDOperandAsType(MI.getOperand(2).getMetadata(), 0);
+ SPIRVType *BaseTy = GR->getOrCreateSPIRVType(ElementTy, MIB);
SPIRVType *AssignedPtrType = GR->getOrCreateSPIRVPointerType(
BaseTy, MI, *MF.getSubtarget<SPIRVSubtarget>().getInstrInfo(),
addressSpaceToStorageClass(MI.getOperand(3).getImm(), *ST));
@@ -453,6 +453,7 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
Ty = TargetExtIt == TargetExtConstTypes.end()
? MI.getOperand(1).getCImm()->getType()
: TargetExtIt->second;
+ GR->add(MI.getOperand(1).getCImm(), &MF, Reg);
} else if (MIOp == TargetOpcode::G_FCONSTANT) {
Ty = MI.getOperand(1).getFPImm()->getType();
} else {
diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
index 65b48c8acf6ab..318c5cebb7a43 100644
--- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
+++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
@@ -689,34 +689,34 @@ class StorageClass<string name, bits<32> value> {
bits<32> Value = value;
}
-multiclass StorageClassOperand<bits<32> value, list<Capability> reqCapabilities> {
+multiclass StorageClassOperand<bits<32> value, list<Extension> reqExtensions, list<Capability> reqCapabilities> {
def : StorageClass<NAME, value>;
- defm : SymbolicOperandWithRequirements<StorageClassOperand, value, NAME, 0, 0, [], reqCapabilities>;
-}
-
-defm UniformConstant : StorageClassOperand<0, []>;
-defm Input : StorageClassOperand<1, []>;
-defm Uniform : StorageClassOperand<2, [Shader]>;
-defm Output : StorageClassOperand<3, [Shader]>;
-defm Workgroup : StorageClassOperand<4, []>;
-defm CrossWorkgroup : StorageClassOperand<5, []>;
-defm Private : StorageClassOperand<6, [Shader]>;
-defm Function : StorageClassOperand<7, []>;
-defm Generic : StorageClassOperand<8, [GenericPointer]>;
-defm PushConstant : StorageClassOperand<9, [Shader]>;
-defm AtomicCounter : StorageClassOperand<10, [AtomicStorage]>;
-defm Image : StorageClassOperand<11, []>;
-defm StorageBuffer : StorageClassOperand<12, [Shader]>;
-defm CallableDataNV : StorageClassOperand<5328, [RayTracingNV]>;
-defm IncomingCallableDataNV : StorageClassOperand<5329, [RayTracingNV]>;
-defm RayPayloadNV : StorageClassOperand<5338, [RayTracingNV]>;
-defm HitAttributeNV : StorageClassOperand<5339, [RayTracingNV]>;
-defm IncomingRayPayloadNV : StorageClassOperand<5342, [RayTracingNV]>;
-defm ShaderRecordBufferNV : StorageClassOperand<5343, [RayTracingNV]>;
-defm PhysicalStorageBufferEXT : StorageClassOperand<5349, [PhysicalStorageBufferAddressesEXT]>;
-defm CodeSectionINTEL : StorageClassOperand<5605, [FunctionPointersINTEL]>;
-defm DeviceOnlyINTEL : StorageClassOperand<5936, [USMStorageClassesINTEL]>;
-defm HostOnlyINTEL : StorageClassOperand<5937, [USMStorageClassesINTEL]>;
+ defm : SymbolicOperandWithRequirements<StorageClassOperand, value, NAME, 0, 0, reqExtensions, reqCapabilities>;
+}
+
+defm UniformConstant : StorageClassOperand<0, [], []>;
+defm Input : StorageClassOperand<1, [], []>;
+defm Uniform : StorageClassOperand<2, [], [Shader]>;
+defm Output : StorageClassOperand<3, [], [Shader]>;
+defm Workgroup : StorageClassOperand<4, [], []>;
+defm CrossWorkgroup : StorageClassOperand<5, [], []>;
+defm Private : StorageClassOperand<6, [], [Shader]>;
+defm Function : StorageClassOperand<7, [], []>;
+defm Generic : StorageClassOperand<8, [], [GenericPointer]>;
+defm PushConstant : StorageClassOperand<9, [], [Shader]>;
+defm AtomicCounter : StorageClassOperand<10, [], [AtomicStorage]>;
+defm Image : StorageClassOperand<11, [], []>;
+defm StorageBuffer : StorageClassOperand<12, [], [Shader]>;
+defm CallableDataNV : StorageClassOperand<5328, [], [RayTracingNV]>;
+defm IncomingCallableDataNV : StorageClassOperand<5329, [], [RayTracingNV]>;
+defm RayPayloadNV : StorageClassOperand<5338, [], [RayTracingNV]>;
+defm HitAttributeNV : StorageClassOperand<5339, [], [RayTracingNV]>;
+defm IncomingRayPayloadNV : StorageClassOperand<5342, [], [RayTracingNV]>;
+defm ShaderRecordBufferNV : StorageClassOperand<5343, [], [RayTracingNV]>;
+defm PhysicalStorageBufferEXT : StorageClassOperand<5349, [], [PhysicalStorageBufferAddressesEXT]>;
+defm CodeSectionINTEL : StorageClassOperand<5605, [SPV_INTEL_function_pointers], [FunctionPointersINTEL]>;
+defm DeviceOnlyINTEL : StorageClassOperand<5936, [SPV_INTEL_usm_storage_classes], [USMStorageClassesINTEL]>;
+defm HostOnlyINTEL : StorageClassOperand<5937, [SPV_INTEL_usm_storage_classes], [USMStorageClassesINTEL]>;
//===----------------------------------------------------------------------===//
// Multiclass used to define Dim enum values and at the same time
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index c20f3546a3e55..c1b90b0e9d884 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -280,7 +280,7 @@ bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID) {
Type *getMDOperandAsType(const MDNode *N, unsigned I) {
Type *ElementTy = cast<ValueAsMetadata>(N->getOperand(I))->getType();
- return toTypedPointer(ElementTy, N->getContext());
+ return toTypedPointer(ElementTy);
}
// The set of names is borrowed from the SPIR-V translator.
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 33cb509dc4a59..c131eecb1c137 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -113,7 +113,7 @@ inline bool isTypedPointerTy(const Type *T) {
// True if this is an instance of PointerType.
inline bool isUntypedPointerTy(const Type *T) {
- return T->getTypeID() == Type::PointerTyID;
+ return T && T->getTypeID() == Type::PointerTyID;
}
// True if this is an instance of PointerType or TypedPointerType.
@@ -153,9 +153,9 @@ inline Type *reconstructFunctionType(Function *F) {
return FunctionType::get(F->getReturnType(), ArgTys, F->isVarArg());
}
-inline Type *toTypedPointer(Type *Ty, LLVMContext &Ctx) {
+inline Type *toTypedPointer(Type *Ty) {
return isUntypedPointerTy(Ty)
- ? TypedPointerType::get(IntegerType::getInt8Ty(Ctx),
+ ? TypedPointerType::get(IntegerType::getInt8Ty(Ty->getContext()),
getPointerAddressSpace(Ty))
: Ty;
}
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll
index b5df462bd8fa9..986d88da41832 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll
@@ -1,9 +1,9 @@
; Modified from: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/test/extensions/INTEL/SPV_INTEL_usm_storage_classes/intel_usm_addrspaces.ll
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-EXT
-; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %}
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %}
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-WITHOUT
-; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
; CHECK-: Capability USMStorageClassesINTEL
; CHECK-SPIRV-WITHOUT-NO: Capability USMStorageClassesINTEL
diff --git a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
index 8d34a40326d70..0e2b26c83bcdd 100644
--- a/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
+++ b/llvm/test/CodeGen/SPIRV/passes/SPIRVEmitIntrinsics-no-divergent-spv_assign_ptr_type.ll
@@ -5,7 +5,7 @@
define spir_kernel void @test_pointer_cast(ptr addrspace(1) %src) {
; CHECK-NOT: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i8 undef, i32 1)
-; CHECK: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i32 0, i32 1)
+; CHECK: call{{.*}} void @llvm.spv.assign.ptr.type.p1(ptr addrspace(1) %src, metadata i32 poison, i32 1)
%b = bitcast ptr addrspace(1) %src to ptr addrspace(1)
%g = getelementptr inbounds i32, ptr addrspace(1) %b, i64 52
ret void
diff --git a/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll b/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll
new file mode 100644
index 0000000000000..8e70bef3a5399
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/duplicate-type-ptr-def.ll
@@ -0,0 +1,26 @@
+; 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: %[[#Char:]] = OpTypeInt 8 0
+; CHECK: %[[#Ptr:]] = OpTypePointer Generic %[[#Char]]
+; CHECK: %[[#TypeDef:]] = OpTypePointer Generic %[[#Ptr]]
+; CHECK-NOT: %[[#TypeDef]] = OpTypePointer Generic %[[#Ptr]]
+
+%Range = type { %Array }
+%Array = type { [1 x i64] }
+
+define spir_func ptr addrspace(4) @foo(ptr addrspace(4) dereferenceable_or_null(32) %this) {
+entry:
+ %addr = alloca ptr addrspace(4)
+ store ptr addrspace(4) %this, ptr %addr
+ %arrayidx = getelementptr inbounds ptr addrspace(4), ptr addrspace(1) null, i64 0
+ %r = addrspacecast ptr addrspace(1) %arrayidx to ptr addrspace(4)
+ ret ptr addrspace(4) %r
+}
+
+define spir_func void @bar() {
+entry:
+ %retval = alloca ptr addrspace(4)
+ %retval.ascast = addrspacecast ptr %retval to ptr addrspace(4)
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll
new file mode 100644
index 0000000000000..e6130cedf6800
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-global-dup.ll
@@ -0,0 +1,27 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-DAG: %[[#Char:]] = OpTypeInt 8 0
+; CHECK-SPIRV-DAG: %[[#ArrayTy:]] = OpTypeArray %[[#Char]] %[[#]]
+; CHECK-SPIRV-DAG: %[[#CharPtrTy:]] = OpTypePointer CrossWorkgroup %[[#Char]]
+; CHECK-SPIRV-DAG: %[[#Const1:]] = OpConstantComposite %[[#]] %[[#]] %[[#]]
+; CHECK-SPIRV-DAG: %[[#CharPtrPtrTy:]] = OpTypePointer CrossWorkgroup %[[#CharPtrTy]]
+; CHECK-SPIRV-DAG: %[[#PtrArrayTy:]] = OpTypePointer CrossWorkgroup %[[#ArrayTy]]
+; CHECK-SPIRV-DAG: OpVariable %[[#PtrArrayTy]] CrossWorkgroup %[[#Const1]]
+; CHECK-SPIRV-DAG: OpVariable %[[#CharPtrPtrTy]] CrossWorkgroup %[[#]]
+
+ at a_var = addrspace(1) global [2 x i8] c"\01\01"
+ at p_var = addrspace(1) global ptr addrspace(1) getelementptr inbounds ([2 x i8], ptr addrspace(1) @a_var, i32 0, i64 1)
+
+define spir_func zeroext i8 @foo() {
+entry:
+ ret i8 1
+}
+
+define spir_func zeroext i8 @bar() {
+entry:
+ ret i8 1
+}
diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll
new file mode 100644
index 0000000000000..ab7f923797f30
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-simple-for.ll
@@ -0,0 +1,65 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - --translator-compatibility-mode | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-COMPAT,CHECK-COMPAT64
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-DEFVER
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - --translator-compatibility-mode | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-COMPAT,CHECK-COMPAT32
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-DAG: %[[#CharTy:]] = OpTypeInt 8 0
+; CHECK-SPIRV-DAG: %[[#IntTy:]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: %[[#IntConst1:]] = OpConstant %[[#IntTy]] 1
+; CHECK-SPIRV-DAG: %[[#ArrTy:]] = OpTypeArray %[[#IntTy]] %[[#IntConst1]]
+; CHECK-SPIRV-DAG: %[[#BoolTy:]] = OpTypeBool
+; CHECK-SPIRV-DAG: %[[#LongTy:]] = OpTypeInt 64 0
+; CHECK-SPIRV-DAG: %[[#LongConst4:]] = OpConstant %[[#LongTy]] 4
+; CHECK-SPIRV-DAG: %[[#IntConst123:]] = OpConstant %[[#IntTy]] 123
+; CHECK-SPIRV-DAG: %[[#CharPtrTy:]] = OpTypePointer Function %[[#CharTy]]
+; CHECK-SPIRV-DAG: %[[#ArrPtrTy:]] = OpTypePointer Function %[[#ArrTy]]
+; CHECK-SPIRV-DAG: %[[#IntPtrTy:]] = OpTypePointer Function %[[#IntTy]]
+; CHECK-SPIRV: OpFunction
+; CHECK-SPIRV: %[[#LblEntry:]] = OpLabel
+; CHECK-SPIRV: %[[#Value:]] = OpVariable %[[#ArrPtrTy]] Function
+; CHECK-SPIRV: %[[#ValueAsCharPtr:]] = OpBitcast %[[#CharPtrTy]] %[[#Value]]
+; CHECK-SPIRV: %[[#Eof:]] = OpInBoundsPtrAccessChain %[[#CharPtrTy]] %[[#ValueAsCharPtr]] %[[#LongConst4]]
+; CHECK-SPIRV: %[[#EofAsArray:]] = OpBitcast %[[#ArrPtrTy]] %[[#Eof]]
+; CHECK-SPIRV: OpBranch %[[#LblCond:]]
+; CHECK-SPIRV: %[[#LblCond]] = OpLabel
+; CHECK-SPIRV: %[[#Iter:]] = OpPhi %[[#ArrPtrTy]] %[[#Value]] %[[#LblEntry]] %[[#CurrValue:]] %[[#LblBody:]]
+; CHECK-COMPAT64: %[[#IterInt:]] = OpConvertPtrToU %[[#LongTy]] %[[#Iter]]
+; CHECK-COMPAT64: %[[#EofInt:]] = OpConvertPtrToU %[[#LongTy]] %[[#EofAsArray]]
+; CHECK-COMPAT32: %[[#IterInt:]] = OpConvertPtrToU %[[#IntTy]] %[[#Iter]]
+; CHECK-COMPAT32: %[[#EofInt:]] = OpConvertPtrToU %[[#IntTy]] %[[#EofAsArray]]
+; CHECK-COMPAT: %[[#Is:]] = OpIEqual %[[#BoolTy]] %[[#IterInt]] %[[#EofInt]]
+; CHECK-DEFVER: %[[#Is:]] = OpPtrEqual %[[#BoolTy]] %[[#Iter]] %[[#EofAsArray]]
+; CHECK-SPIRV: OpBranchConditional %[[#Is]] %[[#LblExit:]] %[[#LblBody]]
+; CHECK-SPIRV: %[[#LblBody]] = OpLabel
+; CHECK-SPIRV: %[[#IterAsIntPtr:]] = OpBitcast %[[#IntPtrTy]] %[[#Iter]]
+; CHECK-SPIRV: OpStore %[[#IterAsIntPtr]] %[[#IntConst123]] Aligned 4
+; CHECK-SPIRV: %[[#IterAsCharPtr:]] = OpBitcast %[[#CharPtrTy]] %[[#Iter]]
+; CHECK-SPIRV: %[[#CurrValueAsCharPtr:]] = OpInBoundsPtrAccessChain %[[#CharPtrTy]] %[[#IterAsCharPtr]] %[[#LongConst4]]
+; CHECK-SPIRV: %[[#CurrValue]] = OpBitcast %[[#ArrPtrTy]] %[[#CurrValueAsCharPtr]]
+; CHECK-SPIRV: OpBranch %[[#LblCond]]
+; CHECK-SPIRV: %[[#LblExit]] = OpLabel
+; CHECK-SPIRV: OpFunctionEnd
+
+define spir_kernel void @foo() {
+entry:
+ %v = alloca [1 x i32], align 4
+ %eof = getelementptr inbounds i8, ptr %v, i64 4
+ br label %cond
+
+cond:
+ %iter = phi ptr [ %v, %entry ], [ %curr, %body ]
+ %is = icmp eq ptr %iter, %eof
+ br i1 %is, label %exit, label %body
+
+body:
+ store i32 123, ptr %iter, align 4
+ %curr = getelementptr inbounds i8, ptr %iter, i64 4
+ br label %cond
+
+exit:
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/bitcast-
diff -addrspace.ll b/llvm/test/CodeGen/SPIRV/transcoding/bitcast-
diff -addrspace.ll
new file mode 100644
index 0000000000000..c1ef3041c4ce5
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/transcoding/bitcast-
diff -addrspace.ll
@@ -0,0 +1,44 @@
+; Check that bitcast for pointers implies that the address spaces must match.
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_usm_storage_classes -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s --spirv-ext=+SPV_INTEL_usm_storage_classes -o - -filetype=obj | spirv-val %}
+
+; CHECK: Capability USMStorageClassesINTEL
+; CHECK: OpExtension "SPV_INTEL_usm_storage_classes"
+; CHECK-DAG: OpName %[[#Bar:]] "bar"
+; CHECK-DAG: %[[#Void:]] = OpTypeVoid
+; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#GenPtrChar:]] = OpTypePointer Generic %[[#Char]]
+; CHECK-DAG: %[[#AtDevice:]] = OpTypePointer DeviceOnlyINTEL %[[#Char]]
+; CHECK-DAG: %[[#AtHost:]] = OpTypePointer HostOnlyINTEL %[[#Char]]
+; CHECK-DAG: %[[#PtrVarHost:]] = OpTypePointer Function %[[#AtHost]]
+; CHECK-DAG: %[[#PtrVarDevice:]] = OpTypePointer Function %[[#AtDevice]]
+; CHECK: OpFunction
+; CHECK: %[[#VarDevice:]] = OpVariable %[[#PtrVarDevice]] Function
+; CHECK: %[[#VarHost:]] = OpVariable %[[#PtrVarHost]] Function
+; CHECK: %[[#LoadedDevice:]] = OpLoad %[[#AtDevice]] %[[#VarDevice]]
+; CHECK: %[[#CastedFromDevice:]] = OpPtrCastToGeneric %[[#GenPtrChar]] %[[#LoadedDevice]]
+; CHECK: OpFunctionCall %[[#Void]] %[[#Bar]] %[[#CastedFromDevice]]
+; CHECK: %[[#LoadedHost:]] = OpLoad %[[#AtHost]] %[[#VarHost]]
+; CHECK: %[[#CastedFromHost:]] = OpPtrCastToGeneric %[[#GenPtrChar]] %[[#LoadedHost]]
+; CHECK: OpFunctionCall %[[#Void]] %[[#Bar]] %[[#CastedFromHost]]
+
+define spir_func void @foo() {
+entry:
+ %device_var = alloca ptr addrspace(5)
+ %host_var = alloca ptr addrspace(6)
+ %p1 = load ptr addrspace(5), ptr %device_var
+ %p2 = addrspacecast ptr addrspace(5) %p1 to ptr addrspace(4)
+ call spir_func void @bar(ptr addrspace(4) %p2)
+ %p3 = load ptr addrspace(6), ptr %host_var
+ %p4 = addrspacecast ptr addrspace(6) %p3 to ptr addrspace(4)
+ call spir_func void @bar(ptr addrspace(4) %p4)
+ ret void
+}
+
+define spir_func void @bar(ptr addrspace(4) %data) {
+entry:
+ %data.addr = alloca ptr addrspace(4)
+ store ptr addrspace(4) %data, ptr %data.addr
+ ret void
+}
More information about the llvm-commits
mailing list