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:
parent
0c36b3ff2d
commit
c3e3a07ed4
2 changed files with 25 additions and 8 deletions
26
tccgen.c
26
tccgen.c
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue