fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case, falltrought to assoc...
authorJan Hubicka <hubicka@freesoft.cz>
Fri, 15 Oct 1999 04:50:09 +0000 (06:50 +0200)
committerJeff Law <law@gcc.gnu.org>
Fri, 15 Oct 1999 04:50:09 +0000 (22:50 -0600)
        * fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case,
        falltrought to assocate code.
        Convert XOR to OR in code like (a&c1)^(a&c2) where c1 and c2 don't have
        bits in common.

        * combine.c (simplify_logical): Convert XOR to IOR if operands have
        no bits in common; remove XOR to ROTATE conversion.

From-SVN: r29998

gcc/ChangeLog
gcc/combine.c
gcc/fold-const.c

index 5f144b450d6df267ab06e7d4ec117b7b1e529f20..af463a9c3ae3806be131729ca2bbef84c6d653da 100644 (file)
@@ -1,3 +1,13 @@
+Thu Oct 14 19:44:08 1999  Jan Hubicka  <hubicka@freesoft.cz>
+
+       * fold-const.c (fold): Move bit_rotate code to the EXPR_PLUS case,
+       falltrought to assocate code.
+       Convert XOR to OR in code like (a&c1)^(a&c2) where c1 and c2 don't have
+       bits in common.
+
+       * combine.c (simplify_logical): Convert XOR to IOR if operands have
+       no bits in common; remove XOR to ROTATE conversion.
+
 Fri Oct 15 17:40:11 1999  Michael Hayes  <m.hayes@elec.canterbury.ac.nz>
 
        * config/c4x/c4x.h (c4x_va_start, c4x_va_arg): Declare.
index a7b9c0c6d4a6c2ee24c85595db317278d34cdd33..7273e8f237e207b23ee62fe0f2337fc0630ce2e1 100644 (file)
@@ -5163,6 +5163,15 @@ simplify_logical (x, last)
       break;
 
     case XOR:
+      /* If we are XORing two things that have no bits in common,
+        convert them into an IOR.  This helps to detect rotation encoded
+        using those methods and possibly other simplifications.  */
+
+      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && (nonzero_bits (op0, mode)
+             & nonzero_bits (op1, mode)) == 0)
+       return (gen_binary (IOR, mode, op0, op1));
+
       /* Convert (XOR (NOT x) (NOT y)) to (XOR x y).
         Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for
         (NOT y).  */
@@ -5232,20 +5241,6 @@ simplify_logical (x, last)
        return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
                                mode, XEXP (op0, 0), XEXP (op0, 1));
 
-      /* Convert (xor (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
-        mode size to (rotate A CX).  */
-
-      if (((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
-          || (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT))
-         && rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
-         && GET_CODE (XEXP (op0, 1)) == CONST_INT
-         && GET_CODE (XEXP (op1, 1)) == CONST_INT
-         && (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
-             == GET_MODE_BITSIZE (mode)))
-       return gen_rtx_ROTATE (mode, XEXP (op0, 0),
-                              (GET_CODE (op0) == ASHIFT
-                               ? XEXP (op0, 1) : XEXP (op1, 1)));
-
       break;
 
     default:
index e38aabde03c3083dad3f7813bc050ace4abff8d5..5ea6129de8046fb7bf966579718c08c8ebcbfe39 100644 (file)
@@ -4874,6 +4874,74 @@ fold (expr)
       else if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
        return non_lvalue (convert (type, arg0));
 
+     bit_rotate:
+      /* (A << C1) + (A >> C2) if A is unsigned and C1+C2 is the size of A
+        is a rotate of A by C1 bits.  */
+      /* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
+        is a rotate of A by B bits.  */
+      {
+        register enum tree_code code0, code1;
+        code0 = TREE_CODE (arg0);
+        code1 = TREE_CODE (arg1);
+        if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
+           || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
+           && operand_equal_p (TREE_OPERAND (arg0, 0),
+                               TREE_OPERAND (arg1,0), 0)
+           && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+         {
+           register tree tree01, tree11;
+           register enum tree_code code01, code11;
+
+           tree01 = TREE_OPERAND (arg0, 1);
+           tree11 = TREE_OPERAND (arg1, 1);
+           STRIP_NOPS (tree01);
+           STRIP_NOPS (tree11);
+           code01 = TREE_CODE (tree01);
+           code11 = TREE_CODE (tree11);
+           if (code01 == INTEGER_CST
+             && code11 == INTEGER_CST
+             && TREE_INT_CST_HIGH (tree01) == 0
+             && TREE_INT_CST_HIGH (tree11) == 0
+             && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
+               == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
+             return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
+                       code0 == LSHIFT_EXPR ? tree01 : tree11);
+           else if (code11 == MINUS_EXPR)
+             {
+               tree tree110, tree111;
+               tree110 = TREE_OPERAND (tree11, 0);
+               tree111 = TREE_OPERAND (tree11, 1);
+               STRIP_NOPS (tree110);
+               STRIP_NOPS (tree111);
+               if (TREE_CODE (tree110) == INTEGER_CST
+                   && TREE_INT_CST_HIGH (tree110) == 0
+                   && (TREE_INT_CST_LOW (tree110)
+                       == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+                   && operand_equal_p (tree01, tree111, 0))
+                 return build ((code0 == LSHIFT_EXPR 
+                                ? LROTATE_EXPR 
+                                : RROTATE_EXPR),
+                               type, TREE_OPERAND (arg0, 0), tree01);
+             }
+           else if (code01 == MINUS_EXPR)
+             {
+               tree tree010, tree011;
+               tree010 = TREE_OPERAND (tree01, 0);
+               tree011 = TREE_OPERAND (tree01, 1);
+               STRIP_NOPS (tree010);
+               STRIP_NOPS (tree011);
+               if (TREE_CODE (tree010) == INTEGER_CST
+                   && TREE_INT_CST_HIGH (tree010) == 0
+                   && (TREE_INT_CST_LOW (tree010)
+                       == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+                   && operand_equal_p (tree11, tree011, 0))
+                 return build ((code0 != LSHIFT_EXPR 
+                                ? LROTATE_EXPR 
+                                : RROTATE_EXPR),
+                                type, TREE_OPERAND (arg0, 0), tree11);
+             }
+         }
+      }
 
     associate:
       /* In most languages, can't associate operations on floats
@@ -5107,9 +5175,6 @@ fold (expr)
 
     case BIT_IOR_EXPR:
     bit_ior:
-      {
-      register enum tree_code code0, code1;
-
       if (integer_all_onesp (arg1))
        return omit_one_operand (type, arg1, arg0);
       if (integer_zerop (arg1))
@@ -5118,85 +5183,34 @@ fold (expr)
       if (t1 != NULL_TREE)
        return t1;
 
-     bit_rotate:
-      /* (A << C1) | (A >> C2) if A is unsigned and C1+C2 is the size of A
-        is a rotate of A by C1 bits.  */
-      /* (A << B) | (A >> (Z - B)) if A is unsigned and Z is the size of A
-        is a rotate of A by B bits.  */
-
-      /* Both transformations noted above also apply to when the inner
-        operation is an XOR.  */
-
-      code0 = TREE_CODE (arg0);
-      code1 = TREE_CODE (arg1);
-      if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
-         || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
-         && operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1,0), 0)
-         && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
-       {
-         register tree tree01, tree11;
-         register enum tree_code code01, code11;
-
-         tree01 = TREE_OPERAND (arg0, 1);
-         tree11 = TREE_OPERAND (arg1, 1);
-         STRIP_NOPS (tree01);
-         STRIP_NOPS (tree11);
-         code01 = TREE_CODE (tree01);
-         code11 = TREE_CODE (tree11);
-         if (code01 == INTEGER_CST
-           && code11 == INTEGER_CST
-           && TREE_INT_CST_HIGH (tree01) == 0
-           && TREE_INT_CST_HIGH (tree11) == 0
-           && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
-             == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
-           return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
-                     code0 == LSHIFT_EXPR ? tree01 : tree11);
-         else if (code11 == MINUS_EXPR)
-           {
-             tree tree110, tree111;
-             tree110 = TREE_OPERAND (tree11, 0);
-             tree111 = TREE_OPERAND (tree11, 1);
-             STRIP_NOPS (tree110);
-             STRIP_NOPS (tree111);
-             if (TREE_CODE (tree110) == INTEGER_CST
-                 && TREE_INT_CST_HIGH (tree110) == 0
-                 && (TREE_INT_CST_LOW (tree110)
-                     == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
-                 && operand_equal_p (tree01, tree111, 0))
-               return build ((code0 == LSHIFT_EXPR 
-                              ? LROTATE_EXPR 
-                              : RROTATE_EXPR),
-                             type, TREE_OPERAND (arg0, 0), tree01);
-           }
-         else if (code01 == MINUS_EXPR)
-           {
-             tree tree010, tree011;
-             tree010 = TREE_OPERAND (tree01, 0);
-             tree011 = TREE_OPERAND (tree01, 1);
-             STRIP_NOPS (tree010);
-             STRIP_NOPS (tree011);
-             if (TREE_CODE (tree010) == INTEGER_CST
-                 && TREE_INT_CST_HIGH (tree010) == 0
-                 && (TREE_INT_CST_LOW (tree010)
-                     == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0))))
-                 && operand_equal_p (tree11, tree011, 0))
-               return build ((code0 != LSHIFT_EXPR 
-                              ? LROTATE_EXPR 
-                              : RROTATE_EXPR),
-                              type, TREE_OPERAND (arg0, 0), tree11);
-           }
-       }
-
-      goto associate;
-      }
+      /* See if this can be simplified into a rotate first.  If that
+        is unsuccessful continue in the association code.  */
+      goto bit_rotate;
 
     case BIT_XOR_EXPR:
       if (integer_zerop (arg1))
        return non_lvalue (convert (type, arg0));
       if (integer_all_onesp (arg1))
        return fold (build1 (BIT_NOT_EXPR, type, arg0));
+
+      /* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
+         with a constant, and the two constants have no bits in common,
+        we should treat this as a BIT_IOR_EXPR since this may produce more
+        simplifications.  */
+      if (TREE_CODE (arg0) == BIT_AND_EXPR
+         && TREE_CODE (arg1) == BIT_AND_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+         && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
+         && integer_zerop (const_binop (BIT_AND_EXPR,
+                                        TREE_OPERAND (arg0, 1),
+                                        TREE_OPERAND (arg1, 1), 0)))
+        {
+           code = BIT_IOR_EXPR;
+          goto bit_ior;
+        }
+
       /* See if this can be simplified into a rotate first.  If that
-        is unsuccessful we will jump to the association code.  */
+        is unsuccessful continue in the association code.  */
       goto bit_rotate;
 
     case BIT_AND_EXPR: