Hi,
>> I think we should handle at least INTEGER_CST and SSA_NAME
>> with VRP, and it seems natural to add a VRP check
The check should be added in the tree_single_nonzero_warnv_p
for SSA_NAME case for tree_expr_nonzero_p.
However, for tree_expr_nonnegative_p, its been handled in a
different way. Should we combine this check with the existing one?
+ (if (!tree_expr_nonnegative_p (@1))
+ (cmp @2 @0))))))
>> Ideally, you would call tree_expr_nonpositive_p, except that that
>> function doesn't exist yet. So for now, I guess we
Would the tree_expr_nonpositive_p function be helpful for other cases
as well, I would try to add it if its useful.
Please find attached the modified patch as per the suggestions and
let me know if its fine?
Thanks,
Naveen
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..6655a3c 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,27 @@ 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_CODE (@1) == INTEGER_CST
+ && wi::lt_p (@1, 0, TYPE_SIGN (TREE_TYPE (@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.c b/gcc/testsuite/gcc.dg/pr31096.c
new file mode 100644
index 0000000..72446bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr31096.c
@@ -0,0 +1,41 @@
+/* PR middle-end/31096 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+f (int a, int b)
+{
+ return a * 67 == b * 67;
+}
+
+int
+f1 (int a, int b)
+{
+ return a * -42 != b * -42;
+}
+
+int
+f2 (int a, int b)
+{
+ return a * 10 >= b * 10;
+}
+
+int
+f3 (int a, int b)
+{
+ return a * -4 < b * -4;
+}
+
+int
+f4 (unsigned int a, unsigned int b)
+{
+ return a * 10 == b * 10;
+}
+
+int
+f5 (unsigned int a, unsigned int b)
+{
+ return a * -42 < b * -42;
+}
+
+/* { dg-final { scan-tree-dump-times "\\(D\\) \\*" 4 "optimized" } } */