Skip to content

Commit 9796b0e

Browse files
Add support for the 'freeze' instruction (#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.
1 parent 288d317 commit 9796b0e

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

Diff for: llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
150150

151151
bool selectOpUndef(Register ResVReg, const SPIRVType *ResType,
152152
MachineInstr &I) const;
153+
bool selectFreeze(Register ResVReg, const SPIRVType *ResType,
154+
MachineInstr &I) const;
153155
bool selectIntrinsic(Register ResVReg, const SPIRVType *ResType,
154156
MachineInstr &I) const;
155157
bool selectExtractVal(Register ResVReg, const SPIRVType *ResType,
@@ -284,6 +286,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
284286
return selectGlobalValue(ResVReg, I);
285287
case TargetOpcode::G_IMPLICIT_DEF:
286288
return selectOpUndef(ResVReg, ResType, I);
289+
case TargetOpcode::G_FREEZE:
290+
return selectFreeze(ResVReg, ResType, I);
287291

288292
case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
289293
case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
@@ -1014,6 +1018,46 @@ bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
10141018
.constrainAllUses(TII, TRI, RBI);
10151019
}
10161020

1021+
bool SPIRVInstructionSelector::selectFreeze(Register ResVReg,
1022+
const SPIRVType *ResType,
1023+
MachineInstr &I) const {
1024+
// There is no way to implement `freeze` correctly without support on SPIR-V
1025+
// standard side, but we may at least address a simple (static) case when
1026+
// undef/poison value presence is obvious. The main benefit of even
1027+
// incomplete `freeze` support is preventing of translation from crashing due
1028+
// to lack of support on legalization and instruction selection steps.
1029+
if (!I.getOperand(0).isReg() || !I.getOperand(1).isReg())
1030+
return false;
1031+
Register OpReg = I.getOperand(1).getReg();
1032+
if (MachineInstr *Def = MRI->getVRegDef(OpReg)) {
1033+
Register Reg;
1034+
switch (Def->getOpcode()) {
1035+
case SPIRV::ASSIGN_TYPE:
1036+
if (MachineInstr *AssignToDef =
1037+
MRI->getVRegDef(Def->getOperand(1).getReg())) {
1038+
if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1039+
Reg = Def->getOperand(2).getReg();
1040+
}
1041+
break;
1042+
case SPIRV::OpUndef:
1043+
Reg = Def->getOperand(1).getReg();
1044+
break;
1045+
}
1046+
unsigned DestOpCode;
1047+
if (Reg.isValid()) {
1048+
DestOpCode = SPIRV::OpConstantNull;
1049+
} else {
1050+
DestOpCode = TargetOpcode::COPY;
1051+
Reg = OpReg;
1052+
}
1053+
return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(DestOpCode))
1054+
.addDef(I.getOperand(0).getReg())
1055+
.addUse(Reg)
1056+
.constrainAllUses(TII, TRI, RBI);
1057+
}
1058+
return false;
1059+
}
1060+
10171061
bool SPIRVInstructionSelector::selectConstVector(Register ResVReg,
10181062
const SPIRVType *ResType,
10191063
MachineInstr &I) const {

Diff for: llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
184184
return Query.Types[0].getSizeInBits() == Query.Types[1].getSizeInBits();
185185
}))));
186186

187-
getActionDefinitionsBuilder(G_IMPLICIT_DEF).alwaysLegal();
187+
getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE}).alwaysLegal();
188188

189189
getActionDefinitionsBuilder(G_INTTOPTR)
190190
.legalForCartesianProduct(allPtrs, allIntScalars);

Diff for: llvm/test/CodeGen/SPIRV/freeze.ll

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
2+
; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: OpName %[[Arg1:.*]] "arg1"
5+
; CHECK: OpName %[[Arg2:.*]] "arg2"
6+
; CHECK: OpName %[[NotAStaticPoison:.*]] "poison1"
7+
; CHECK: OpName %[[NotAStaticPoison]] "nil0"
8+
; CHECK: OpName %[[StaticPoisonIntFreeze:.*]] "nil1"
9+
; CHECK: OpName %[[StaticPoisonFloatFreeze:.*]] "nil2"
10+
; CHECK: OpName %[[Arg1]] "val1"
11+
; CHECK: OpName %[[Const100:.*]] "val2"
12+
; CHECK: OpName %[[Const100]] "val3"
13+
; CHECK: OpDecorate
14+
; CHECK-DAG: %[[FloatTy:.*]] = OpTypeFloat 32
15+
; CHECK-DAG: %[[ShortTy:.*]] = OpTypeInt 16 0
16+
; CHECK-DAG: %[[IntTy:.*]] = OpTypeInt 32 0
17+
; CHECK-DAG: %[[Undef:.*]] = OpUndef %[[ShortTy]]
18+
; CHECK-DAG: %[[Const100]] = OpConstant %[[IntTy]] 100
19+
; CHECK-DAG: %[[StaticPoisonIntFreeze]] = OpConstantNull %[[IntTy]]
20+
; CHECK-DAG: %[[StaticPoisonFloatFreeze]] = OpConstantNull %[[FloatTy]]
21+
; CHECK: %[[Arg1]] = OpFunctionParameter %[[FloatTy]]
22+
; CHECK: %[[NotAStaticPoison]] = OpIAdd %[[ShortTy]] %[[Arg2]] %[[Undef]]
23+
24+
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"
25+
target triple = "spir64-unknown-unknown"
26+
27+
define spir_func void @foo(float %arg1, i16 %arg2) {
28+
entry:
29+
%poison1 = add i16 %arg2, undef
30+
%nil0 = freeze i16 %poison1
31+
%nil1 = freeze i32 undef
32+
%nil2 = freeze float poison
33+
%val1 = freeze float %arg1
34+
%val2 = freeze i32 100
35+
%val3 = freeze i32 %val2
36+
ret void
37+
}

0 commit comments

Comments
 (0)