[llvm] Add PreLegalizer pattern matching for degrees GL extension (PR #216506)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 15 12:41:31 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-spir-v
Author: albertbolt1
<details>
<summary>Changes</summary>
Pattern matching done using SPIRVCombine.td and SPIRVCombinerHelper.cpp
matchDegrees and applyDegrees added
1) matchDegrees checks if the fmul x , constant or fmul constant, x has the constant as 180/pi and returns true if it passes the condition
2) applyDegrees is run after the above check passes and it creates the intrinsic and passes x and result register to it
3) added a positive test case to test the above
Locally tested using
degrees.ll
```
float test(float x)
{
return degrees(x);
}
```
./build/bin/clang \
-x hlsl \
-Xclang -triple \
-Xclang dxil-pc-shadermodel6.0-library \
-S -emit-llvm \
degrees.hlsl \
-o degrees.ll
generated (trimmed down to required IR)
```
%mul.i = fmul reassoc nnan ninf nsz arcp afn float %3, f0x42652EE1
```
./build/bin/llc \
-mtriple=spirv64 \
degrees.ll \
-o degrees.spv
SPV (trimmed to show required)
%9 = OpLoad %3 %8 Aligned 4
%10 = OpExtInst %3 %1 degrees %9
**Things to check**
1) can the 180/pi check be performed in a better way? is there an existing function for it ?
---
Full diff: https://github.com/llvm/llvm-project/pull/216506.diff
4 Files Affected:
- (modified) llvm/lib/Target/SPIRV/SPIRVCombine.td (+8-2)
- (modified) llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp (+49)
- (modified) llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h (+2)
- (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees_nointrinsic.ll (+14)
``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVCombine.td b/llvm/lib/Target/SPIRV/SPIRVCombine.td
index 7d69465de4ffb..a4ed0b5161d81 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombine.td
+++ b/llvm/lib/Target/SPIRV/SPIRVCombine.td
@@ -34,10 +34,16 @@ def matrix_multiply_lowering
[{ return Helper.matchMatrixMultiply(*${root}); }]),
(apply [{ Helper.applyMatrixMultiply(*${root}); }])>;
+def degrees_lowering
+ : GICombineRule<(defs root:$root),
+ (match (wip_match_opcode G_FMUL):$root,
+ [{ return Helper.matchDegrees(*${root}); }]),
+ (apply [{ Helper.applyDegrees(*${root}); }])>;
+
def SPIRVPreLegalizerCombiner
: GICombiner<"SPIRVPreLegalizerCombinerImpl",
[vector_length_sub_to_distance_lowering,
vector_select_to_faceforward_lowering,
- matrix_transpose_lowering, matrix_multiply_lowering]> {
+ matrix_transpose_lowering, matrix_multiply_lowering, degrees_lowering]> {
let CombineAllMethodName = "tryCombineAllImpl";
-}
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
index 0882970895452..58ea761c2769a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
@@ -381,3 +381,52 @@ void SPIRVCombinerHelper::applyMatrixMultiply(MachineInstr &MI) const {
Builder.buildBuildVector(ResReg, ResultScalars);
MI.eraseFromParent();
}
+
+bool SPIRVCombinerHelper::matchDegrees(MachineInstr &MI) const {
+ if (MI.getOpcode() != TargetOpcode::G_FMUL)
+ return false;
+ Register Op1 = MI.getOperand(1).getReg();
+ Register Op2 = MI.getOperand(2).getReg();
+ MachineInstr *Op1Def = MRI.getVRegDef(Op1);
+ MachineInstr *Op2Def = MRI.getVRegDef(Op2);
+
+ if (!Op1Def || !Op2Def)
+ return false;
+
+ if (Op1Def->getOpcode() != TargetOpcode::G_FCONSTANT && Op2Def->getOpcode() != TargetOpcode::G_FCONSTANT)
+ return false;
+
+ MachineInstr *constantMachineInstruction = (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op1Def : Op2Def;
+ MachineOperand &ConstantOperand = constantMachineInstruction->getOperand(1);
+
+ if (!ConstantOperand.isFPImm())
+ return false;
+
+ const ConstantFP *Constant = ConstantOperand.getFPImm();
+ const APFloat &Val = Constant->getValueAPF();
+ APFloat Expected(180.0 / std::acos(-1.0));
+ bool LostInfo = false;
+ Expected.convert(Val.getSemantics(),
+ APFloat::rmNearestTiesToEven,
+ &LostInfo);
+
+ if (Expected.compare(Val) != APFloat::cmpEqual)
+ return false;
+
+ return true;
+}
+
+void SPIRVCombinerHelper::applyDegrees(MachineInstr &MI) const {
+ Register ResultReg = MI.getOperand(0).getReg();
+ Register Op1 = MI.getOperand(1).getReg();
+ Register Op2 = MI.getOperand(2).getReg();
+ MachineInstr *Op1Def = MRI.getVRegDef(Op1);
+ MachineInstr *Op2Def = MRI.getVRegDef(Op2);
+ Register nonConstantReg = (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op2 : Op1;
+
+ Builder.setInstrAndDebugLoc(MI);
+ Builder.buildIntrinsic(Intrinsic::spv_degrees, ResultReg)
+ .addUse(nonConstantReg);
+
+ MI.eraseFromParent();
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h
index 19e2a6901b8f0..3a25940b61c14 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h
@@ -37,6 +37,8 @@ class SPIRVCombinerHelper : public CombinerHelper {
void applyMatrixTranspose(MachineInstr &MI) const;
bool matchMatrixMultiply(MachineInstr &MI) const;
void applyMatrixMultiply(MachineInstr &MI) const;
+ bool matchDegrees(MachineInstr &MI) const;
+ void applyDegrees(MachineInstr &MI) const;
private:
SPIRVTypeInst getDotProductVectorType(Register ResReg, uint32_t K,
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees_nointrinsic.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees_nointrinsic.ll
new file mode 100644
index 0000000000000..4554559ca6b14
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees_nointrinsic.ll
@@ -0,0 +1,14 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-vulkan %s -o - | FileCheck %s
+
+; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+
+; CHECK-LABEL: Begin function fmul_to_degrees
+; CHECK: %[[#arg:]] = OpFunctionParameter %[[#float_32]]
+; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Degrees %[[#arg]]
+
+define noundef float @fmul_to_degrees(float noundef %x) {
+entry:
+ %mul = fmul reassoc nnan ninf nsz arcp afn float %x, f0x42652EE1
+ ret float %mul
+}
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/216506
More information about the llvm-commits
mailing list