Skip to content

Commit 3e1bd64

Browse files
rguenthRichard Biener
authored and
Richard Biener
committed
tree-optimization/116906 - unsafe PRE with never executed edges
When we're computing ANTIC for PRE we treat edges to not yet visited blocks as having a maximum ANTIC solution to get at an optimistic solution in the iteration. That assumes the edges visted eventually execute. This is a wrong assumption that can lead to wrong code (and not only non-optimality) when possibly trapping expressions are involved as the testcases in the PR show. The following mitigates this by pruning trapping expressions from ANTIC computed when maximum sets are involved. PR tree-optimization/116906 * tree-ssa-pre.cc (prune_clobbered_mems): Add clean_traps argument. (compute_antic_aux): Direct prune_clobbered_mems to prune all traps when any MAX solution was involved in the ANTIC computation. (compute_partial_antic_aux): Adjust. * gcc.dg/pr116906-1.c: New testcase. * gcc.dg/pr116906-2.c: Likewise.
1 parent de25f17 commit 3e1bd64

File tree

3 files changed

+93
-6
lines changed

3 files changed

+93
-6
lines changed

gcc/testsuite/gcc.dg/pr116906-1.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* { dg-do run { target *-*-linux* *-*-gnu* *-*-uclinux* } } */
2+
/* { dg-options "-O2" } */
3+
4+
#include <stdint.h>
5+
#include <unistd.h>
6+
#include <signal.h>
7+
#include <stdlib.h>
8+
9+
int a = 1, b = 0;
10+
11+
uint64_t safe_mod(uint64_t a, uint64_t b)
12+
{
13+
if (b == 0) return a;
14+
else return a % b;
15+
}
16+
17+
int __attribute__((noipa))
18+
f(uint64_t p)
19+
{
20+
int c = 0;
21+
j:
22+
b = safe_mod(
23+
(c = ((a &= (0 < p)) && 1), 1), p);
24+
if (!c)
25+
goto j;
26+
return 0;
27+
}
28+
29+
void do_exit (int i)
30+
{
31+
exit (0);
32+
}
33+
34+
int main()
35+
{
36+
struct sigaction s;
37+
sigemptyset (&s.sa_mask);
38+
s.sa_handler = do_exit;
39+
s.sa_flags = 0;
40+
sigaction (SIGALRM, &s, NULL);
41+
alarm (1);
42+
f(b);
43+
}

gcc/testsuite/gcc.dg/pr116906-2.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* { dg-do run { target *-*-linux* *-*-gnu* *-*-uclinux* } } */
2+
/* { dg-options "-O2 -fno-tree-ch" } */
3+
4+
#include <unistd.h>
5+
#include <signal.h>
6+
#include <stdlib.h>
7+
8+
int x;
9+
10+
void __attribute__((noipa))
11+
foo (int *p, unsigned n)
12+
{
13+
unsigned i = 0;
14+
do
15+
{
16+
if (i == n)
17+
break;
18+
if (p)
19+
x = *p;
20+
i += 2;
21+
}
22+
while (1);
23+
x = *p;
24+
}
25+
26+
void do_exit (int i)
27+
{
28+
exit (0);
29+
}
30+
31+
int main()
32+
{
33+
struct sigaction s;
34+
sigemptyset (&s.sa_mask);
35+
s.sa_handler = do_exit;
36+
s.sa_flags = 0;
37+
sigaction (SIGALRM, &s, NULL);
38+
alarm (1);
39+
foo ((int *)0, 1);
40+
}

gcc/tree-ssa-pre.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,10 +2008,11 @@ clean (bitmap_set_t set1, bitmap_set_t set2 = NULL)
20082008
}
20092009

20102010
/* Clean the set of expressions that are no longer valid in SET because
2011-
they are clobbered in BLOCK or because they trap and may not be executed. */
2011+
they are clobbered in BLOCK or because they trap and may not be executed.
2012+
When CLEAN_TRAPS is true remove all possibly trapping expressions. */
20122013

20132014
static void
2014-
prune_clobbered_mems (bitmap_set_t set, basic_block block)
2015+
prune_clobbered_mems (bitmap_set_t set, basic_block block, bool clean_traps)
20152016
{
20162017
bitmap_iterator bi;
20172018
unsigned i;
@@ -2049,7 +2050,7 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block)
20492050
a possible exit point.
20502051
??? This is overly conservative if we translate AVAIL_OUT
20512052
as the available expression might be after the exit point. */
2052-
if (BB_MAY_NOTRETURN (block)
2053+
if ((BB_MAY_NOTRETURN (block) || clean_traps)
20532054
&& vn_reference_may_trap (ref))
20542055
to_remove = i;
20552056
}
@@ -2060,7 +2061,7 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block)
20602061
a possible exit point.
20612062
??? This is overly conservative if we translate AVAIL_OUT
20622063
as the available expression might be after the exit point. */
2063-
if (BB_MAY_NOTRETURN (block)
2064+
if ((BB_MAY_NOTRETURN (block) || clean_traps)
20642065
&& vn_nary_may_trap (nary))
20652066
to_remove = i;
20662067
}
@@ -2114,6 +2115,8 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
21142115

21152116
bool was_visited = BB_VISITED (block);
21162117
bool changed = ! BB_VISITED (block);
2118+
bool any_max_on_edge = false;
2119+
21172120
BB_VISITED (block) = 1;
21182121
old = ANTIC_OUT = S = NULL;
21192122

@@ -2158,6 +2161,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
21582161
maximal set to arrive at a maximum ANTIC_IN solution.
21592162
We can ignore them in the intersection operation and thus
21602163
need not explicitely represent that maximum solution. */
2164+
any_max_on_edge = true;
21612165
if (dump_file && (dump_flags & TDF_DETAILS))
21622166
fprintf (dump_file, "ANTIC_IN is MAX on %d->%d\n",
21632167
e->src->index, e->dest->index);
@@ -2223,7 +2227,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
22232227

22242228
/* Prune expressions that are clobbered in block and thus become
22252229
invalid if translated from ANTIC_OUT to ANTIC_IN. */
2226-
prune_clobbered_mems (ANTIC_OUT, block);
2230+
prune_clobbered_mems (ANTIC_OUT, block, any_max_on_edge);
22272231

22282232
/* Generate ANTIC_OUT - TMP_GEN. */
22292233
S = bitmap_set_subtract_expressions (ANTIC_OUT, TMP_GEN (block));
@@ -2396,7 +2400,7 @@ compute_partial_antic_aux (basic_block block,
23962400

23972401
/* Prune expressions that are clobbered in block and thus become
23982402
invalid if translated from PA_OUT to PA_IN. */
2399-
prune_clobbered_mems (PA_OUT, block);
2403+
prune_clobbered_mems (PA_OUT, block, false);
24002404

24012405
/* PA_IN starts with PA_OUT - TMP_GEN.
24022406
Then we subtract things from ANTIC_IN. */

0 commit comments

Comments
 (0)