https://gcc.gnu.org/g:439f966973a77f97f6c015cde6a9507e3be9f620
commit r17-389-g439f966973a77f97f6c015cde6a9507e3be9f620 Author: Richard Sandiford <[email protected]> Date: Thu May 7 21:18:03 2026 +0100 combine: Tweak make_compound_operation PLUS/MINUS cases This patch tackles two problems with the make_compound_operation(_int) handling of PLUS: (a) The PLUS case had some simplifications related to multiplications of negative numbers. Those simplifications assigned the simplified form to the variable "new_rtx", but the rest of the case ignored new_rtx and returned the original expression "x". This had the effect of discarding both the simplification result and the recursive make_compound_operation results. (b) The PLUS case applied maybe_swap_commutative_operands after substituting the recursive make_compound_operation results. That's good enough for unchained PLUSes. However, if the expression is a nest of PLUSes, we might need to redistribute operands in the entire nest. For example, expand_compound_operation converts sign and zero extensions to shifts. The extensions have commutative operand priority 0, whereas the shifts have priority 2. This means that: (plus (plus (not X) (zero_extend Y)) (zero_extend Z)) is correctly ordered, since PLUS has priority 4, NOT has priority 1, and ZERO_EXTEND has priority 0. But when expand_compound_operation converts the extends to shifts, the NOT becomes the lowest priority operand, giving: (plus (plus (lshiftrt ...) (lshiftrt ...)) (not X)) Currently, make_compound_operation would convert that back to: (plus (plus (zero_extend Y) (zero_extend Z)) (not X)) since, considered in isolation, neither PLUS needs a swap. This result is not canonical, since the NOT should be first. Both problems can be dealt with by using simplify_gen_binary instead. That already has the simplifications for (a) and knows how to redistribute operands in nested operations. Although the MINUS case seemed to be ok, the simplifications there also duplicate what simplify_gen_binary would do. This is likely to be needed for Muhammad's uaddc/usubc patches. gcc/ * combine.cc (make_compound_operation_int): Remove PLUS and MINUS simplifications and PLUS operand order swapping. Delegate those tasks to simplify_gen_binary instead. Diff: --- gcc/combine.cc | 57 +++++---------------------------------------------------- 1 file changed, 5 insertions(+), 52 deletions(-) diff --git a/gcc/combine.cc b/gcc/combine.cc index e0dab3d88280..d401ca10083b 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -8118,59 +8118,12 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr, break; case PLUS: - lhs = XEXP (x, 0); - rhs = XEXP (x, 1); - lhs = make_compound_operation (lhs, next_code); - rhs = make_compound_operation (rhs, next_code); - if (GET_CODE (lhs) == MULT && GET_CODE (XEXP (lhs, 0)) == NEG) - { - tem = simplify_gen_binary (MULT, mode, XEXP (XEXP (lhs, 0), 0), - XEXP (lhs, 1)); - new_rtx = simplify_gen_binary (MINUS, mode, rhs, tem); - } - else if (GET_CODE (lhs) == MULT - && (CONST_INT_P (XEXP (lhs, 1)) && INTVAL (XEXP (lhs, 1)) < 0)) - { - tem = simplify_gen_binary (MULT, mode, XEXP (lhs, 0), - simplify_gen_unary (NEG, mode, - XEXP (lhs, 1), - mode)); - new_rtx = simplify_gen_binary (MINUS, mode, rhs, tem); - } - else - { - SUBST (XEXP (x, 0), lhs); - SUBST (XEXP (x, 1), rhs); - } - maybe_swap_commutative_operands (x); - return x; - case MINUS: - lhs = XEXP (x, 0); - rhs = XEXP (x, 1); - lhs = make_compound_operation (lhs, next_code); - rhs = make_compound_operation (rhs, next_code); - if (GET_CODE (rhs) == MULT && GET_CODE (XEXP (rhs, 0)) == NEG) - { - tem = simplify_gen_binary (MULT, mode, XEXP (XEXP (rhs, 0), 0), - XEXP (rhs, 1)); - return simplify_gen_binary (PLUS, mode, tem, lhs); - } - else if (GET_CODE (rhs) == MULT - && (CONST_INT_P (XEXP (rhs, 1)) && INTVAL (XEXP (rhs, 1)) < 0)) - { - tem = simplify_gen_binary (MULT, mode, XEXP (rhs, 0), - simplify_gen_unary (NEG, mode, - XEXP (rhs, 1), - mode)); - return simplify_gen_binary (PLUS, mode, tem, lhs); - } - else - { - SUBST (XEXP (x, 0), lhs); - SUBST (XEXP (x, 1), rhs); - return x; - } + lhs = make_compound_operation (XEXP (x, 0), next_code); + rhs = make_compound_operation (XEXP (x, 1), next_code); + if (lhs != XEXP (x, 0) || rhs != XEXP (x, 1)) + return simplify_gen_binary (code, mode, lhs, rhs); + return x; case AND: /* If the second operand is not a constant, we can't do anything
