Commit 08926e6f by Richard Biener Committed by Richard Biener

re PR tree-optimization/88533 (Higher performance penalty of array-bounds…

re PR tree-optimization/88533 (Higher performance penalty of array-bounds checking for sparse-matrix vector multiply)

2018-12-19  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/88533
	Revert
	2018-04-30  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/28364
	PR tree-optimization/85275
	* tree-ssa-loop-ch.c (ch_base::copy_headers): Stop after
	copying first exit test.

	* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.

	* tree-ssa-loop-ch.c: Include tree-phinodes.h and
	ssa-iterators.h.
	(should_duplicate_loop_header_p): Track whether stmt compute
	loop invariants or values based on IVs.  Apart from the
	original loop header only duplicate blocks with exit tests
	that are based on IVs or invariants.

	* gcc.dg/tree-ssa/copy-headers-6.c: New testcase.
	* gcc.dg/tree-ssa/copy-headers-7.c: Likewise.
	* gcc.dg/tree-ssa/ivopt_mult_1.c: Un-XFAIL.
	* gcc.dg/tree-ssa/ivopt_mult_2.c: Likewise.

From-SVN: r267262
parent 3c55d60f
2018-12-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/88533
Revert
2018-04-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/28364
PR tree-optimization/85275
* tree-ssa-loop-ch.c (ch_base::copy_headers): Stop after
copying first exit test.
* tree-ssa-loop-ch.c: Include tree-phinodes.h and
ssa-iterators.h.
(should_duplicate_loop_header_p): Track whether stmt compute
loop invariants or values based on IVs. Apart from the
original loop header only duplicate blocks with exit tests
that are based on IVs or invariants.
2018-12-19 Tom de Vries <tdevries@suse.de> 2018-12-19 Tom de Vries <tdevries@suse.de>
* config/nvptx/nvptx.c (nvptx_gen_shared_bcast, shared_prop_gen) * config/nvptx/nvptx.c (nvptx_gen_shared_bcast, shared_prop_gen)
2018-12-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/88533
Revert
2018-04-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/28364
PR tree-optimization/85275
* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.
* gcc.dg/tree-ssa/copy-headers-6.c: New testcase.
* gcc.dg/tree-ssa/copy-headers-7.c: Likewise.
* gcc.dg/tree-ssa/ivopt_mult_1.c: Un-XFAIL.
* gcc.dg/tree-ssa/ivopt_mult_2.c: Likewise.
2018-12-19 Jakub Jelinek <jakub@redhat.com> 2018-12-19 Jakub Jelinek <jakub@redhat.com>
PR target/88541 PR target/88541
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ch2-details" } */
int is_sorted(int *a, int n)
{
for (int i = 0; i < n - 1; i++)
if (a[i] > 0)
return 0;
return 1;
}
/* Verify we apply loop header copying but only copy the IV test and
not the alternate exit test. */
/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */
/* { dg-final { scan-tree-dump-times " if " 3 "ch2" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-ch2-details --param logical-op-non-short-circuit=0" } */
int is_sorted(int *a, int n, int m, int k)
{
for (int i = 0; i < n - 1 && m && k > i; i++)
if (a[i] > a[i + 1])
return 0;
return 1;
}
/* Verify we apply loop header copying but only copy the IV tests and
the invariant test, not the alternate exit test. */
/* { dg-final { scan-tree-dump "is now do-while loop" "ch2" } } */
/* { dg-final { scan-tree-dump-times "Will duplicate bb" 3 "ch2" } } */
...@@ -20,4 +20,4 @@ long foo(long* p, long* p2, int N1, int N2) ...@@ -20,4 +20,4 @@ long foo(long* p, long* p2, int N1, int N2)
return s; return s;
} }
/* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts" } } */
...@@ -21,4 +21,4 @@ long foo(long* p, long* p2, int N1, int N2) ...@@ -21,4 +21,4 @@ long foo(long* p, long* p2, int N1, int N2)
return s; return s;
} }
/* { dg-final { scan-tree-dump-times "Replacing" 2 "ivopts" { xfail *-*-* } } } */ /* { dg-final { scan-tree-dump-times "Replacing" 2 "ivopts" } } */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */ /* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */
/* { dg-final { scan-tree-dump "Jumps threaded: 16" "thread1" } } */ /* { dg-final { scan-tree-dump "Jumps threaded: 16" "thread1" } } */
/* { dg-final { scan-tree-dump "Jumps threaded: 9" "thread2" } } */ /* { dg-final { scan-tree-dump "Jumps threaded: 9" "thread2" } } */
/* { dg-final { scan-tree-dump "Jumps threaded: 1" "dom2" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */
/* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough /* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough
to change decisions in switch expansion which in turn can expose new to change decisions in switch expansion which in turn can expose new
jump threading opportunities. Skip the later tests on aarch64. */ jump threading opportunities. Skip the later tests on aarch64. */
......
...@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-scopedtables.h" #include "tree-ssa-scopedtables.h"
#include "tree-ssa-threadedge.h" #include "tree-ssa-threadedge.h"
#include "tree-ssa-sccvn.h" #include "tree-ssa-sccvn.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "params.h" #include "params.h"
/* Duplicates headers of loops if they are small enough, so that the statements /* Duplicates headers of loops if they are small enough, so that the statements
...@@ -50,7 +52,6 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, ...@@ -50,7 +52,6 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
int *limit) int *limit)
{ {
gimple_stmt_iterator bsi; gimple_stmt_iterator bsi;
gimple *last;
gcc_assert (!header->aux); gcc_assert (!header->aux);
...@@ -99,8 +100,8 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, ...@@ -99,8 +100,8 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
return false; return false;
} }
last = last_stmt (header); gcond *last = dyn_cast <gcond *> (last_stmt (header));
if (gimple_code (last) != GIMPLE_COND) if (!last)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, fprintf (dump_file,
...@@ -109,10 +110,24 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, ...@@ -109,10 +110,24 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
return false; return false;
} }
/* Count number of instructions and punt on calls. */ for (gphi_iterator psi = gsi_start_phis (header); !gsi_end_p (psi);
gsi_next (&psi))
{
gphi *phi = psi.phi ();
tree res = gimple_phi_result (phi);
if (INTEGRAL_TYPE_P (TREE_TYPE (res))
|| POINTER_TYPE_P (TREE_TYPE (res)))
gimple_set_uid (phi, 1 /* IV */);
else
gimple_set_uid (phi, 0);
}
/* Count number of instructions and punt on calls.
Populate stmts INV/IV flag to later apply heuristics to the
kind of conditions we want to copy. */
for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi)) for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
{ {
last = gsi_stmt (bsi); gimple *last = gsi_stmt (bsi);
if (gimple_code (last) == GIMPLE_LABEL) if (gimple_code (last) == GIMPLE_LABEL)
continue; continue;
...@@ -142,7 +157,52 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop, ...@@ -142,7 +157,52 @@ should_duplicate_loop_header_p (basic_block header, struct loop *loop,
header->index); header->index);
return false; return false;
} }
/* Classify the stmt based on whether its computation is based
on a IV or whether it is invariant in the loop. */
gimple_set_uid (last, 0);
if (!gimple_vuse (last))
{
bool inv = true;
bool iv = false;
ssa_op_iter i;
tree op;
FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
if (!SSA_NAME_IS_DEFAULT_DEF (op)
&& flow_bb_inside_loop_p (loop,
gimple_bb (SSA_NAME_DEF_STMT (op))))
{
if (!(gimple_uid (SSA_NAME_DEF_STMT (op)) & 2 /* INV */))
inv = false;
if (gimple_uid (SSA_NAME_DEF_STMT (op)) & 1 /* IV */)
iv = true;
}
gimple_set_uid (last, (iv ? 1 : 0) | (inv ? 2 : 0));
}
} }
/* If the condition tests a non-IV loop variant we do not want to rotate
the loop further. Unless this is the original loop header. */
tree lhs = gimple_cond_lhs (last);
tree rhs = gimple_cond_rhs (last);
if (header != loop->header
&& ((TREE_CODE (lhs) == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (lhs)
&& flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (lhs)))
&& gimple_uid (SSA_NAME_DEF_STMT (lhs)) == 0)
|| (TREE_CODE (rhs) == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (rhs)
&& flow_bb_inside_loop_p (loop,
gimple_bb (SSA_NAME_DEF_STMT (rhs)))
&& gimple_uid (SSA_NAME_DEF_STMT (rhs)) == 0)))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file,
" Not duplicating bb %i: condition based on non-IV loop"
"variant.\n", header->index);
return false;
}
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Will duplicate bb %i\n", header->index); fprintf (dump_file, " Will duplicate bb %i\n", header->index);
return true; return true;
...@@ -343,11 +403,6 @@ ch_base::copy_headers (function *fun) ...@@ -343,11 +403,6 @@ ch_base::copy_headers (function *fun)
bbs[n_bbs++] = header; bbs[n_bbs++] = header;
gcc_assert (bbs_size > n_bbs); gcc_assert (bbs_size > n_bbs);
header = exit->dest; header = exit->dest;
/* Make sure to stop copying after we copied the first exit test.
Without further heuristics we do not want to rotate the loop
any further. */
if (loop_exits_from_bb_p (loop, exit->src))
break;
} }
if (!exit) if (!exit)
......
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