https://gcc.gnu.org/g:8ef8f0714336e02565dc9c4981afe2f987669fdb

commit r15-11327-g8ef8f0714336e02565dc9c4981afe2f987669fdb
Author: Jakub Jelinek <[email protected]>
Date:   Mon Jun 29 13:06:06 2026 +0200

    i386: Fix up *add<mode>_1<nf_name> [PR125469]
    
    I've debugged this now on the 16 branch where my patch is not present.
    The
    (define_split
      [(set (match_operand:SWI 0 "register_operand")
            (plus:SWI (match_operand:SWI 1 "register_operand")
                      (match_operand:SWI 2 "<nonmemory_operand>")))]
      "TARGET_APX_NF && reload_completed
       && ix86_lea_for_add_ok (insn, operands)"
      [(set (match_dup 0)
            (plus:<LEAMODE> (match_dup 1) (match_dup 2)))]
    {
      if (<MODE>mode != <LEAMODE>mode)
        {
          operands[0] = gen_lowpart (<LEAMODE>mode, operands[0]);
          operands[1] = gen_lowpart (<LEAMODE>mode, operands[1]);
          operands[2] = gen_lowpart (<LEAMODE>mode, operands[2]);
        }
    })
    splitter there is matched, including ix86_lea_for_add_ok on
    (insn 12 10 13 2 (set (reg:DI 2 cx [108])
            (plus:DI (reg:DI 0 ax [orig:104 s ] [104])
                (reg:DI 5 di [ _2+8 ]))) "apx-nf-pr125469.c":10:5 288 
{*adddi_1_nf}
         (nil))
    But then goes into:
     rtx_insn *
     gen_split_138 (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands)
     {
       if (dump_file)
         fprintf (dump_file, "Splitting with gen_split_138 (i386.md:7136)\n");
       start_sequence ();
     #define FAIL return (end_sequence (), nullptr)
     #define DONE return end_sequence ()
     #line 7144 "../../gcc/config/i386/i386.md"
     {
       if (DImode != DImode)
         {
           operands[0] = gen_lowpart (DImode, operands[0]);
           operands[1] = gen_lowpart (DImode, operands[1]);
           operands[2] = gen_lowpart (DImode, operands[2]);
         }
     }
     #undef DONE
     #undef FAIL
       static const uint8_t expand_encoding[] = {
          0x01, 0x1f, 0x01, 0x00, 0x3b, 0x12, 0x01, 0x01,
          0x01, 0x02
       };
       return complete_seq (expand_encoding, operands);
     }
    That returns
    (insn 37 0 0 (set (reg:DI 2 cx [108])
            (plus:DI (reg:DI 0 ax [orig:104 s ] [104])
                (reg:DI 5 di [ _2+8 ]))) -1
         (nil))
    But then in try_split we have:
       /* Avoid infinite loop if any insn of the result matches
          the original pattern.  */
       insn_last = seq;
       while (1)
         {
           if (INSN_P (insn_last)
               && rtx_equal_p (PATTERN (insn_last), pat))
             return trial;
    which is a must, otherwise we'd try to split the newly created insn again
    and again succeed in splitting it and so forth forever.
    
    So, this patch instead sets INSN_CODE to -1 in the splitter to indicate
    that it needs to be re-recognized.
    
    2026-06-29  Jakub Jelinek  <[email protected]>
    
            PR target/125469
            * config/i386/i386.md (*add<mode>_1<nf_name>): Revert 2026-05-28
            changes.
            (define_split from *add<mode>_1_nf to *lea<mode>): Set INSN_CODE
            to -1 if <LEAMODE> and <MODE> are the same.
    
    Reviewed-by: Uros Bizjak <[email protected]>
    (cherry picked from commit c474154437b7ea4e3c3570c045f2e9e737ac8b9e)

Diff:
---
 gcc/config/i386/i386.md | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 857dc315a4f9..408eebb2af19 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6679,10 +6679,7 @@
       if (TARGET_APX_NDD && <nf_applied>)
        return "%{nf%} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
       else
-       {
-         operands[3] = gen_rtx_PLUS (<MODE>mode, operands[1], operands[2]);
-         return "lea{<imodesuffix>}\t{%E3, %0|%0, %E3}";
-       }
+       return "#";
 
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
@@ -7163,6 +7160,11 @@
       operands[1] = gen_lowpart (<LEAMODE>mode, operands[1]);
       operands[2] = gen_lowpart (<LEAMODE>mode, operands[2]);
     }
+  else
+    /* *lea<mode> and *add<mode>_1_nf have the same pattern, try_split
+       refuses to split an insn into itself, so just request
+       a new recog which will match *lea<mode> which comes first.  */
+    INSN_CODE (curr_insn) = -1;
 })
 
 ;; Convert add to the lea pattern to avoid flags dependency.

Reply via email to