This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch, avr, pr71676 and pr71678] Issues with casesi expand


On Thursday 13 October 2016 08:42 PM, Georg-Johann Lay wrote:
On 13.10.2016 13:44, Pitchumani Sivanupandi wrote:
On Monday 26 September 2016 08:19 PM, Georg-Johann Lay wrote:
On 26.09.2016 15:19, Pitchumani Sivanupandi wrote:
Attached patch for PR71676 and PR71678.

PR71676 is for AVR target that generates wrong code when switch case index is
more than 16 bits.

Switch case index of larger than SImode are checked for out of range before 'casesi' expand. RTL expand of casesi gets index as SImode, but index is
compared in HImode and ignores upper 16bits.

Attached patch changes the expansion for casesi to make the index comparison
in SImode and code generation accordingly.

PR71678 is ICE because below pattern in 'casesi' is not recognized.
(set (reg:HI 47)
     (minus:HI (subreg:HI (subreg:SI (reg:DI 44) 0) 0)
               (reg:HI 45)))

Fix of PR71676 avoids the above pattern as it changes the comparison
to SImode.

But this means that all comparisons are now performed in SImode which is a great performance loss for most programs which will switch on 16-bit values.

IMO we need a less intrusive (w.r.t. performance) approach.

Yes.

I tried to split 'casesi' into several based on case values so that compare is
done
in less expensive modes (i.e. QI or HI). In few cases it is not possible without
SImode subtract/ compare.

Pattern casesi will have index in SI mode. So, out of range checks will be
expensive
as most common uses (in AVR) of case values will be in QI/HI mode.

e.g.
  if case values in QI range
    if upper three bytes index is set
      goto out_of_range

    offset = index - lower_bound (QImode)
    if offset > case_range       (QImode)
      goto out_of_range
    goto jump_table + offset

  else if case values in HI range
    if index[2,3] is set
      goto out_of_range

    offset = index - lower_bound (HImode)
    if offset > case_range       (HImode)
      goto out_of_range
    goto jump_table + offset

This modification will not work for the negative index values. Because code to
check
upper bytes of index will be expensive than the SImode subtract/ compare.

So, I'm trying to update fix to have SImode subtract/ compare if the case
values include
negative integers. For, others will try to optimize as mentioned above. Is that
approach OK?

But the above code will be executed at run time and add even more overhead, or am I missing something? If you conclude statically at expand time from the case ranges then we might hit a similar problem as with the original subreg computation.

No. Lower bound and case range are const_int_operand, known at compile time.
Tried to optimize code generated based on case values range.
Attached the revised patch.

Tested with avrtest, no regression found.

Is it OK?

Unfortunately, the generated code (setting cc0, a reg and pc) cannot be wrapped into an unspec or parallel and then later be rectified...

I am thinking about a new avr target pass to tidy up the code if no 32-bit computation is needed, but this will be some effort.
Ok.


Regards,
Pitchumani

gcc/ChangeLog

2016-10-17  Pitchumani Sivanupandi <pitchumani.s@atmel.com>

    PR target/71676
    PR target/71678
* config/avr/avr.md (casesi_index_qi, casesi_index_hi, casesi_index_si):
    Add new expands, called by casesi based on case values range.

gcc/testsuite/ChangeLog

2016-10-17  Pitchumani Sivanupandi <pitchumani.s@atmel.com>

    PR target/71676
    PR target/71678
    * gcc.target/avr/pr71676-1.c: New test.
    * gcc.target/avr/pr71676.c: New test.
    * gcc.target/avr/pr71678.c: New test.

diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 97f3561..b58db14 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -5152,16 +5152,95 @@
    (set_attr "isa" "eijmp")
    (set_attr "cc" "clobber")])
 
+; casesi for QI mode case values
+(define_expand "casesi_index_qi"
+  [(set (cc0)
+        (compare:QI (subreg:QI (match_dup 0) 0)
+                    (match_operand 2 "const_int_operand" "")))
 
-(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" "")))
-              (clobber (scratch:QI))])
-   (parallel [(set (cc0)
-                   (compare (match_dup 6)
-                            (match_operand:HI 2 "register_operand" "")))
-              (clobber (match_scratch:QI 9 ""))])
+   (set (pc)
+        (if_then_else (gtu (cc0)
+                           (const_int 0))
+                      (label_ref (match_operand 4 "" ""))
+                      (pc)))
+
+   (set (match_dup 9)
+        (match_dup 7))
+
+   (parallel [(set (pc)
+	               (unspec:HI [(match_dup 9)] UNSPEC_INDEX_JMP))
+              (use (label_ref (match_operand 3 "" "")))
+              (clobber (match_dup 9))
+              (clobber (match_dup 8))])]
+  ""
+  {
+    operands[5] = gen_reg_rtx (QImode);
+    unsigned int original_byte_number = 0;
+    /* if subreg, take out inner exp and byte number.
+       Later subreg shall use that byte number accordingly to
+       avoid list of nested SUBREGs.  */
+    if (SUBREG_P (operands[0]))
+      {
+        rtx original_index = operands[0];
+        original_index = SUBREG_REG (operands[0]);
+        original_byte_number = SUBREG_BYTE (operands[0]);
+        operands[0] = original_index;
+      }
+
+    /* jump to out_of_range label if any of the
+       higher 3 bytes of switch index is set.  */
+    emit_insn (gen_rtx_SET (operands[5], gen_rtx_IOR (QImode,
+                                           gen_rtx_SUBREG (QImode, operands[0], original_byte_number + 2),
+                                           gen_rtx_SUBREG (QImode, operands[0], original_byte_number + 3))));
+    emit_insn (gen_rtx_SET (operands[5], gen_rtx_IOR (QImode,
+                                           gen_rtx_SUBREG (QImode, operands[0], original_byte_number + 1),
+                                           operands[5])));
+    emit_insn (gen_rtx_SET (cc0_rtx,
+                 gen_rtx_COMPARE (QImode, operands[5], const0_rtx)));
+    emit_jump_insn (gen_rtx_SET (pc_rtx,
+        gen_rtx_IF_THEN_ELSE (VOIDmode,
+            gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx),
+            gen_rtx_LABEL_REF (VOIDmode, operands[4]),
+            pc_rtx)));
+
+    /* Subtract lower bound from index iff lower bound is not zero.  */
+    operands[6] = gen_rtx_SUBREG (HImode, operands[0], original_byte_number);
+    if (operands[1] != const0_rtx)
+      {
+        rtx reg = gen_reg_rtx (HImode);
+        emit_insn (gen_addhi3 (reg, operands[6],
+                     gen_int_mode (-INTVAL (operands[1]), HImode)));
+        operands[0] = reg;
+        operands[6] = operands[0];
+      }
+
+    if (!s8_operand (operands[2], QImode))
+      {
+        INTVAL (operands[2]) = -(256 - INTVAL (operands[2]));
+      }
+
+    if (AVR_HAVE_EIJMP_EICALL)
+      {
+        operands[7] = operands[6];
+        operands[8] = all_regs_rtx[24];
+        operands[9] = gen_rtx_REG (HImode, REG_Z);
+      }
+    else
+      {
+        operands[7] = gen_rtx_PLUS (HImode, operands[6],
+                                    gen_rtx_LABEL_REF (VOIDmode, operands[3]));
+        operands[8] = const0_rtx;
+        operands[9] = gen_reg_rtx (HImode);
+      }
+  }
+  )
+
+; casesi for HI mode case values
+(define_expand "casesi_index_hi"
+  [(parallel [(set (cc0)
+                   (compare (match_dup 0)
+                            (match_operand:HI 2 "const_int_operand" "")))
+              (clobber (match_scratch:QI 10 ""))])
 
    (set (pc)
         (if_then_else (gtu (cc0)
@@ -5169,31 +5248,148 @@
                       (label_ref (match_operand 4 "" ""))
                       (pc)))
 
-   (set (match_dup 10)
+   (set (match_dup 9)
         (match_dup 7))
 
    (parallel [(set (pc)
-                   (unspec:HI [(match_dup 10)] UNSPEC_INDEX_JMP))
-              (use (label_ref (match_dup 3)))
-              (clobber (match_dup 10))
+	               (unspec:HI [(match_dup 9)] UNSPEC_INDEX_JMP))
+              (use (label_ref (match_operand 3 "" "")))
+              (clobber (match_dup 9))
               (clobber (match_dup 8))])]
   ""
   {
-    operands[6] = gen_reg_rtx (HImode);
+    operands[5] = gen_reg_rtx (QImode);
+    unsigned int original_byte_number = 0;
+    /* if subreg, take out inner exp and byte number.
+       Later subreg shall use that byte number accordingly to
+       avoid list of nested SUBREGs.  */
+    if (SUBREG_P (operands[0]))
+      {
+        rtx original_index = operands[0];
+        original_index = SUBREG_REG (operands[0]);
+        original_byte_number = SUBREG_BYTE (operands[0]);
+        operands[0] = original_index;
+      }
+
+    /* jump to out_of_range label if any of the
+       higher 3 bytes of switch index is set.  */
+    emit_insn (gen_rtx_SET (operands[5], gen_rtx_IOR (QImode,
+                                           gen_rtx_SUBREG (QImode, operands[0], original_byte_number + 2),
+                                           gen_rtx_SUBREG (QImode, operands[0], original_byte_number + 3))));
+    emit_insn (gen_rtx_SET (cc0_rtx,
+                 gen_rtx_COMPARE (QImode, operands[5], const0_rtx)));
+    emit_jump_insn (gen_rtx_SET (pc_rtx,
+        gen_rtx_IF_THEN_ELSE (VOIDmode,
+            gen_rtx_NE (VOIDmode, cc0_rtx, const0_rtx),
+            gen_rtx_LABEL_REF (VOIDmode, operands[4]),
+            pc_rtx)));
+
+    /* Subtract lower bound from index iff lower bound is not zero.  */
+    operands[6] = gen_rtx_SUBREG (HImode, operands[0], original_byte_number);
+    if (operands[1] != const0_rtx)
+      {
+        rtx reg = gen_reg_rtx (HImode);
+        emit_insn (gen_addhi3 (reg, operands[6],
+                     gen_int_mode (-INTVAL (operands[1]), HImode)));
+        operands[0] = reg;
+        operands[6] = operands[0];
+      }
 
     if (AVR_HAVE_EIJMP_EICALL)
       {
         operands[7] = operands[6];
         operands[8] = all_regs_rtx[24];
-        operands[10] = gen_rtx_REG (HImode, REG_Z);
+        operands[9] = gen_rtx_REG (HImode, REG_Z);
       }
     else
       {
         operands[7] = gen_rtx_PLUS (HImode, operands[6],
                                     gen_rtx_LABEL_REF (VOIDmode, operands[3]));
         operands[8] = const0_rtx;
-        operands[10] = operands[6];
+        operands[9] = gen_reg_rtx (HImode);
+      }
+  }
+  )
+  
+; casesi for SI mode case values
+(define_expand "casesi_index_si"
+  [(parallel [(set (cc0)
+                   (compare (match_dup 0)
+                            (match_operand:SI 2 "const_int_operand" "")))
+              (clobber (match_scratch:QI 8 ""))])
+
+   (set (pc)
+        (if_then_else (gtu (cc0)
+                           (const_int 0))
+                      (label_ref (match_operand 4 "" ""))
+                      (pc)))
+
+   (set (match_dup 7)
+        (match_dup 5))
+
+   (parallel [(set (pc)
+	               (unspec:HI [(match_dup 7)] UNSPEC_INDEX_JMP))
+              (use (label_ref (match_operand 3 "" "")))
+              (clobber (match_dup 7))
+              (clobber (match_dup 6))])]
+  ""
+  {
+    /* Subtract lower bound from index iff lower bound is not zero.  */
+    if (operands[1] != const0_rtx)
+      {
+        rtx reg = gen_reg_rtx (SImode);
+        emit_insn (gen_addsi3 (reg, operands[0],
+                     gen_int_mode (-INTVAL (operands[1]), SImode)));
+        operands[0] = reg;
+      }
+
+    if (AVR_HAVE_EIJMP_EICALL)
+      {
+        operands[5] = simplify_gen_subreg (HImode, operands[0], SImode, 0);
+        operands[6] = all_regs_rtx[24];
+        operands[7] = gen_rtx_REG (HImode, REG_Z);
+      }
+    else
+      {
+        operands[5] = gen_rtx_PLUS (HImode, simplify_gen_subreg (HImode, operands[0], SImode, 0),
+                                    gen_rtx_LABEL_REF (VOIDmode, operands[3]));
+        operands[6] = const0_rtx;
+        operands[7] = gen_reg_rtx (HImode);
       }
+  }
+  )
+
+(define_expand "casesi"
+  [(match_operand:SI 0 "register_operand" "")  ; index to jump on
+   (match_operand    1 "const_int_operand" "") ; lower bound
+   (match_operand    2 "const_int_operand" "") ; total range
+   (match_operand    3 "" "")                  ; table label
+   (match_operand    4 "" "")]                 ; out of range label
+  ""
+  {
+    /* Can not handle the ranges greater than 16bit wide.  */
+    if (INTVAL (operands[2]) > UINT16_MAX)
+      gcc_unreachable ();
+
+    /* case values include negative or greater than HImode.  */
+    if ((INTVAL (operands[1]) < 0) ||
+        ((INTVAL (operands[1]) + INTVAL (operands[2])) > UINT16_MAX))
+      {
+        emit_insn (gen_casesi_index_si (operand0, operand1, operand2, operand3, operand4));
+      }
+    else if ((s8_operand (operands[1], QImode) || u8_operand (operands[1], QImode)) &&
+             (s8_operand (operands[2], QImode) || u8_operand (operands[2], QImode)))
+      {
+        emit_insn (gen_casesi_index_qi (operand0, operand1, operand2, operand3, operand4));
+      }
+    else
+      {
+        gcc_assert (s16_operand (operands[1], HImode) ||
+                    u16_operand (operands[1], HImode));
+
+        emit_insn (gen_casesi_index_hi (operand0, operand1, operand2, operand3, operand4));
+      }
+    DONE;
   })
 
 
diff --git a/gcc/testsuite/gcc.target/avr/pr71676-1.c b/gcc/testsuite/gcc.target/avr/pr71676-1.c
new file mode 100644
index 0000000..7315e03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr71676-1.c
@@ -0,0 +1,332 @@
+/* { dg-do run } */
+/* { dg-options "-Os -Wno-overflow" } */
+
+#include "exit-abort.h"
+volatile unsigned char y;
+
+unsigned char __attribute__((noinline)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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)) 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 (0x13LL) != 8)
+	  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.c b/gcc/testsuite/gcc.target/avr/pr71676.c
new file mode 100644
index 0000000..d7a543a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr71676.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+
+#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
index 0000000..290d6cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr71678.c
@@ -0,0 +1,20 @@
+/* { 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;
+}
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]