https://gcc.gnu.org/g:4bcb92dcb23daa446bb930179a7e7a16b920720f

commit r17-1585-g4bcb92dcb23daa446bb930179a7e7a16b920720f
Author: Richard Biener <[email protected]>
Date:   Mon Jun 15 11:29:08 2026 +0200

    Improve fold_plusminus_mult_expr for 64bit and larger types
    
    The following enhances fold_plusminus_mult_expr to catch
    a * -4U + b * 4 and factor it as (a * -1u + b) * 4.  This
    does not work currently because we're using HOST_WIDE_INT
    arithmetic.  Switch that to wide_int, which makes the
    folding apply more consistently.
    
    For gcc.dg/loop-versioning-13.c the heuristics in
    gimple-loop-versioning.cc get confused as they fail to
    truncate some computations.  I did not inverstigate further.
    
            * fold-const.cc (fold_plusminus_mult_expr): Use
            wide_int for the case of two INTEGER_CST multiplicands.
    
            * gcc.dg/loop-versioning-13.c: XFAIL one transfor for ilp32.
            * gcc.dg/pr109393.c: Remove XFAIL for ilp32.

Diff:
---
 gcc/fold-const.cc                         | 27 ++++++++++++++-------------
 gcc/testsuite/gcc.dg/loop-versioning-13.c |  8 ++++++--
 gcc/testsuite/gcc.dg/pr109393.c           |  3 +--
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 7f49126c95ab..11d1129f1253 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -7275,28 +7275,28 @@ fold_plusminus_mult_expr (location_t loc, enum 
tree_code code, tree type,
   /* No identical multiplicands; see if we can find a common
      power-of-two factor in non-power-of-two multiplies.  This
      can help in multi-dimensional array access.  */
-  else if (tree_fits_shwi_p (arg01) && tree_fits_shwi_p (arg11))
+  else if (TREE_CODE (arg01) == INTEGER_CST
+          && TREE_CODE (arg11) == INTEGER_CST)
     {
-      HOST_WIDE_INT int01 = tree_to_shwi (arg01);
-      HOST_WIDE_INT int11 = tree_to_shwi (arg11);
-      HOST_WIDE_INT tmp;
+      wide_int int01 = wi::to_wide (arg01);
+      wide_int int11 = wi::to_wide (arg11);
       bool swap = false;
       tree maybe_same;
 
       /* Move min of absolute values to int11.  */
-      if (absu_hwi (int01) < absu_hwi (int11))
+      if (wi::ltu_p (wi::abs (int01), wi::abs (int11)))
         {
-         tmp = int01, int01 = int11, int11 = tmp;
-         alt0 = arg00, arg00 = arg10, arg10 = alt0;
+         std::swap (int01, int11);
+         std::swap (arg00, arg10);
          maybe_same = arg01;
          swap = true;
        }
       else
        maybe_same = arg11;
 
-      const unsigned HOST_WIDE_INT factor = absu_hwi (int11);
-      if (factor > 1
-         && pow2p_hwi (factor)
+      wide_int factor = wi::abs (int11);
+      if (wi::gtu_p (factor, 1u)
+         && wi::exact_log2 (factor) != -1
          && (int01 & (factor - 1)) == 0
          /* The remainder should not be a constant, otherwise we
             end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
@@ -7304,12 +7304,13 @@ fold_plusminus_mult_expr (location_t loc, enum 
tree_code code, tree type,
          && TREE_CODE (arg10) != INTEGER_CST)
         {
          alt0 = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg00), arg00,
-                             build_int_cst (TREE_TYPE (arg00),
-                                            int01 / int11));
+                                 wide_int_to_tree (TREE_TYPE (arg00),
+                                                   wi::sdiv_trunc (int01,
+                                                                   int11)));
          alt1 = arg10;
          same = maybe_same;
          if (swap)
-           maybe_same = alt0, alt0 = alt1, alt1 = maybe_same;
+           std::swap (alt0, alt1);
        }
     }
 
diff --git a/gcc/testsuite/gcc.dg/loop-versioning-13.c 
b/gcc/testsuite/gcc.dg/loop-versioning-13.c
index c67da047fa6c..12c658aabe18 100644
--- a/gcc/testsuite/gcc.dg/loop-versioning-13.c
+++ b/gcc/testsuite/gcc.dg/loop-versioning-13.c
@@ -105,5 +105,9 @@ g5 (int stepx, int n)
     }
 }
 
-/* { dg-final { scan-tree-dump-times {want to version containing loop} 10 
"lversion" } } */
-/* { dg-final { scan-tree-dump-times {versioned this loop} 10 "lversion" } } */
+/* { dg-final { scan-tree-dump-times {want to version containing loop} 10 
"lversion" { target lp64 } } } */
+/* { dg-final { scan-tree-dump-times {want to version containing loop} 10 
"lversion" { xfail { ilp32 } } } } */
+/* { dg-final { scan-tree-dump-times {want to version containing loop} 9 
"lversion" { target ilp32 } } } */
+/* { dg-final { scan-tree-dump-times {versioned this loop} 10 "lversion" { 
target lp64 } } } */
+/* { dg-final { scan-tree-dump-times {versioned this loop} 10 "lversion" { 
xfail ilp32 } } } */
+/* { dg-final { scan-tree-dump-times {versioned this loop} 9 "lversion" { 
target ilp32 } } } */
diff --git a/gcc/testsuite/gcc.dg/pr109393.c b/gcc/testsuite/gcc.dg/pr109393.c
index 108d30913894..b2dd5a0b645c 100644
--- a/gcc/testsuite/gcc.dg/pr109393.c
+++ b/gcc/testsuite/gcc.dg/pr109393.c
@@ -20,5 +20,4 @@ int bar(int *a, int j)
   return (&a[j + 1] - 2) == &a[k];
 }
 
-/* The pattern is not applied on ilp32 targets (PR116845).  */
-/* { dg-final { scan-tree-dump-times "return 1;" 3 "optimized" { xfail { ilp32 
} } } } */
+/* { dg-final { scan-tree-dump-times "return 1;" 3 "optimized" } } */

Reply via email to