[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