https://gcc.gnu.org/g:a947f841925f5e65c4c47711c995ae4094a20ea4
commit r17-5188-ga947f841925f5e65c4c47711c995ae4094a20ea4 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. 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 51a04ff89f7d..4abf2b7baae6 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1932,18 +1932,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" @@ -2905,7 +2914,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")))] "" @@ -2938,7 +2947,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 "" ""))] @@ -2972,7 +2981,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 "" ""))] @@ -3680,7 +3689,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")))] "" @@ -3700,7 +3709,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 "" ""))] @@ -3719,7 +3728,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 "" ""))] @@ -4501,7 +4510,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"))))] "" @@ -4520,9 +4529,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);
