Commit c29c92c7 by Feng Xue Committed by Feng Xue

PR tree-optimization/89713 - Assume loop with an exit is finite

gcc/ChangeLog:

        * doc/invoke.texi (-ffinite-loops): Document new option.
        * common.opt (-ffinite-loops): New option.
        * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Mark
        IFN_GOACC_LOOP calls as necessary.
        * tree-ssa-loop-niter.c (finite_loop_p): Assume loop with an exit
        is finite.
        * omp-offload.c (oacc_xform_loop): Skip lowering if return value of
        IFN_GOACC_LOOP call is not used.
        * opts.c (default_options_table): Enable -ffinite-loops at -O2+.

gcc/testsuite/ChangeLog:

        * g++.dg/tree-ssa/empty-loop.C: New test.
        * gcc.dg/tree-ssa/dce-2.c: New test.
        * gcc.dg/const-1.c: Add -fno-finite-loops option.
        * gcc.dg/graphite/graphite.exp: Likewise.
        * gcc.dg/loop-unswitch-1.c: Likewise.
        * gcc.dg/predict-9.c: Likewise.
        * gcc.dg/pure-2.c: Likewise.
        * gcc.dg/tree-ssa/20040211-1.c: Likewise.
        * gcc.dg/tree-ssa/loop-10.c: Likewise.
        * gcc.dg/tree-ssa/split-path-6.c: Likewise.
        * gcc.dg/tree-ssa/ssa-thread-12.c: Likewise.

libgomp/ChangeLog:

        * testsuite/libgomp.oacc-c-c++-common/pr84955-1.c: New test.

From-SVN: r272234
parent 9b884225
2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
PR tree-optimization/89713
* doc/invoke.texi (-ffinite-loops): Document new option.
* common.opt (-ffinite-loops): New option.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Mark
IFN_GOACC_LOOP calls as necessary.
* tree-ssa-loop-niter.c (finite_loop_p): Assume loop with an exit
is finite.
* omp-offload.c (oacc_xform_loop): Skip lowering if return value of
IFN_GOACC_LOOP call is not used.
* opts.c (default_options_table): Enable -ffinite-loops at -O2+.
2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
PR target/88838
......
......@@ -1437,6 +1437,10 @@ ffinite-math-only
Common Report Var(flag_finite_math_only) Optimization SetByCombined
Assume no NaNs or infinities are generated.
ffinite-loops
Common Report Var(flag_finite_loops) Optimization
Assume that loops with an exit will terminate and not loop indefinitely.
ffixed-
Common Joined RejectNegative Var(common_deferred_options) Defer
-ffixed-<register> Mark <register> as being unavailable to the compiler.
......
......@@ -413,6 +413,7 @@ Objective-C and Objective-C++ Dialects}.
-fdevirtualize-at-ltrans -fdse @gol
-fearly-inlining -fipa-sra -fexpensive-optimizations -ffat-lto-objects @gol
-ffast-math -ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
-ffinite-loops @gol
-fforward-propagate -ffp-contract=@var{style} -ffunction-sections @gol
-fgcse -fgcse-after-reload -fgcse-las -fgcse-lm -fgraphite-identity @gol
-fgcse-sm -fhoist-adjacent-loads -fif-conversion @gol
......@@ -8303,6 +8304,7 @@ also turns on the following optimization flags:
-fdelete-null-pointer-checks @gol
-fdevirtualize -fdevirtualize-speculatively @gol
-fexpensive-optimizations @gol
-ffinite-loops @gol
-fgcse -fgcse-lm @gol
-fhoist-adjacent-loads @gol
-finline-small-functions @gol
......@@ -9524,6 +9526,15 @@ that may set @code{errno} but are otherwise free of side effects. This flag is
enabled by default at @option{-O2} and higher if @option{-Os} is not also
specified.
@item -ffinite-loops
@opindex ffinite-loops
@opindex fno-finite-loops
Assume that a loop with an exit will eventually take the exit and not loop
indefinitely. This allows the compiler to remove loops that otherwise have
no side-effects, not considering eventual endless looping as such.
This option is enabled by default at @option{-O2}.
@item -ftree-dominator-opts
@opindex ftree-dominator-opts
Perform a variety of simple scalar cleanups (constant/copy
......@@ -300,7 +300,7 @@ oacc_xform_loop (gcall *call)
tree chunk_size = NULL_TREE;
unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
tree lhs = gimple_call_lhs (call);
tree type = TREE_TYPE (lhs);
tree type = NULL_TREE;
tree diff_type = TREE_TYPE (range);
tree r = NULL_TREE;
gimple_seq seq = NULL;
......@@ -308,6 +308,15 @@ oacc_xform_loop (gcall *call)
unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
/* Skip lowering if return value of IFN_GOACC_LOOP call is not used. */
if (!lhs)
{
gsi_replace_with_seq (&gsi, seq, true);
return;
}
type = TREE_TYPE (lhs);
#ifdef ACCEL_COMPILER
chunk_size = gimple_call_arg (call, 4);
if (integer_minus_onep (chunk_size) /* Force static allocation. */
......
......@@ -494,6 +494,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ffinite_loops, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },
......
2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
PR tree-optimization/89713
* g++.dg/tree-ssa/empty-loop.C: New test.
* gcc.dg/tree-ssa/dce-2.c: New test.
* gcc.dg/const-1.c: Add -fno-finite-loops option.
* gcc.dg/graphite/graphite.exp: Likewise.
* gcc.dg/loop-unswitch-1.c: Likewise.
* gcc.dg/predict-9.c: Likewise.
* gcc.dg/pure-2.c: Likewise.
* gcc.dg/tree-ssa/20040211-1.c: Likewise.
* gcc.dg/tree-ssa/loop-10.c: Likewise.
* gcc.dg/tree-ssa/split-path-6.c: Likewise.
* gcc.dg/tree-ssa/ssa-thread-12.c: Likewise.
2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
PR target/88838
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-cddce2 -ffinite-loops" } */
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
using namespace std;
int foo (vector<string> &v, list<string> &l, set<string> &s, map<int, string> &m)
{
for (vector<string>::iterator it = v.begin (); it != v.end (); ++it)
it->length();
for (list<string>::iterator it = l.begin (); it != l.end (); ++it)
it->length();
for (map<int, string>::iterator it = m.begin (); it != m.end (); ++it)
it->first + it->second.length();
for (set<string>::iterator it0 = s.begin (); it0 != s.end(); ++it0)
for (vector<string>::reverse_iterator it1 = v.rbegin(); it1 != v.rend(); ++it1)
{
it0->length();
it1->length();
}
return 0;
}
/* { dg-final { scan-tree-dump-not "if" "cddce2"} } */
/* { dg-do compile { target nonpic } } */
/* { dg-options "-O2 -Wsuggest-attribute=const" } */
/* { dg-options "-O2 -Wsuggest-attribute=const -fno-finite-loops" } */
extern int extern_const(int a) __attribute__ ((const));
......
......@@ -56,7 +56,7 @@ set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.c ] ]
# Tests to be compiled.
set dg-do-what-default compile
dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all"
dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all -fno-finite-loops"
dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math -fdump-tree-graphite-details"
# Tests to be run.
......
/* For PR rtl-optimization/27735 */
/* { dg-do compile } */
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details" } */
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details -fno-finite-loops" } */
void set_color(void);
void xml_colorize_line(unsigned int *p, int state)
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-profile_estimate" } */
/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-profile_estimate -fno-finite-loops" } */
extern int global;
extern int global2;
......
/* { dg-do compile } */
/* { dg-options "-O2 -Wsuggest-attribute=pure" } */
/* { dg-options "-O2 -Wsuggest-attribute=pure -fno-finite-loops" } */
/* { dg-add-options bind_pic_locally } */
extern int extern_const(int a) __attribute__ ((pure));
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-cddce2" } */
/* { dg-options "-O2 -fdump-tree-cddce2 -fno-finite-loops" } */
struct rtx_def;
typedef struct rtx_def *rtx;
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-cddce1 -ffinite-loops" } */
typedef struct list {
char pad[15];
struct list *next;
} list;
int data;
list *head, *tail;
int __attribute__((pure)) pfn (int);
int foo (unsigned u, int s)
{
unsigned i;
list *p;
int j;
for (i = 0; i < u; i += 2)
;
for (p = head; p; p = p->next)
;
for (j = data; j & s; j = pfn (j + 3))
;
for (p = head; p != tail; p = p->next)
for (j = data + 1; j > s; j = pfn (j + 2))
;
return 0;
}
/* { dg-final { scan-tree-dump-not "if" "cddce1"} } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
/* { dg-options "-O2 -fdump-tree-optimized -fno-finite-loops" } */
/* { dg-require-effective-target int32plus } */
int bar (void);
......
/* { dg-do compile } */
/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fdump-tree-split-paths-details -w" } */
/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fdump-tree-split-paths-details -w -fno-finite-loops" } */
struct __sFILE
{
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details" } */
/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops" } */
/* { dg-final { scan-tree-dump "FSM" "thread2" } } */
/* { dg-final { scan-tree-dump "FSM" "thread3" } } */
/* { dg-final { scan-tree-dump "FSM" "thread4" { xfail *-*-* } } } */
......
......@@ -245,6 +245,17 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
mark_stmt_necessary (stmt, true);
return;
}
/* IFN_GOACC_LOOP calls are necessary in that they are used to
represent parameter (i.e. step, bound) of a lowered OpenACC
partitioned loop. But this kind of partitioned loop might not
survive from aggressive loop removal for it has loop exit and
is assumed to be finite. Therefore, we need to explicitly mark
these calls. (An example is libgomp.oacc-c-c++-common/pr84955.c) */
if (gimple_call_internal_p (stmt, IFN_GOACC_LOOP))
{
mark_stmt_necessary (stmt, true);
return;
}
if (!gimple_call_lhs (stmt))
return;
break;
......
......@@ -2830,6 +2830,27 @@ finite_loop_p (struct loop *loop)
loop->num);
return true;
}
if (flag_finite_loops)
{
unsigned i;
vec<edge> exits = get_loop_exit_edges (loop);
edge ex;
/* If the loop has a normal exit, we can assume it will terminate. */
FOR_EACH_VEC_ELT (exits, i, ex)
if (!(ex->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_FAKE)))
{
exits.release ();
if (dump_file)
fprintf (dump_file, "Assume loop %i to be finite: it has an exit "
"and -ffinite-loops is on.\n", loop->num);
return true;
}
exits.release ();
}
return false;
}
......
2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
PR tree-optimization/89713
* testsuite/libgomp.oacc-c-c++-common/pr84955-1.c: New test.
2019-06-11 Jakub Jelinek <jakub@redhat.com>
PR target/90811
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-cddce2 -ffinite-loops" } */
int
f1 (void)
{
int i, j;
#pragma acc parallel loop tile(2,3)
for (i = 1; i < 10; i++)
for (j = 1; j < 10; j++)
for (;;)
;
return i + j;
}
int
f2 (void)
{
int i, j, k;
#pragma acc parallel loop tile(2,3)
for (i = 1; i < 10; i++)
for (j = 1; j < 10; j++)
for (k = 1; k < 10; k++)
;
return i + j;
}
/* { dg-final { scan-tree-dump-not "if" "cddce2"} } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment