https://gcc.gnu.org/g:c681c4f2aa8fc44c4e3822cc34b32fc93d1c607d

commit r16-9759-gc681c4f2aa8fc44c4e3822cc34b32fc93d1c607d
Author: Jakub Jelinek <[email protected]>
Date:   Tue Sep 15 12:02:18 2026 +0200

    i386: Fix up split_double_mode [PR127352]
    
    The following testcase ICEs, because we try to split during split2 pass
    (insn 313 311 314 36 (parallel [
                (set (reg:TI 36 r8 [orig:118 b_lsm.27 ] [118])
                    (and:TI (subreg:TI (reg:SI 36 r8 [orig:107 f ] [107]) 0)
                        (const_int 15 [0xf])))
                (clobber (reg:CC 17 flags))
            ]) 734 {*andti3_doubleword}
         (nil))
    where the paradoxical subreg is quite reasonable, const_int 15 doesn't have
    any non-zero bits in the high half, so what exact value we get in the other
    operand in the high 64 bits is irrelevant.
    
    But split_double_mode in that case just calls gen_reg_rtx (half_mode),
    which ICEs.
    The high bits of a paradoxical SUBREG can be anything, so this patch after
    RA chooses one particular value for that, 0 (as the cheapest one and 
something
    that likely matches the predicates/constraints of insns using it).
    
    2026-09-15  Jakub Jelinek  <[email protected]>
    
            PR target/127352
            * config/i386/i386-expand.cc (split_double_mode): For high halves of
            paradoxical subregs after RA use CONST0_RTX (half_mode) instead of
            ICE.
    
            * gcc.target/i386/pr127352.c: New test.
    
    Reviewed-by: Uros Bizjak <[email protected]>
    (cherry picked from commit 920fbabbc3b30c2677b2445c55b29c8547abf01c)

Diff:
---
 gcc/config/i386/i386-expand.cc           |  9 ++++--
 gcc/testsuite/gcc.target/i386/pr127352.c | 53 ++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 3c2b2dc6e7ec..f4968af6c72d 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -161,8 +161,13 @@ split_double_mode (machine_mode mode, rtx operands[],
                                         GET_MODE (op) == VOIDmode
                                         ? mode : GET_MODE (op), byte);
          /* simplify_gen_subreg will return NULL RTX for the
-            high half of the paradoxical subreg. */
-         hi_half[num] = tmp ? tmp : gen_reg_rtx (half_mode);
+            high half of the paradoxical subreg.  */
+         if (tmp)
+           hi_half[num] = tmp;
+         else if (can_create_pseudo_p ())
+           hi_half[num] = gen_reg_rtx (half_mode);
+         else
+           hi_half[num] = CONST0_RTX (half_mode);
        }
     }
 }
diff --git a/gcc/testsuite/gcc.target/i386/pr127352.c 
b/gcc/testsuite/gcc.target/i386/pr127352.c
new file mode 100644
index 000000000000..8f7b3a3c2522
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127352.c
@@ -0,0 +1,53 @@
+/* PR target/127352 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O3" } */
+
+_BitInt(65) a, b, c;
+__int128 d;
+_BitInt(7) e;
+
+long
+foo (long x)
+{
+  return x;
+}
+
+_BitInt(13)
+bar (unsigned x, _BitInt(3) y)
+{
+  return y == 0 ? : x;
+}
+
+_BitInt(65)
+baz (_BitInt(65) x, _BitInt(5) y)
+{
+  return y == 0 ? x : y;
+}
+
+_BitInt(5)
+qux ()
+{
+  _BitInt(47) f;
+  unsigned g = d & 15;
+  for (unsigned i = 0; i < g; i++)
+    {
+      switch (a)
+       {
+       case 0:
+         b = 0;
+       case 8:
+         e = 0;
+         break;
+       case 10:
+         long h = g;
+         f = ~foo (~h);
+         e = f;
+       }
+      if (0 >= b)
+       continue;
+      for (unsigned j = 0; j < 1; j++)
+       b = (_BitInt(7)) (0 >= d ? bar (e, a) : 0);
+      e = c ? baz (b, i) : 0;
+    }
+  return b;
+}

Reply via email to