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

View File

@ -1184,6 +1184,57 @@ void optimize_out(void)
printf("oo:%d\n", defined_function()); printf("oo:%d\n", defined_function());
else else
printf("oo:%d\n", undefined_function()); 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) int defined_function(void)