re PR target/71676 ([avr] casesi won't handle switch values larger than 16 bits)
authorGeorg-Johann Lay <avr@gjlay.de>
Tue, 25 Oct 2016 08:26:59 +0000 (08:26 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Tue, 25 Oct 2016 08:26:59 +0000 (08:26 +0000)
gcc/
PR target/71676
PR target/71678
* config/avr/avr.md (casesi): Rewrite avoiding subregs of SI.
gcc/testsuite/
PR target/71676
PR target/71678
* gcc.target/avr/pr71676-1.c: New test.
* gcc.target/avr/pr71676-3.c: New test.
* gcc.target/avr/pr71676.c: New test.
* gcc.target/avr/pr71678.c: New test.

Co-Authored-By: Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
From-SVN: r241503

gcc/ChangeLog
gcc/config/avr/avr.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/avr/pr71676-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/pr71676-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/pr71676.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/pr71678.c [new file with mode: 0644]

index 88bace4ea16b5c7ece1a433f95dadf825e641c01..183efac17446e14b636a83081d1355e52202e6c1 100644 (file)
@@ -1,3 +1,10 @@
+2016-10-25  Georg-Johann Lay  <avr@gjlay.de>
+           Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
+
+       PR target/71676
+       PR target/71678
+       * config/avr/avr.md (casesi): Rewrite avoiding subregs of SI.
+
 2016-10-24  Jakub Jelinek  <jakub@redhat.com>
 
        * dwarf2out.c (gen_subprogram_die): Add DW_AT_reference or
index 97f35616d1f0ce82a357770841e3ac793ff38cd2..446ee402d79265dd61fb25dfcaddb9313cb93e09 100644 (file)
 
 
 (define_expand "casesi"
-  [(parallel [(set (match_dup 6)
-                   (minus:HI (subreg:HI (match_operand:SI 0 "register_operand" "") 0)
-                             (match_operand:HI 1 "register_operand" "")))
+  [(parallel [(set (match_dup 5)
+                   (plus:SI (match_operand:SI 0 "register_operand")
+                            (match_operand:SI 1 "const_int_operand")))
               (clobber (scratch:QI))])
    (parallel [(set (cc0)
-                   (compare (match_dup 6)
-                            (match_operand:HI 2 "register_operand" "")))
-              (clobber (match_scratch:QI 9 ""))])
+                   (compare (match_dup 5)
+                            (match_operand:SI 2 "const_int_operand")))
+              (clobber (scratch:QI))])
 
    (set (pc)
         (if_then_else (gtu (cc0)
                            (const_int 0))
-                      (label_ref (match_operand 4 "" ""))
+                      (label_ref (match_operand 4))
                       (pc)))
 
-   (set (match_dup 10)
-        (match_dup 7))
+   (set (match_dup 7)
+        (match_dup 6))
 
    (parallel [(set (pc)
-                   (unspec:HI [(match_dup 10)] UNSPEC_INDEX_JMP))
+                   (unspec:HI [(match_dup 7)] UNSPEC_INDEX_JMP))
               (use (label_ref (match_dup 3)))
-              (clobber (match_dup 10))
+              (clobber (match_dup 7))
               (clobber (match_dup 8))])]
   ""
   {
-    operands[6] = gen_reg_rtx (HImode);
+    operands[1] = simplify_unary_operation (NEG, SImode, operands[1], SImode);
+    operands[5] = gen_reg_rtx (SImode);
+    operands[6] = simplify_gen_subreg (HImode, operands[5], SImode, 0);
 
     if (AVR_HAVE_EIJMP_EICALL)
       {
-        operands[7] = operands[6];
+        operands[7] = gen_rtx_REG (HImode, REG_Z);
         operands[8] = all_regs_rtx[24];
-        operands[10] = gen_rtx_REG (HImode, REG_Z);
       }
     else
       {
-        operands[7] = gen_rtx_PLUS (HImode, operands[6],
+        operands[6] = gen_rtx_PLUS (HImode, operands[6],
                                     gen_rtx_LABEL_REF (VOIDmode, operands[3]));
+        operands[7] = gen_reg_rtx (HImode);
         operands[8] = const0_rtx;
-        operands[10] = operands[6];
       }
   })
 
index e5497e41cfed958cdabcd2170018445d3ad8837c..07cc777723f3486201b716bacbc95e570cafb2a6 100644 (file)
@@ -1,3 +1,13 @@
+2016-10-25  Georg-Johann Lay  <avr@gjlay.de>
+           Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
+
+       PR target/71676
+       PR target/71678
+       * gcc.target/avr/pr71676-1.c: New test.
+       * gcc.target/avr/pr71676-3.c: New test.
+       * gcc.target/avr/pr71676.c: New test.
+       * gcc.target/avr/pr71678.c: New test.
+
 2016-10-24  Kugan Vivekanandarajah  <kuganvi@linaro.org>
 
        * gcc.target/aarch64/test_frame_common.h: Add noclone attribute
diff --git a/gcc/testsuite/gcc.target/avr/pr71676-1.c b/gcc/testsuite/gcc.target/avr/pr71676-1.c
new file mode 100644 (file)
index 0000000..0d41a60
--- /dev/null
@@ -0,0 +1,347 @@
+/* { dg-do run } */
+/* { dg-options "-Os -Wno-overflow -fno-tree-switch-conversion" } */
+
+#include "exit-abort.h"
+volatile unsigned char y;
+
+unsigned char __attribute__((noinline,noclone))
+foo1 (char x)
+{
+  switch (x)
+    {
+    case (char)0x11: y = 7; break;
+    case (char)0x12: y = 4; break;
+    case (char)0x13: y = 8; break;
+    case (char)0x14: y = 21; break;
+    case (char)0x15: y = 65; break;
+    case (char)0x16: y = 27; break;
+    case (char)0x17: y = 72; break;
+    case (char)0x18: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo2 (char x)
+{
+  switch (x)
+    {
+    case 0x01: y = 7; break;
+    case 0x02: y = 4; break;
+    case 0x03: y = 8; break;
+    case 0x04: y = 21; break;
+    case 0x05: y = 65; break;
+    case 0x06: y = 27; break;
+    case 0x07: y = 72; break;
+    case 0x08: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo3 (char x)
+{
+  switch (x)
+    {
+    case 0x1000001L: y = 7; break;
+    case 0x1000002L: y = 4; break;
+    case 0x1000003L: y = 8; break;
+    case 0x1000004L: y = 21; break;
+    case 0x1000005L: y = 65; break;
+    case 0x1000006L: y = 27; break;
+    case 0x1000007L: y = 72; break;
+    case 0x1000008L: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo4 (char x)
+{
+  switch (x)
+    {
+    case 0x100000001LL: y = 7; break;
+    case 0x100000002LL: y = 4; break;
+    case 0x100000003LL: y = 8; break;
+    case 0x100000004LL: y = 21; break;
+    case 0x100000005LL: y = 65; break;
+    case 0x100000006LL: y = 27; break;
+    case 0x100000007LL: y = 72; break;
+    case 0x100000008LL: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo5 (int x)
+{
+  switch (x)
+    {
+    case (char)0x11: y = 7; break;
+    case (char)0x12: y = 4; break;
+    case (char)0x13: y = 8; break;
+    case (char)0x14: y = 21; break;
+    case (char)0x15: y = 65; break;
+    case (char)0x16: y = 27; break;
+    case (char)0x17: y = 72; break;
+    case (char)0x18: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo6 (int x)
+{
+  switch (x)
+    {
+    case 0x101: y = 7; break;
+    case 0x102: y = 4; break;
+    case 0x103: y = 8; break;
+    case 0x104: y = 21; break;
+    case 0x105: y = 65; break;
+    case 0x106: y = 27; break;
+    case 0x107: y = 72; break;
+    case 0x108: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo7 (int x)
+{
+  switch (x)
+    {
+    case 0x1000001L: y = 7; break;
+    case 0x1000002L: y = 4; break;
+    case 0x1000003L: y = 8; break;
+    case 0x1000004L: y = 21; break;
+    case 0x1000005L: y = 65; break;
+    case 0x1000006L: y = 27; break;
+    case 0x1000007L: y = 72; break;
+    case 0x1000008L: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo8 (int x)
+{
+  switch (x)
+    {
+    case 0x100000001LL: y = 7; break;
+    case 0x100000002LL: y = 4; break;
+    case 0x100000003LL: y = 8; break;
+    case 0x100000004LL: y = 21; break;
+    case 0x100000005LL: y = 65; break;
+    case 0x100000006LL: y = 27; break;
+    case 0x100000007LL: y = 72; break;
+    case 0x100000008LL: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo9 (long x)
+{
+  switch (x)
+    {
+    case (char)0x11: y = 7; break;
+    case (char)0x12: y = 4; break;
+    case (char)0x13: y = 8; break;
+    case (char)0x14: y = 21; break;
+    case (char)0x15: y = 65; break;
+    case (char)0x16: y = 27; break;
+    case (char)0x17: y = 72; break;
+    case (char)0x18: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo10 (unsigned long x)
+{
+  switch (x)
+    {
+    case 0x100: y = 39; break;
+    case 0x101: y = 7; break;
+    case 0x102: y = 4; break;
+    case 0x103: y = 8; break;
+    case 0x104: y = 21; break;
+    case 0x105: y = 65; break;
+    case 0x106: y = 27; break;
+    case 0x107: y = 72; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo11 (long x)
+{
+  switch (x)
+    {
+    case 0x1000001L: y = 7; break;
+    case 0x1000002L: y = 4; break;
+    case 0x1000003L: y = 8; break;
+    case 0x1000004L: y = 21; break;
+    case 0x1000005L: y = 65; break;
+    case 0x1000006L: y = 27; break;
+    case 0x1000007L: y = 72; break;
+    case 0x1000008L: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo12 (long x)
+{
+  switch (x)
+    {
+    case 0x100000001LL: y = 7; break;
+    case 0x100000002LL: y = 4; break;
+    case 0x100000003LL: y = 8; break;
+    case 0x100000004LL: y = 21; break;
+    case 0x100000005LL: y = 65; break;
+    case 0x100000006LL: y = 27; break;
+    case 0x100000007LL: y = 72; break;
+    case 0x100000008LL: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo13 (long long x)
+{
+  switch (x)
+    {
+    case (char)0x11: y = 7; break;
+    case (char)0x12: y = 4; break;
+    case (char)0x13: y = 8; break;
+    case (char)0x14: y = 21; break;
+    case (char)0x15: y = 65; break;
+    case (char)0x16: y = 27; break;
+    case (char)0x17: y = 72; break;
+    case (char)0x18: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo14 (long long x)
+{
+  switch (x)
+    {
+    case 0x101: y = 7; break;
+    case 0x102: y = 4; break;
+    case 0x103: y = 8; break;
+    case 0x104: y = 21; break;
+    case 0x105: y = 65; break;
+    case 0x106: y = 27; break;
+    case 0x107: y = 72; break;
+    case 0x108: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+unsigned char __attribute__((noinline,noclone))
+foo15 (long long x)
+{
+  switch (x)
+    {
+    case 0x1000001L: y = 7; break;
+    case 0x1000002L: y = 4; break;
+    case 0x1000003L: y = 8; break;
+    case 0x1000004L: y = 21; break;
+    case 0x1000005L: y = 65; break;
+    case 0x1000006L: y = 27; break;
+    case 0x1000007L: y = 72; break;
+    case 0x1000008L: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+
+unsigned char __attribute__((noinline,noclone))
+foo16 (long long x)
+{
+  switch (x)
+    {
+    case 0x100000001LL: y = 7; break;
+    case 0x100000002LL: y = 4; break;
+    case 0x100000003LL: y = 8; break;
+    case 0x100000004LL: y = 21; break;
+    case 0x100000005LL: y = 65; break;
+    case 0x100000006LL: y = 27; break;
+    case 0x100000007LL: y = 72; break;
+    case 0x100000008LL: y = 39; break;
+    default: y=0;
+    }
+  return y;
+}
+
+int main ()
+{
+  if (foo1 (0x13) != 8)
+    abort();
+
+  if (foo2 (0x06) != 27)
+    abort();
+
+  if (foo3 (0x02) != 4)
+    abort();
+
+  if (foo4 (0x01) != 7)
+    abort();
+
+  if (foo5 (0x15) != 65)
+    abort();
+
+  if (foo6 (0x103) != 8)
+    abort();
+
+  if (foo7 (0x04) != 21)
+    abort();
+
+  if (foo8 (0x07) != 72)
+    abort();
+
+  if (foo9 (0x10000011L) != 0)
+    abort();
+
+  if (foo10 (0x1000105L) != 0)
+    abort();
+
+  if (foo11 (0x1000008L) != 39)
+    abort();
+
+  if (foo12 (0x1000004L) != 0)
+    abort();
+
+  if (foo13 (0x109LL) != 0)
+    abort();
+
+  if (foo14 (0x108LL) != 39)
+    abort();
+
+  if (foo15 (0x1000001LL) != 7)
+    abort();
+
+  if (foo16 (0x100000004LL) != 21)
+    abort();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/pr71676-3.c b/gcc/testsuite/gcc.target/avr/pr71676-3.c
new file mode 100644 (file)
index 0000000..6c10f04
--- /dev/null
@@ -0,0 +1,80 @@
+/* { dg-do run } */
+/* { dg-options "-Os -fno-tree-switch-conversion" } */
+
+#define MK_FUN(NAME, TYP, V)                            \
+  static __inline__ __attribute__((always_inline))      \
+  unsigned char value_## NAME (TYP x, unsigned char y)  \
+  {                                                     \
+    switch (x)                                          \
+      {                                                 \
+      case V + 0: return 0 + y;                         \
+      case V + 1: return 1;                             \
+      case V + 2: return 2 + y;                         \
+      case V + 3: return 3;                             \
+      case V + 4: return 4 + y;                         \
+      case V + 5: return 5;                             \
+      case V + 6: return 6 + y;                         \
+      case V + 7: return 7;                             \
+      case V + 8: return 8 + y;                         \
+      case V + 9: return 9;                             \
+      case V + 10: return 10 + y;                       \
+      case V + 11: return 11;                           \
+      case V + 12: return 12 + y;                       \
+      case V + 13: return 13;                           \
+      case V + 14: return 14 + y;                       \
+      case V + 15: return 15;                           \
+      }                                                 \
+    return x;                                           \
+  }                                                     \
+                                                        \
+  __attribute__((noinline,noclone))                     \
+  unsigned char select_## NAME (TYP x, unsigned char y) \
+  {                                                     \
+    return value_## NAME (x, y);                        \
+  }                                                     \
+                                                        \
+  static __inline__ __attribute__((always_inline))      \
+  void test1_## NAME (TYP x)                            \
+  {                                                     \
+    if (select_## NAME (x, 0) != value_## NAME (x, 0))  \
+      __builtin_abort();                                \
+  }                                                     \
+                                                        \
+  void test_## NAME (void)                              \
+  {                                                     \
+    test1_## NAME (V);                                  \
+    test1_## NAME (V - 1);                              \
+    test1_## NAME (V + 15);                             \
+    test1_## NAME (V + 16);                             \
+  }
+
+MK_FUN (0_s8, signed char, 0)
+MK_FUN (0_u8, unsigned char, 0)
+MK_FUN (0_s16, signed int, 0)
+MK_FUN (0_u16, unsigned int, 0)
+
+MK_FUN (m4_s8, signed char, -4)
+MK_FUN (m4_s16, signed int, -4)
+
+MK_FUN (4_s8, signed char, 4)
+MK_FUN (4_u8, unsigned char, 4)
+MK_FUN (4_s16, signed int, 4)
+MK_FUN (4_u16, unsigned int, 4)
+
+int main (void)
+{
+  test_0_s8();
+  test_0_u8();
+  test_0_s16();
+  test_0_u16();
+
+  test_m4_s8();
+  test_m4_s16();
+
+  test_4_s8();
+  test_4_u8();
+  test_4_s16();
+  test_4_u16();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/pr71676.c b/gcc/testsuite/gcc.target/avr/pr71676.c
new file mode 100644 (file)
index 0000000..7737c1e
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-Os -fno-tree-switch-conversion" } */
+
+#include "exit-abort.h"
+
+volatile unsigned char y;
+
+__attribute__((noinline,noclone))
+unsigned char foo (unsigned long x) 
+{
+  switch (x)
+    {
+    case 0:    y = 67; break;
+    case 1:    y = 20; break;
+    case 2:    y = 109; break;
+    case 3:    y = 33; break;
+    case 4:    y = 44; break;
+    case 5:    y = 37; break;
+    case 6:    y = 10; break;
+    case 7:    y = 98; break;
+    }
+  return y;
+}
+
+int main (void)
+{
+  if (0 != foo (7L + 0x10000L))
+    abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/pr71678.c b/gcc/testsuite/gcc.target/avr/pr71678.c
new file mode 100644 (file)
index 0000000..160810f
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fno-tree-switch-conversion" } */
+
+unsigned char foo (long long x) 
+{
+  unsigned char y = 0;
+  switch (x)
+    {
+    case 0: y = 67; break;
+    case 1: y = 20; break;
+    case 2: y = 109; break;
+    case 3: y = 33; break;
+    case 4: y = 44; break;
+    case 5: y = 37; break;
+    case 6: y = 10; break;
+    case 7: y = 11; break;
+    }
+  return y;
+}