using range_operator::op1_range;
using range_operator::op2_range;
using range_operator::update_bitmask;
+ using range_operator::op1_op2_relation_effect;
bool op1_range (irange &r, tree type,
const irange &lhs, const irange &op2,
relation_trio) const final override;
const wide_int &rh_ub) const final override;
bool wi_op_overflows (wide_int &res, tree type, const wide_int &w0,
const wide_int &w1) const final override;
+ bool op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &op1_range,
+ const irange &op2_range,
+ relation_kind rel) const final override;
void rv_fold (frange &r, tree type,
const REAL_VALUE_TYPE &lh_lb, const REAL_VALUE_TYPE &lh_ub,
}
}
+bool
+operator_mult::op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &,
+ const irange &,
+ relation_kind rel) const
+{
+ // a*a is nonnegative without overflow.
+ // tree_binary_nonnegative_p handles this in a similar way.
+ if (rel == VREL_EQ
+ && TYPE_OVERFLOW_UNDEFINED (type))
+ {
+ int_range<2> nonnegative;
+ nonnegative.set_nonnegative (type);
+ lhs_range.intersect (nonnegative);
+ return true;
+ }
+ return false;
+}
+
class operator_widen_mult_signed : public range_operator
{
public:
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-evrp-details" } */
+/* PR tree-optimization/23471 */
+
+int f(int a, int b)
+{
+ if (a == b)
+ {
+ int t = a*b;
+ return t < 0; /* Should be optimized to 0. */
+ }
+ return 0;
+}
+
+
+/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
+/* { dg-final { scan-tree-dump "Global Exported: t_" "evrp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-forwprop -fdump-tree-optimized -fdump-tree-evrp-details" } */
+/* PR tree-optimization/125513 */
+
+
+int f(int a)
+{
+ int t = a*a;
+ return t < 0; /* Should be optimized to 0. */
+}
+
+
+/* { dg-final { scan-tree-dump "return 0" "optimized" } } */
+/* { dg-final { scan-tree-dump "Global Exported: t_" "evrp" } } */