
Fix for the ICE of PR19293 and the "wrong-code" part
of PR19329.  These two bugs are subtly similar as
they all affect shift insns.

GCC 3.4 sometimes generates RTL code like this:

 (insn 46 65 49 (set (reg:QI 25 r25 [66])
        (ashift:QI (reg:QI 25 r25 [66])
            (const_int 0 [0x0]))) 57 {ashlqi3} (nil)
    (nil))

Even if shifts by 0 positions are somewhat bogus, the
documentation the for ashlqi3, ashrqui and lshrqi3 patterns
does not explicitly disallow it.  In this case the AVR backend
would inappropriately output a clr instruction (which is
otherwise correct for shifts 8 or more).

This patch only addresses the backend problem, so I think
PR19329 should remain open until someone else comes up with
a middle-end patch to eliminate the spurious shift by zero
positions.

Tested on mainline by comparing asm output on the test case
and a larger C application.  OK for mainline and 3.4?


gcc/
2005-01-23  Björn Haase  <bjoern.m.haase@web.de>
	    Bernardo Innocenti  <bernie@develer.com>
	    Giovanni Bajo  <rasky@develer.com>
	    Stefano Fedrigo  <aleph@develer.com>

	PR target/19293
	PR target/19329
	* config/avr/avr.c (ashlqi3_out, ashrqi3_out, lshrqi3_out): Handle
	shifts by 0 positions.
	(ashrhi3_out, ashrsi3_out, lshrhi3_out, lshrsi3_out): Handle out of
	range shift counts.



--- avr.c.orig	2004-12-31 14:57:13.000000000 +0100
+++ avr.c	2005-01-23 09:07:13.000000000 +0100
@@ -2870,17 +2870,21 @@ ashlqi3_out (rtx insn, rtx operands[], i
 
       switch (INTVAL (operands[2]))
 	{
 	default:
 	  *len = 1;
 	  return AS1 (clr,%0);
-	  
+
+	case 0:
+	  *len = 0;
+	  return "";
+
 	case 1:
 	  *len = 1;
 	  return AS1 (lsl,%0);
-	  
+
 	case 2:
 	  *len = 2;
 	  return (AS1 (lsl,%0) CR_TAB
 		  AS1 (lsl,%0));
 
 	case 3:
@@ -3315,12 +3319,16 @@ ashrqi3_out (rtx insn, rtx operands[], i
 
       if (!len)
 	len = &k;
 
       switch (INTVAL (operands[2]))
 	{
+	case 0:
+	  *len = 0;
+	  return "";
+
 	case 1:
 	  *len = 1;
 	  return AS1 (asr,%0);
 
 	case 2:
 	  *len = 2;
@@ -3379,16 +3387,23 @@ ashrhi3_out (rtx insn, rtx operands[], i
   if (GET_CODE (operands[2]) == CONST_INT)
     {
       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
       int k;
       int *t = len;
-      
+
       if (!len)
 	len = &k;
 
+      /* Test for out of range shift count.  */
+      if ((INTVAL (operands[2]) <= 0) || (INTVAL (operands[2]) >= 16))
+        {
+          *len = 0;
+          return "";
+        }
+
       switch (INTVAL (operands[2]))
 	{
 	case 4:
 	case 5:
 	  /* XXX try to optimize this too? */
 	  break;
@@ -3539,16 +3554,23 @@ const char *
 ashrsi3_out (rtx insn, rtx operands[], int *len)
 {
   if (GET_CODE (operands[2]) == CONST_INT)
     {
       int k;
       int *t = len;
-      
+
       if (!len)
 	len = &k;
-      
+
+      /* Test for out of range shift count.  */
+      if ((INTVAL (operands[2]) <= 0) || (INTVAL (operands[2]) >= 32))
+        {
+          *len = 0;
+          return "";
+        }
+
       switch (INTVAL (operands[2]))
 	{
 	case 8:
 	  {
 	    int reg0 = true_regnum (operands[0]);
 	    int reg1 = true_regnum (operands[1]);
@@ -3657,19 +3679,23 @@ lshrqi3_out (rtx insn, rtx operands[], i
   if (GET_CODE (operands[2]) == CONST_INT)
     {
       int k;
 
       if (!len)
 	len = &k;
-      
+
       switch (INTVAL (operands[2]))
 	{
 	default:
 	  *len = 1;
 	  return AS1 (clr,%0);
 
+	case 0:
+	  *len = 0;
+	  return "";
+
 	case 1:
 	  *len = 1;
 	  return AS1 (lsr,%0);
 
 	case 2:
 	  *len = 2;
@@ -3752,13 +3778,20 @@ lshrhi3_out (rtx insn, rtx operands[], i
       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
       int k;
       int *t = len;
 
       if (!len)
 	len = &k;
-      
+
+      /* Test for out of range shift count.  */
+      if ((INTVAL (operands[2]) <= 0) || (INTVAL (operands[2]) >= 16))
+        {
+          *len = 0;
+          return "";
+        }
+
       switch (INTVAL (operands[2]))
 	{
 	case 4:
 	  if (optimize_size && scratch)
 	    break;  /* 5 */
 	  if (ldi_ok)
@@ -3999,16 +4032,23 @@ const char *
 lshrsi3_out (rtx insn, rtx operands[], int *len)
 {
   if (GET_CODE (operands[2]) == CONST_INT)
     {
       int k;
       int *t = len;
-      
+
       if (!len)
 	len = &k;
-      
+
+      /* Test for out of range shift count.  */
+      if ((INTVAL (operands[2]) <= 0) || (INTVAL (operands[2]) >= 32))
+        {
+          *len = 0;
+          return "";
+        }
+
       switch (INTVAL (operands[2]))
 	{
 	case 8:
 	  {
 	    int reg0 = true_regnum (operands[0]);
 	    int reg1 = true_regnum (operands[1]);

