https://gcc.gnu.org/g:178835acba38205ffec57ce01af1b26e440f06b3
commit r17-4494-g178835acba38205ffec57ce01af1b26e440f06b3 Author: Konstantinos Eleftheriou <[email protected]> Date: Tue Aug 25 16:28:15 2026 +0200 widening_mul: Factor the long-mul operand split into a helper build_long_mul_partials handled the two operands with duplicated inline code. Move the per-operand half split into build_long_mul_partial_operand. No functional change. Only the order in which the two operands' halves are emitted differs. gcc/ChangeLog: * tree-ssa-math-opts.cc (build_long_mul_partial_operand): New function. (build_long_mul_partials): Use it. Diff: --- gcc/tree-ssa-math-opts.cc | 85 ++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 450116add1d3..df418435d0be 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -6571,6 +6571,41 @@ can_widen_to_narrow_p (scalar_int_mode narrow_mode, unsigned int half_width, static bool long_mul_op_fits_p (tree, unsigned, bitmap); +/* Build into *SEQ the (N/2)-bit halves *LO and *HI of OP, in the form + USE_WIDEN selects. An operand provably within N/2 bits has a zero + high half: *HI is left null. */ + +static void +build_long_mul_partial_operand (gimple_seq *seq, location_t loc, tree op, + tree half_type, tree half_amt, bool use_widen, + tree *lo, tree *hi) +{ + tree acc_type = TREE_TYPE (op); + unsigned int half_prec = TYPE_PRECISION (half_type); + auto_bitmap phi_seen; + bool fits = long_mul_op_fits_p (op, half_prec, phi_seen); + + *hi = NULL_TREE; + if (!fits) + *hi = gimple_build (seq, loc, RSHIFT_EXPR, acc_type, op, half_amt); + + if (use_widen) + { + *lo = gimple_build (seq, loc, NOP_EXPR, half_type, op); + if (*hi) + *hi = gimple_build (seq, loc, NOP_EXPR, half_type, *hi); + } + else if (fits) + *lo = op; + else + { + tree mask = wide_int_to_tree (acc_type, + wi::mask (half_prec, false, + TYPE_PRECISION (acc_type))); + *lo = gimple_build (seq, loc, BIT_AND_EXPR, acc_type, op, mask); + } +} + /* Append to *SEQ the operand split and partial products for an unsigned long multiply of OP1 by OP2 at the precision of TREE_TYPE (OP1). HALF_TYPE is the (N/2)-bit unsigned type; HALF_AMT is the integer-typed @@ -6594,48 +6629,22 @@ build_long_mul_partials (gimple_seq *seq, location_t loc, tree op1, tree op2, bool use_widen) { tree acc_type = TREE_TYPE (op1); - unsigned int half_prec = TYPE_PRECISION (half_type); - auto_bitmap phi_seen1, phi_seen2; - bool op1_fits = long_mul_op_fits_p (op1, half_prec, phi_seen1); - bool op2_fits = long_mul_op_fits_p (op2, half_prec, phi_seen2); tree zero = build_zero_cst (acc_type); - tree op1_hi = NULL_TREE, op2_hi = NULL_TREE; - if (!op1_fits) - op1_hi = gimple_build (seq, loc, RSHIFT_EXPR, acc_type, op1, half_amt); - if (!op2_fits) - op2_hi = gimple_build (seq, loc, RSHIFT_EXPR, acc_type, op2, half_amt); - tree op1_lo, op2_lo; - tree_code mul_code; + tree_code mul_code = use_widen ? WIDEN_MULT_EXPR : MULT_EXPR; + tree op1_lo, op1_hi, op2_lo, op2_hi; - if (use_widen) - { - op1_lo = gimple_build (seq, loc, NOP_EXPR, half_type, op1); - op2_lo = gimple_build (seq, loc, NOP_EXPR, half_type, op2); - if (op1_hi) - op1_hi = gimple_build (seq, loc, NOP_EXPR, half_type, op1_hi); - if (op2_hi) - op2_hi = gimple_build (seq, loc, NOP_EXPR, half_type, op2_hi); - mul_code = WIDEN_MULT_EXPR; - } - else - { - tree mask = wide_int_to_tree (acc_type, - wi::mask (half_prec, false, - TYPE_PRECISION (acc_type))); - op1_lo = op1_fits ? op1 - : gimple_build (seq, loc, BIT_AND_EXPR, acc_type, op1, mask); - op2_lo = op2_fits ? op2 - : gimple_build (seq, loc, BIT_AND_EXPR, acc_type, op2, mask); - mul_code = MULT_EXPR; - } + build_long_mul_partial_operand (seq, loc, op1, half_type, half_amt, use_widen, + &op1_lo, &op1_hi); + build_long_mul_partial_operand (seq, loc, op2, half_type, half_amt, use_widen, + &op2_lo, &op2_hi); *lolo = gimple_build (seq, loc, mul_code, acc_type, op1_lo, op2_lo); - *hilo = op1_fits ? zero - : gimple_build (seq, loc, mul_code, acc_type, op1_hi, op2_lo); - *lohi = op2_fits ? zero - : gimple_build (seq, loc, mul_code, acc_type, op1_lo, op2_hi); - *hihi = op1_fits || op2_fits ? zero - : gimple_build (seq, loc, mul_code, acc_type, op1_hi, op2_hi); + *hilo = op1_hi + ? gimple_build (seq, loc, mul_code, acc_type, op1_hi, op2_lo) : zero; + *lohi = op2_hi + ? gimple_build (seq, loc, mul_code, acc_type, op1_lo, op2_hi) : zero; + *hihi = op1_hi && op2_hi + ? gimple_build (seq, loc, mul_code, acc_type, op1_hi, op2_hi) : zero; } /* Emit into *SEQ the high N bits of the unsigned product A * B, where A and B
