From: Richard Biener Date: Tue, 23 Oct 2018 11:34:56 +0000 (+0000) Subject: re PR tree-optimization/87105 (Autovectorization [X86, SSE2, AVX2, DoublePrecision]) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1cab645d3e321132dca5e43d9d5057c60852a17c;p=gcc.git re PR tree-optimization/87105 (Autovectorization [X86, SSE2, AVX2, DoublePrecision]) 2018-10-23 Richard Biener PR tree-optimization/87105 PR tree-optimization/87608 * passes.def (pass_all_early_optimizations): Add early phi-opt after dce. * tree-ssa-phiopt.c (value_replacement): Ignore NOPs and predicts in addition to debug stmts. (tree_ssa_phiopt_worker): Add early_p argument, do only min/max and abs replacement early. * tree-cfg.c (gimple_empty_block_p): Likewise. * g++.dg/tree-ssa/phiopt-1.C: New testcase. g++.dg/vect/slp-pr87105.cc: Likewise. * g++.dg/tree-ssa/pr21463.C: Scan phiopt2 because this testcase relies on phiprop run before. * g++.dg/tree-ssa/pr30738.C: Likewise. * g++.dg/tree-ssa/pr57380.C: Likewise. * gcc.dg/tree-ssa/pr84859.c: Likewise. * gcc.dg/tree-ssa/pr45397.c: Scan phiopt2 because phiopt1 is confused by copies in the IL left by EVRP. * gcc.dg/tree-ssa/phi-opt-5.c: Likewise, this time confused by predictors. * gcc.dg/tree-ssa/phi-opt-12.c: Scan phiopt2. * gcc.dg/pr24574.c: Likewise. * g++.dg/tree-ssa/pr86544.C: Scan phiopt4. From-SVN: r265421 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3314b50f8a4..367e60f4c6b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2018-10-23 Richard Biener + + PR tree-optimization/87105 + PR tree-optimization/87608 + * passes.def (pass_all_early_optimizations): Add early phi-opt + after dce. + * tree-ssa-phiopt.c (value_replacement): Ignore NOPs and predicts in + addition to debug stmts. + (tree_ssa_phiopt_worker): Add early_p argument, do only min/max + and abs replacement early. + * tree-cfg.c (gimple_empty_block_p): Likewise. + 2018-10-23 Richard Earnshaw PR target/86383 diff --git a/gcc/passes.def b/gcc/passes.def index 7f4b3479a35..24f212c8e31 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -88,6 +88,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_merge_phi); NEXT_PASS (pass_dse); NEXT_PASS (pass_cd_dce); + NEXT_PASS (pass_phiopt, true /* early_p */); NEXT_PASS (pass_early_ipa_sra); NEXT_PASS (pass_tail_recursion); NEXT_PASS (pass_convert_switch); @@ -208,7 +209,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_tree_ifcombine); NEXT_PASS (pass_merge_phi); - NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_phiopt, false /* early_p */); NEXT_PASS (pass_tail_recursion); NEXT_PASS (pass_ch); NEXT_PASS (pass_lower_complex); @@ -237,7 +238,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_reassoc, true /* insert_powi_p */); NEXT_PASS (pass_dce); NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_phiopt, false /* early_p */); NEXT_PASS (pass_ccp, true /* nonzero_p */); /* After CCP we rewrite no longer addressed locals into SSA form if possible. */ @@ -328,7 +329,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_dse); NEXT_PASS (pass_cd_dce); NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_phiopt, false /* early_p */); NEXT_PASS (pass_fold_builtins); NEXT_PASS (pass_optimize_widening_mul); NEXT_PASS (pass_store_merging); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9ca348875ea..fe6699e80a9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2018-10-23 Richard Biener + + PR tree-optimization/87105 + PR tree-optimization/87608 + * g++.dg/tree-ssa/phiopt-1.C: New testcase. + g++.dg/vect/slp-pr87105.cc: Likewise. + * g++.dg/tree-ssa/pr21463.C: Scan phiopt2 because this testcase + relies on phiprop run before. + * g++.dg/tree-ssa/pr30738.C: Likewise. + * g++.dg/tree-ssa/pr57380.C: Likewise. + * gcc.dg/tree-ssa/pr84859.c: Likewise. + * gcc.dg/tree-ssa/pr45397.c: Scan phiopt2 because phiopt1 is + confused by copies in the IL left by EVRP. + * gcc.dg/tree-ssa/phi-opt-5.c: Likewise, this time confused + by predictors. + * gcc.dg/tree-ssa/phi-opt-12.c: Scan phiopt2. + * gcc.dg/pr24574.c: Likewise. + * g++.dg/tree-ssa/pr86544.C: Scan phiopt4. + 2018-10-23 Richard Biener PR tree-optimization/87700 diff --git a/gcc/testsuite/g++.dg/tree-ssa/phiopt-1.C b/gcc/testsuite/g++.dg/tree-ssa/phiopt-1.C new file mode 100644 index 00000000000..83d976a7ac9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/phiopt-1.C @@ -0,0 +1,94 @@ +// { dg-do compile } +// { dg-options "-O -fdump-tree-phiopt1" } + +#define cond_swap5(a,b);\ + t = *(a);\ + *(a) = (t<*(b))?t:*(b);\ + *(b) = (t<*(b))?*(b):t; + +template +void static_sort1(int *a){ + return; +} + +template<> +void static_sort1<32>(int* first){ + int t; + static_sort1<16>(first); + static_sort1<16>(first+16); + + cond_swap5(first + 0u, first + 16u); + cond_swap5(first + 8u, first + 24u); + cond_swap5(first + 8u, first + 16u); + cond_swap5(first + 4u, first + 20u); + cond_swap5(first + 12u, first + 28u); + cond_swap5(first + 12u, first + 20u); + cond_swap5(first + 4u, first + 8u); + cond_swap5(first + 12u, first + 16u); + cond_swap5(first + 20u, first + 24u); + cond_swap5(first + 2u, first + 18u); + cond_swap5(first + 10u, first + 26u); + cond_swap5(first + 10u, first + 18u); + cond_swap5(first + 6u, first + 22u); + cond_swap5(first + 14u, first + 30u); + cond_swap5(first + 14u, first + 22u); + cond_swap5(first + 6u, first + 10u); + cond_swap5(first + 14u, first + 18u); + cond_swap5(first + 22u, first + 26u); + cond_swap5(first + 2u, first + 4u); + cond_swap5(first + 6u, first + 8u); + cond_swap5(first + 10u, first + 12u); + cond_swap5(first + 14u, first + 16u); + cond_swap5(first + 18u, first + 20u); + cond_swap5(first + 22u, first + 24u); + cond_swap5(first + 26u, first + 28u); + cond_swap5(first + 1u, first + 17u); + cond_swap5(first + 9u, first + 25u); + cond_swap5(first + 9u, first + 17u); + cond_swap5(first + 5u, first + 21u); + cond_swap5(first + 13u, first + 29u); + cond_swap5(first + 13u, first + 21u); + cond_swap5(first + 5u, first + 9u); + cond_swap5(first + 13u, first + 17u); + cond_swap5(first + 21u, first + 25u); + cond_swap5(first + 3u, first + 19u); + cond_swap5(first + 11u, first + 27u); + cond_swap5(first + 11u, first + 19u); + cond_swap5(first + 7u, first + 23u); + cond_swap5(first + 15u, first + 31u); + cond_swap5(first + 15u, first + 23u); + cond_swap5(first + 7u, first + 11u); + cond_swap5(first + 15u, first + 19u); + cond_swap5(first + 23u, first + 27u); + cond_swap5(first + 3u, first + 5u); + cond_swap5(first + 7u, first + 9u); + cond_swap5(first + 11u, first + 13u); + cond_swap5(first + 15u, first + 17u); + cond_swap5(first + 19u, first + 21u); + cond_swap5(first + 23u, first + 25u); + cond_swap5(first + 27u, first + 29u); + cond_swap5(first + 1u, first + 2u); + cond_swap5(first + 3u, first + 4u); + cond_swap5(first + 5u, first + 6u); + cond_swap5(first + 7u, first + 8u); + cond_swap5(first + 9u, first + 10u); + cond_swap5(first + 11u, first + 12u); + cond_swap5(first + 13u, first + 14u); + cond_swap5(first + 15u, first + 16u); + cond_swap5(first + 17u, first + 18u); + cond_swap5(first + 19u, first + 20u); + cond_swap5(first + 21u, first + 22u); + cond_swap5(first + 23u, first + 24u); + cond_swap5(first + 25u, first + 26u); + cond_swap5(first + 27u, first + 28u); + cond_swap5(first + 29u, first + 30u); +}; + +void foo(int *a) +{ + static_sort1<32>(a); +} + +// { dg-final { scan-tree-dump-not "if " "phiopt1" } } +// { dg-final { scan-tree-dump-times "MIN" 65 "phiopt1" } } +// { dg-final { scan-tree-dump-times "MAX" 65 "phiopt1" } } diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr21463.C b/gcc/testsuite/g++.dg/tree-ssa/pr21463.C index 0aed8482e6f..45d83415648 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr21463.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr21463.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-phiopt2" } */ template static inline const T &ref_max(const T &a, const T &b) { return a struct foo_t { template struct foo_t; -/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 2 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 2 "phiopt2" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr30738.C b/gcc/testsuite/g++.dg/tree-ssa/pr30738.C index 84cfdd98cc1..1c989bde741 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr30738.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr30738.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-phiopt2" } */ template static inline const T& @@ -13,4 +13,4 @@ int test_min_ref (int x, int y) return min_ref (x, y); } -/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt1" } } */ +/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt2" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr57380.C b/gcc/testsuite/g++.dg/tree-ssa/pr57380.C index fce6279eeb5..864129bfa69 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr57380.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr57380.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt1" } */ +/* { dg-options "-O2 -fdump-tree-phiopt2" } */ /* { dg-add-options bind_pic_locally } */ struct my_array { @@ -18,4 +18,4 @@ int f(my_array a, my_array b) { return res; } -/* { dg-final { scan-tree-dump "MAX_EXPR" "phiopt1" } } */ +/* { dg-final { scan-tree-dump "MAX_EXPR" "phiopt2" } } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr86544.C b/gcc/testsuite/g++.dg/tree-ssa/pr86544.C index 8a900896e50..fd844b48deb 100644 --- a/gcc/testsuite/g++.dg/tree-ssa/pr86544.C +++ b/gcc/testsuite/g++.dg/tree-ssa/pr86544.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt3 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-phiopt4 -fdump-tree-optimized" } */ int PopCount (long b) { int c = 0; @@ -12,4 +12,4 @@ int PopCount (long b) { } /* { dg-final { scan-tree-dump-times "__builtin_popcount" 1 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "if" 0 "phiopt3" } } */ +/* { dg-final { scan-tree-dump-times "if" 0 "phiopt4" } } */ diff --git a/gcc/testsuite/g++.dg/vect/slp-pr87105.cc b/gcc/testsuite/g++.dg/vect/slp-pr87105.cc new file mode 100644 index 00000000000..1023d915201 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/slp-pr87105.cc @@ -0,0 +1,104 @@ +// { dg-do compile } +// { dg-require-effective-target c++11 } +// { dg-require-effective-target vect_double } +// For MIN/MAX recognition +// { dg-additional-options "-ffast-math -fvect-cost-model" } + +#include +#include +#include + +// Point structure [x, y] +struct Point { + double x, y; + + inline Point() noexcept = default; + constexpr Point(const Point&) noexcept = default; + + constexpr Point(double x, double y) noexcept + : x(x), y(y) {} +}; + +// Box structure [x0, y0, x1, y1] +struct Box { + double x0, y0, x1, y1; + + inline void reset(double x0, double y0, double x1, double y1) noexcept { + this->x0 = x0; + this->y0 = y0; + this->x1 = x1; + this->y1 = y1; + } +}; + +// Overloads to make vector processing simpler. +static constexpr Point operator-(const Point& a) noexcept { return Point(-a.x, -a.y); } + +static constexpr Point operator+(const Point& a, double b) noexcept +{ return Point(a.x + b, a.y + b); } +static constexpr Point operator-(const Point& a, double b) noexcept +{ return Point(a.x - b, a.y - b); } +static constexpr Point operator*(const Point& a, double b) noexcept +{ return Point(a.x * b, a.y * b); } +static constexpr Point operator/(const Point& a, double b) noexcept +{ return Point(a.x / b, a.y / b); } + +static constexpr Point operator+(const Point& a, const Point& b) noexcept +{ return Point(a.x + b.x, a.y + b.y); } +static constexpr Point operator-(const Point& a, const Point& b) noexcept +{ return Point(a.x - b.x, a.y - b.y); } +static constexpr Point operator*(const Point& a, const Point& b) noexcept +{ return Point(a.x * b.x, a.y * b.y); } +static constexpr Point operator/(const Point& a, const Point& b) noexcept +{ return Point(a.x / b.x, a.y / b.y); } + +static constexpr Point operator+(double a, const Point& b) noexcept +{ return Point(a + b.x, a + b.y); } +static constexpr Point operator-(double a, const Point& b) noexcept +{ return Point(a - b.x, a - b.y); } +static constexpr Point operator*(double a, const Point& b) noexcept +{ return Point(a * b.x, a * b.y); } +static constexpr Point operator/(double a, const Point& b) noexcept +{ return Point(a / b.x, a / b.y); } + +// Min/Max - different semantics compared to std. +template constexpr T myMin(const T& a, const T& b) noexcept +{ return b < a ? b : a; } +template constexpr T myMax(const T& a, const T& b) noexcept +{ return a < b ? b : a; } + +// Linear interpolation, works with points as well. +template +inline V lerp(const V& a, const V& b, const T& t) noexcept { + return (a * (1.0 - t)) + (b * t); +} + +// Merge a point into a box by possibly increasing its bounds. +inline void boxMergePoint(Box& box, const Point& p) noexcept { + box.x0 = myMin(box.x0, p.x); + box.y0 = myMin(box.y0, p.y); + box.x1 = myMax(box.x1, p.x); + box.y1 = myMax(box.y1, p.y); +} + +void quadBoundingBoxA(const Point bez[3], Box& bBox) noexcept { + // Bounding box of start and end points. + bBox.reset(myMin(bez[0].x, bez[2].x), myMin(bez[0].y, bez[2].y), + myMax(bez[0].x, bez[2].x), myMax(bez[0].y, bez[2].y)); + + Point t = (bez[0] - bez[1]) / (bez[0] - bez[1] * 2.0 + bez[2]); + + t.x = myMax(t.x, 0.0); + t.y = myMax(t.y, 0.0); + t.x = myMin(t.x, 1.0); + t.y = myMin(t.y, 1.0); + + boxMergePoint(bBox, lerp(lerp(bez[0], bez[1], t), + lerp(bez[1], bez[2], t), t)); +} + +// We should have if-converted everything down to straight-line code +// { dg-final { scan-tree-dump-times "" 1 "slp2" } } +// We fail to elide an earlier store which makes us not handle a later +// duplicate one for vectorization. +// { dg-final { scan-tree-dump-times "basic block part vectorized" 1 "slp2" { xfail *-*-* } } } diff --git a/gcc/testsuite/gcc.dg/pr24574.c b/gcc/testsuite/gcc.dg/pr24574.c index db0d8692a76..93ce0f68429 100644 --- a/gcc/testsuite/gcc.dg/pr24574.c +++ b/gcc/testsuite/gcc.dg/pr24574.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-phiopt2" } */ int f0(int i) { @@ -33,4 +33,4 @@ int f5(int i) /* We should if-convert all functions to carry out the operation unconditionally. */ -/* { dg-final { scan-tree-dump-not "= PHI" "phiopt1" } } */ +/* { dg-final { scan-tree-dump-not "= PHI" "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c index 91fa65d070b..364ce6a6966 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ +/* { dg-options "-O1 -fdump-tree-phiopt2-details" } */ int t( int i) { @@ -15,4 +15,4 @@ end: } /* Should have no ifs left after straightening. */ -/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */ +/* { dg-final { scan-tree-dump-times "if " 0 "phiopt2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c index f80a74a14ea..a093c77d913 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ +/* { dg-options "-O1 -fdump-tree-phiopt2-details" } */ int f(int a, int b) { int c = b; @@ -9,4 +9,4 @@ int f(int a, int b) } /* Should have no ifs left after straightening. */ -/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */ +/* { dg-final { scan-tree-dump-times "if " 0 "phiopt2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c index f00d0fcc474..a221b762e1d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-12.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-phiopt2" } */ int f(int a, int b, int c) { if (c > 5) return c; @@ -19,4 +19,4 @@ unsigned m(unsigned a, unsigned b) { return a & b; } -/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c index 31c0fc1f2fb..5a00f3ddf8c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -ffinite-math-only -fno-signed-zeros -fdump-tree-phiopt1" } */ +/* { dg-options "-O1 -ffinite-math-only -fno-signed-zeros -fdump-tree-phiopt" } */ float repl1 (float varx) { @@ -16,8 +16,11 @@ float repl1 (float varx) varx_4 = MIN_EXPR <1.0e+0, varx_2>; varx_5 = MAX_EXPR ; */ -/* { dg-final { scan-tree-dump "varx.*MIN_EXPR.*1\\.0" "phiopt1"} } */ -/* { dg-final { scan-tree-dump "varx.*MAX_EXPR.*0\\.0" "phiopt1"} } */ +/* phiopt1 confused by predictors. */ +/* { dg-final { scan-tree-dump "varx.*MIN_EXPR.*1\\.0" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "varx.*MAX_EXPR.*0\\.0" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "varx.*MIN_EXPR.*1\\.0" "phiopt2"} } */ +/* { dg-final { scan-tree-dump "varx.*MAX_EXPR.*0\\.0" "phiopt2"} } */ float repl2 (float vary) { @@ -34,8 +37,11 @@ float repl2 (float vary) vary_4 = MAX_EXPR <0.0, vary_2>; vary_5 = MIN_EXPR ; */ -/* { dg-final { scan-tree-dump "vary.*MAX_EXPR.*0\\.0" "phiopt1"} } */ -/* { dg-final { scan-tree-dump "vary.*MIN_EXPR.*1\\.0" "phiopt1"} } */ +/* phiopt1 confused by predictors. */ +/* { dg-final { scan-tree-dump "vary.*MAX_EXPR.*0\\.0" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "vary.*MIN_EXPR.*1\\.0" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "vary.*MAX_EXPR.*0\\.0" "phiopt2"} } */ +/* { dg-final { scan-tree-dump "vary.*MIN_EXPR.*1\\.0" "phiopt2"} } */ float repl3 (float varz, float vara, float varb) { @@ -54,5 +60,7 @@ float repl3 (float varz, float vara, float varb) :; vara_6 = MAX_EXPR ; */ -/* { dg-final { scan-tree-dump "if .*varz" "phiopt1"} } */ -/* { dg-final { scan-tree-dump "vara.*MAX_EXPR" "phiopt1"} } */ +/* phiopt1 confused by predictors. */ +/* { dg-final { scan-tree-dump "vara.*MAX_EXPR" "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "if .*varz" "phiopt2"} } */ +/* { dg-final { scan-tree-dump "vara.*MAX_EXPR" "phiopt2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c index 780530d1e42..a5020c05867 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-phiopt2" } */ struct C { int i; }; int *g(struct C *p) @@ -9,4 +9,4 @@ int *g(struct C *p) return (int *)0; } -/* { dg-final { scan-tree-dump-not "if" "phiopt1" } } */ +/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c index e3b2771dbb2..98c596b6aa4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O -fdump-tree-optimized -fdump-tree-phiopt1" } */ +/* { dg-options "-O -fdump-tree-optimized -fdump-tree-phiopt2" } */ int g(int,int); int f(int t, int c) @@ -19,6 +19,6 @@ int f(int t, int c) but currently is not as PHI-OPT does not reduce the t PHI as we have two phis. Note this is fixed with http://gcc.gnu.org/ml/gcc-patches/2012-01/msg01195.html . */ -/* { dg-final { scan-tree-dump-not "if" "phiopt1" } } */ +/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */ /* { dg-final { scan-tree-dump "g .t_\[0-9\]*.D.," "optimized" } } */ /* { dg-final { scan-tree-dump-not "PHI" "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c b/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c index 8a900896e50..fd844b48deb 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt3 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-phiopt4 -fdump-tree-optimized" } */ int PopCount (long b) { int c = 0; @@ -12,4 +12,4 @@ int PopCount (long b) { } /* { dg-final { scan-tree-dump-times "__builtin_popcount" 1 "optimized" } } */ -/* { dg-final { scan-tree-dump-times "if" 0 "phiopt3" } } */ +/* { dg-final { scan-tree-dump-times "if" 0 "phiopt4" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45397.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45397.c index af75a75b1e2..8eacb518777 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr45397.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45397.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-phiopt1 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-phiopt -fdump-tree-evrp" } */ int foo_add (const unsigned char *tmp, int i, int val) { @@ -18,7 +18,12 @@ int foo_mul (const unsigned char *tmp, int i, int val) /* All cases should end up using min/max for the saturated operations and have no control flow. */ +/* EVRP leaves copies in the IL which confuses phiopt1 so we have + to rely on phiopt2 instead. */ /* { dg-final { scan-tree-dump-not " & 255;" "evrp" } } */ -/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" } } */ -/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-not "if " "phiopt1" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "MAX_EXPR" 3 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-times "MIN_EXPR" 3 "phiopt2" } } */ +/* { dg-final { scan-tree-dump-not "if " "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr84859.c b/gcc/testsuite/gcc.dg/tree-ssa/pr84859.c index 577b561545d..a2c98866e6c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr84859.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr84859.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -Warray-bounds -fdump-tree-phiopt1" } */ +/* { dg-options "-O2 -Warray-bounds -fdump-tree-phiopt2" } */ void h (const void *p, unsigned n) @@ -19,4 +19,4 @@ h (const void *p, unsigned n) } } -/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt1" } } */ +/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt2" } } */ diff --git a/gcc/testsuite/gcc.dg/uninit-15.c b/gcc/testsuite/gcc.dg/uninit-15.c index 6154f4b638a..67aac41d49e 100644 --- a/gcc/testsuite/gcc.dg/uninit-15.c +++ b/gcc/testsuite/gcc.dg/uninit-15.c @@ -3,14 +3,14 @@ line 11, which is very confusing. Make sure we print out a note to make it less confusing. (not xfailed alternative) But it is of course ok if we warn in bar about uninitialized use - of j. (xfailed alternative) */ + of j. (not xfailed alternative) */ /* { dg-do compile } */ /* { dg-options "-O1 -Wuninitialized" } */ inline int foo (int i) { - if (i) /* { dg-warning "used uninitialized in this function" } */ + if (i) /* { dg-warning "used uninitialized in this function" "" } */ return 1; return 0; } @@ -20,7 +20,7 @@ void baz (void); void bar (void) { - int j; /* { dg-message "note: 'j' was declared here" } */ + int j; /* { dg-message "note: 'j' was declared here" "" } */ for (; foo (j); ++j) /* { dg-warning "'j' is used uninitialized" "" { xfail *-*-* } } */ baz (); } diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index d30e4aca773..5f334ca7927 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -6104,11 +6104,19 @@ gimple_empty_block_p (basic_block bb) gimple_stmt_iterator gsi = gsi_after_labels (bb); if (phi_nodes (bb)) return false; - if (gsi_end_p (gsi)) - return true; - if (is_gimple_debug (gsi_stmt (gsi))) - gsi_next_nondebug (&gsi); - return gsi_end_p (gsi); + while (!gsi_end_p (gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + ; + else if (gimple_code (stmt) == GIMPLE_NOP + || gimple_code (stmt) == GIMPLE_PREDICT) + ; + else + return false; + gsi_next (&gsi); + } + return true; } diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 1667bad873b..07845101b86 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "case-cfn-macros.h" -static unsigned int tree_ssa_phiopt_worker (bool, bool); +static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); static bool conditional_replacement (basic_block, basic_block, edge, edge, gphi *, tree, tree); static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, @@ -119,7 +119,7 @@ tree_ssa_cs_elim (void) An interfacing issue of find_data_references_in_bb. */ loop_optimizer_init (LOOPS_NORMAL); scev_initialize (); - todo = tree_ssa_phiopt_worker (true, false); + todo = tree_ssa_phiopt_worker (true, false, false); scev_finalize (); loop_optimizer_finalize (); return todo; @@ -159,7 +159,7 @@ single_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1) DO_HOIST_LOADS is true when we want to hoist adjacent loads out of diamond control flow patterns, false otherwise. */ static unsigned int -tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) +tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p) { basic_block bb; basic_block *bb_order; @@ -289,18 +289,19 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) /* Value replacement can work with more than one PHI so try that first. */ - for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi)) - { - phi = as_a (gsi_stmt (gsi)); - arg0 = gimple_phi_arg_def (phi, e1->dest_idx); - arg1 = gimple_phi_arg_def (phi, e2->dest_idx); - if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2) - { - candorest = false; - cfgchanged = true; - break; - } - } + if (!early_p) + for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi)) + { + phi = as_a (gsi_stmt (gsi)); + arg0 = gimple_phi_arg_def (phi, e1->dest_idx); + arg1 = gimple_phi_arg_def (phi, e2->dest_idx); + if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2) + { + candorest = false; + cfgchanged = true; + break; + } + } if (!candorest) continue; @@ -331,12 +332,14 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads) } /* Do the replacement of conditional if it can be done. */ - if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) + if (!early_p + && conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; - else if (cond_removal_in_popcount_pattern (bb, bb1, e1, e2, - phi, arg0, arg1)) + else if (!early_p + && cond_removal_in_popcount_pattern (bb, bb1, e1, e2, + phi, arg0, arg1)) cfgchanged = true; else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) cfgchanged = true; @@ -913,7 +916,9 @@ value_replacement (basic_block cond_bb, basic_block middle_bb, gsi_next_nondebug (&gsi); if (!is_gimple_assign (stmt)) { - emtpy_or_with_defined_p = false; + if (gimple_code (stmt) != GIMPLE_PREDICT + && gimple_code (stmt) != GIMPLE_NOP) + emtpy_or_with_defined_p = false; continue; } /* Now try to adjust arg0 or arg1 according to the computation @@ -2794,17 +2799,26 @@ class pass_phiopt : public gimple_opt_pass { public: pass_phiopt (gcc::context *ctxt) - : gimple_opt_pass (pass_data_phiopt, ctxt) + : gimple_opt_pass (pass_data_phiopt, ctxt), early_p (false) {} /* opt_pass methods: */ opt_pass * clone () { return new pass_phiopt (m_ctxt); } + void set_pass_param (unsigned n, bool param) + { + gcc_assert (n == 0); + early_p = param; + } virtual bool gate (function *) { return flag_ssa_phiopt; } virtual unsigned int execute (function *) { - return tree_ssa_phiopt_worker (false, gate_hoist_loads ()); + return tree_ssa_phiopt_worker (false, + !early_p ? gate_hoist_loads () : false, + early_p); } +private: + bool early_p; }; // class pass_phiopt } // anon namespace