void Switch4(int x) {
   switch (x & 7) {

   }
}
>>
.globl _Switch4
.def _Switch4; .scl 2; .type 32; .endef
_Switch4:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
andl $7, %eax
cmpl $7, %eax
ja L12
jmp *L11(,%eax,4)


cmpl+ja are redundant in both cases.
Do you think it is possible for gcc to optimize them away?

I believe VRP could be taught about inferring ranges from bit_and_expr and
similar operations. Right?

Yes, but the range check is not emitted until trees are expanded to RTL. combine does a lot of simplifications, but unfortunately not this one. It is also quite hard to teach combine to *remove* jumps, though it has some ability to turn conditional jumps into unconditional.

The attached patch would at least cause simplify-rtx.c to realize that (gtu (reg:SI 61) (const_int 7)) is false, but not cause any code generation improvement.

Paolo
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.230.2.6
diff -u -r1.230.2.6 simplify-rtx.c
--- simplify-rtx.c      24 Apr 2005 22:15:04 -0000      1.230.2.6
+++ simplify-rtx.c      22 Aug 2005 12:23:03 -0000
@@ -2912,6 +2912,7 @@
 
   if (GET_CODE (op1) == CONST_INT)
     {
+      HOST_WIDE_INT mask;
       if (INTVAL (op1) == 0 && COMPARISON_P (op0))
        {
          /* If op0 is a comparison, extract the comparison arguments form it.  
*/
@@ -2931,6 +2932,46 @@
                                                XEXP (op0, 0), XEXP (op0, 1));
            }
        }
+
+       
+      mask = nonzero_bits (op0, cmp_mode);
+      switch (code)
+       {
+       case GE:
+         if (mask < 0)
+           break;
+         /* fall through */
+       case GEU:
+          if (INTVAL (op1) > mask)
+           return const0_rtx;
+
+       case GT:
+         if (mask < 0)
+           break;
+         /* fall through */
+       case GTU:
+          if (INTVAL (op1) >= mask)
+           return const0_rtx;
+
+       case LE:
+         if (mask < 0)
+           break;
+         /* fall through */
+       case LEU:
+          if (INTVAL (op1) >= mask)
+           return const_true_rtx;
+
+       case LT:
+         if (mask < 0)
+           break;
+         /* fall through */
+       case LTU:
+          if (INTVAL (op1) > mask)
+           return const_true_rtx;
+         break;
+       default:
+         break;
+       }
     }
 
   /* (eq/ne (plus x cst1) cst2) simplifies to (eq/ne x (cst2 - cst1))  */

Reply via email to