-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for the 'freeze' instruction #82979
Add support for the 'freeze' instruction #82979
Conversation
@llvm/pr-subscribers-backend-spir-v Author: Vyacheslav Levytskyy (VyacheslavLevytskyy) ChangesThis PR is to add support for the 'freeze' instruction: https://llvm.org/docs/LangRef.html#freeze-instruction There is no way to implement Full diff: https://github.com/llvm/llvm-project/pull/82979.diff 3 Files Affected:
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 7258d3b4d88ed3..f1e18f0601b87c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -150,6 +150,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectOpUndef(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
+ bool selectFreeze(Register ResVReg, const SPIRVType *ResType,
+ MachineInstr &I) const;
bool selectIntrinsic(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
bool selectExtractVal(Register ResVReg, const SPIRVType *ResType,
@@ -284,6 +286,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
return selectGlobalValue(ResVReg, I);
case TargetOpcode::G_IMPLICIT_DEF:
return selectOpUndef(ResVReg, ResType, I);
+ case TargetOpcode::G_FREEZE:
+ return selectFreeze(ResVReg, ResType, I);
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
@@ -1014,6 +1018,46 @@ bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
.constrainAllUses(TII, TRI, RBI);
}
+bool SPIRVInstructionSelector::selectFreeze(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I) const {
+ // There is no way to implement `freeze` correctly without support on SPIR-V
+ // standard side, but we may at least address a simple (static) case when
+ // undef/poison value presence is obvious. The main benefit of even
+ // incomplete `freeze` support is preventing of translation from crashing due
+ // to lack of support on legalization and instruction selection steps.
+ if (!I.getOperand(0).isReg() || !I.getOperand(1).isReg())
+ return false;
+ Register OpReg = I.getOperand(1).getReg();
+ if (MachineInstr *Def = MRI->getVRegDef(OpReg)) {
+ Register Reg;
+ switch (Def->getOpcode()) {
+ case SPIRV::ASSIGN_TYPE:
+ if (MachineInstr *AssignToDef =
+ MRI->getVRegDef(Def->getOperand(1).getReg())) {
+ if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
+ Reg = Def->getOperand(2).getReg();
+ }
+ break;
+ case SPIRV::OpUndef:
+ Reg = Def->getOperand(1).getReg();
+ break;
+ }
+ unsigned DestOpCode;
+ if (Reg.isValid()) {
+ DestOpCode = SPIRV::OpConstantNull;
+ } else {
+ DestOpCode = TargetOpcode::COPY;
+ Reg = OpReg;
+ }
+ return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(DestOpCode))
+ .addDef(I.getOperand(0).getReg())
+ .addUse(Reg)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ return false;
+}
+
bool SPIRVInstructionSelector::selectConstVector(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 4f2e7a240fc2cc..aedca798b4f6ae 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -184,7 +184,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
return Query.Types[0].getSizeInBits() == Query.Types[1].getSizeInBits();
}))));
- getActionDefinitionsBuilder(G_IMPLICIT_DEF).alwaysLegal();
+ getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE}).alwaysLegal();
getActionDefinitionsBuilder(G_INTTOPTR)
.legalForCartesianProduct(allPtrs, allIntScalars);
diff --git a/llvm/test/CodeGen/SPIRV/freeze.ll b/llvm/test/CodeGen/SPIRV/freeze.ll
new file mode 100644
index 00000000000000..fe4335722fe8b8
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/freeze.ll
@@ -0,0 +1,37 @@
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpName %[[Arg1:.*]] "arg1"
+; CHECK: OpName %[[Arg2:.*]] "arg2"
+; CHECK: OpName %[[NotAStaticPoison:.*]] "poison1"
+; CHECK: OpName %[[NotAStaticPoison]] "nil0"
+; CHECK: OpName %[[StaticPoisonIntFreeze:.*]] "nil1"
+; CHECK: OpName %[[StaticPoisonFloatFreeze:.*]] "nil2"
+; CHECK: OpName %[[Arg1]] "val1"
+; CHECK: OpName %[[Const100:.*]] "val2"
+; CHECK: OpName %[[Const100]] "val3"
+; CHECK: OpDecorate
+; CHECK-DAG: %[[FloatTy:.*]] = OpTypeFloat 32
+; CHECK-DAG: %[[ShortTy:.*]] = OpTypeInt 16 0
+; CHECK-DAG: %[[IntTy:.*]] = OpTypeInt 32 0
+; CHECK-DAG: %[[Undef:.*]] = OpUndef %[[ShortTy]]
+; CHECK-DAG: %[[Const100]] = OpConstant %[[IntTy]] 100
+; CHECK-DAG: %[[StaticPoisonIntFreeze]] = OpConstantNull %[[IntTy]]
+; CHECK-DAG: %[[StaticPoisonFloatFreeze]] = OpConstantNull %[[FloatTy]]
+; CHECK: %[[Arg1]] = OpFunctionParameter %[[FloatTy]]
+; CHECK: %[[NotAStaticPoison]] = OpIAdd %[[ShortTy]] %[[Arg2]] %[[Undef]]
+
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
+target triple = "spir64-unknown-unknown"
+
+define spir_func void @foo(float %arg1, i16 %arg2) {
+entry:
+ %poison1 = add i16 %arg2, undef
+ %nil0 = freeze i16 %poison1
+ %nil1 = freeze i32 undef
+ %nil2 = freeze float poison
+ %val1 = freeze float %arg1
+ %val2 = freeze i32 100
+ %val3 = freeze i32 %val2
+ ret void
+}
|
This PR is to add support for the 'freeze' instruction: https://llvm.org/docs/LangRef.html#freeze-instruction
There is no way to implement
freeze
correctly without support on SPIR-V standard side, but we may at least address a simple (static) case when undef/poison value presence is obvious. The main benefit of even incompletefreeze
support is preventing of translation from crashing due to lack of support on legalization and instruction selection steps.