Thinking about unreachable vs all noreturn calls,
ch should support all noreturn calls similarly. This
allows the testcase be optimized to memset as expected.
This should also improve code generation of GCC code itself.
Since there are a lot of `if(a)assert_failed();` calls.
Also we don't want to treat `if(static)abort();` that way as that
will most likely be the induction variable comparison.
We do want to stop looking for noreturn if the first bb was not
a noreturn and not an invariant comparison.
20030711-1.c needed to be updated since we copy the "full" loop header
which included the `if(a) abort();`. Which it was before r9-68-g2925cd9d1c9d9e .
PR tree-optimization/122734
gcc/ChangeLog:
* tree-ssa-loop-ch.cc (should_duplicate_loop_header_p):
s/canbe_unreachable/canbe_noreturn/. Instead of checking for
__builtin_unreachable just allow for the first stmt being a
noreturn call.
(ch_base::copy_headers): s/canbe_unreachable/canbe_noreturn/.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/copy-headers-11.c: New test.
* gcc.dg/tree-ssa/20030711-1.c: Update.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c | 8 +++---
.../gcc.dg/tree-ssa/copy-headers-11.c | 25 +++++++++++++++++++
gcc/tree-ssa-loop-ch.cc | 19 +++++++-------
3 files changed, 39 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/copy-headers-11.c
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c
index c3f75eff29e..29e1df7a707 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c
@@ -44,12 +44,12 @@ record_component_aliases (type)
/* The call to blah can not be eliminated. */
/* { dg-final { scan-tree-dump-times "blah \\(\\)" 1 "dom2" } } */
-/* There should be three IF conditionals. */
-/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */
+/* There should be four IF conditionals. */
+/* { dg-final { scan-tree-dump-times "if " 4 "dom2"} } */
/* There should be two loads of type.binfo. */
/* { dg-final { scan-tree-dump-times "type\\.binfo" 2 "dom2"} } */
-/* There should be three loads of vec.length. */
-/* { dg-final { scan-tree-dump-times "vec.length" 3 "dom2"} } */
+/* There should be four loads of vec.length. */
+/* { dg-final { scan-tree-dump-times "vec.length" 4 "dom2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-11.c
b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-11.c
new file mode 100644
index 00000000000..2223a72f023
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers-11.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-ch-details -fdump-tree-ldist-details" } */
+
+/* PR tree-optimization/122734 */
+/* We want to duplicate the block after the one containing the condition going
to unreachable.
+ Since later on we will be removing the condition going to unreachable
anyways. */
+/* So in the end ldist can generate a memset. */
+
+static inline int size(int *a)
+{
+ int t = *a;
+ if (t < 0) __builtin_trap();
+ return t;
+}
+
+void f(int *l, short *d)
+{
+ for(int i = 0; i < size(l); i++)
+ d[i] = 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Duplicating bb . is a win" 1 "ch2" } } */
+/* { dg-final { scan-tree-dump-times "Will duplicate bb" 2 "ch2" } } */
+/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */
+/* { dg-final { scan-tree-dump "generated memset zero" "ldist" } } */
diff --git a/gcc/tree-ssa-loop-ch.cc b/gcc/tree-ssa-loop-ch.cc
index 56b60022360..51ba8971be3 100644
--- a/gcc/tree-ssa-loop-ch.cc
+++ b/gcc/tree-ssa-loop-ch.cc
@@ -190,7 +190,7 @@ enum ch_decision
/* Check whether we should duplicate HEADER of LOOP. At most *LIMIT
instructions should be duplicated, limit is decreased by the actual
- amount. In the case of *CANBE_UNREACHBABLE, if there is a exit edge of the
HEADER, that goes directly to unreachable, then consider that as invariant and
continue. Set *CANBE_UNREACHBABLE to false otherwise. */
+ amount. In the case of *CANBE_NORETURN, if there is a exit edge of the
HEADER, that goes directly to unreachable, then consider that as invariant and
continue. Set *CANBE_NORETURN to false otherwise. */
static ch_decision
should_duplicate_loop_header_p (basic_block header, class loop *loop,
@@ -198,7 +198,7 @@ should_duplicate_loop_header_p (basic_block header, class
loop *loop,
int *limit,
hash_set <edge> *invariant_exits,
hash_set <edge> *static_exits,
- bool *canbe_unreachable)
+ bool *canbe_noreturn)
{
gimple_stmt_iterator bsi;
@@ -461,9 +461,9 @@ should_duplicate_loop_header_p (basic_block header, class
loop *loop,
}
return ch_win_invariant_exit;
}
- if (*canbe_unreachable)
+ if (!static_exit && *canbe_noreturn)
{
- /* See if one of the edges are an edge to __builtin_unreachable().
+ /* See if one of the edges are an edge to noreturn function call.
If so treat it as invariant exit win. */
edge e;
edge_iterator ei;
@@ -473,19 +473,20 @@ should_duplicate_loop_header_p (basic_block header, class
loop *loop,
{
auto gsi = gsi_start_nondebug_after_labels_bb (e->dest);
if (!gsi_end_p (gsi)
- && gimple_call_builtin_p (*gsi, BUILT_IN_UNREACHABLE))
+ && is_a<gcall*>(*gsi)
+ && gimple_call_noreturn_p (*gsi))
{
hasone = true;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
- " `unreachable` exit %i->%i\n",
+ " `noreturn` exit %i->%i\n",
e->src->index, e->dest->index);
}
}
if (hasone)
return ch_win_invariant_exit;
- *canbe_unreachable = false;
}
+ *canbe_noreturn = false;
/* If the static exit fully optimize out, it is win to "duplicate"
it.
@@ -872,12 +873,12 @@ ch_base::copy_headers (function *fun)
auto_vec <ch_decision, 32> decision;
hash_set <edge> *invariant_exits = new hash_set <edge>;
hash_set <edge> *static_exits = new hash_set <edge>;
- bool canbe_unreachable = true;
+ bool canbe_noreturn = true;
while ((ret = should_duplicate_loop_header_p (header, loop, ranger,
&remaining_limit,
invariant_exits,
static_exits,
- &canbe_unreachable))
+ &canbe_noreturn))
!= ch_impossible)
{
nheaders++;
--
2.43.0