From cf2141a0c640fc9b1c497db3f4d5b270f4b8252a Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 15 Feb 2022 10:17:26 -0500 Subject: [PATCH] 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. --- gcc/gimple-range-fold.cc | 4 +-- gcc/range-op.cc | 62 +++++++++++++++++++++++++++++++---------- gcc/range-op.h | 7 +++-- gcc/testsuite/g++.dg/pr104547.C | 13 +++++++++ 4 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr104547.C 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 + +void shrink(std::vector& v, unsigned n) { + if (v.size() < n) + __builtin_unreachable(); + v.resize(v.size() - n); +} + +// Verify that std::vector::_M_default_append() has been removed by vrp2. +// { dg-final { scan-tree-dump-not "_M_default_append" vrp2 } } -- 2.7.4