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);

Reply via email to