Move "X +- C1 CMP C2 to X CMP C2 -+ C1" to match.pd
authorMarc Glisse <marc.glisse@inria.fr>
Mon, 2 May 2016 14:09:07 +0000 (16:09 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Mon, 2 May 2016 14:09:07 +0000 (14:09 +0000)
2016-05-02  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* flag-types.h (enum warn_strict_overflow_code): Move ...
* coretypes.h: ... here.
* fold-const.h (fold_overflow_warning): Declare.
* fold-const.c (fold_overflow_warning): Make non-static.
(fold_comparison): Move the transformation of X +- C1 CMP C2
into X CMP C2 -+ C1 ...
* match.pd: ... here.
* gimple-fold.c (fold_stmt_1): Protect with
fold_defer_overflow_warnings.

gcc/testsuite/
* gcc.dg/tree-ssa/20040305-1.c: Adjust.

From-SVN: r235760

gcc/ChangeLog
gcc/coretypes.h
gcc/flag-types.h
gcc/fold-const.c
gcc/fold-const.h
gcc/gimple-fold.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c

index ff0b573b0c927ed2d906b77cf3c2edd3777ef067..10bf855f351f6fdcf7f28351f45ca8cc33dc0e61 100644 (file)
@@ -1,3 +1,15 @@
+2016-05-02  Marc Glisse  <marc.glisse@inria.fr>
+
+       * flag-types.h (enum warn_strict_overflow_code): Move ...
+       * coretypes.h: ... here.
+       * fold-const.h (fold_overflow_warning): Declare.
+       * fold-const.c (fold_overflow_warning): Make non-static.
+       (fold_comparison): Move the transformation of X +- C1 CMP C2
+       into X CMP C2 -+ C1 ...
+       * match.pd: ... here.
+       * gimple-fold.c (fold_stmt_1): Protect with
+       fold_defer_overflow_warnings.
+
 2016-05-02  Nathan Sidwell  <nathan@codesourcery.com>
 
        * omp-low.c (struct oacc_loop): Add 'inner' field.
index 12067fdf53486da006fe32e86da2f5ee9cc9d3d3..2932d73e2614c94f55b11b8854b3e84912314093 100644 (file)
@@ -222,6 +222,30 @@ enum var_init_status
   VAR_INIT_STATUS_INITIALIZED
 };
 
+/* Names for the different levels of -Wstrict-overflow=N.  The numeric
+   values here correspond to N.  */
+enum warn_strict_overflow_code
+{
+  /* Overflow warning that should be issued with -Wall: a questionable
+     construct that is easy to avoid even when using macros.  Example:
+     folding (x + CONSTANT > x) to 1.  */
+  WARN_STRICT_OVERFLOW_ALL = 1,
+  /* Overflow warning about folding a comparison to a constant because
+     of undefined signed overflow, other than cases covered by
+     WARN_STRICT_OVERFLOW_ALL.  Example: folding (abs (x) >= 0) to 1
+     (this is false when x == INT_MIN).  */
+  WARN_STRICT_OVERFLOW_CONDITIONAL = 2,
+  /* Overflow warning about changes to comparisons other than folding
+     them to a constant.  Example: folding (x + 1 > 1) to (x > 0).  */
+  WARN_STRICT_OVERFLOW_COMPARISON = 3,
+  /* Overflow warnings not covered by the above cases.  Example:
+     folding ((x * 10) / 5) to (x * 2).  */
+  WARN_STRICT_OVERFLOW_MISC = 4,
+  /* Overflow warnings about reducing magnitude of constants in
+     comparison.  Example: folding (x + 2 > y) to (x + 1 >= y).  */
+  WARN_STRICT_OVERFLOW_MAGNITUDE = 5
+};
+
 /* The type of an alias set.  Code currently assumes that variables of
    this type can take the values 0 (the alias set which aliases
    everything) and -1 (sometimes indicating that the alias set is
index 820167636216d683ec8550c42d677f3a090dccfb..dd57e167098a334f193b4f072e45feecd975dedf 100644 (file)
@@ -178,30 +178,6 @@ enum stack_check_type
   FULL_BUILTIN_STACK_CHECK
 };
 
-/* Names for the different levels of -Wstrict-overflow=N.  The numeric
-   values here correspond to N.  */
-enum warn_strict_overflow_code
-{
-  /* Overflow warning that should be issued with -Wall: a questionable
-     construct that is easy to avoid even when using macros.  Example:
-     folding (x + CONSTANT > x) to 1.  */
-  WARN_STRICT_OVERFLOW_ALL = 1,
-  /* Overflow warning about folding a comparison to a constant because
-     of undefined signed overflow, other than cases covered by
-     WARN_STRICT_OVERFLOW_ALL.  Example: folding (abs (x) >= 0) to 1
-     (this is false when x == INT_MIN).  */
-  WARN_STRICT_OVERFLOW_CONDITIONAL = 2,
-  /* Overflow warning about changes to comparisons other than folding
-     them to a constant.  Example: folding (x + 1 > 1) to (x > 0).  */
-  WARN_STRICT_OVERFLOW_COMPARISON = 3,
-  /* Overflow warnings not covered by the above cases.  Example:
-     folding ((x * 10) / 5) to (x * 2).  */
-  WARN_STRICT_OVERFLOW_MISC = 4,
-  /* Overflow warnings about reducing magnitude of constants in
-     comparison.  Example: folding (x + 2 > y) to (x + 1 >= y).  */
-  WARN_STRICT_OVERFLOW_MAGNITUDE = 5
-};
-
 /* Floating-point contraction mode.  */
 enum fp_contract_mode {
   FP_CONTRACT_OFF = 0,
index 3c389ee446e48381a8502d48a1f2ead4743a4c34..0004f789d53269ade669457a8e6475e43b9cf76c 100644 (file)
@@ -297,7 +297,7 @@ fold_deferring_overflow_warnings_p (void)
 /* This is called when we fold something based on the fact that signed
    overflow is undefined.  */
 
-static void
+void
 fold_overflow_warning (const char* gmsgid, enum warn_strict_overflow_code wc)
 {
   if (fold_deferring_overflow_warnings > 0)
@@ -8392,75 +8392,6 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
   STRIP_SIGN_NOPS (arg0);
   STRIP_SIGN_NOPS (arg1);
 
-  /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1.  */
-  if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-      && (equality_code
-         || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg0))
-             && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))))
-      && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
-      && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
-      && TREE_CODE (arg1) == INTEGER_CST
-      && !TREE_OVERFLOW (arg1))
-    {
-      const enum tree_code
-       reverse_op = TREE_CODE (arg0) == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR;
-      tree const1 = TREE_OPERAND (arg0, 1);
-      tree const2 = fold_convert_loc (loc, TREE_TYPE (const1), arg1);
-      tree variable = TREE_OPERAND (arg0, 0);
-      tree new_const = int_const_binop (reverse_op, const2, const1);
-
-      /* If the constant operation overflowed this can be
-        simplified as a comparison against INT_MAX/INT_MIN.  */
-      if (TREE_OVERFLOW (new_const)
-         && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0)))
-       {
-         int const1_sgn = tree_int_cst_sgn (const1);
-         enum tree_code code2 = code;
-
-         /* Get the sign of the constant on the lhs if the
-            operation were VARIABLE + CONST1.  */
-         if (TREE_CODE (arg0) == MINUS_EXPR)
-           const1_sgn = -const1_sgn;
-
-         /* The sign of the constant determines if we overflowed
-            INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1).
-            Canonicalize to the INT_MIN overflow by swapping the comparison
-            if necessary.  */
-         if (const1_sgn == -1)
-           code2 = swap_tree_comparison (code);
-
-         /* We now can look at the canonicalized case
-              VARIABLE + 1  CODE2  INT_MIN
-            and decide on the result.  */
-         switch (code2)
-           {
-           case EQ_EXPR:
-           case LT_EXPR:
-           case LE_EXPR:
-             return
-               omit_one_operand_loc (loc, type, boolean_false_node, variable);
-
-           case NE_EXPR:
-           case GE_EXPR:
-           case GT_EXPR:
-             return
-               omit_one_operand_loc (loc, type, boolean_true_node, variable);
-
-           default:
-             gcc_unreachable ();
-           }
-       }
-      else
-       {
-         if (!equality_code)
-           fold_overflow_warning ("assuming signed overflow does not occur "
-                                  "when changing X +- C1 cmp C2 to "
-                                  "X cmp C2 -+ C1",
-                                  WARN_STRICT_OVERFLOW_COMPARISON);
-         return fold_build2_loc (loc, code, type, variable, new_const);
-       }
-    }
-
   /* For comparisons of pointers we can decompose it to a compile time
      comparison of the base objects and the offsets into the object.
      This requires at least one operand being an ADDR_EXPR or a
index 02f42709c4e0eec08f06311a7f6ebd023775af53..637e46b0d48788217196ba53110b69d302b17db7 100644 (file)
@@ -86,6 +86,7 @@ extern void fold_defer_overflow_warnings (void);
 extern void fold_undefer_overflow_warnings (bool, const gimple *, int);
 extern void fold_undefer_and_ignore_overflow_warnings (void);
 extern bool fold_deferring_overflow_warnings_p (void);
+extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code);
 extern int operand_equal_p (const_tree, const_tree, unsigned int);
 extern int multiple_of_p (tree, const_tree, const_tree);
 #define omit_one_operand(T1,T2,T3)\
index 5607598210b15197b49f48a1e3624560f1c33dac..d5e859c95737022808ce512965e6070caf0af817 100644 (file)
@@ -3525,7 +3525,9 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
 {
   bool changed = false;
   gimple *stmt = gsi_stmt (*gsi);
+  bool nowarning = gimple_no_warning_p (stmt);
   unsigned i;
+  fold_defer_overflow_warnings ();
 
   /* First do required canonicalization of [TARGET_]MEM_REF addresses
      after propagation.
@@ -3818,6 +3820,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
        }
     }
 
+  fold_undefer_overflow_warnings (changed && !nowarning, stmt, 0);
   return changed;
 }
 
index 608afa3e25eb885efcd4af002727bf0e8cc8ecdb..f1b1f15412568896f91f44f2ba01780d4da02b00 100644 (file)
@@ -3186,3 +3186,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (SIGNBIT @0)
  (if (!HONOR_SIGNED_ZEROS (@0))
   (convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); }))))
+
+/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1.  */
+(for cmp (eq ne)
+ (for op (plus minus)
+      rop (minus plus)
+  (simplify
+   (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+   (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+       && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+       && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0))
+       && !TYPE_SATURATING (TREE_TYPE (@0)))
+    (with { tree res = int_const_binop (rop, @2, @1); }
+     (if (TREE_OVERFLOW (res))
+      { constant_boolean_node (cmp == NE_EXPR, type); }
+      (if (single_use (@3))
+       (cmp @0 { res; }))))))))
+(for cmp (lt le gt ge)
+ (for op (plus minus)
+      rop (minus plus)
+  (simplify
+   (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+   (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+    (with { tree res = int_const_binop (rop, @2, @1); }
+     (if (TREE_OVERFLOW (res))
+      {
+       fold_overflow_warning (("assuming signed overflow does not occur "
+                               "when simplifying conditional to constant"),
+                              WARN_STRICT_OVERFLOW_CONDITIONAL);
+        bool less = cmp == LE_EXPR || cmp == LT_EXPR;
+       /* wi::ges_p (@2, 0) should be sufficient for a signed type.  */
+       bool ovf_high = wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1)))
+                       != (op == MINUS_EXPR);
+       constant_boolean_node (less == ovf_high, type);
+      }
+      (if (single_use (@3))
+       (with
+       {
+         fold_overflow_warning (("assuming signed overflow does not occur "
+                                 "when changing X +- C1 cmp C2 to "
+                                 "X cmp C2 -+ C1"),
+                                WARN_STRICT_OVERFLOW_COMPARISON);
+       }
+       (cmp @0 { res; })))))))))
index 27a5972024ea7deea77ad677e045a9b74b1582cc..f40758432842b288d2c4796f799f624f88f87398 100644 (file)
@@ -1,3 +1,7 @@
+2016-05-02  Marc Glisse  <marc.glisse@inria.fr>
+
+       * gcc.dg/tree-ssa/20040305-1.c: Adjust.
+
 2016-05-02  Nathan Sidwell  <nathan@codesourcery.com>
 
        * c-c++-common/goacc/loop-auto-1.c: Adjust expected warnings.
index d00acba07e42e438af9c49c2aa2038bdc7ead484..501e28cff54df34998a3c278238c2ee20d39ecfb 100644 (file)
@@ -23,7 +23,7 @@ void foo(int edx, int eax)
  
 
 /* Verify that we did a forward propagation.  */
-/* { dg-final { scan-tree-dump-times "Replaced" 1 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "gimple_simplified" 1 "forwprop1"} } */
 
 /* After cddce we should have two IF statements remaining as the other
    two tests can be threaded.  */