[llvm] [GISel] Extend ConstantFoldFPBinOp with fminimumnum, fmaximumnum, fix frem vs fmod (PR #190561)

Tim Gymnich via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 5 16:36:07 PDT 2026


https://github.com/tgymnich created https://github.com/llvm/llvm-project/pull/190561

- Distinguish G_FREM (IEEE remainder) from G_FMODF (fmod), using APFloat::remainder() and APFloat::mod() respectively.
- Add constant folding for G_FMINIMUMNUM and G_FMAXIMUMNUM using the minimumnum/maximumnum APFloat helpers.
- Update AArch64 select_const.ll test to reflect that GISel now folds both frem operands, replacing fmov+fcsel with two constant loads.

>From f2655c6c03fe0c400a8f226750559ce64512f326 Mon Sep 17 00:00:00 2001
From: Tim Gymnich <tim at gymni.ch>
Date: Mon, 6 Apr 2026 01:22:32 +0200
Subject: [PATCH] [GISel] Extend ConstantFoldFPBinOp with fminimumnum,
 fmaximumnum, and fix frem vs fmod

- Distinguish G_FREM (IEEE remainder) from G_FMODF (fmod), using
  APFloat::remainder() and APFloat::mod() respectively.
- Add constant folding for G_FMINIMUMNUM and G_FMAXIMUMNUM using the
  minimumnum/maximumnum APFloat helpers.
- Update AArch64 select_const.ll test to reflect that GISel now folds
  both frem operands, replacing fmov+fcsel with two constant loads.
---
 llvm/lib/CodeGen/GlobalISel/Utils.cpp     | 7 +++++++
 llvm/test/CodeGen/AArch64/select_const.ll | 9 +++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index d019633369163..4ebab8b3da2e2 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -763,6 +763,9 @@ llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
     C1.divide(C2, APFloat::rmNearestTiesToEven);
     return C1;
   case TargetOpcode::G_FREM:
+    C1.remainder(C2);
+    return C1;
+  case TargetOpcode::G_FMODF:
     C1.mod(C2);
     return C1;
   case TargetOpcode::G_FCOPYSIGN:
@@ -776,6 +779,10 @@ llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
     return minimum(C1, C2);
   case TargetOpcode::G_FMAXIMUM:
     return maximum(C1, C2);
+  case TargetOpcode::G_FMINIMUMNUM:
+    return minimumnum(C1, C2);
+  case TargetOpcode::G_FMAXIMUMNUM:
+    return maximumnum(C1, C2);
   case TargetOpcode::G_FMINNUM_IEEE:
   case TargetOpcode::G_FMAXNUM_IEEE:
     // FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
diff --git a/llvm/test/CodeGen/AArch64/select_const.ll b/llvm/test/CodeGen/AArch64/select_const.ll
index 0a73aed803415..48616d6af96d2 100644
--- a/llvm/test/CodeGen/AArch64/select_const.ll
+++ b/llvm/test/CodeGen/AArch64/select_const.ll
@@ -933,12 +933,13 @@ define double @sel_constants_frem_constant(i1 %cond) {
 ;
 ; CHECK-GI-LABEL: sel_constants_frem_constant:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    adrp x8, .LCPI48_0
-; CHECK-GI-NEXT:    fmov d0, #-4.00000000
-; CHECK-GI-NEXT:    ldr d1, [x8, :lo12:.LCPI48_0]
+; CHECK-GI-NEXT:    adrp x8, .LCPI48_1
+; CHECK-GI-NEXT:    adrp x9, .LCPI48_0
+; CHECK-GI-NEXT:    ldr d0, [x8, :lo12:.LCPI48_1]
+; CHECK-GI-NEXT:    ldr d1, [x9, :lo12:.LCPI48_0]
 ; CHECK-GI-NEXT:    and w8, w0, #0x1
 ; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    fcsel d0, d0, d1, ne
+; CHECK-GI-NEXT:    fcsel d0, d1, d0, ne
 ; CHECK-GI-NEXT:    ret
   %sel = select i1 %cond, double -4.0, double 23.3
   %bo = frem double %sel, 5.1



More information about the llvm-commits mailing list