re PR target/18002 ('while' loop performace regression on avr target)
authorRoger Sayle <roger@eyesopen.com>
Sat, 11 Dec 2004 01:49:05 +0000 (01:49 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sat, 11 Dec 2004 01:49:05 +0000 (01:49 +0000)
PR target/18002
PR middle-end/18424
* dojump.c (do_jump): When attempting to reverse the effects of
fold_single_bit_test, we need to STRIP_NOPS and narrowing type
conversions, and handle BIT_XOR_EXPR that's used to invert the
sense of the single bit test.

From-SVN: r92024

gcc/ChangeLog
gcc/dojump.c

index 971c24967ec75fdd106a199c2fd24f8d508c6029..4656a74f36f80451f363e9f1864191a87eaae9d2 100644 (file)
@@ -1,3 +1,12 @@
+2004-12-10  Roger Sayle  <roger@eyesopen.com>
+
+       PR target/18002
+       PR middle-end/18424
+       * dojump.c (do_jump): When attempting to reverse the effects of
+       fold_single_bit_test, we need to STRIP_NOPS and narrowing type
+       conversions, and handle BIT_XOR_EXPR that's used to invert the
+       sense of the single bit test.
+
 2004-12-10  Devang Patel  <dpatel@apple.com>
 
        PR 18732
index 27a3cd68cee05cadc298301637f641917e705d3b..93bcb8be41a1f2131ea8138f76e519af65182922 100644 (file)
@@ -218,24 +218,52 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
       /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
         See if the former is preferred for jump tests and restore it
         if so.  */
-      if (TREE_CODE (TREE_OPERAND (exp, 0)) == RSHIFT_EXPR
-         && integer_onep (TREE_OPERAND (exp, 1)))
+      if (integer_onep (TREE_OPERAND (exp, 1)))
        {
-         tree arg = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
-         tree shift = TREE_OPERAND (TREE_OPERAND (exp, 0), 1);
-         tree one = TREE_OPERAND (exp, 1);
-         tree argtype = TREE_TYPE (arg);
-         if (TREE_CODE (shift) == INTEGER_CST
-             && compare_tree_int (shift, 0) > 0
-             && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
-             && prefer_and_bit_test (TYPE_MODE (argtype),
-                                     TREE_INT_CST_LOW (shift)))
+         tree exp0 = TREE_OPERAND (exp, 0);
+         rtx set_label, clr_label;
+
+         /* Strip narrowing integral type conversions.  */
+         while ((TREE_CODE (exp0) == NOP_EXPR
+                 || TREE_CODE (exp0) == CONVERT_EXPR
+                 || TREE_CODE (exp0) == NON_LVALUE_EXPR)
+                && TREE_OPERAND (exp0, 0) != error_mark_node
+                && TYPE_PRECISION (TREE_TYPE (exp0))
+                   <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
+           exp0 = TREE_OPERAND (exp0, 0);
+
+         /* "exp0 ^ 1" inverts the sense of the single bit test.  */
+         if (TREE_CODE (exp0) == BIT_XOR_EXPR
+             && integer_onep (TREE_OPERAND (exp0, 1)))
            {
-             do_jump (build2 (BIT_AND_EXPR, argtype, arg,
-                              fold (build2 (LSHIFT_EXPR, argtype,
-                                            one, shift))),
-                      if_false_label, if_true_label);
-             break;
+             exp0 = TREE_OPERAND (exp0, 0);
+             clr_label = if_true_label;
+             set_label = if_false_label;
+           }
+         else
+           {
+             clr_label = if_false_label;
+             set_label = if_true_label;
+           }
+
+         if (TREE_CODE (exp0) == RSHIFT_EXPR)
+           {
+             tree arg = TREE_OPERAND (exp0, 0);
+             tree shift = TREE_OPERAND (exp0, 1);
+             tree argtype = TREE_TYPE (arg);
+             if (TREE_CODE (shift) == INTEGER_CST
+                 && compare_tree_int (shift, 0) >= 0
+                 && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
+                 && prefer_and_bit_test (TYPE_MODE (argtype),
+                                         TREE_INT_CST_LOW (shift)))
+               {
+                 HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
+                                      << TREE_INT_CST_LOW (shift);
+                 do_jump (build2 (BIT_AND_EXPR, argtype, arg,
+                                  build_int_cst_type (argtype, mask)),
+                          clr_label, set_label);
+                 break;
+               }
            }
        }