diff mbox

Fix PR31096

Message ID CO2PR07MB26941B6AA9C0417C2151C59B8E950@CO2PR07MB2694.namprd07.prod.outlook.com
State New
Headers show

Commit Message

Hurugalawadi, Naveen April 12, 2016, 8:25 a.m. UTC
Hi,

>> type is the return type of the comparison. The relevant type here is
TREE_TYPE (@0). 
Done.

>>Maybe add a testcase with unsigned, to check that it
does not transform?
Added the testcase

>> you could probably use tree_expr_nonzero_p
Done.
I had !wi::eq_p (@1, 0) for INTEGER_CST, but when tried to
use it for general, then used the integer_zerop

Please find attached the modified patch with all the modifications
and let me know if its okay?

Thanks,
Naveen

Comments

Marc Glisse April 12, 2016, 9:33 a.m. UTC | #1
On Tue, 12 Apr 2016, Hurugalawadi, Naveen wrote:

+/* Fold A * 10 == B * 10 into A == B.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && tree_expr_nonzero_p (@1))
+   (cmp @0 @2))))

(another case we could handle here (but that's for another time) is when 
TYPE_OVERFLOW_WRAPS and @1 is odd)

+/* Fold A * 10 < B * 10 into A < B.  */
+(for cmp (lt gt le ge)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && tree_expr_nonzero_p (@1))
+   (if (tree_expr_nonnegative_p (@1))
+    (cmp @0 @2)

Up to here it looks good to me (maybe someone has a better suggestion
than tree_expr_nonzero_p && tree_expr_nonnegative_p? I think we should
handle at least INTEGER_CST and SSA_NAME with VRP, and it seems natural
to add a VRP check in those 2 functions, expr_not_equal_to in the same
file already has one).

+   (if (!tree_expr_nonnegative_p (@1))
+    (cmp @2 @0))))))

No, same issue as before. !tree_expr_nonnegative_p means that we don't
know for sure that @1 is >=0, so it might be that we know @1 is
negative, or it might be that we simply have no idea, you cannot deduce
anything from it.  Ideally, you would call tree_expr_nonpositive_p,
except that that function doesn't exist yet. So for now, I guess we
could restrict to something like (untested)

if (TREE_CODE (@1) == INTEGER_CST && wi::lt_p (@1, 0))

+int
+f (int a, int b)
+{
+  return a > b;
+}

+int
+f3 (int a, int b)
+{
+  return a * 0 <= b * 0;
+}

Not sure what you are testing with those 2. The second one is optimized
to 'true' before it even reaches this pattern. Multiplying by a third
variable 'c' (where the compiler has no idea what the sign of c is)
could be nicer.

Then you'll need to wait for a real reviewer to show up.
diff mbox

Patch

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0f4bf7e..5922dbd 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9177,7 +9177,7 @@  tree_expr_nonzero_warnv_p (tree t, bool *strict_overflow_p)
 /* Return true when T is an address and is known to be nonzero.
    Handle warnings about undefined signed overflow.  */
 
-static bool
+bool
 tree_expr_nonzero_p (tree t)
 {
   bool ret, strict_overflow_p;
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 02f4270..8579622 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -167,6 +167,7 @@  extern tree size_diffop_loc (location_t, tree, tree);
 #define non_lvalue(T) non_lvalue_loc (UNKNOWN_LOCATION, T)
 extern tree non_lvalue_loc (location_t, tree);
 
+extern bool tree_expr_nonzero_p (tree);
 extern bool tree_expr_nonnegative_p (tree);
 extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
 extern tree make_range (tree, int *, tree *, tree *, bool *);
diff --git a/gcc/match.pd b/gcc/match.pd
index 75aa601..479a3a3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -31,6 +31,7 @@  along with GCC; see the file COPYING3.  If not see
    zerop
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
+   tree_expr_nonzero_p
    integer_valued_real_p
    integer_pow2p
    HONOR_NANS)
@@ -894,7 +895,26 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       && tree_nop_conversion_p (type, TREE_TYPE (@1)))
   (convert (bit_and (bit_not @1) @0))))
 
+/* Fold A * 10 == B * 10 into A == B.  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && tree_expr_nonzero_p (@1))
+   (cmp @0 @2))))
 
+/* Fold A * 10 < B * 10 into A < B.  */
+(for cmp (lt gt le ge)
+ (simplify
+  (cmp (mult:c @0 @1) (mult:c @2 @1))
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+       && tree_expr_nonzero_p (@1))
+   (if (tree_expr_nonnegative_p (@1))
+    (cmp @0 @2)
+   (if (!tree_expr_nonnegative_p (@1))
+    (cmp @2 @0))))))
 
 /* ((X inner_op C0) outer_op C1)
    With X being a tree where value_range has reasoned certain bits to always be
diff --git a/gcc/testsuite/gcc.dg/pr31096-1.c b/gcc/testsuite/gcc.dg/pr31096-1.c
new file mode 100644
index 0000000..5f62ddc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096-1.c
@@ -0,0 +1,29 @@ 
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" }  */
+
+int
+f (int a, int b)
+{
+  return a > b;
+}
+
+int
+f1 (int a, int b)
+{
+  return a * 10 >= b * 10;
+}
+
+int
+f2 (int a, int b)
+{
+  return a * -42 <  b * -42;
+}
+
+int
+f3 (int a, int b)
+{
+  return a * 0 <= b * 0;
+}
+
+/* { dg-final { scan-tree-dump-not "\\(D\\) \\*" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr31096-2.c b/gcc/testsuite/gcc.dg/pr31096-2.c
new file mode 100644
index 0000000..ec51817
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096-2.c
@@ -0,0 +1,29 @@ 
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" }  */
+
+int
+f (unsigned int a, unsigned int b)
+{
+  return a == b;
+}
+
+int
+f1 (unsigned int a, unsigned int b)
+{
+  return a * 10 == b * 10;
+}
+
+int
+f2 (unsigned int a, unsigned int b)
+{
+  return a * -42 <  b * -42;
+}
+
+int
+f3 (unsigned int a, unsigned int b)
+{
+  return a * 0 <= b * 0;
+}
+
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\*" 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr31096.c b/gcc/testsuite/gcc.dg/pr31096.c
new file mode 100644
index 0000000..90cb71b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096.c
@@ -0,0 +1,29 @@ 
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" }  */
+
+int
+f (int a, int b)
+{
+  return a == b;
+}
+
+int
+f1 (int a, int b)
+{
+  return a * 10 == b * 10;
+}
+
+int
+f2 (int a, int b)
+{
+  return a * -42 !=  b * -42;
+}
+
+int
+f3 (int a, int b)
+{
+  return a * 0 != b * 0;
+}
+
+/* { dg-final { scan-tree-dump-not "\\(D\\) \\*" "optimized" } } */