* [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA
@ 2021-11-11 14:01 Richard Biener
2021-11-11 16:43 ` Aldy Hernandez
0 siblings, 1 reply; 4+ messages in thread
From: Richard Biener @ 2021-11-11 14:01 UTC (permalink / raw)
To: gcc-patches
The following splits loop header copying into an analysis phase
that uses ranger and a transform phase that can do without to avoid
running ranger on IL that has SSA form not updated.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
2021-11-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/103188
* tree-ssa-loop-ch.c (should_duplicate_loop_header_p):
Remove query parameter, split out check for size
optimization.
(ch_base::m_ranger, cb_base::m_query): Remove.
(ch_base::copy_headers): Split processing loop into
analysis around which we allocate and use ranger and
transform where we do not.
(pass_ch::execute): Do not allocate/free ranger here.
(pass_ch_vect::execute): Likewise.
* gcc.dg/torture/pr103188.c: New testcase.
---
gcc/testsuite/gcc.dg/torture/pr103188.c | 38 +++++++++++++
gcc/tree-ssa-loop-ch.c | 72 ++++++++++++++-----------
2 files changed, 78 insertions(+), 32 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr103188.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr103188.c b/gcc/testsuite/gcc.dg/torture/pr103188.c
new file mode 100644
index 00000000000..0412f6f9b79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr103188.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+
+int a, b, c, d = 10, e = 1, f, g, h, i;
+int main()
+{
+ int j = -1;
+k:
+ h = c;
+l:
+ c = ~c;
+ if (e)
+ m:
+ a = 0;
+ if (j > 1)
+ goto m;
+ if (!e)
+ goto l;
+ if (c)
+ goto p;
+n:
+ goto m;
+o:
+ if (f) {
+ if (g)
+ goto k;
+ j = 0;
+ p:
+ if (d)
+ goto o;
+ goto n;
+ }
+ if (i)
+ goto l;
+ for (; a < 1; a++)
+ while (a > d)
+ b++;
+ return 0;
+}
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index c7d86d751d4..0cee38159fb 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -69,26 +69,12 @@ entry_loop_condition_is_static (class loop *l, path_range_query *query)
static bool
should_duplicate_loop_header_p (basic_block header, class loop *loop,
- int *limit, path_range_query *query)
+ int *limit)
{
gimple_stmt_iterator bsi;
gcc_assert (!header->aux);
- /* Avoid loop header copying when optimizing for size unless we can
- determine that the loop condition is static in the first
- iteration. */
- if (optimize_loop_for_size_p (loop)
- && !loop->force_vectorize
- && !entry_loop_condition_is_static (loop, query))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file,
- " Not duplicating bb %i: optimizing for size.\n",
- header->index);
- return false;
- }
-
gcc_assert (EDGE_COUNT (header->succs) > 0);
if (single_succ_p (header))
{
@@ -223,8 +209,6 @@ should_duplicate_loop_header_p (basic_block header, class loop *loop,
return false;
}
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Will duplicate bb %i\n", header->index);
return true;
}
@@ -289,9 +273,6 @@ class ch_base : public gimple_opt_pass
/* Return true to copy headers of LOOP or false to skip. */
virtual bool process_loop_p (class loop *loop) = 0;
-
- gimple_ranger *m_ranger = NULL;
- path_range_query *m_query = NULL;
};
const pass_data pass_data_ch =
@@ -386,8 +367,11 @@ ch_base::copy_headers (function *fun)
copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
bbs_size = n_basic_blocks_for_fn (fun);
+ auto_vec<loop_p> candidates;
auto_vec<std::pair<edge, loop_p> > copied;
+ gimple_ranger *ranger = new gimple_ranger;
+ path_range_query *query = new path_range_query (*ranger, /*resolve=*/true);
for (auto loop : loops_list (cfun, 0))
{
int initial_limit = param_max_loop_header_insns;
@@ -406,6 +390,37 @@ ch_base::copy_headers (function *fun)
|| !process_loop_p (loop))
continue;
+ /* Avoid loop header copying when optimizing for size unless we can
+ determine that the loop condition is static in the first
+ iteration. */
+ if (optimize_loop_for_size_p (loop)
+ && !loop->force_vectorize
+ && !entry_loop_condition_is_static (loop, query))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " Not duplicating bb %i: optimizing for size.\n",
+ header->index);
+ continue;
+ }
+
+ if (should_duplicate_loop_header_p (header, loop, &remaining_limit))
+ candidates.safe_push (loop);
+ }
+ /* Do not use ranger after we change the IL and not have updated SSA. */
+ delete query;
+ delete ranger;
+
+ for (auto loop : candidates)
+ {
+ int initial_limit = param_max_loop_header_insns;
+ int remaining_limit = initial_limit;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Copying headers of loop %i\n", loop->num);
+
+ header = loop->header;
+
/* Iterate the header copying up to limit; this takes care of the cases
like while (a && b) {...}, where we want to have both of the conditions
copied. TODO -- handle while (a || b) - like cases, by not requiring
@@ -414,9 +429,11 @@ ch_base::copy_headers (function *fun)
exit = NULL;
n_bbs = 0;
- while (should_duplicate_loop_header_p (header, loop, &remaining_limit,
- m_query))
+ while (should_duplicate_loop_header_p (header, loop, &remaining_limit))
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Will duplicate bb %i\n", header->index);
+
/* Find a successor of header that is inside a loop; i.e. the new
header after the condition is copied. */
if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
@@ -552,13 +569,9 @@ pass_ch::execute (function *fun)
loop_optimizer_init (LOOPS_HAVE_PREHEADERS
| LOOPS_HAVE_SIMPLE_LATCHES
| LOOPS_HAVE_RECORDED_EXITS);
- m_ranger = new gimple_ranger;
- m_query = new path_range_query (*m_ranger, /*resolve=*/true);
unsigned int res = copy_headers (fun);
- delete m_query;
- delete m_ranger;
loop_optimizer_finalize ();
return res;
}
@@ -570,12 +583,7 @@ pass_ch::execute (function *fun)
unsigned int
pass_ch_vect::execute (function *fun)
{
- m_ranger = new gimple_ranger;
- m_query = new path_range_query (*m_ranger, /*resolve=*/true);
- unsigned int res = copy_headers (fun);
- delete m_query;
- delete m_ranger;
- return res;
+ return copy_headers (fun);
}
/* Apply header copying according to a very simple test of do-while shape. */
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA
2021-11-11 14:01 [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA Richard Biener
@ 2021-11-11 16:43 ` Aldy Hernandez
2021-11-11 16:57 ` Richard Biener
2021-11-11 17:09 ` Aldy Hernandez
0 siblings, 2 replies; 4+ messages in thread
From: Aldy Hernandez @ 2021-11-11 16:43 UTC (permalink / raw)
To: Richard Biener; +Cc: gcc-patches
Thanks for doing this!
>
> + gimple_ranger *ranger = new gimple_ranger;
> + path_range_query *query = new path_range_query (*ranger, /*resolve=*/true);
Hmmm, it looks like both clients are now instantiating a gimple_ranger
just so they can pass it down to the path_range_query. Maybe we
should have another ctor with just:
path_range_query (bool resolve);
...and have it allocate its own ranger.
Does this seem like a useful improvement? For that matter, resolve
should default to true. The option is only there so the backward
threader can run in a "light" mode (early threading, etc).
Aldy
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA
2021-11-11 16:43 ` Aldy Hernandez
@ 2021-11-11 16:57 ` Richard Biener
2021-11-11 17:09 ` Aldy Hernandez
1 sibling, 0 replies; 4+ messages in thread
From: Richard Biener @ 2021-11-11 16:57 UTC (permalink / raw)
To: Aldy Hernandez; +Cc: gcc-patches
On November 11, 2021 5:43:48 PM GMT+01:00, Aldy Hernandez <aldyh@redhat.com> wrote:
>Thanks for doing this!
>
>>
>> + gimple_ranger *ranger = new gimple_ranger;
>> + path_range_query *query = new path_range_query (*ranger, /*resolve=*/true);
>
>Hmmm, it looks like both clients are now instantiating a gimple_ranger
>just so they can pass it down to the path_range_query. Maybe we
>should have another ctor with just:
>
>path_range_query (bool resolve);
>
>...and have it allocate its own ranger.
>
>Does this seem like a useful improvement? For that matter, resolve
>should default to true. The option is only there so the backward
>threader can run in a "light" mode (early threading, etc).
I've just copied from the two duplicate instances of this, so I don't know nothing here ;)
Richard.
>
>Aldy
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA
2021-11-11 16:43 ` Aldy Hernandez
2021-11-11 16:57 ` Richard Biener
@ 2021-11-11 17:09 ` Aldy Hernandez
1 sibling, 0 replies; 4+ messages in thread
From: Aldy Hernandez @ 2021-11-11 17:09 UTC (permalink / raw)
To: Richard Biener; +Cc: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 823 bytes --]
Like this. It simplifies both loop-ch and the threader.
I'll push this pending tests unless someone objects.
On Thu, Nov 11, 2021 at 5:43 PM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> Thanks for doing this!
>
> >
> > + gimple_ranger *ranger = new gimple_ranger;
> > + path_range_query *query = new path_range_query (*ranger, /*resolve=*/true);
>
> Hmmm, it looks like both clients are now instantiating a gimple_ranger
> just so they can pass it down to the path_range_query. Maybe we
> should have another ctor with just:
>
> path_range_query (bool resolve);
>
> ...and have it allocate its own ranger.
>
> Does this seem like a useful improvement? For that matter, resolve
> should default to true. The option is only there so the backward
> threader can run in a "light" mode (early threading, etc).
>
> Aldy
[-- Attachment #2: 0002-Make-ranger-optional-in-path_range_query.patch --]
[-- Type: text/x-patch, Size: 8552 bytes --]
From c446a8c3110b6629e6dc6897028312ed760440df Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Thu, 11 Nov 2021 18:06:50 +0100
Subject: [PATCH] Make ranger optional in path_range_query.
All users of path_range_query are currently allocating a gimple_ranger
only to pass it to the query object. It's tidier to just do it from
path_range_query if no ranger was passed.
gcc/ChangeLog:
* gimple-range-path.cc (path_range_query::path_range_query): New
ctor without a ranger.
(path_range_query::~path_range_query): Free ranger if necessary.
(path_range_query::range_on_path_entry): Adjust m_ranger for pointer.
(path_range_query::ssa_range_in_phi): Same.
(path_range_query::compute_ranges_in_block): Same.
(path_range_query::compute_imports): Same.
(path_range_query::compute_ranges): Same.
(path_range_query::range_of_stmt): Same.
(path_range_query::compute_outgoing_relations): Same.
* gimple-range-path.h (class path_range_query): New ctor.
* tree-ssa-loop-ch.c (ch_base::copy_headers): Remove gimple_ranger
as path_range_query allocates one.
* tree-ssa-threadbackward.c (class back_threader): Remove m_ranger.
(back_threader::~back_threader): Same.
---
gcc/gimple-range-path.cc | 43 +++++++++++++++++++++++------------
gcc/gimple-range-path.h | 9 ++++++--
gcc/tree-ssa-loop-ch.c | 4 +---
gcc/tree-ssa-threadbackward.c | 5 +---
4 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index 4843c133e62..b9aceaf2565 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -36,13 +36,24 @@ along with GCC; see the file COPYING3. If not see
// Internal construct to help facilitate debugging of solver.
#define DEBUG_SOLVER (dump_file && (param_threader_debug == THREADER_DEBUG_ALL))
-path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
- : m_ranger (ranger)
+path_range_query::path_range_query (gimple_ranger *ranger, bool resolve)
+ : m_cache (new ssa_global_cache),
+ m_has_cache_entry (BITMAP_ALLOC (NULL)),
+ m_ranger (ranger),
+ m_resolve (resolve),
+ m_alloced_ranger (false)
{
- m_cache = new ssa_global_cache;
- m_has_cache_entry = BITMAP_ALLOC (NULL);
- m_resolve = resolve;
- m_oracle = new path_oracle (ranger.oracle ());
+ m_oracle = new path_oracle (ranger->oracle ());
+}
+
+path_range_query::path_range_query (bool resolve)
+ : m_cache (new ssa_global_cache),
+ m_has_cache_entry (BITMAP_ALLOC (NULL)),
+ m_ranger (new gimple_ranger),
+ m_resolve (resolve),
+ m_alloced_ranger (true)
+{
+ m_oracle = new path_oracle (m_ranger->oracle ());
}
path_range_query::~path_range_query ()
@@ -50,6 +61,8 @@ path_range_query::~path_range_query ()
BITMAP_FREE (m_has_cache_entry);
delete m_cache;
delete m_oracle;
+ if (m_alloced_ranger)
+ delete m_ranger;
}
// Mark cache entry for NAME as unused.
@@ -140,7 +153,7 @@ path_range_query::range_on_path_entry (irange &r, tree name)
gimple *last = last_stmt (entry);
if (last)
{
- if (m_ranger.range_of_expr (r, name, last))
+ if (m_ranger->range_of_expr (r, name, last))
return;
gcc_unreachable ();
}
@@ -156,7 +169,7 @@ path_range_query::range_on_path_entry (irange &r, tree name)
{
edge e = EDGE_PRED (entry, i);
if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
- && m_ranger.range_on_edge (tmp, e, name))
+ && m_ranger->range_on_edge (tmp, e, name))
{
r.union_ (tmp);
changed = true;
@@ -244,7 +257,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
if (at_entry ())
{
- if (m_resolve && m_ranger.range_of_expr (r, name, phi))
+ if (m_resolve && m_ranger->range_of_expr (r, name, phi))
return;
// Try fold just in case we can resolve simple things like PHI <5(99), 6(88)>.
@@ -275,7 +288,7 @@ path_range_query::ssa_range_in_phi (irange &r, gphi *phi)
range_on_path_entry (r, arg);
else
r.set_varying (TREE_TYPE (name));
- m_ranger.range_on_edge (tmp, e_in, arg);
+ m_ranger->range_on_edge (tmp, e_in, arg);
r.intersect (tmp);
return;
}
@@ -370,7 +383,7 @@ path_range_query::compute_ranges_in_block (basic_block bb)
EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
{
tree name = ssa_name (i);
- gori_compute &g = m_ranger.gori ();
+ gori_compute &g = m_ranger->gori ();
bitmap exports = g.exports (bb);
if (bitmap_bit_p (exports, i))
@@ -452,7 +465,7 @@ void
path_range_query::compute_imports (bitmap imports, basic_block exit)
{
// Start with the imports from the exit block...
- bitmap r_imports = m_ranger.gori ().imports (exit);
+ bitmap r_imports = m_ranger->gori ().imports (exit);
bitmap_copy (imports, r_imports);
auto_vec<tree> worklist (bitmap_count_bits (imports));
@@ -539,7 +552,7 @@ path_range_query::compute_ranges (const vec<basic_block> &path,
if (m_resolve)
{
- gori_compute &gori = m_ranger.gori ();
+ gori_compute &gori = m_ranger->gori ();
tree name;
// Exported booleans along the path, may help conditionals.
@@ -659,7 +672,7 @@ path_range_query::range_of_stmt (irange &r, gimple *stmt, tree)
if (m_resolve)
{
fold_using_range f;
- jt_fur_source src (stmt, this, &m_ranger.gori (), m_path);
+ jt_fur_source src (stmt, this, &m_ranger->gori (), m_path);
if (!f.fold_stmt (r, stmt, src))
r.set_varying (type);
}
@@ -750,7 +763,7 @@ path_range_query::compute_outgoing_relations (basic_block bb, basic_block next)
else
gcc_unreachable ();
- jt_fur_source src (NULL, this, &m_ranger.gori (), m_path);
+ jt_fur_source src (NULL, this, &m_ranger->gori (), m_path);
src.register_outgoing_edges (cond, r, e0, e1);
}
}
diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h
index b5a054359ad..ea4864d35ef 100644
--- a/gcc/gimple-range-path.h
+++ b/gcc/gimple-range-path.h
@@ -32,7 +32,8 @@ along with GCC; see the file COPYING3. If not see
class path_range_query : public range_query
{
public:
- path_range_query (class gimple_ranger &ranger, bool resolve);
+ path_range_query (class gimple_ranger *ranger, bool resolve = true);
+ path_range_query (bool resolve = true);
virtual ~path_range_query ();
void compute_ranges (const vec<basic_block> &, const bitmap_head *imports = NULL);
void compute_ranges (edge e);
@@ -86,7 +87,7 @@ private:
auto_vec<basic_block> m_path;
auto_bitmap m_imports;
- gimple_ranger &m_ranger;
+ gimple_ranger *m_ranger;
non_null_ref m_non_null;
// Current path position.
@@ -97,6 +98,10 @@ private:
// Set if there were any undefined expressions while pre-calculating path.
bool m_undefined_path;
+
+ // True if m_ranger was allocated in this class and must be freed at
+ // destruction.
+ bool m_alloced_ranger;
};
// Return TRUE if NAME is in the import bitmap.
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index b87361c3741..566cc275317 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -384,8 +384,7 @@ ch_base::copy_headers (function *fun)
auto_vec<loop_p> candidates;
auto_vec<std::pair<edge, loop_p> > copied;
- gimple_ranger *ranger = new gimple_ranger;
- path_range_query *query = new path_range_query (*ranger, /*resolve=*/true);
+ path_range_query *query = new path_range_query;
for (auto loop : loops_list (cfun, 0))
{
int initial_limit = param_max_loop_header_insns;
@@ -423,7 +422,6 @@ ch_base::copy_headers (function *fun)
}
/* Do not use ranger after we change the IL and not have updated SSA. */
delete query;
- delete ranger;
for (auto loop : candidates)
{
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 61aee25d236..71989c288a7 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -100,7 +100,6 @@ private:
back_threader_registry m_registry;
back_threader_profitability m_profit;
- gimple_ranger *m_ranger;
path_range_query *m_solver;
// Current path being analyzed.
@@ -143,15 +142,13 @@ back_threader::back_threader (function *fun, unsigned flags, bool first)
m_fun = fun;
m_flags = flags;
- m_ranger = new gimple_ranger;
- m_solver = new path_range_query (*m_ranger, flags & BT_RESOLVE);
+ m_solver = new path_range_query (flags & BT_RESOLVE);
m_last_stmt = NULL;
}
back_threader::~back_threader ()
{
delete m_solver;
- delete m_ranger;
loop_optimizer_finalize ();
}
--
2.31.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-11-11 17:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-11 14:01 [PATCH] tree-optimization/103188 - avoid running ranger on not-up-to-date SSA Richard Biener
2021-11-11 16:43 ` Aldy Hernandez
2021-11-11 16:57 ` Richard Biener
2021-11-11 17:09 ` Aldy Hernandez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).