From patchwork Mon Oct 17 07:27:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pitchumani Sivanupandi X-Patchwork-Id: 682806 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3sy8tp0TMSz9s8x for ; Mon, 17 Oct 2016 18:27:58 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=HXczsrsm; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:references:cc:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=tEoWRJlNmH6PYHiAZ Y432zRG0yFlpDCrCb2T7Hx1X7hQRCSUb79Yuys9bAQ2Uq60/569Ti0PEViSBWQMK JT2Yxl8gzXxf9DZOH6VjvDyQvRgfCzLPOTG6dWX72Lva9Sa/90uFuu1qZZ6P+y2a Bt9LhHxttRRkO02bTvMOHbEHXY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:references:cc:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=JvI100L1SxLYZZsB0h5YVfU dPEg=; b=HXczsrsmeCL+ATu0hVEskjPACqziRuN8/yQj+wE0vIN4L+tM9TCItJi X7A2RaOGu9jvfBMRCi97gyTtuvmVD3ZRinnNl0hdgIW8MuFtWHBdTM01+UMpFvBQ V2bnFqKX2lBr0mrfVs1XqIk2tUNEaZ0LycIjA7RKpz0Dcwne7QCA= Received: (qmail 2257 invoked by alias); 17 Oct 2016 07:27:43 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 2174 invoked by uid 89); 17 Oct 2016 07:27:42 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy=0x100, 1, 31, Lower, Hx-spam-relays-external:sk:smtpout X-HELO: email.microchip.com Received: from smtpout.microchip.com (HELO email.microchip.com) (198.175.253.82) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Oct 2016 07:27:31 +0000 Received: from [10.40.233.140] (10.10.76.4) by chn-sv-exch05.mchp-main.com (10.10.76.106) with Microsoft SMTP Server id 14.3.181.6; Mon, 17 Oct 2016 00:27:25 -0700 From: Pitchumani Sivanupandi Subject: Re: [patch, avr, pr71676 and pr71678] Issues with casesi expand To: Georg-Johann Lay , GCC Patches References: <0b4dab65-8c26-fb81-c300-2064e02794e2@gjlay.de> <6ac98f18-c457-0e8c-2fab-8fb43f2c6016@microchip.com> <7bb387d0-f9a6-b8b1-0906-e349245f1377@gjlay.de> CC: Denis Chertykov Message-ID: <8fb8b56d-7eab-6aea-7f67-ae6598efc124@microchip.com> Date: Mon, 17 Oct 2016 12:57:22 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0 MIME-Version: 1.0 In-Reply-To: <7bb387d0-f9a6-b8b1-0906-e349245f1377@gjlay.de> 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 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 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; +} +