Hi, in the ARM "casesi" expand pattern, when the table base index
constant is 0x8000000, it is stored sign extended as an rtx (const_int
0xffffffff8000000) (assuming 64-bit HOST_WIDE_INT).

Subtraction by adding GEN_INT(-INTVAL(operands[1])) then creates
(const_int 0x80000000), which is not sign-extended, and fails to match
the nonmemory_operand predicate later, causing a extract_insn failure
ICE.  So the fix is to use gen_int_mode() instead of GEN_INT, which does
the needed sign-extension.

Cross-tested on QEMU without regressions, okay for trunk?

Thanks,
Chung-Lin
Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md   (revision 171339)
+++ config/arm/arm.md   (working copy)
@@ -8354,7 +8354,8 @@
        rtx reg = gen_reg_rtx (SImode);
 
        emit_insn (gen_addsi3 (reg, operands[0],
-                              GEN_INT (-INTVAL (operands[1]))));
+                              gen_int_mode (-INTVAL (operands[1]),
+                                             SImode)));
        operands[0] = reg;
       }
 
Index: testsuite/gcc.target/arm/pr46934.c
===================================================================
--- testsuite/gcc.target/arm/pr46934.c  (revision 0)
+++ testsuite/gcc.target/arm/pr46934.c  (revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv5te -mthumb -Os" }  */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+int caller (unsigned int reg_type)
+{
+  switch (reg_type)
+    {
+    case 0x80000000:
+      return (int)foo();
+
+    case 0x80000003:
+      return (int) bar();
+
+    case 0x80000001:
+      return (int) baz();
+
+    case 0x80000004:
+      return (int) fooz();
+    }
+}

Reply via email to