re PR tree-optimization/87105 (Autovectorization [X86, SSE2, AVX2, DoublePrecision])
2018-10-23 Richard Biener <rguenther@suse.de> 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
This commit is contained in:
parent
7a43314023
commit
1cab645d3e
@ -1,3 +1,15 @@
|
||||
2018-10-23 Richard Biener <rguenther@suse.de>
|
||||
|
||||
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 <rearnsha@arm.com>
|
||||
|
||||
PR target/86383
|
||||
|
@ -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);
|
||||
|
@ -1,3 +1,22 @@
|
||||
2018-10-23 Richard Biener <rguenther@suse.de>
|
||||
|
||||
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 <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/87700
|
||||
|
94
gcc/testsuite/g++.dg/tree-ssa/phiopt-1.C
Normal file
94
gcc/testsuite/g++.dg/tree-ssa/phiopt-1.C
Normal file
@ -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<int n>
|
||||
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" } }
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-phiopt1" } */
|
||||
/* { dg-options "-O -fdump-tree-phiopt2" } */
|
||||
|
||||
template<class T> static inline const T &ref_max(const T &a, const T &b)
|
||||
{ return a<b ? b : a; }
|
||||
@ -15,5 +15,5 @@ template<class T> struct foo_t {
|
||||
|
||||
template struct foo_t<int>;
|
||||
|
||||
/* { 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" } } */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O -fdump-tree-phiopt1" } */
|
||||
/* { dg-options "-O -fdump-tree-phiopt2" } */
|
||||
|
||||
template <class T>
|
||||
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" } } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
104
gcc/testsuite/g++.dg/vect/slp-pr87105.cc
Normal file
104
gcc/testsuite/g++.dg/vect/slp-pr87105.cc
Normal file
@ -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 <algorithm>
|
||||
#include <cmath>
|
||||
#include <stdint.h>
|
||||
|
||||
// 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<typename T> constexpr T myMin(const T& a, const T& b) noexcept
|
||||
{ return b < a ? b : a; }
|
||||
template<typename T> constexpr T myMax(const T& a, const T& b) noexcept
|
||||
{ return a < b ? b : a; }
|
||||
|
||||
// Linear interpolation, works with points as well.
|
||||
template<typename V, typename T = double>
|
||||
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 "<bb \[0-9\]+>" 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 *-*-* } } }
|
@ -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" } } */
|
||||
|
@ -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"} } */
|
||||
|
@ -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"} } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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 <varx_4, 0.0>; */
|
||||
|
||||
/* { 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 <vary_4, 1.0e+0>; */
|
||||
|
||||
/* { 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)
|
||||
<L1>:;
|
||||
vara_6 = MAX_EXPR <varb_5, varz_2>; */
|
||||
|
||||
/* { 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"} } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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" } } */
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <gphi *> (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 <gphi *> (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
|
||||
|
Loading…
Reference in New Issue
Block a user