[llvm] [GlobalIsel] Enabling more rules for fp constant folding (PR #177902)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 25 22:46:50 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Julian Pokrovsky (raventid)

<details>
<summary>Changes</summary>

This PR extends GlobalISel to enable additional compile time constant foldings

Resolves https://github.com/llvm/llvm-project/issues/86406

---
Full diff: https://github.com/llvm/llvm-project/pull/177902.diff


3 Files Affected:

- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+14) 
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+20) 
- (added) llvm/test/CodeGen/AArch64/GlobalISel/combine-constant-fold-fp-rounding.mir (+167) 


``````````diff
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index a9b4932b2e317..dae5809a4e052 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -689,6 +689,13 @@ def constant_fold_fsqrt : constant_fold_unary_fp_op_rule<G_FSQRT>;
 def constant_fold_flog2 : constant_fold_unary_fp_op_rule<G_FLOG2>;
 def constant_fold_fptrunc : constant_fold_unary_fp_op_rule<G_FPTRUNC>;
 def constant_fold_fpext : constant_fold_unary_fp_op_rule<G_FPEXT>;
+def constant_fold_fceil : constant_fold_unary_fp_op_rule<G_FCEIL>;
+def constant_fold_ffloor : constant_fold_unary_fp_op_rule<G_FFLOOR>;
+def constant_fold_intrinsic_trunc : constant_fold_unary_fp_op_rule<G_INTRINSIC_TRUNC>;
+def constant_fold_intrinsic_round : constant_fold_unary_fp_op_rule<G_INTRINSIC_ROUND>;
+def constant_fold_intrinsic_roundeven : constant_fold_unary_fp_op_rule<G_INTRINSIC_ROUNDEVEN>;
+def constant_fold_frint : constant_fold_unary_fp_op_rule<G_FRINT>;
+def constant_fold_fnearbyint : constant_fold_unary_fp_op_rule<G_FNEARBYINT>;
 
 // Fold constant zero int to fp conversions.
 class itof_const_zero_fold_rule<Instruction opcode> : GICombineRule <
@@ -708,6 +715,13 @@ def constant_fold_fp_ops : GICombineGroup<[
   constant_fold_flog2,
   constant_fold_fptrunc,
   constant_fold_fpext,
+  constant_fold_fceil,
+  constant_fold_ffloor,
+  constant_fold_intrinsic_trunc,
+  constant_fold_intrinsic_round,
+  constant_fold_intrinsic_roundeven,
+  constant_fold_frint,
+  constant_fold_fnearbyint,
   itof_const_zero_fold_si,
   itof_const_zero_fold_ui
 ]>;
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 85d5f06b9813d..08696f08284b1 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1681,6 +1681,26 @@ static APFloat constantFoldFpUnary(const MachineInstr &MI,
     Result.clearSign();
     return Result;
   }
+  case TargetOpcode::G_FCEIL:
+    Result.roundToIntegral(APFloat::rmTowardPositive);
+    return Result;
+  case TargetOpcode::G_FFLOOR:
+    Result.roundToIntegral(APFloat::rmTowardNegative);
+    return Result;
+  case TargetOpcode::G_INTRINSIC_TRUNC:
+    Result.roundToIntegral(APFloat::rmTowardZero);
+    return Result;
+  case TargetOpcode::G_INTRINSIC_ROUND:
+    Result.roundToIntegral(APFloat::rmNearestTiesToAway);
+    return Result;
+  case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
+    Result.roundToIntegral(APFloat::rmNearestTiesToEven);
+    return Result;
+  case TargetOpcode::G_FRINT:
+  case TargetOpcode::G_FNEARBYINT:
+    // Use default rounding mode (round to nearest, ties to even)
+    Result.roundToIntegral(APFloat::rmNearestTiesToEven);
+    return Result;
   case TargetOpcode::G_FPEXT:
   case TargetOpcode::G_FPTRUNC: {
     bool Unused;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-constant-fold-fp-rounding.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-constant-fold-fp-rounding.mir
new file mode 100644
index 0000000000000..a4a53448e8637
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-constant-fold-fp-rounding.mir
@@ -0,0 +1,167 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            fceil
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: fceil
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 3.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_FCEIL %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            fceil_negative
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: fceil_negative
+    ; CHECK: %res:_(s64) = G_FCONSTANT double -2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double -2.5
+    %res:_(s64) = G_FCEIL %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            ffloor
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: ffloor
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_FFLOOR %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            ffloor_negative
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: ffloor_negative
+    ; CHECK: %res:_(s64) = G_FCONSTANT double -3.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double -2.5
+    %res:_(s64) = G_FFLOOR %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            intrinsic_trunc
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: intrinsic_trunc
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.7
+    %res:_(s64) = G_INTRINSIC_TRUNC %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            intrinsic_trunc_negative
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: intrinsic_trunc_negative
+    ; CHECK: %res:_(s64) = G_FCONSTANT double -2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double -2.7
+    %res:_(s64) = G_INTRINSIC_TRUNC %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            intrinsic_round
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: intrinsic_round
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 3.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_INTRINSIC_ROUND %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            intrinsic_roundeven
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: intrinsic_roundeven
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_INTRINSIC_ROUNDEVEN %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            intrinsic_roundeven_odd
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: intrinsic_roundeven_odd
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 4.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 3.5
+    %res:_(s64) = G_INTRINSIC_ROUNDEVEN %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            frint
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: frint
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_FRINT %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...
+
+---
+name:            fnearbyint
+body:             |
+  bb.1.entry:
+    ; CHECK-LABEL: name: fnearbyint
+    ; CHECK: %res:_(s64) = G_FCONSTANT double 2.000000e+00
+    ; CHECK-NEXT: $d0 = COPY %res(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $d0
+    %a:_(s64) = G_FCONSTANT double 2.5
+    %res:_(s64) = G_FNEARBYINT %a
+    $d0 = COPY %res(s64)
+    RET_ReallyLR implicit $d0
+
+...

``````````

</details>


https://github.com/llvm/llvm-project/pull/177902


More information about the llvm-commits mailing list