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" } } */
