fold-const.c (fold_binary_loc): Move simplification of (X <<>> C1) & C2 ...
authorRichard Biener <rguenther@suse.de>
Thu, 25 Jun 2015 14:02:35 +0000 (14:02 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 25 Jun 2015 14:02:35 +0000 (14:02 +0000)
2015-06-25  Richard Biener  <rguenther@suse.de>

* fold-const.c (fold_binary_loc): Move simplification of
(X <<>> C1) & C2 ...
* match.pd: ... here.

* gcc.dg/tree-ssa/pr52631.c: Disable forwprop.

From-SVN: r224943

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr52631.c

index a414549449e62407e1d86d229722639df65ebff1..604b7635b061be7fa88e7c188a719794199ee95b 100644 (file)
@@ -1,3 +1,9 @@
+2015-06-25  Richard Biener  <rguenther@suse.de>
+
+       * fold-const.c (fold_binary_loc): Move simplification of
+       (X <<>> C1) & C2 ...
+       * match.pd: ... here.
+
 2015-06-25  Eric Botcazou  <ebotcazou@adacore.com>
 
        * lto-streamer-out.c (DFS::hash_scc): Fix typos & formatting glitches.
index 60aa210496005041d7f8e7bf1920dad9e79b898f..6fa784a17cbf704975b62c4f8162113386cbf2a9 100644 (file)
@@ -11516,106 +11516,6 @@ fold_binary_loc (location_t loc,
            return build_int_cst (type, residue & low);
        }
 
-      /* Fold (X << C1) & C2 into (X << C1) & (C2 | ((1 << C1) - 1))
-             (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1))
-        if the new mask might be further optimized.  */
-      if ((TREE_CODE (arg0) == LSHIFT_EXPR
-          || TREE_CODE (arg0) == RSHIFT_EXPR)
-         && TYPE_PRECISION (TREE_TYPE (arg0)) <= HOST_BITS_PER_WIDE_INT
-         && TREE_CODE (arg1) == INTEGER_CST
-         && tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
-         && tree_to_uhwi (TREE_OPERAND (arg0, 1)) > 0
-         && (tree_to_uhwi (TREE_OPERAND (arg0, 1))
-             < TYPE_PRECISION (TREE_TYPE (arg0))))
-       {
-         unsigned int shiftc = tree_to_uhwi (TREE_OPERAND (arg0, 1));
-         unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (arg1);
-         unsigned HOST_WIDE_INT newmask, zerobits = 0;
-         tree shift_type = TREE_TYPE (arg0);
-
-         if (TREE_CODE (arg0) == LSHIFT_EXPR)
-           zerobits = ((((unsigned HOST_WIDE_INT) 1) << shiftc) - 1);
-         else if (TREE_CODE (arg0) == RSHIFT_EXPR
-                  && TYPE_PRECISION (TREE_TYPE (arg0))
-                     == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg0))))
-           {
-             prec = TYPE_PRECISION (TREE_TYPE (arg0));
-             tree arg00 = TREE_OPERAND (arg0, 0);
-             /* See if more bits can be proven as zero because of
-                zero extension.  */
-             if (TREE_CODE (arg00) == NOP_EXPR
-                 && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg00, 0))))
-               {
-                 tree inner_type = TREE_TYPE (TREE_OPERAND (arg00, 0));
-                 if (TYPE_PRECISION (inner_type)
-                     == GET_MODE_PRECISION (TYPE_MODE (inner_type))
-                     && TYPE_PRECISION (inner_type) < prec)
-                   {
-                     prec = TYPE_PRECISION (inner_type);
-                     /* See if we can shorten the right shift.  */
-                     if (shiftc < prec)
-                       shift_type = inner_type;
-                     /* Otherwise X >> C1 is all zeros, so we'll optimize
-                        it into (X, 0) later on by making sure zerobits
-                        is all ones.  */
-                   }
-               }
-             zerobits = ~(unsigned HOST_WIDE_INT) 0;
-             if (shiftc < prec)
-               {
-                 zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
-                 zerobits <<= prec - shiftc;
-               }
-             /* For arithmetic shift if sign bit could be set, zerobits
-                can contain actually sign bits, so no transformation is
-                possible, unless MASK masks them all away.  In that
-                case the shift needs to be converted into logical shift.  */
-             if (!TYPE_UNSIGNED (TREE_TYPE (arg0))
-                 && prec == TYPE_PRECISION (TREE_TYPE (arg0)))
-               {
-                 if ((mask & zerobits) == 0)
-                   shift_type = unsigned_type_for (TREE_TYPE (arg0));
-                 else
-                   zerobits = 0;
-               }
-           }
-
-         /* ((X << 16) & 0xff00) is (X, 0).  */
-         if ((mask & zerobits) == mask)
-           return omit_one_operand_loc (loc, type,
-                                        build_int_cst (type, 0), arg0);
-
-         newmask = mask | zerobits;
-         if (newmask != mask && (newmask & (newmask + 1)) == 0)
-           {
-             /* Only do the transformation if NEWMASK is some integer
-                mode's mask.  */
-             for (prec = BITS_PER_UNIT;
-                  prec < HOST_BITS_PER_WIDE_INT; prec <<= 1)
-               if (newmask == (((unsigned HOST_WIDE_INT) 1) << prec) - 1)
-                 break;
-             if (prec < HOST_BITS_PER_WIDE_INT
-                 || newmask == ~(unsigned HOST_WIDE_INT) 0)
-               {
-                 tree newmaskt;
-
-                 if (shift_type != TREE_TYPE (arg0))
-                   {
-                     tem = fold_build2_loc (loc, TREE_CODE (arg0), shift_type,
-                                        fold_convert_loc (loc, shift_type,
-                                                          TREE_OPERAND (arg0, 0)),
-                                        TREE_OPERAND (arg0, 1));
-                     tem = fold_convert_loc (loc, type, tem);
-                   }
-                 else
-                   tem = op0;
-                 newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
-                 if (!tree_int_cst_equal (newmaskt, arg1))
-                   return fold_build2_loc (loc, BIT_AND_EXPR, type, tem, newmaskt);
-               }
-           }
-       }
-
       goto associate;
 
     case RDIV_EXPR:
index 30383c649441687db7f3e68c9014d61e98ff349b..292ce6d75c690347a08a810aa91370de881ca467 100644 (file)
@@ -738,6 +738,97 @@ along with GCC; see the file COPYING3.  If not see
        && wi::eq_p (wi::lshift (@0, cand), @2))
     (cmp @1 { build_int_cst (TREE_TYPE (@1), cand); })))))
 
+/* Fold (X << C1) & C2 into (X << C1) & (C2 | ((1 << C1) - 1))
+        (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1))
+   if the new mask might be further optimized.  */
+(for shift (lshift rshift)
+ (simplify
+  (bit_and (convert?@4 (shift@5 (convert1?@3 @0) INTEGER_CST@1)) INTEGER_CST@2)
+   (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5))
+       && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT
+       && tree_fits_uhwi_p (@1)
+       && tree_to_uhwi (@1) > 0
+       && tree_to_uhwi (@1) < TYPE_PRECISION (type))
+    (with
+     {
+       unsigned int shiftc = tree_to_uhwi (@1);
+       unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (@2);
+       unsigned HOST_WIDE_INT newmask, zerobits = 0;
+       tree shift_type = TREE_TYPE (@3);
+       unsigned int prec;
+
+       if (shift == LSHIFT_EXPR)
+        zerobits = ((((unsigned HOST_WIDE_INT) 1) << shiftc) - 1);
+       else if (shift == RSHIFT_EXPR
+               && (TYPE_PRECISION (shift_type)
+                   == GET_MODE_PRECISION (TYPE_MODE (shift_type))))
+        {
+          prec = TYPE_PRECISION (TREE_TYPE (@3));
+          tree arg00 = @0;
+          /* See if more bits can be proven as zero because of
+             zero extension.  */
+          if (@3 != @0
+              && TYPE_UNSIGNED (TREE_TYPE (@0)))
+            {
+              tree inner_type = TREE_TYPE (@0);
+              if ((TYPE_PRECISION (inner_type)
+                   == GET_MODE_PRECISION (TYPE_MODE (inner_type)))
+                  && TYPE_PRECISION (inner_type) < prec)
+                {
+                  prec = TYPE_PRECISION (inner_type);
+                  /* See if we can shorten the right shift.  */
+                  if (shiftc < prec)
+                    shift_type = inner_type;
+                  /* Otherwise X >> C1 is all zeros, so we'll optimize
+                     it into (X, 0) later on by making sure zerobits
+                     is all ones.  */
+                }
+            }
+          zerobits = ~(unsigned HOST_WIDE_INT) 0;
+          if (shiftc < prec)
+            {
+              zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
+              zerobits <<= prec - shiftc;
+            }
+          /* For arithmetic shift if sign bit could be set, zerobits
+             can contain actually sign bits, so no transformation is
+             possible, unless MASK masks them all away.  In that
+             case the shift needs to be converted into logical shift.  */
+          if (!TYPE_UNSIGNED (TREE_TYPE (@3))
+              && prec == TYPE_PRECISION (TREE_TYPE (@3)))
+            {
+              if ((mask & zerobits) == 0)
+                shift_type = unsigned_type_for (TREE_TYPE (@3));
+              else
+                zerobits = 0;
+            }
+        }
+     }
+     /* ((X << 16) & 0xff00) is (X, 0).  */
+     (if ((mask & zerobits) == mask)
+      { build_int_cst (type, 0); })
+     (with { newmask = mask | zerobits; }
+      (if (newmask != mask && (newmask & (newmask + 1)) == 0)
+       (with
+       {
+         /* Only do the transformation if NEWMASK is some integer
+            mode's mask.  */
+         for (prec = BITS_PER_UNIT;
+              prec < HOST_BITS_PER_WIDE_INT; prec <<= 1)
+           if (newmask == (((unsigned HOST_WIDE_INT) 1) << prec) - 1)
+             break;
+       }
+       (if (prec < HOST_BITS_PER_WIDE_INT
+            || newmask == ~(unsigned HOST_WIDE_INT) 0)
+        (with
+         { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); }
+         (if (!tree_int_cst_equal (newmaskt, @2))
+          (if (shift_type != TREE_TYPE (@3)
+               && single_use (@4) && single_use (@5))
+           (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; }))
+          (if (shift_type == TREE_TYPE (@3))
+           (bit_and @4 { newmaskt; }))))))))))))
+
 /* Simplifications of conversions.  */
 
 /* Basic strip-useless-type-conversions / strip_nops.  */
index 2f3986877d27b107777b943c5caa6d113355ba13..b6486ac18e4cc1c95e15fbd8c83df6a23606d521 100644 (file)
@@ -1,3 +1,7 @@
+2015-06-25  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/pr52631.c: Disable forwprop.
+
 2015-06-25  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/aarch64/vect-add-sub-cond.c: New test.
index 59523ae0ddf167bb2ab93f6f0895bd9e9223219a..c18a5d570b446e62a8f77baaa6a12f47721bdf3f 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-fre1-details" } */
+/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-fre1-details" } */
 
 unsigned f(unsigned a)
 {