opt: Make break and goto not fallthrough

As we can optimize dead code a bit already it's fitting
to disable code emission after break and goto.
master
Michael Matz 2016-09-26 20:31:24 +02:00
parent 31c7ea0165
commit ca435dc2e3
2 changed files with 68 additions and 2 deletions

View File

@ -5396,7 +5396,8 @@ static void block(int *bsym, int *csym, int is_expr)
nocode_wanted |= 2;
a = gvtst(1, 0);
block(bsym, csym, 0);
nocode_wanted = saved_nocode_wanted;
if (cond != 1)
nocode_wanted = saved_nocode_wanted;
c = tok;
if (c == TOK_ELSE) {
next();
@ -5406,10 +5407,12 @@ static void block(int *bsym, int *csym, int is_expr)
gsym(a);
block(bsym, csym, 0);
gsym(d); /* patch else jmp */
nocode_wanted = saved_nocode_wanted;
if (cond != 0)
nocode_wanted = saved_nocode_wanted;
} else
gsym(a);
} else if (tok == TOK_WHILE) {
int saved_nocode_wanted;
nocode_wanted &= ~2;
next();
d = ind;
@ -5420,7 +5423,9 @@ static void block(int *bsym, int *csym, int is_expr)
a = gvtst(1, 0);
b = 0;
++local_scope;
saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted;
--local_scope;
if(!nocode_wanted)
gjmp_addr(d);
@ -5556,6 +5561,7 @@ static void block(int *bsym, int *csym, int is_expr)
/* jump unless last stmt in top-level block */
if (tok != '}' || local_scope != 1)
rsym = gjmp(rsym);
nocode_wanted |= 2;
} else if (tok == TOK_BREAK) {
/* compute jump */
if (!bsym)
@ -5563,6 +5569,7 @@ static void block(int *bsym, int *csym, int is_expr)
*bsym = gjmp(*bsym);
next();
skip(';');
nocode_wanted |= 2;
} else if (tok == TOK_CONTINUE) {
/* compute jump */
if (!csym)
@ -5573,6 +5580,7 @@ static void block(int *bsym, int *csym, int is_expr)
skip(';');
} else if (tok == TOK_FOR) {
int e;
int saved_nocode_wanted;
nocode_wanted &= ~2;
next();
skip('(');
@ -5607,7 +5615,9 @@ static void block(int *bsym, int *csym, int is_expr)
gsym(e);
}
skip(')');
saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted;
if(!nocode_wanted)
gjmp_addr(c);
gsym(a);
@ -5617,13 +5627,16 @@ static void block(int *bsym, int *csym, int is_expr)
} else
if (tok == TOK_DO) {
int saved_nocode_wanted;
nocode_wanted &= ~2;
next();
a = 0;
b = 0;
d = ind;
vla_sp_restore();
saved_nocode_wanted = nocode_wanted;
block(&a, &b, 0);
nocode_wanted = saved_nocode_wanted;
skip(TOK_WHILE);
skip('(');
gsym(b);
@ -5637,6 +5650,7 @@ static void block(int *bsym, int *csym, int is_expr)
} else
if (tok == TOK_SWITCH) {
struct switch_t *saved, sw;
int saved_nocode_wanted = nocode_wanted;
next();
skip('(');
gexpr();
@ -5650,6 +5664,7 @@ static void block(int *bsym, int *csym, int is_expr)
saved = cur_switch;
cur_switch = &sw;
block(&a, csym, 0);
nocode_wanted = saved_nocode_wanted;
a = gjmp(a); /* add implicit break */
/* case lookup */
gsym(b);

View File

@ -1184,6 +1184,57 @@ void optimize_out(void)
printf("oo:%d\n", defined_function());
else
printf("oo:%d\n", undefined_function());
while (1) {
printf("oow:%d\n", defined_function());
break;
printf("oow:%d\n", undefined_function());
}
j = 1;
/* Following is a switch without {} block intentionally. */
switch (j)
case 1: break;
printf ("oos:%d\n", defined_function());
/* The following break shouldn't lead to disabled code after
the while. */
while (1)
break;
printf ("ool1:%d\n", defined_function());
/* Same for the other types of loops. */
do
break;
while (1);
printf ("ool2:%d\n", defined_function());
for (;;)
break;
printf ("ool3:%d\n", defined_function());
/* Normal {} blocks without controlling statements
shouldn't reactivate code emission */
while (1) {
{
break;
}
printf ("ool4:%d\n", undefined_function());
}
j = 1;
while (j) {
if (j == 0)
break; /* this break shouldn't disable code outside the if. */
printf("ool5:%d\n", defined_function());
j--;
}
j = 1;
while (j) {
if (1)
j--;
else
breakhere: break;
printf("ool6:%d\n", defined_function());
goto breakhere;
}
if (1)
return;
printf ("oor:%d\n", undefined_function());
}
int defined_function(void)