[llvm] Add support for the 'freeze' instruction (PR #82979)
Vyacheslav Levytskyy via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 26 02:21:27 PST 2024
https://github.com/VyacheslavLevytskyy created https://github.com/llvm/llvm-project/pull/82979
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 incomplete `freeze` support is preventing of translation from crashing due to lack of support on legalization and instruction selection steps.
>From 439ff505e31cdba27f55f3ffa880738a40b3fe00 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Mon, 26 Feb 2024 02:15:54 -0800
Subject: [PATCH] as support for legalization and instruction selection of
'freeze'
---
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 44 +++++++++++++++++++
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 2 +-
llvm/test/CodeGen/SPIRV/freeze.ll | 37 ++++++++++++++++
3 files changed, 82 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/SPIRV/freeze.ll
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
+}
More information about the llvm-commits
mailing list