[llvm] Add PreLegalizer pattern matching for degrees GL extension (PR #216506)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 16 10:54:20 PDT 2026


https://github.com/albertbolt1 updated https://github.com/llvm/llvm-project/pull/216506

>From e60fac977acc6fcc7ece0e50dc2a69ee8537c195 Mon Sep 17 00:00:00 2001
From: albertbolt <albertboltinfinity at gmail.com>
Date: Sun, 16 Aug 2026 01:04:30 +0530
Subject: [PATCH 1/5] Added required code and test case

---
 llvm/lib/Target/SPIRV/SPIRVCombine.td         | 10 +++-
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 49 +++++++++++++++++++
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.h   |  2 +
 .../hlsl-intrinsics/degrees_nointrinsic.ll    | 14 ++++++
 4 files changed, 73 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees_nointrinsic.ll

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

>From 368ceed2146cd645b2c3b36663d44d41415bfd90 Mon Sep 17 00:00:00 2001
From: albertbolt <albertboltinfinity at gmail.com>
Date: Sun, 16 Aug 2026 01:17:48 +0530
Subject: [PATCH 2/5] Added required code and test case

---
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
index 58ea761c2769a..0da5ab6337ebb 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
@@ -393,10 +393,12 @@ bool SPIRVCombinerHelper::matchDegrees(MachineInstr &MI) const {
   if (!Op1Def || !Op2Def)
     return false;
 
-  if (Op1Def->getOpcode() != TargetOpcode::G_FCONSTANT && Op2Def->getOpcode() != TargetOpcode::G_FCONSTANT)
+  if (Op1Def->getOpcode() != TargetOpcode::G_FCONSTANT && 
+      Op2Def->getOpcode() != TargetOpcode::G_FCONSTANT)
     return false;
 
-  MachineInstr *constantMachineInstruction = (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op1Def : Op2Def;
+  MachineInstr *constantMachineInstruction = 
+      (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op1Def : Op2Def;
   MachineOperand &ConstantOperand = constantMachineInstruction->getOperand(1);
 
   if (!ConstantOperand.isFPImm())
@@ -406,9 +408,7 @@ bool SPIRVCombinerHelper::matchDegrees(MachineInstr &MI) const {
   const APFloat &Val = Constant->getValueAPF();
   APFloat Expected(180.0 / std::acos(-1.0));
   bool LostInfo = false;
-  Expected.convert(Val.getSemantics(),
-                            APFloat::rmNearestTiesToEven,
-                            &LostInfo);
+  Expected.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &LostInfo);
 
   if (Expected.compare(Val) != APFloat::cmpEqual)
     return false;
@@ -422,7 +422,8 @@ void SPIRVCombinerHelper::applyDegrees(MachineInstr &MI) const {
   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;
+  Register nonConstantReg = 
+      (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op2 : Op1;
   
   Builder.setInstrAndDebugLoc(MI);
   Builder.buildIntrinsic(Intrinsic::spv_degrees, ResultReg)

>From e2b3a3627501859a3eafc93aedc60bae8a0d9b7f Mon Sep 17 00:00:00 2001
From: albertbolt <albertboltinfinity at gmail.com>
Date: Sun, 16 Aug 2026 01:21:51 +0530
Subject: [PATCH 3/5] clang format

---
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
index 0da5ab6337ebb..49bd2bb1f0901 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
@@ -393,11 +393,11 @@ bool SPIRVCombinerHelper::matchDegrees(MachineInstr &MI) const {
   if (!Op1Def || !Op2Def)
     return false;
 
-  if (Op1Def->getOpcode() != TargetOpcode::G_FCONSTANT && 
+  if (Op1Def->getOpcode() != TargetOpcode::G_FCONSTANT &&
       Op2Def->getOpcode() != TargetOpcode::G_FCONSTANT)
     return false;
 
-  MachineInstr *constantMachineInstruction = 
+  MachineInstr *constantMachineInstruction =
       (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op1Def : Op2Def;
   MachineOperand &ConstantOperand = constantMachineInstruction->getOperand(1);
 
@@ -422,9 +422,9 @@ void SPIRVCombinerHelper::applyDegrees(MachineInstr &MI) const {
   Register Op2 = MI.getOperand(2).getReg();
   MachineInstr *Op1Def = MRI.getVRegDef(Op1);
   MachineInstr *Op2Def = MRI.getVRegDef(Op2);
-  Register nonConstantReg = 
+  Register nonConstantReg =
       (Op1Def->getOpcode() == TargetOpcode::G_FCONSTANT) ? Op2 : Op1;
-  
+
   Builder.setInstrAndDebugLoc(MI);
   Builder.buildIntrinsic(Intrinsic::spv_degrees, ResultReg)
       .addUse(nonConstantReg);

>From 711e56136b3cc45cd2ce207d6aa45184ab6ed576 Mon Sep 17 00:00:00 2001
From: albertbolt <albertboltinfinity at gmail.com>
Date: Sun, 16 Aug 2026 09:49:51 +0530
Subject: [PATCH 4/5] using llvm pi instead of acos

---
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
index 49bd2bb1f0901..4a03a87c312ac 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
@@ -406,7 +406,8 @@ bool SPIRVCombinerHelper::matchDegrees(MachineInstr &MI) const {
 
   const ConstantFP *Constant = ConstantOperand.getFPImm();
   const APFloat &Val = Constant->getValueAPF();
-  APFloat Expected(180.0 / std::acos(-1.0));
+
+  APFloat Expected(180.0 / llvm::numbers::pi);
   bool LostInfo = false;
   Expected.convert(Val.getSemantics(), APFloat::rmNearestTiesToEven, &LostInfo);
 

>From 5c8a18eb6afd81658781e5bb9863879b968f8f2d Mon Sep 17 00:00:00 2001
From: albertbolt <albertboltinfinity at gmail.com>
Date: Sun, 16 Aug 2026 23:23:58 +0530
Subject: [PATCH 5/5] removed unused variable

---
 llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
index 4a03a87c312ac..f15a3aa63f8ad 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCombinerHelper.cpp
@@ -422,7 +422,6 @@ void SPIRVCombinerHelper::applyDegrees(MachineInstr &MI) const {
   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;
 



More information about the llvm-commits mailing list