https://gcc.gnu.org/g:04d9b422a9dbf55726d2f6c4a7c877663bf53089
commit r16-9789-g04d9b422a9dbf55726d2f6c4a7c877663bf53089 Author: Richard Earnshaw <[email protected]> Date: Mon Oct 5 17:00:08 2026 +0100 aarch64: Fix more cases of gen_highpart on subregs [PR127393] Following on from the fix in r17-4565, there were reports of more cases where we could get ICEs during expansion of TImode patterns when subregs were in use. I've now gone through the machine description file and hopefully identified the remaining cases where this could be a problem. gcc/ChangeLog: PR target/127393 * config/aarch64/aarch64.md (movti): Ensure we don't call gen_highpart on a subreg. (addti3): Use pure_register_operand for the destination. (addvti4): Likewise. (uaddvti4): Likewise. (subti3): Likewise. (subvti4): Likewise. (usubti4): Likewise. (<su_optab>mulditi3): Likewise. (multi3): Require pure_register_operand for all operands. (cherry picked from commit a947f841925f5e65c4c47711c995ae4094a20ea4) Diff: --- gcc/config/aarch64/aarch64.md | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 9510025aef29..ef998fa4ef95 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1934,18 +1934,27 @@ [(set (match_operand:TI 0 "nonimmediate_operand") (match_operand:TI 1 "general_operand"))] "" - " + { if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx) operands[1] = force_reg (TImode, operands[1]); if (GET_CODE (operands[1]) == CONST_POLY_INT) { - emit_move_insn (gen_lowpart (DImode, operands[0]), + rtx op0 = operands[0]; + /* It's not generally safe to use gen_highpart on a SUBREG, so + write the initial result to a temporary. The optimizer will + simplify things later. */ + if (SUBREG_P (op0)) + op0 = gen_reg_rtx (TImode); + + emit_move_insn (gen_lowpart (DImode, op0), gen_lowpart (DImode, operands[1])); - emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx); + emit_move_insn (gen_highpart (DImode, op0), const0_rtx); + if (op0 != operands[0]) + emit_move_insn (operands[0], op0); DONE; } - " + } ) (define_insn "*movti_aarch64" @@ -2907,7 +2916,7 @@ }) (define_expand "addti3" - [(set (match_operand:TI 0 "register_operand") + [(set (match_operand:TI 0 "pure_register_operand") (plus:TI (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm")))] "" @@ -2940,7 +2949,7 @@ }) (define_expand "addvti4" - [(match_operand:TI 0 "register_operand") + [(match_operand:TI 0 "pure_register_operand") (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] @@ -2974,7 +2983,7 @@ }) (define_expand "uaddvti4" - [(match_operand:TI 0 "register_operand") + [(match_operand:TI 0 "pure_register_operand") (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] @@ -3682,7 +3691,7 @@ }) (define_expand "subti3" - [(set (match_operand:TI 0 "register_operand") + [(set (match_operand:TI 0 "pure_register_operand") (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero") (match_operand:TI 2 "register_operand")))] "" @@ -3702,7 +3711,7 @@ }) (define_expand "subvti4" - [(match_operand:TI 0 "register_operand") + [(match_operand:TI 0 "pure_register_operand") (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] @@ -3721,7 +3730,7 @@ }) (define_expand "usubvti4" - [(match_operand:TI 0 "register_operand") + [(match_operand:TI 0 "pure_register_operand") (match_operand:TI 1 "register_operand") (match_operand:TI 2 "aarch64_reg_or_imm") (label_ref (match_operand 3 "" ""))] @@ -4503,7 +4512,7 @@ ) (define_expand "<su_optab>mulditi3" - [(set (match_operand:TI 0 "register_operand") + [(set (match_operand:TI 0 "pure_register_operand") (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand")) (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))] "" @@ -4522,9 +4531,9 @@ ;; The default expansion of multi3 using umuldi3_highpart will perform ;; the additions in an order that fails to combine into two madd insns. (define_expand "multi3" - [(set (match_operand:TI 0 "register_operand") - (mult:TI (match_operand:TI 1 "register_operand") - (match_operand:TI 2 "register_operand")))] + [(set (match_operand:TI 0 "pure_register_operand") + (mult:TI (match_operand:TI 1 "pure_register_operand") + (match_operand:TI 2 "pure_register_operand")))] "" { rtx l0 = gen_reg_rtx (DImode);
