[llvm] b8435e3 - [SPIR-V] Emit spv_undef intrinsic for aggregate undef operands
Michal Paszkowski via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 21 12:47:30 PST 2023
Author: Michal Paszkowski
Date: 2023-02-21T21:17:33+01:00
New Revision: b8435e392cc82639c3c5e9adff078063ac76c27d
URL: https://github.com/llvm/llvm-project/commit/b8435e392cc82639c3c5e9adff078063ac76c27d
DIFF: https://github.com/llvm/llvm-project/commit/b8435e392cc82639c3c5e9adff078063ac76c27d.diff
LOG: [SPIR-V] Emit spv_undef intrinsic for aggregate undef operands
This change adds a new spv_undef intrinsic which is emitted in place of
aggregate undef operands and later selected to single OpUndef SPIR-V
instruction. The behavior matches that of Khronos SPIR-V Translator and
should support nested aggregates.
Differential Revision: https://reviews.llvm.org/D143107
Added:
llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
Modified:
llvm/include/llvm/IR/IntrinsicsSPIRV.td
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index bf90aa0c0402..2b8602f430df 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -31,4 +31,5 @@ let TargetPrefix = "spv" in {
def int_spv_cmpxchg : Intrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_unreachable : Intrinsic<[], []>;
def int_spv_alloca : Intrinsic<[llvm_any_ty], []>;
+ def int_spv_undef : Intrinsic<[llvm_i32_ty], []>;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index f91b6ea5cb14..4e8afbe2e77e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -56,6 +56,7 @@ class SPIRVEmitIntrinsics
DenseMap<Instruction *, Constant *> AggrConsts;
DenseSet<Instruction *> AggrStores;
void preprocessCompositeConstants();
+ void preprocessUndefs();
CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
Value *Arg, Value *Arg2) {
ConstantAsMetadata *CM = ValueAsMetadata::getConstant(Arg);
@@ -151,6 +152,29 @@ void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
Old->eraseFromParent();
}
+void SPIRVEmitIntrinsics::preprocessUndefs() {
+ std::queue<Instruction *> Worklist;
+ for (auto &I : instructions(F))
+ Worklist.push(&I);
+
+ while (!Worklist.empty()) {
+ Instruction *I = Worklist.front();
+ Worklist.pop();
+
+ for (auto &Op : I->operands()) {
+ auto *AggrUndef = dyn_cast<UndefValue>(Op);
+ if (!AggrUndef || !Op->getType()->isAggregateType())
+ continue;
+
+ IRB->SetInsertPoint(I);
+ auto *IntrUndef = IRB->CreateIntrinsic(Intrinsic::spv_undef, {}, {});
+ Worklist.push(IntrUndef);
+ I->replaceUsesOfWith(Op, IntrUndef);
+ AggrConsts[IntrUndef] = AggrUndef;
+ }
+ }
+}
+
void SPIRVEmitIntrinsics::preprocessCompositeConstants() {
std::queue<Instruction *> Worklist;
for (auto &I : instructions(F))
@@ -369,7 +393,8 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) {
setInsertPointSkippingPhis(*IRB, I->getNextNode());
Type *TypeToAssign = Ty;
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
- if (II->getIntrinsicID() == Intrinsic::spv_const_composite) {
+ if (II->getIntrinsicID() == Intrinsic::spv_const_composite ||
+ II->getIntrinsicID() == Intrinsic::spv_undef) {
auto t = AggrConsts.find(II);
assert(t != AggrConsts.end());
TypeToAssign = t->second->getType();
@@ -453,6 +478,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
for (auto &GV : Func.getParent()->globals())
processGlobalValue(GV);
+ preprocessUndefs();
preprocessCompositeConstants();
SmallVector<Instruction *> Worklist;
for (auto &I : instructions(Func))
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 5ebec6b8fa13..f48b7032ba4f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1316,25 +1316,18 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
switch (I.getIntrinsicID()) {
case Intrinsic::spv_load:
return selectLoad(ResVReg, ResType, I);
- break;
case Intrinsic::spv_store:
return selectStore(I);
- break;
case Intrinsic::spv_extractv:
return selectExtractVal(ResVReg, ResType, I);
- break;
case Intrinsic::spv_insertv:
return selectInsertVal(ResVReg, ResType, I);
- break;
case Intrinsic::spv_extractelt:
return selectExtractElt(ResVReg, ResType, I);
- break;
case Intrinsic::spv_insertelt:
return selectInsertElt(ResVReg, ResType, I);
- break;
case Intrinsic::spv_gep:
return selectGEP(ResVReg, ResType, I);
- break;
case Intrinsic::spv_unref_global:
case Intrinsic::spv_init_global: {
MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());
@@ -1343,7 +1336,13 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
: nullptr;
assert(MI);
return selectGlobalValue(MI->getOperand(0).getReg(), *MI, Init);
- } break;
+ }
+ case Intrinsic::spv_undef: {
+ auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType));
+ return MIB.constrainAllUses(TII, TRI, RBI);
+ }
case Intrinsic::spv_const_composite: {
// If no values are attached, the composite is null constant.
bool IsNull = I.getNumExplicitDefs() + 1 == I.getNumExplicitOperands();
@@ -1360,7 +1359,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
}
}
return MIB.constrainAllUses(TII, TRI, RBI);
- } break;
+ }
case Intrinsic::spv_assign_name: {
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpName));
MIB.addUse(I.getOperand(I.getNumExplicitDefs() + 1).getReg());
@@ -1369,7 +1368,7 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
MIB.addImm(I.getOperand(i).getImm());
}
return MIB.constrainAllUses(TII, TRI, RBI);
- } break;
+ }
case Intrinsic::spv_switch: {
auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSwitch));
for (unsigned i = 1; i < I.getNumExplicitOperands(); ++i) {
@@ -1383,16 +1382,14 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
llvm_unreachable("Unexpected OpSwitch operand");
}
return MIB.constrainAllUses(TII, TRI, RBI);
- } break;
+ }
case Intrinsic::spv_cmpxchg:
return selectAtomicCmpXchg(ResVReg, ResType, I);
- break;
case Intrinsic::spv_unreachable:
BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUnreachable));
break;
case Intrinsic::spv_alloca:
return selectFrameIndex(ResVReg, ResType, I);
- break;
default:
llvm_unreachable("Intrinsic selection not implemented");
}
diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
new file mode 100644
index 000000000000..9fa94b848463
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/instructions/undef-nested-composite-store.ll
@@ -0,0 +1,29 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK-DAG: %[[#I32:]] = OpTypeInt 32
+; CHECK-DAG: %[[#I16:]] = OpTypeInt 16
+; CHECK-DAG: %[[#STRUCT:]] = OpTypeStruct %[[#I32]] %[[#I16]]
+; CHECK-DAG: %[[#NESTED_STRUCT:]] = OpTypeStruct %[[#STRUCT]] %[[#I16]]
+; CHECK-DAG: %[[#UNDEF:]] = OpUndef %[[#NESTED_STRUCT]]
+
+; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
+; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
+; CHECK-NEXT: %[[#]] = OpLabel
+; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4
+; CHECK-NEXT: OpReturn
+; CHECK-NEXT: OpFunctionEnd
+
+%struct = type {
+ i32,
+ i16
+}
+
+%nested_struct = type {
+ %struct,
+ i16
+}
+
+define void @foo(ptr %ptr) {
+ store %nested_struct undef, ptr %ptr
+ ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
new file mode 100644
index 000000000000..6a274732417d
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/instructions/undef-simple-composite-store.ll
@@ -0,0 +1,18 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK-DAG: %[[#I32:]] = OpTypeInt 32
+; CHECK-DAG: %[[#I16:]] = OpTypeInt 16
+; CHECK-DAG: %[[#STRUCT:]] = OpTypeStruct %[[#I32]] %[[#I16]]
+; CHECK-DAG: %[[#UNDEF:]] = OpUndef %[[#STRUCT]]
+
+; CHECK: %[[#]] = OpFunction %[[#]] None %[[#]]
+; CHECK-NEXT: %[[#PTR:]] = OpFunctionParameter %[[#]]
+; CHECK-NEXT: %[[#]] = OpLabel
+; CHECK-NEXT: OpStore %[[#PTR]] %[[#UNDEF]] Aligned 4
+; CHECK-NEXT: OpReturn
+; CHECK-NEXT: OpFunctionEnd
+
+define void @foo(ptr %ptr) {
+ store { i32, i16 } undef, ptr %ptr
+ ret void
+}
More information about the llvm-commits
mailing list