From 973dfbb4a63ba7c580e4de0c99b4970ef159631c Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Sat, 6 May 2017 09:03:40 -0600 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c | 38 +++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c | 36 ++++++++++++ gcc/tree-vrp.c | 55 ++++++++++++++++++- 5 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b0c253b09ae..0f78f2a2ed1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-05-06 Jeff Law + + 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 * lra-constraints.c (lra_copy_reg_equiv): New function. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fca5b87e798..42782a6d17c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-05-06 Jeff Law + + 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 * gcc.target/aarch64/spill_1.c: New test. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c new file mode 100644 index 00000000000..78c349ca14d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-16.c @@ -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: + ; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c new file mode 100644 index 00000000000..692658fbb4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-17.c @@ -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 (); +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index cf50e908257..461a48f5c9c 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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 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; }