dce: Don't force unreachable case label to be live

if a switch is unreachable then so are the case labels.
Unlike normal labels they can't possibly be reached from not-yet
parsed code, so there's no reason to enable codegen again for those.
This commit is contained in:
Michael Matz 2022-07-12 17:07:33 +02:00
parent 0c36b3ff2d
commit c3e3a07ed4
2 changed files with 25 additions and 8 deletions

View file

@ -62,7 +62,15 @@ ST_DATA int nocode_wanted; /* no code generation wanted */
/* Clear 'nocode_wanted' at label if it was used */ /* Clear 'nocode_wanted' at label if it was used */
ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }} ST_FUNC void gsym(int t) { if (t) { gsym_addr(t, ind); CODE_ON(); }}
static int gind(void) { int t = ind; CODE_ON(); if (debug_modes) tcc_tcov_block_begin(tcc_state); return t; } static int gind(int known_unreachable)
{
int t = ind;
if (!known_unreachable)
CODE_ON();
if (debug_modes)
tcc_tcov_block_begin(tcc_state);
return t;
}
/* Set 'nocode_wanted' after unconditional jumps */ /* Set 'nocode_wanted' after unconditional jumps */
static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }
@ -99,6 +107,7 @@ static struct switch_t {
int sym; int sym;
} **p; int n; /* list of case ranges */ } **p; int n; /* list of case ranges */
int def_sym; /* default symbol */ int def_sym; /* default symbol */
int nocode_wanted;
int *bsym; int *bsym;
struct scope *scope; struct scope *scope;
struct switch_t *prev; struct switch_t *prev;
@ -6769,7 +6778,7 @@ again:
} }
} else if (t == TOK_WHILE) { } else if (t == TOK_WHILE) {
d = gind(); d = gind(0);
skip('('); skip('(');
gexpr(); gexpr();
skip(')'); skip(')');
@ -6869,7 +6878,7 @@ again:
} }
skip(';'); skip(';');
a = b = 0; a = b = 0;
c = d = gind(); c = d = gind(0);
if (tok != ';') { if (tok != ';') {
gexpr(); gexpr();
a = gvtst(1, 0); a = gvtst(1, 0);
@ -6877,7 +6886,7 @@ again:
skip(';'); skip(';');
if (tok != ')') { if (tok != ')') {
e = gjmp(0); e = gjmp(0);
d = gind(); d = gind(0);
gexpr(); gexpr();
vpop(); vpop();
gjmp_addr(c); gjmp_addr(c);
@ -6892,7 +6901,7 @@ again:
} else if (t == TOK_DO) { } else if (t == TOK_DO) {
a = b = 0; a = b = 0;
d = gind(); d = gind(0);
lblock(&a, &b); lblock(&a, &b);
gsym(b); gsym(b);
skip(TOK_WHILE); skip(TOK_WHILE);
@ -6911,6 +6920,7 @@ again:
sw->bsym = &a; sw->bsym = &a;
sw->scope = cur_scope; sw->scope = cur_scope;
sw->prev = cur_switch; sw->prev = cur_switch;
sw->nocode_wanted = nocode_wanted;
cur_switch = sw; cur_switch = sw;
skip('('); skip('(');
@ -6965,7 +6975,7 @@ again:
} }
if (debug_modes) if (debug_modes)
tcc_tcov_reset_ind(tcc_state); tcc_tcov_reset_ind(tcc_state);
cr->sym = gind(); cr->sym = gind(cur_switch->nocode_wanted);
dynarray_add(&cur_switch->p, &cur_switch->n, cr); dynarray_add(&cur_switch->p, &cur_switch->n, cr);
skip(':'); skip(':');
is_expr = 0; is_expr = 0;
@ -6978,7 +6988,7 @@ again:
tcc_error("too many 'default'"); tcc_error("too many 'default'");
if (debug_modes) if (debug_modes)
tcc_tcov_reset_ind(tcc_state); tcc_tcov_reset_ind(tcc_state);
cur_switch->def_sym = gind(); cur_switch->def_sym = gind(cur_switch->nocode_wanted);
skip(':'); skip(':');
is_expr = 0; is_expr = 0;
goto block_after_label; goto block_after_label;
@ -7044,7 +7054,7 @@ again:
} else { } else {
s = label_push(&global_label_stack, t, LABEL_DEFINED); s = label_push(&global_label_stack, t, LABEL_DEFINED);
} }
s->jnext = gind(); s->jnext = gind(0);
s->cleanupstate = cur_scope->cl.s; s->cleanupstate = cur_scope->cl.s;
block_after_label: block_after_label:

View file

@ -1418,6 +1418,13 @@ void optimize_out_test(void)
undefined_function(); undefined_function();
} }
if (0) {
switch (defined_function()) {
case 0: undefined_function(); break;
default: undefined_function(); break;
}
}
/* Leave the "if(1)return; printf()" in this order and last in the function */ /* Leave the "if(1)return; printf()" in this order and last in the function */
if (1) if (1)
return; return;