Jeff Law <jeffreya...@gmail.com> writes: > On 12/30/24 3:02 PM, Richard Sandiford wrote: > >> >> So it seems like it's a bit of a mess :( >> >> If we do try to fix combine, I think something like the attached >> would fit within the current scheme. It is a pure shift-for-shift >> transformation, avoiding any extensions. >> >> Will think more about it, but wanted to get the above stream of >> consciousness out before I finish for the day :) > So your approach in simplify-rtx ended up much cleaner than mine; unless > there's some objection from you, I'd like to go with it. Obviously I'll > run it through the usual testing cycles first ;-)
Yeah, that's fine with me. Reading it back, I realised that we should probably also check for an in-range shift value, fixed below. Richard diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index dda8fc689e7..c478bd060fc 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -4494,6 +4494,60 @@ simplify_context::simplify_binary_operation_1 (rtx_code code, return simplify_gen_binary (code, mode, op0, gen_int_shift_amount (mode, val)); } + + /* Simplify: + + (code:M1 + (subreg:M1 + ([al]shiftrt:M2 + (subreg:M2 + (ashift:M1 X C1)) + C2)) + C3) + + to: + + (code:M1 + ([al]shiftrt:M1 + (ashift:M1 X C1+N) + C2+N) + C3) + + where M1 is N bits wider than M2. Optimizing the (subreg:M1 ...) + directly would be arithmetically correct, but restricting the + simplification to shifts by constants is more conservative, + since it is more likely to lead to further simplifications. */ + if (is_a<scalar_int_mode> (mode, &int_mode) + && paradoxical_subreg_p (op0) + && is_a<scalar_int_mode> (GET_MODE (SUBREG_REG (op0)), &inner_mode) + && (GET_CODE (SUBREG_REG (op0)) == ASHIFTRT + || GET_CODE (SUBREG_REG (op0)) == LSHIFTRT) + && CONST_INT_P (op1)) + { + auto xcode = GET_CODE (SUBREG_REG (op0)); + rtx xop0 = XEXP (SUBREG_REG (op0), 0); + rtx xop1 = XEXP (SUBREG_REG (op0), 1); + if (SUBREG_P (xop0) + && GET_MODE (SUBREG_REG (xop0)) == mode + && GET_CODE (SUBREG_REG (xop0)) == ASHIFT + && CONST_INT_P (xop1) + && UINTVAL (xop1) < GET_MODE_PRECISION (inner_mode)) + { + rtx yop0 = XEXP (SUBREG_REG (xop0), 0); + rtx yop1 = XEXP (SUBREG_REG (xop0), 1); + if (CONST_INT_P (yop1) + && UINTVAL (yop1) < GET_MODE_PRECISION (inner_mode)) + { + auto bias = (GET_MODE_BITSIZE (int_mode) + - GET_MODE_BITSIZE (inner_mode)); + tem = simplify_gen_binary (ASHIFT, mode, yop0, + GEN_INT (INTVAL (yop1) + bias)); + tem = simplify_gen_binary (xcode, mode, tem, + GEN_INT (INTVAL (xop1) + bias)); + return simplify_gen_binary (code, mode, tem, op1); + } + } + } break; case SS_ASHIFT: -- 2.25.1