https://gcc.gnu.org/g:896c822afed0aad4c0ca761777cdc5f0085bbce0

commit r17-890-g896c822afed0aad4c0ca761777cdc5f0085bbce0
Author: Jakub Jelinek <[email protected]>
Date:   Thu May 28 10:28:12 2026 +0200

    i386: Fix up *add<mode>_1<nf_name> [PR125469]
    
    The following testcase ICEs, because combine matches
    (set (reg:DI 108) (plus:DI (reg:DI 104 [ s ]) (subreg:DI (reg:TI 103 [ _2 
]) 8)))
    Now, because ix86_validate_address_register has:
    12038         /* Don't allow SUBREGs that span more than a word.  It can
    12039            lead to spill failures when the register is one word out
    12040            of a two word structure.  */
    12041         if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
    12042           return NULL_RTX;
    this isn't recognized as *leadi, but is recognized as *adddi_1_nf pattern
    instead.  Now, later on the RA turns it into:
    (set (reg:DI 2 cx [108]) (plus:DI (reg:DI 0 ax [orig:104 s ] [104]) (reg:DI 
5 di [ _2+8 ])))
    which would be valid *leadi, but given that INSN_CODE is already set to the
    *adddi_1_nf and that also satisfies it, nothing re-recognizes it as *leadi.
    But in that case without TARGET_APX_NDD the pattern has return "#";
    That is a bug, because there is no splitter to split that
    (set (reg:DI 2 cx [108]) (plus:DI (reg:DI 0 ax [orig:104 s ] [104]) (reg:DI 
5 di [ _2+8 ])))
    into itself so that it is re-recognized as *leadi, so it just ICEs.
    I think having a splitter to split to the same thing would be just weird, so
    this just outputs lea insn directly.
    
    2026-05-28  Jakub Jelinek  <[email protected]>
    
            PR target/125469
            * config/i386/i386.md (*add<mode>_1<nf_name>): Don't return "#" for
            the lea non-TARGET_APX_NDD case, instead emit a lea directly.
    
            * gcc.target/i386/apx-nf-pr125469.c: New test.
    
    Reviewed-by: Uros Bizjak <[email protected]>

Diff:
---
 gcc/config/i386/i386.md                         |  5 ++++-
 gcc/testsuite/gcc.target/i386/apx-nf-pr125469.c | 11 +++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 063e14cb2c17..20d57c69bd3b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6749,7 +6749,10 @@
       if (TARGET_APX_NDD && <nf_applied>)
        return "%{nf%} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
       else
-       return "#";
+       {
+         operands[3] = gen_rtx_PLUS (<MODE>mode, operands[1], operands[2]);
+         return "lea{<imodesuffix>}\t{%E3, %0|%0, %E3}";
+       }
 
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
diff --git a/gcc/testsuite/gcc.target/i386/apx-nf-pr125469.c 
b/gcc/testsuite/gcc.target/i386/apx-nf-pr125469.c
new file mode 100644
index 000000000000..dc9f1c241abe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-nf-pr125469.c
@@ -0,0 +1,11 @@
+/* PR target/125469 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-Ofast -mapx-features=nf" } */
+
+int s;
+
+void
+foo ()
+{
+  s /= ((__int128) 0x33333333333333333333333333333333uwb) + 1i;
+}

Reply via email to