Commit 2925cd9d by Richard Biener Committed by Richard Biener

re PR tree-optimization/28364 (poor optimization choices when iterating over a…

re PR tree-optimization/28364 (poor optimization choices when iterating over a std::string (probably not c++-specific))

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/copy-headers-5.c: New testcase.
	* gcc.dg/tree-ssa/predcom-8.c: Likewise.
	* gcc.dg/tree-ssa/cunroll-13.c: Rewrite to gimple testcase.
	* gcc.dg/tree-ssa/ivopt_mult_1.c: XFAIL.
	* gcc.dg/tree-ssa/ivopt_mult_1g.c: Add gimple variant that
	still passes.
	* gcc.dg/tree-ssa/ivopt_mult_2.c: XFAIL.
	* gcc.dg/tree-ssa/ivopt_mult_2g.c: Add gimple variant that
	still passes.
	* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.
	* gcc.dg/tree-ssa/20030710-1.c: Likewise.
	* gcc.dg/tree-ssa/20030711-1.c: Likewise.

From-SVN: r259754
parent 03b42a71
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.
2018-04-28 Mark Wielaard <mark@klomp.org> 2018-04-28 Mark Wielaard <mark@klomp.org>
* dwarf2out.c (dwarf2out_finish): Add .debug_addr table header for * dwarf2out.c (dwarf2out_finish): Add .debug_addr table header for
......
2018-04-30 Richard Biener <rguenther@suse.de>
PR tree-optimization/28364
PR tree-optimization/85275
* gcc.dg/tree-ssa/copy-headers-5.c: New testcase.
* gcc.dg/tree-ssa/predcom-8.c: Likewise.
* gcc.dg/tree-ssa/cunroll-13.c: Rewrite to gimple testcase.
* gcc.dg/tree-ssa/ivopt_mult_1.c: XFAIL.
* gcc.dg/tree-ssa/ivopt_mult_1g.c: Add gimple variant that
still passes.
* gcc.dg/tree-ssa/ivopt_mult_2.c: XFAIL.
* gcc.dg/tree-ssa/ivopt_mult_2g.c: Add gimple variant that
still passes.
* gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust.
* gcc.dg/tree-ssa/20030710-1.c: Likewise.
* gcc.dg/tree-ssa/20030711-1.c: Likewise.
2018-04-28 Uros Bizjak <ubizjak@gmail.com> 2018-04-28 Uros Bizjak <ubizjak@gmail.com>
PR target/84431 PR target/84431
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-dom2" } */ /* { dg-options "-O1 -fdump-tree-phicprop1" } */
extern void abort (void); extern void abort (void);
extern void blah (void); extern void blah (void);
...@@ -42,14 +42,14 @@ record_component_aliases (type) ...@@ -42,14 +42,14 @@ record_component_aliases (type)
/* The call to blah should have been eliminated. If the call is not /* The call to blah should have been eliminated. If the call is not
eliminated, then dominator optimizations failed and it'll be eliminated, then dominator optimizations failed and it'll be
impossible to delete other unnecessary code. */ impossible to delete other unnecessary code. */
/* { dg-final { scan-tree-dump-not "blah \\(\\)" "dom2" } } */ /* { dg-final { scan-tree-dump-not "blah \\(\\)" "phicprop1" } } */
/* There should be two IF conditionals. */ /* There should be two IF conditionals. */
/* { dg-final { scan-tree-dump-times "if " 2 "dom2"} } */ /* { dg-final { scan-tree-dump-times "if " 2 "phicprop1"} } */
/* There should be a single load of type.binfo. */ /* There should be a single load of type.binfo. */
/* { dg-final { scan-tree-dump-times "type\\.binfo" 1 "dom2"} } */ /* { dg-final { scan-tree-dump-times "type\\.binfo" 1 "phicprop1"} } */
/* There should be two loads of vec.length. */ /* There should be two loads of vec.length. */
/* { dg-final { scan-tree-dump-times "vec.length" 2 "dom2"} } */ /* { dg-final { scan-tree-dump-times "vec.length" 2 "phicprop1"} } */
...@@ -44,12 +44,12 @@ record_component_aliases (type) ...@@ -44,12 +44,12 @@ record_component_aliases (type)
/* The call to blah can not be eliminated. */ /* The call to blah can not be eliminated. */
/* { dg-final { scan-tree-dump-times "blah \\(\\)" 1 "dom2" } } */ /* { dg-final { scan-tree-dump-times "blah \\(\\)" 1 "dom2" } } */
/* There should be four IF conditionals. */ /* There should be three IF conditionals. */
/* { dg-final { scan-tree-dump-times "if " 4 "dom2"} } */ /* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */
/* There should be two loads of type.binfo. */ /* There should be two loads of type.binfo. */
/* { dg-final { scan-tree-dump-times "type\\.binfo" 2 "dom2"} } */ /* { dg-final { scan-tree-dump-times "type\\.binfo" 2 "dom2"} } */
/* There should be four loads of vec.length. */ /* There should be three loads of vec.length. */
/* { dg-final { scan-tree-dump-times "vec.length" 4 "dom2"} } */ /* { dg-final { scan-tree-dump-times "vec.length" 3 "dom2"} } */
/* { 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] > a[i + 1])
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-do compile } */
/* { dg-options "-O3 -fdisable-tree-evrp -fdisable-tree-cunrolli -fdisable-tree-vrp1 -fdump-tree-cunroll-blocks-details" } */ /* { dg-options "-O3 -fgimple -fdump-tree-cunroll-blocks-details" } */
#if __SIZEOF_INT__ < 4 #if __SIZEOF_INT__ < 4
__extension__ typedef __INT32_TYPE__ i32; __extension__ typedef __INT32_TYPE__ i32;
...@@ -7,15 +7,53 @@ __extension__ typedef __INT32_TYPE__ i32; ...@@ -7,15 +7,53 @@ __extension__ typedef __INT32_TYPE__ i32;
typedef int i32; typedef int i32;
#endif #endif
struct a {int a[8];int b;}; struct a {i32 a[8];i32 b;};
void
t(struct a *a) void __GIMPLE (startwith("fix_loops"))
t (struct a * a)
{ {
for (i32 i=0;i<123456 && a->a[i];i++) i32 i;
a->a[i]++; i32 _1;
i32 _2;
i32 _9;
i32 _11;
bb_2:
_11 = a_6(D)->a[0];
if (_11 != _Literal (i32) 0)
goto bb_6;
else
goto bb_3;
bb_3:
return;
bb_4:
_1 = _2 + 1;
a_6(D)->a[i_19] = _1;
i_8 = i_19 + _Literal (i32) 1;
if (i_8 <= _Literal (i32) 123455)
goto bb_5;
else
goto bb_3;
bb_5:
i_19 = __PHI (bb_6: _Literal (i32) 1, bb_4: i_8);
_2 = a_6(D)->a[i_19];
if (_2 != _Literal (i32) 0)
goto bb_4;
else
goto bb_3;
bb_6:
_9 = _11 + _Literal (i32) 1;
a_6(D)->a[0] = _9;
goto bb_5;
} }
/* This pass relies on the fact that we do not eliminate the redundant test for i early.
It is necessary to disable all passes that do so. At the moment it is evrp, vrp1 and cunrolli. */ /* This testcase relies on the fact that we do not eliminate the redundant test
for i early. It is necessary to disable all passes that do so, for the
moment starting with the loop pipeline is good enough. */
/* { dg-final { scan-tree-dump-times "Loop 1 iterates 123454 times" 1 "cunroll" } } */ /* { dg-final { scan-tree-dump-times "Loop 1 iterates 123454 times" 1 "cunroll" } } */
/* { dg-final { scan-tree-dump-times "Last iteration exit edge was proved true" 1 "cunroll" } } */ /* { dg-final { scan-tree-dump-times "Last iteration exit edge was proved true" 1 "cunroll" } } */
/* { dg-final { scan-tree-dump-times "Exit condition of peeled iterations was eliminated" 1 "cunroll" } } */ /* { dg-final { scan-tree-dump-times "Exit condition of peeled iterations was eliminated" 1 "cunroll" } } */
......
...@@ -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"} } */ /* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts" { xfail *-*-* } } } */
/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */
/* { dg-options "-O2 -fgimple -m64 -fdump-tree-ivopts-details" } */
/* The test 'if (p2 > p_limit2)' can be replaced, so iv p2 can be
* eliminated. */
long int __GIMPLE (startwith("fix_loops"))
foo (long int * p, long int * p2, int N1, int N2)
{
long int s;
long int * p_limit2;
long int * p_limit;
long unsigned int _1;
long unsigned int _2;
long unsigned int _3;
long unsigned int _4;
long int _5;
bb_2:
_1 = (long unsigned int) N1_10(D);
_2 = _1 * 8ul;
p_limit_12 = p_11(D) + _2;
_3 = (long unsigned int) N2_13(D);
_4 = _3 * 8ul;
p_limit2_15 = p2_14(D) + _4;
if (p_11(D) <= p_limit_12)
goto bb_3;
else
goto bb_13;
bb_13:
bb_9:
goto bb_6;
bb_3:
p_20 = p_11(D) + 8ul;
p2_23 = p2_14(D) + 8ul;
if (p_limit2_15 < p2_23)
goto bb_14;
else
goto bb_7;
bb_14:
goto bb_9;
bb_7:
goto bb_5;
bb_4:
p_16 = p_26 + 8ul;
p2_17 = p2_27 + 8ul;
if (p_limit2_15 < p2_17)
goto bb_11;
else
goto bb_8;
bb_11:
goto bb_6;
bb_8:
;
bb_5:
s_24 = __PHI (bb_7: 0l, bb_8: s_19);
p_26 = __PHI (bb_7: p_20, bb_8: p_16);
p2_27 = __PHI (bb_7: p2_23, bb_8: p2_17);
_5 = __MEM <long int> (p_26);
s_19 = _5 + s_24;
if (p_limit_12 >= p_26)
goto bb_4;
else
goto bb_12;
bb_12:
;
bb_6:
s_25 = __PHI (bb_12: s_19, bb_11: s_19, bb_9: 0l);
return s_25;
}
/* { 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"} } */ /* { dg-final { scan-tree-dump-times "Replacing" 2 "ivopts" { xfail *-*-* } } } */
/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */
/* { dg-options "-O2 -fgimple -m64 -fdump-tree-ivopts-details" } */
/* Exit tests 'i < N1' and 'p2 > p_limit2' can be replaced, so
* two ivs i and p2 can be eliminate. */
long int __GIMPLE (startwith("fix_loops"))
foo (long int * p, long int * p2, int N1, int N2)
{
long int s;
long int * p_limit2;
int i;
long unsigned int _1;
long unsigned int _2;
long int _3;
bb_2:
_1 = (long unsigned int) N2_9(D);
_2 = _1 * 8ul;
p_limit2_11 = p2_10(D) + _2;
if (N1_13(D) > 0)
goto bb_3;
else
goto bb_13;
bb_13:
bb_9:
goto bb_6;
bb_3:
p_22 = p_12(D) + 8ul;
p2_23 = p2_10(D) + 8ul;
if (p_limit2_11 < p2_23)
goto bb_14;
else
goto bb_7;
bb_14:
goto bb_9;
bb_7:
goto bb_5;
bb_4:
p_14 = p_27 + 8ul;
p2_15 = p2_28 + 8ul;
i_16 = i_29 + 1;
if (p_limit2_11 < p2_15)
goto bb_11;
else
goto bb_8;
bb_11:
goto bb_6;
bb_8:
;
bb_5:
s_25 = __PHI (bb_7: 0l, bb_8: s_18);
p_27 = __PHI (bb_7: p_22, bb_8: p_14);
p2_28 = __PHI (bb_7: p2_23, bb_8: p2_15);
i_29 = __PHI (bb_7: 1, bb_8: i_16);
_3 = __MEM <long int> (p_27);
s_18 = _3 + s_25;
if (N1_13(D) > i_29)
goto bb_4;
else
goto bb_12;
bb_12:
;
bb_6:
s_26 = __PHI (bb_12: s_18, bb_11: s_18, bb_9: 0l);
return s_26;
}
/* { dg-final { scan-tree-dump-times "Replacing" 2 "ivopts"} } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-pcom-details" } */
int is_sorted(int *a, int n)
{
for (int i = 0; i < n - 1; i++)
if (a[i] > a[i + 1])
return 0;
return 1;
}
/* { dg-final { scan-tree-dump "Executing predictive commoning without unrolling" "pcom" } } */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
/* { 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: 3" "thread3" } } */ /* { dg-final { scan-tree-dump "Jumps threaded: 3" "thread3" } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */ /* { dg-final { scan-tree-dump "Jumps threaded: 1" "dom2" } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom3" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom3" } } */
/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp2" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp2" } } */
......
...@@ -340,6 +340,11 @@ ch_base::copy_headers (function *fun) ...@@ -340,6 +340,11 @@ 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