diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/gimple-range-gori.cc | 70 | ||||
-rw-r--r-- | gcc/range-op.cc | 4 | ||||
-rw-r--r-- | gcc/value-relation.cc | 34 | ||||
-rw-r--r-- | gcc/value-relation.h | 1 |
4 files changed, 62 insertions, 47 deletions
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc index 930e2a0..3dc4576 100644 --- a/gcc/gimple-range-gori.cc +++ b/gcc/gimple-range-gori.cc @@ -632,6 +632,9 @@ gori_compute::compute_operand_range (vrange &r, gimple *stmt, if (op1 && op2) { relation_kind k = handler.op1_op2_relation (lhs); + // If there is no relation, and op1 == op2, create a relation. + if (!vrel_ptr && k == VREL_VARYING && op1 == op2) + k = VREL_EQ; if (k != VREL_VARYING) { vrel.set_relation (k, op1, op2); @@ -952,7 +955,9 @@ gori_compute::refine_using_relation (tree op1, vrange &op1_range, { gcc_checking_assert (TREE_CODE (op1) == SSA_NAME); gcc_checking_assert (TREE_CODE (op2) == SSA_NAME); - gcc_checking_assert (k != VREL_VARYING && k != VREL_UNDEFINED); + + if (k == VREL_VARYING || k == VREL_EQ || k == VREL_UNDEFINED) + return false; bool change = false; bool op1_def_p = in_chain_p (op2, op1); @@ -991,7 +996,7 @@ gori_compute::refine_using_relation (tree op1, vrange &op1_range, Value_Range new_result (type); if (!op_handler.op1_range (new_result, type, op1_def_p ? op1_range : op2_range, - other_op, relation_trio::lhs_op2 (k))) + other_op, relation_trio::lhs_op1 (k))) return false; if (op1_def_p) { @@ -1023,7 +1028,7 @@ gori_compute::refine_using_relation (tree op1, vrange &op1_range, Value_Range new_result (type); if (!op_handler.op2_range (new_result, type, op1_def_p ? op1_range : op2_range, - other_op, relation_trio::lhs_op1 (k))) + other_op, relation_trio::lhs_op2 (k))) return false; if (op1_def_p) { @@ -1062,6 +1067,10 @@ gori_compute::compute_operand1_range (vrange &r, tree op2 = handler.operand2 (); tree lhs_name = gimple_get_lhs (stmt); + relation_trio trio; + if (rel) + trio = rel->create_trio (lhs_name, op1, op2); + Value_Range op1_range (TREE_TYPE (op1)); Value_Range tmp (TREE_TYPE (op1)); Value_Range op2_range (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1)); @@ -1073,27 +1082,11 @@ gori_compute::compute_operand1_range (vrange &r, if (op2) { src.get_operand (op2_range, op2); - relation_kind k = VREL_VARYING; - relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING; - if (rel) - { - if (lhs_name == rel->op1 () && op1 == rel->op2 ()) - k = rel->kind (); - else if (lhs_name == rel->op2 () && op1 == rel->op1 ()) - k = relation_swap (rel->kind ()); - else if (op1 == rel->op1 () && op2 == rel->op2 ()) - { - op_op = rel->kind (); - refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); - } - else if (op1 == rel->op2 () && op2 == rel->op1 ()) - { - op_op = relation_swap (rel->kind ()); - refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); - } - } - if (!handler.calc_op1 (tmp, lhs, op2_range, relation_trio (VREL_VARYING, - k, op_op))) + relation_kind op_op = trio.op1_op2 (); + if (op_op != VREL_VARYING) + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); + + if (!handler.calc_op1 (tmp, lhs, op2_range, trio)) return false; } else @@ -1101,7 +1094,7 @@ gori_compute::compute_operand1_range (vrange &r, // We pass op1_range to the unary operation. Nomally it's a // hidden range_for_type parameter, but sometimes having the // actual range can result in better information. - if (!handler.calc_op1 (tmp, lhs, op1_range, TRIO_VARYING)) + if (!handler.calc_op1 (tmp, lhs, op1_range, trio)) return false; } @@ -1172,29 +1165,16 @@ gori_compute::compute_operand2_range (vrange &r, src.get_operand (op1_range, op1); src.get_operand (op2_range, op2); - relation_kind k = VREL_VARYING; - relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING; + + relation_trio trio; if (rel) - { - if (lhs_name == rel->op1 () && op2 == rel->op2 ()) - k = rel->kind (); - else if (lhs_name == rel->op2 () && op2 == rel->op1 ()) - k = relation_swap (rel->kind ()); - else if (op1 == rel->op1 () && op2 == rel->op2 ()) - { - op_op = rel->kind (); - refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); - } - else if (op1 == rel->op2 () && op2 == rel->op1 ()) - { - op_op = relation_swap (rel->kind ()); - refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); - } - } + trio = rel->create_trio (lhs_name, op1, op2); + relation_kind op_op = trio.op1_op2 (); + if (op_op != VREL_VARYING) + refine_using_relation (op1, op1_range, op2, op2_range, src, op_op); // Intersect with range for op2 based on lhs and op1. - if (!handler.calc_op2 (tmp, lhs, op1_range, relation_trio (k, VREL_VARYING, - op_op))) + if (!handler.calc_op2 (tmp, lhs, op1_range, trio)) return false; unsigned idx; diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 6e5754e..ed2dd1e 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -1460,7 +1460,7 @@ operator_plus::op1_range (irange &r, tree type, if (!minus) return false; bool res = minus.fold_range (r, type, lhs, op2); - relation_kind rel = trio.lhs_op2 (); + relation_kind rel = trio.lhs_op1 (); // Check for a relation refinement. if (res) adjust_op1_for_overflow (r, op2, rel, true /* PLUS_EXPR */); @@ -1632,7 +1632,7 @@ operator_minus::op1_range (irange &r, tree type, if (!minus) return false; bool res = minus.fold_range (r, type, lhs, op2); - relation_kind rel = trio.lhs_op2 (); + relation_kind rel = trio.lhs_op1 (); if (res) adjust_op1_for_overflow (r, op2, rel, false /* PLUS_EXPR */); return res; diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 5ca8a7e..f5b1e67 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -883,6 +883,40 @@ value_relation::apply_transitive (const value_relation &rel) return false; } +// Create a trio from this value relation given LHS, OP1 and OP2. + +relation_trio +value_relation::create_trio (tree lhs, tree op1, tree op2) +{ + relation_kind lhs_1; + if (lhs == name1 && op1 == name2) + lhs_1 = related; + else if (lhs == name2 && op1 == name1) + lhs_1 = relation_swap (related); + else + lhs_1 = VREL_VARYING; + + relation_kind lhs_2; + if (lhs == name1 && op2 == name2) + lhs_2 = related; + else if (lhs == name2 && op2 == name1) + lhs_2 = relation_swap (related); + else + lhs_2 = VREL_VARYING; + + relation_kind op_op; + if (op1 == name1 && op2 == name2) + op_op = related; + else if (op1 == name2 && op2 == name1) + op_op = relation_swap (related); + else if (op1 == op2) + op_op = VREL_EQ; + else + op_op = VREL_VARYING; + + return relation_trio (lhs_1, lhs_2, op_op); +} + // Dump the relation to file F. void diff --git a/gcc/value-relation.h b/gcc/value-relation.h index 664fd71..340f9c4 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -426,6 +426,7 @@ public: inline tree op1 () const { return name1; } inline tree op2 () const { return name2; } + relation_trio create_trio (tree lhs, tree op1, tree op2); bool union_ (value_relation &p); bool intersect (value_relation &p); void negate (); |