re PR tree-optimization/78496 (Missed opportunities for jump threading)
PR tree-optimization/78496 * tree-vrp.c (simplify_assert_expr_using_ranges): New function. (simplify_stmt_using_ranges): Call it. (vrp_dom_walker::before_dom_children): Extract equivalences from an ASSERT_EXPR with an equality comparison against a constant. PR tree-optimization/78496 * gcc.dg/tree-ssa/ssa-thread-16.c: New test. * gcc.dg/tree-ssa/ssa-thread-17.c: New test. From-SVN: r247721
This commit is contained in:
parent
8ffa3150d3
commit
973dfbb4a6
@ -1,3 +1,12 @@
|
||||
2017-05-06 Jeff Law <law@redhat.com>
|
||||
|
||||
PR tree-optimization/78496
|
||||
* tree-vrp.c (simplify_assert_expr_using_ranges): New function.
|
||||
(simplify_stmt_using_ranges): Call it.
|
||||
(vrp_dom_walker::before_dom_children): Extract equivalences
|
||||
from an ASSERT_EXPR with an equality comparison against a
|
||||
constant.
|
||||
|
||||
2017-05-06 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* lra-constraints.c (lra_copy_reg_equiv): New function.
|
||||
|
@ -1,3 +1,9 @@
|
||||
2017-05-06 Jeff Law <law@redhat.com>
|
||||
|
||||
PR tree-optimization/78496
|
||||
* gcc.dg/tree-ssa/ssa-thread-16.c: New test.
|
||||
* gcc.dg/tree-ssa/ssa-thread-17.c: New test.
|
||||
|
||||
2017-05-06 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
* gcc.target/aarch64/spill_1.c: New test.
|
||||
|
38
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c
Normal file
38
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
/* We should thread the if (exp == 2) conditional on the
|
||||
the path from inside the if (x) THEN arm. It is the only
|
||||
jump threading opportunity in this code. */
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" } } */
|
||||
|
||||
|
||||
extern void abort (void) __attribute__ ((__nothrow__, __leaf__))
|
||||
__attribute__ ((__noreturn__));
|
||||
|
||||
int x;
|
||||
|
||||
|
||||
int code;
|
||||
void
|
||||
do_jump (int exp)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case 4:
|
||||
if ((exp) == 1)
|
||||
goto normal;
|
||||
if (x)
|
||||
{
|
||||
if (exp != 0)
|
||||
abort ();
|
||||
}
|
||||
if ((exp) == 2)
|
||||
goto normal;
|
||||
case 3:
|
||||
abort ();
|
||||
}
|
||||
normal:
|
||||
;
|
||||
}
|
36
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c
Normal file
36
gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c
Normal file
@ -0,0 +1,36 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
|
||||
|
||||
/* We should simplify one ASSERT_EXPR from a relational
|
||||
into an equality test. */
|
||||
/* { dg-final { scan-tree-dump-times "Folded into:\[^\r\n\]*ASSERT_EXPR\*\[^\r\n\]* == 1" 1 "vrp1" } } */
|
||||
|
||||
/* And simplification of the ASSERT_EXPR leads to a jump threading opportunity. */
|
||||
/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" } } */
|
||||
|
||||
extern void abort (void) __attribute__ ((__nothrow__, __leaf__))
|
||||
__attribute__ ((__noreturn__));
|
||||
|
||||
union gimple_statement_d;
|
||||
typedef union gimple_statement_d *gimple;
|
||||
|
||||
|
||||
|
||||
union gimple_statement_d
|
||||
{
|
||||
unsigned num_ops;
|
||||
};
|
||||
|
||||
void
|
||||
gimple_assign_set_rhs_with_ops_1 (int code, gimple stmt, unsigned new_rhs_ops)
|
||||
{
|
||||
|
||||
stmt->num_ops = new_rhs_ops + 1;
|
||||
if (stmt->num_ops <= 1)
|
||||
abort ();
|
||||
if (new_rhs_ops > 1)
|
||||
if (stmt->num_ops <= 2)
|
||||
abort ();
|
||||
if (new_rhs_ops > 2)
|
||||
abort ();
|
||||
}
|
@ -9600,6 +9600,43 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Simplify STMT, an ASSERT_EXPR, using ranges. This is helpful because jump
|
||||
threading looks at the ASSERT_EXPRs. Collapsing the condition of
|
||||
an ASSERT_EXPR from a relational to an equality test is where most
|
||||
of the benefit occurrs, so that's the only thing we currently do. */
|
||||
|
||||
static bool
|
||||
simplify_assert_expr_using_ranges (gimple *stmt)
|
||||
{
|
||||
return false;
|
||||
tree cond = TREE_OPERAND (gimple_assign_rhs1 (stmt), 1);
|
||||
tree_code code = TREE_CODE (cond);
|
||||
tree op0 = TREE_OPERAND (cond, 0);
|
||||
|
||||
/* The condition of the ASSERT_EXPR must be a simple relational
|
||||
between an SSA_NAME (with a range) and a constant. */
|
||||
if (TREE_CODE (op0) != SSA_NAME
|
||||
|| !INTEGRAL_TYPE_P (TREE_TYPE (op0)))
|
||||
return false;
|
||||
|
||||
tree op1 = TREE_OPERAND (cond, 1);
|
||||
if (TREE_CODE (op1) != INTEGER_CST)
|
||||
return false;
|
||||
|
||||
value_range *vr = get_value_range (op0);
|
||||
if (!vr || vr->type != VR_RANGE)
|
||||
return false;
|
||||
|
||||
tree res = test_for_singularity (code, op0, op1, vr);
|
||||
if (res)
|
||||
{
|
||||
TREE_SET_CODE (cond, EQ_EXPR);
|
||||
TREE_OPERAND (cond, 1) = res;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Simplify a conditional using a relational operator to an equality
|
||||
test if the range information indicates only one value can satisfy
|
||||
the original conditional. */
|
||||
@ -10334,6 +10371,9 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
|
||||
case MAX_EXPR:
|
||||
return simplify_min_or_max_using_ranges (gsi, stmt);
|
||||
|
||||
case ASSERT_EXPR:
|
||||
return simplify_assert_expr_using_ranges (stmt);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -10598,6 +10638,18 @@ vrp_dom_walker::before_dom_children (basic_block bb)
|
||||
{
|
||||
tree rhs1 = gimple_assign_rhs1 (stmt);
|
||||
tree cond = TREE_OPERAND (rhs1, 1);
|
||||
tree lhs = gimple_assign_lhs (stmt);
|
||||
m_const_and_copies->record_const_or_copy (lhs, TREE_OPERAND (rhs1, 0));
|
||||
|
||||
if (TREE_CODE (cond) == EQ_EXPR)
|
||||
{
|
||||
tree cond_op0 = TREE_OPERAND (cond, 0);
|
||||
tree cond_op1 = TREE_OPERAND (cond, 1);
|
||||
if (TREE_CODE (cond_op0) == SSA_NAME)
|
||||
m_const_and_copies->record_const_or_copy (cond_op0, cond_op1);
|
||||
continue;
|
||||
}
|
||||
|
||||
tree inverted = invert_truthvalue (cond);
|
||||
vec<cond_equivalence> p;
|
||||
p.create (3);
|
||||
@ -10605,9 +10657,6 @@ vrp_dom_walker::before_dom_children (basic_block bb)
|
||||
for (unsigned int i = 0; i < p.length (); i++)
|
||||
m_avail_exprs_stack->record_cond (&p[i]);
|
||||
|
||||
tree lhs = gimple_assign_lhs (stmt);
|
||||
m_const_and_copies->record_const_or_copy (lhs,
|
||||
TREE_OPERAND (rhs1, 0));
|
||||
p.release ();
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user