diff options
27 files changed, 270 insertions, 63 deletions
diff --git a/gcc/passes.def b/gcc/passes.def index d7a1f8c..9115da7 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -212,6 +212,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_merge_phi); NEXT_PASS (pass_thread_jumps); NEXT_PASS (pass_vrp, true /* warn_array_bounds_p */); + NEXT_PASS (pass_vrp_threader); NEXT_PASS (pass_dse); NEXT_PASS (pass_dce); /* pass_stdarg is always run and at this point we execute @@ -337,6 +338,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_strlen); NEXT_PASS (pass_thread_jumps); NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */); + NEXT_PASS (pass_vrp_threader); /* Threading can leave many const/copy propagations in the IL. Clean them up. Instead of just copy_prop, we use ccp to compute alignment and nonzero bits. */ diff --git a/gcc/testsuite/gcc.dg/torture/pr55107.c b/gcc/testsuite/gcc.dg/torture/pr55107.c index d757c04..2edb75f 100644 --- a/gcc/testsuite/gcc.dg/torture/pr55107.c +++ b/gcc/testsuite/gcc.dg/torture/pr55107.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-fno-split-loops" } */ +/* { dg-additional-options "-fno-split-loops -w" } */ typedef unsigned short uint16_t; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c index 5227c87..59663dd 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -fdump-tree-vrp1" } */ +/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */ void g (int); void g1 (int); @@ -27,4 +27,4 @@ f (long a, long b, long c, long d, long x) g (a); } -/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c index eaf89bb..0c2f6e0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -fdump-tree-vrp1" } */ +/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */ void g (void); void g1 (void); @@ -20,4 +20,4 @@ f (long a, long b, long c, long d, int x) } } -/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c index d5a1e0b..6a3d359 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -fdump-tree-vrp1" } */ +/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */ void g (void); void g1 (void); @@ -22,4 +22,4 @@ f (long a, long b, long c, long d, int x) } } -/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c index 53acabc..9bc4c6d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -fdump-tree-vrp1" } */ +/* { dg-options "-Ofast -fdump-tree-vrp-thread1" } */ void g (int); void g1 (int); @@ -37,4 +37,4 @@ f (long a, long b, long c, long d, int x) g (c + d); } -/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index b406566..51b3b7a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp1-details" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-vrp-thread1-details" } */ static int blocksize = 4096; @@ -39,6 +39,6 @@ void foo (void) statement. We also realize that the final bytes == 0 test is useless, and thread over it. We also know that toread != 0 is useless when entering while loop and thread over it. */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c index dab16ab..2caa1f5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-Ofast -fdump-tree-vrp1-details" } */ +/* { dg-options "-Ofast -fdump-tree-vrp-thread1-details" } */ typedef unsigned short u16; typedef unsigned char u8; @@ -56,6 +56,11 @@ main (int argc, char argv[]) return crc; } -/* { dg-final { scan-tree-dump-times "Registering jump thread" 3 "vrp1" } } */ -/* { dg-final { scan-tree-dump-not "joiner" "vrp1" } } */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ +/* Previously we had 3 jump threads, but one of them crossed loops. + The reason the old threader was allowing it, was because there was + an ASSERT_EXPR getting in the way. Without the ASSERT_EXPR, we + have an empty pre-header block as the final block in the thread, + which the threader will simply join with the next block which *is* + in a different loop. */ +/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ +/* { dg-final { scan-tree-dump-not "joiner" "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c index ddc53fb..0229a82 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c @@ -1,6 +1,6 @@ /* PR tree-optimization/61839. */ /* { dg-do run } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdisable-tree-evrp -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */ /* { dg-require-effective-target int32plus } */ __attribute__ ((noinline)) @@ -38,7 +38,11 @@ int main () } /* Scan for c = 972195717) >> [0, 1] in function foo. */ -/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp-thread1" } } */ + +/* Previously we were checking for two ?: with constant PHI arguments, + but now we collapse them into one. */ /* Scan for c = 972195717) >> [2, 3] in function bar. */ -/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 1 "vrp-thread1" } } */ + /* { dg-final { scan-tree-dump-times "486097858" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c index cc322d6..7be1873 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c @@ -1,6 +1,6 @@ /* PR tree-optimization/61839. */ /* { dg-do run } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1 -fdump-tree-optimized -fdisable-tree-ethread -fdisable-tree-thread1" } */ __attribute__ ((noinline)) int foo (int a, unsigned b) @@ -22,5 +22,5 @@ int main () } /* Scan for c [12, 13] << 8 in function foo. */ -/* { dg-final { scan-tree-dump-times "3072 : 3328" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "3072 : 3328" 1 "vrp-thread1" } } */ /* { dg-final { scan-tree-dump-times "3072" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c index 66a5405..a2386ba 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-ffast-math -O3 -fdump-tree-vrp1-details" } */ +/* { dg-options "-ffast-math -O3 -fdump-tree-vrp-thread1-details" } */ int I = 50, J = 50; int S, L; @@ -39,4 +39,4 @@ void foo (int K) bar (LD, SD); } } -/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c index 856ab38..73969bb 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-11.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2" } */ +/* { dg-options "-O2 -fdump-tree-dom2-details --param logical-op-non-short-circuit=1 -fdisable-tree-thread1 -fdisable-tree-thread2 -fdisable-tree-vrp-thread1 " } */ static int *bb_ticks; extern void frob (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c index ffbdc98..1b677f4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1" } */ +/* { dg-options "-O2 -fdump-tree-dom2-details -w --param logical-op-non-short-circuit=1 -fdisable-tree-vrp-thread1" } */ unsigned char validate_subreg (unsigned int offset, unsigned int isize, unsigned int osize, int zz, int qq) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c index 2d78d04..0246ebf 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */ #include "ssa-dom-thread-4.c" @@ -24,4 +24,4 @@ /* There used to be 6 jump threads found by thread1, but they all depended on threading through distinct loops in ethread. */ -/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c index b972f64..8f0a12c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom2-stats" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-stats -fdump-tree-dom2-stats" } */ void bla(); @@ -16,6 +16,6 @@ void thread_entry_through_header (void) /* There's a single jump thread that should be handled by the VRP jump threading pass. */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp1"} } */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp1"} } */ +/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp-thread1"} } */ +/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp-thread1"} } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c index 521754f..46e464f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ struct bitmap_head_def; typedef struct bitmap_head_def *bitmap; typedef const struct bitmap_head_def *const_bitmap; @@ -58,4 +58,5 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b, code we missed the edge when the first conditional is false (b_elt is zero, which means the second conditional is always zero. VRP1 catches all three. */ -/* { dg-final { scan-tree-dump-times "Threaded" 3 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ +/* { dg-final { scan-tree-dump-times "Path crosses loops" 1 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c index f9152b9..8c5cc82 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ -/* { dg-additional-options "-O2 -fdump-tree-vrp-details --param logical-op-non-short-circuit=1" } */ +/* { dg-additional-options "-O2 -fdump-tree-vrp-thread1-details --param logical-op-non-short-circuit=1" } */ /* { dg-additional-options "-fdisable-tree-thread1" } */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp-thread1" } } */ void foo (void); void bar (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c index ef5611f..86d07ef 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-vrp-thread-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdelete-null-pointer-checks" } */ /* { dg-skip-if "" keeps_null_pointer_checks } */ void oof (void); @@ -29,5 +29,5 @@ build_omp_regions_1 (basic_block bb, struct omp_region *parent, /* ARM Cortex-M defined LOGICAL_OP_NON_SHORT_CIRCUIT to false, so skip below test. */ -/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp1" { target { ! arm_cortex_m } } } } */ +/* { dg-final { scan-tree-dump-times "Threaded" 1 "vrp-thread1" { target { ! arm_cortex_m } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c index e2e48d8..f25ea9c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp106.c @@ -1,6 +1,6 @@ /* PR tree-optimization/18046 */ -/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" } } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-details" } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" } } */ /* During VRP we expect to thread the true arm of the conditional through the switch and to the BB that corresponds to the 7 ... 9 case label. */ extern void foo (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c index 8ae9b8d..a478a69 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp55.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1-blocks-vops-details -fdelete-null-pointer-checks" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread1-blocks-vops-details -fdelete-null-pointer-checks" } */ void arf (void); @@ -12,6 +12,6 @@ fu (char *p, int x) arf (); } -/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp-thread1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 0 "vrp-thread1" { target { keeps_null_pointer_checks } } } } */ diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index eb75eb1..84477a4 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -462,6 +462,7 @@ extern gimple_opt_pass *make_pass_copy_prop (gcc::context *ctxt); extern gimple_opt_pass *make_pass_isolate_erroneous_paths (gcc::context *ctxt); extern gimple_opt_pass *make_pass_early_vrp (gcc::context *ctxt); extern gimple_opt_pass *make_pass_vrp (gcc::context *ctxt); +extern gimple_opt_pass *make_pass_vrp_threader (gcc::context *ctxt); extern gimple_opt_pass *make_pass_uncprop (gcc::context *ctxt); extern gimple_opt_pass *make_pass_return_slot (gcc::context *ctxt); extern gimple_opt_pass *make_pass_reassoc (gcc::context *ctxt); diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index ae77e5e..29ed60a 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "vr-values.h" #include "gimple-ssa-evrp-analyze.h" #include "gimple-range.h" +#include "gimple-range-path.h" /* To avoid code explosion due to jump threading, we limit the number of statements we are going to copy. This variable @@ -1397,3 +1398,73 @@ jt_state::register_equivs_stmt (gimple *stmt, basic_block bb, register_equiv (gimple_get_lhs (stmt), cached_lhs, /*update_range=*/false); } + +// Hybrid threader implementation. + + +void +hybrid_jt_state::register_equivs_stmt (gimple *, basic_block, jt_simplifier *) +{ + // Ranger has no need to simplify anything to improve equivalences. +} + +hybrid_jt_simplifier::hybrid_jt_simplifier (gimple_ranger *r, + path_range_query *q) +{ + m_ranger = r; + m_query = q; +} + +tree +hybrid_jt_simplifier::simplify (gimple *stmt, gimple *, basic_block, + jt_state *state) +{ + int_range_max r; + + compute_ranges_from_state (stmt, state); + + if (gimple_code (stmt) == GIMPLE_COND + || gimple_code (stmt) == GIMPLE_ASSIGN) + { + tree ret; + if (m_query->range_of_stmt (r, stmt) && r.singleton_p (&ret)) + return ret; + } + else if (gimple_code (stmt) == GIMPLE_SWITCH) + { + gswitch *switch_stmt = dyn_cast <gswitch *> (stmt); + tree index = gimple_switch_index (switch_stmt); + if (m_query->range_of_expr (r, index, stmt)) + return find_case_label_range (switch_stmt, &r); + } + return NULL; +} + +// Use STATE to generate the list of imports needed for the solver, +// and calculate the ranges along the path. + +void +hybrid_jt_simplifier::compute_ranges_from_state (gimple *stmt, jt_state *state) +{ + auto_bitmap imports; + gori_compute &gori = m_ranger->gori (); + + state->get_path (m_path); + + // Start with the imports to the final conditional. + bitmap_copy (imports, gori.imports (m_path[0])); + + // Add any other interesting operands we may have missed. + if (gimple_bb (stmt) != m_path[0]) + { + for (unsigned i = 0; i < gimple_num_ops (stmt); ++i) + { + tree op = gimple_op (stmt, i); + if (op + && TREE_CODE (op) == SSA_NAME + && irange::supports_type_p (TREE_TYPE (op))) + bitmap_set_bit (imports, SSA_NAME_VERSION (op)); + } + } + m_query->precompute_ranges (m_path, imports); +} diff --git a/gcc/tree-ssa-threadedge.h b/gcc/tree-ssa-threadedge.h index 0b47a52..ac605a3 100644 --- a/gcc/tree-ssa-threadedge.h +++ b/gcc/tree-ssa-threadedge.h @@ -53,6 +53,26 @@ public: virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) = 0; }; +class hybrid_jt_state : public jt_state +{ +private: + void register_equivs_stmt (gimple *, basic_block, jt_simplifier *) override; +}; + +class hybrid_jt_simplifier : public jt_simplifier +{ +public: + hybrid_jt_simplifier (class gimple_ranger *r, class path_range_query *q); + +private: + tree simplify (gimple *stmt, gimple *, basic_block, jt_state *) override; + void compute_ranges_from_state (gimple *stmt, jt_state *); + + gimple_ranger *m_ranger; + path_range_query *m_query; + auto_vec<basic_block> m_path; +}; + // This is the high level threader. The entry point is // thread_outgoing_edges(), which calculates and registers paths to be // threaded. When all candidates have been registered, diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a5079ee..c55a749 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -66,6 +66,8 @@ along with GCC; see the file COPYING3. If not see #include "range-op.h" #include "value-range-equiv.h" #include "gimple-array-bounds.h" +#include "gimple-range.h" +#include "gimple-range-path.h" #include "tree-ssa-dom.h" /* Set of SSA names found live during the RPO traversal of the function @@ -4591,11 +4593,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) array_checker.check (); } - /* We must identify jump threading opportunities before we release - the datastructures built by VRP. */ - vrp_jump_threader threader (fun, &vrp_vr_values); - threader.thread_jumps (); - simplify_casted_conds (fun, &vrp_vr_values); free_numbers_of_iterations_estimates (fun); @@ -4605,21 +4602,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) does not properly handle ASSERT_EXPRs. */ assert_engine.remove_range_assertions (); - /* If we exposed any new variables, go ahead and put them into - SSA form now, before we handle jump threading. This simplifies - interactions between rewriting of _DECL nodes into SSA form - and rewriting SSA_NAME nodes into SSA form after block - duplication and CFG manipulation. */ - update_ssa (TODO_update_ssa); - - /* We identified all the jump threading opportunities earlier, but could - not transform the CFG at that time. This routine transforms the - CFG and arranges for the dominator tree to be rebuilt if necessary. - - Note the SSA graph update will occur during the normal TODO - processing by the pass manager. */ - threader.thread_through_all_blocks (); - scev_finalize (); loop_optimizer_finalize (); return 0; @@ -4669,3 +4651,124 @@ make_pass_vrp (gcc::context *ctxt) { return new pass_vrp (ctxt); } + +// This is the dom walker for the hybrid threader. The reason this is +// here, as opposed to the generic threading files, is because the +// other client would be DOM, and they have their own custom walker. + +class hybrid_threader : public dom_walker +{ +public: + hybrid_threader (); + ~hybrid_threader (); + + void thread_jumps (function *fun) + { + walk (fun->cfg->x_entry_block_ptr); + } + void thread_through_all_blocks () + { + m_threader->thread_through_all_blocks (false); + } + +private: + edge before_dom_children (basic_block) override; + void after_dom_children (basic_block bb) override; + + hybrid_jt_simplifier *m_simplifier; + jump_threader *m_threader; + jt_state *m_state; + gimple_ranger *m_ranger; + path_range_query *m_query; +}; + +hybrid_threader::hybrid_threader () : dom_walker (CDI_DOMINATORS, REACHABLE_BLOCKS) +{ + loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); + scev_initialize (); + calculate_dominance_info (CDI_DOMINATORS); + mark_dfs_back_edges (); + + m_ranger = new gimple_ranger; + m_query = new path_range_query (*m_ranger, /*resolve=*/true); + m_simplifier = new hybrid_jt_simplifier (m_ranger, m_query); + m_state = new hybrid_jt_state; + m_threader = new jump_threader (m_simplifier, m_state); +} + +hybrid_threader::~hybrid_threader () +{ + delete m_simplifier; + delete m_threader; + delete m_state; + delete m_ranger; + + scev_finalize (); + loop_optimizer_finalize (); +} + +edge +hybrid_threader::before_dom_children (basic_block bb) +{ + gimple_stmt_iterator gsi; + int_range<2> r; + + for (gsi = gsi_start_nondebug_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + m_ranger->range_of_stmt (r, stmt); + } + return NULL; +} + +void +hybrid_threader::after_dom_children (basic_block bb) +{ + m_threader->thread_outgoing_edges (bb); +} + +static unsigned int +execute_vrp_threader (function *fun) +{ + hybrid_threader threader; + threader.thread_jumps (fun); + threader.thread_through_all_blocks (); + return 0; +} + +namespace { + +const pass_data pass_data_vrp_threader = +{ + GIMPLE_PASS, /* type */ + "vrp-thread", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_TREE_VRP, /* tv_id */ + PROP_ssa, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + ( TODO_cleanup_cfg | TODO_update_ssa ), /* todo_flags_finish */ +}; + +class pass_vrp_threader : public gimple_opt_pass +{ +public: + pass_vrp_threader (gcc::context *ctxt) + : gimple_opt_pass (pass_data_vrp_threader, ctxt) + {} + + /* opt_pass methods: */ + opt_pass * clone () { return new pass_vrp_threader (m_ctxt); } + virtual bool gate (function *) { return flag_tree_vrp != 0; } + virtual unsigned int execute (function *fun) + { return execute_vrp_threader (fun); } +}; + +} // namespace { + +gimple_opt_pass * +make_pass_vrp_threader (gcc::context *ctxt) +{ + return new pass_vrp_threader (ctxt); +} diff --git a/libgomp/team.c b/libgomp/team.c index ba57152..11a2521 100644 --- a/libgomp/team.c +++ b/libgomp/team.c @@ -312,7 +312,7 @@ gomp_team_start (void (*fn) (void *), void *data, unsigned nthreads, unsigned flags, struct gomp_team *team, struct gomp_taskgroup *taskgroup) { - struct gomp_thread_start_data *start_data; + struct gomp_thread_start_data *start_data = NULL; struct gomp_thread *thr, *nthr; struct gomp_task *task; struct gomp_task_icv *icv; diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c index ef6f64d..6caa934 100644 --- a/libgomp/testsuite/libgomp.graphite/force-parallel-4.c +++ b/libgomp/testsuite/libgomp.graphite/force-parallel-4.c @@ -1,5 +1,5 @@ /* Autopar with IF conditions. */ -/* { dg-additional-options "-fdisable-tree-thread1" } */ +/* { dg-additional-options "-fdisable-tree-thread1 -fdisable-tree-vrp-thread1" } */ void abort(); diff --git a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c index a97eb97..f9e0703 100644 --- a/libgomp/testsuite/libgomp.graphite/force-parallel-8.c +++ b/libgomp/testsuite/libgomp.graphite/force-parallel-8.c @@ -1,4 +1,4 @@ -/* { dg-additional-options "-fdisable-tree-thread1" } */ +/* { dg-additional-options "-fdisable-tree-thread1 -fdisable-tree-vrp-thread1" } */ #define N 1500 |