aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2022-02-15 10:17:26 -0500
committerAndrew MacLeod <amacleod@redhat.com>2022-05-13 10:20:15 -0400
commitcf2141a0c640fc9b1c497db3f4d5b270f4b8252a (patch)
tree7a2d27079325d796a225a21adf13ea5b89907c08
parent0ee9a62ef4b718ce7a66051f768c2bf5e1b62263 (diff)
downloadgcc-cf2141a0c640fc9b1c497db3f4d5b270f4b8252a.zip
gcc-cf2141a0c640fc9b1c497db3f4d5b270f4b8252a.tar.gz
gcc-cf2141a0c640fc9b1c497db3f4d5b270f4b8252a.tar.bz2
Add relation between op1 & op2 to lhs_opN_relation API.
We use the relation between op1 and op2 to help fold a statement, but it was not provided to the lhs_op1_relation and lhs_op2_relation routines to determine if is also creates a relation between the LHS and either operand. gcc/ PR tree-optimization/104547 * gimple-range-fold.cc (fold_using_range::range_of_range_op): Add the op1/op2 relation to the relation call. * range-op.cc (*::lhs_op1_relation): Add param. (*::lhs_op2_relation): Ditto. (operator_minus::lhs_op1_relation): New. (range_relational_tests): Add relation param. * range-op.h (lhs_op1_relation, lhs_op2_relation): Adjust prototype. gcc/testsuite/ * g++.dg/pr104547.C: New.
-rw-r--r--gcc/gimple-range-fold.cc4
-rw-r--r--gcc/range-op.cc62
-rw-r--r--gcc/range-op.h7
-rw-r--r--gcc/testsuite/g++.dg/pr104547.C13
4 files changed, 68 insertions, 18 deletions
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 08d791a..bc8174e 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -640,13 +640,13 @@ fold_using_range::range_of_range_op (irange &r, gimple *s, fur_source &src)
}
if (gimple_range_ssa_p (op1))
{
- rel = handler->lhs_op1_relation (r, range1, range2);
+ rel = handler->lhs_op1_relation (r, range1, range2, rel);
if (rel != VREL_NONE)
src.register_relation (s, rel, lhs, op1);
}
if (gimple_range_ssa_p (op2))
{
- rel= handler->lhs_op2_relation (r, range1, range2);
+ rel= handler->lhs_op2_relation (r, range1, range2, rel);
if (rel != VREL_NONE)
src.register_relation (s, rel, lhs, op2);
}
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index eaa0230..d015b9f 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -249,7 +249,8 @@ range_operator::op2_range (irange &r ATTRIBUTE_UNUSED,
enum tree_code
range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1 ATTRIBUTE_UNUSED,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return VREL_NONE;
}
@@ -257,7 +258,8 @@ range_operator::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
enum tree_code
range_operator::lhs_op2_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1 ATTRIBUTE_UNUSED,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind rel ATTRIBUTE_UNUSED) const
{
return VREL_NONE;
}
@@ -1182,9 +1184,11 @@ public:
const wide_int &rh_lb,
const wide_int &rh_ub) const;
virtual enum tree_code lhs_op1_relation (const irange &lhs, const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel) const;
virtual enum tree_code lhs_op2_relation (const irange &lhs, const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel) const;
} op_plus;
// Check to see if the range of OP2 indicates anything about the relation
@@ -1193,7 +1197,8 @@ public:
enum tree_code
operator_plus::lhs_op1_relation (const irange &lhs,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind) const
{
if (lhs.undefined_p () || op1.undefined_p () || op2.undefined_p ())
return VREL_NONE;
@@ -1258,9 +1263,9 @@ operator_plus::lhs_op1_relation (const irange &lhs,
enum tree_code
operator_plus::lhs_op2_relation (const irange &lhs, const irange &op1,
- const irange &op2) const
+ const irange &op2, relation_kind rel) const
{
- return lhs_op1_relation (lhs, op2, op1);
+ return lhs_op1_relation (lhs, op2, op1, rel);
}
void
@@ -1310,6 +1315,10 @@ public:
const wide_int &lh_ub,
const wide_int &rh_lb,
const wide_int &rh_ub) const;
+ virtual enum tree_code lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2,
+ relation_kind rel) const;
virtual bool op1_op2_relation_effect (irange &lhs_range,
tree type,
const irange &op1_range,
@@ -1329,6 +1338,27 @@ operator_minus::wi_fold (irange &r, tree type,
value_range_with_overflow (r, type, new_lb, new_ub, ov_lb, ov_ub);
}
+
+// Return the relation between LHS and OP1 based on the relation between
+// OP1 and OP2.
+
+enum tree_code
+operator_minus::lhs_op1_relation (const irange &lhs, const irange &,
+ const irange &, relation_kind rel) const
+{
+ if (TYPE_SIGN (lhs.type ()) == UNSIGNED)
+ switch (rel)
+ {
+ case GT_EXPR:
+ return LT_EXPR;
+ case GE_EXPR:
+ return LE_EXPR;
+ default:
+ break;
+ }
+ return VREL_NONE;
+}
+
// Check to see if the relation REL between OP1 and OP2 has any effect on the
// LHS of the expression. If so, apply it to LHS_RANGE. This is a helper
// function for both MINUS_EXPR and POINTER_DIFF_EXPR.
@@ -1899,14 +1929,16 @@ public:
relation_kind rel = VREL_NONE) const;
virtual enum tree_code lhs_op1_relation (const irange &lhs,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel) const;
} op_rshift;
enum tree_code
operator_rshift::lhs_op1_relation (const irange &lhs ATTRIBUTE_UNUSED,
const irange &op1,
- const irange &op2) const
+ const irange &op2,
+ relation_kind) const
{
// If both operands range are >= 0, then the LHS <= op1.
if (!op1.undefined_p () && !op2.undefined_p ()
@@ -3532,7 +3564,8 @@ public:
relation_kind rel = VREL_NONE) const;
virtual enum tree_code lhs_op1_relation (const irange &lhs,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel) const;
} op_identity;
// Determine if there is a relationship between LHS and OP1.
@@ -3540,7 +3573,8 @@ public:
enum tree_code
operator_identity::lhs_op1_relation (const irange &lhs,
const irange &op1 ATTRIBUTE_UNUSED,
- const irange &op2 ATTRIBUTE_UNUSED) const
+ const irange &op2 ATTRIBUTE_UNUSED,
+ relation_kind) const
{
if (lhs.undefined_p ())
return VREL_NONE;
@@ -4427,19 +4461,19 @@ range_relational_tests ()
int_range<2> op2 (UCHAR (20), UCHAR (20));
// Never wrapping additions mean LHS > OP1.
- tree_code code = op_plus.lhs_op1_relation (lhs, op1, op2);
+ tree_code code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
ASSERT_TRUE (code == GT_EXPR);
// Most wrapping additions mean nothing...
op1 = int_range<2> (UCHAR (8), UCHAR (10));
op2 = int_range<2> (UCHAR (0), UCHAR (255));
- code = op_plus.lhs_op1_relation (lhs, op1, op2);
+ code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
ASSERT_TRUE (code == VREL_NONE);
// However, always wrapping additions mean LHS < OP1.
op1 = int_range<2> (UCHAR (1), UCHAR (255));
op2 = int_range<2> (UCHAR (255), UCHAR (255));
- code = op_plus.lhs_op1_relation (lhs, op1, op2);
+ code = op_plus.lhs_op1_relation (lhs, op1, op2, VREL_NONE);
ASSERT_TRUE (code == LT_EXPR);
}
diff --git a/gcc/range-op.h b/gcc/range-op.h
index c93eb84..a1f98cd 100644
--- a/gcc/range-op.h
+++ b/gcc/range-op.h
@@ -78,12 +78,15 @@ public:
// The following routines are used to represent relations between the
// various operations. If the caller knows where the symbolics are,
// it can query for relationships between them given known ranges.
+ // the optional relation passed in is the relation between op1 and op2.
virtual enum tree_code lhs_op1_relation (const irange &lhs,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual enum tree_code lhs_op2_relation (const irange &lhs,
const irange &op1,
- const irange &op2) const;
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
virtual enum tree_code op1_op2_relation (const irange &lhs) const;
protected:
// Perform an integral operation between 2 sub-ranges and return it.
diff --git a/gcc/testsuite/g++.dg/pr104547.C b/gcc/testsuite/g++.dg/pr104547.C
new file mode 100644
index 0000000..b6135ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr104547.C
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-O3 -fdump-tree-vrp2" }
+
+#include <vector>
+
+void shrink(std::vector<int>& v, unsigned n) {
+ if (v.size() < n)
+ __builtin_unreachable();
+ v.resize(v.size() - n);
+}
+
+// Verify that std::vector<T>::_M_default_append() has been removed by vrp2.
+// { dg-final { scan-tree-dump-not "_M_default_append" vrp2 } }