https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125469

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think the bug is in both *leadi and *adddi_1_nf matching insn like
(set (reg:DI 2 cx [108])
        (plus:DI (reg:DI 0 ax [orig:104 s ] [104])
            (reg:DI 5 di [ _2+8 ])))
without TARGET_APX_NDD (but with TARGET_APX_NF).
This is matched by combine:
insn 12 10 13 2 (set (reg:DI 108)
        (plus:DI (reg:DI 104 [ s ])
            (subreg:DI (reg:TI 103 [ _2 ]) 8))) "pr125469.c":6:5 288
{*adddi_1_nf}
     (expr_list:REG_DEAD (reg:TI 103 [ _2 ])
        (nil)))
and at that point the subreg in there prevents it from being matched as *leadi.
This is due to ix86_validate_address_register
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;
So, INSN_CODE is set to 288 (*adddi_1_nf) and not *leadi.
But *add<mode>_1<nf_name> has
    case TYPE_LEA:
      if (TARGET_APX_NDD && <nf_applied>)
        return "%{nf%} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
      else
        return "#";
TARGET_APX_NDD is false, so we require splitting into lea.  Except there is no
splitter for that case, all we need instead is re-recog the insn, but that
won't happen, so we ICE.
So, either we'd need a dumb splitter that does nothing for this case (matches
the (set (reg:SWI48) (plus:SWI48 (reg:SWI48) (nonimmediate_operand:SWI48
"le"))) case and splits it into the same thing), or handle that case here
directly instead of "#".

I think the easier fix is
--- gcc/config/i386/i386.md.jj  2026-05-20 14:05:56.000000000 +0200
+++ gcc/config/i386/i386.md     2026-05-27 18:12:47.265960379 +0200
@@ -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)

Reply via email to