[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