As we can optimize dead code a bit already it's fitting to disable code emission after break and goto.
Unified · Split
| @@ -5396,7 +5396,8 @@ static void block(int *bsym, int *csym, int is_expr) · 5395 unmodified lines | |||
| 5396 | nocode_wanted |= 2; | 5396 | nocode_wanted |= 2; |
| 5397 | a = gvtst(1, 0); | 5397 | a = gvtst(1, 0); |
| 5398 | block(bsym, csym, 0); | 5398 | block(bsym, csym, 0); |
| 5399 | nocode_wanted = saved_nocode_wanted; | 5399 | if (cond != 1) |
| 5400 | nocode_wanted = saved_nocode_wanted; | ||
| 5400 | c = tok; | 5401 | c = tok; |
| 5401 | if (c == TOK_ELSE) { | 5402 | if (c == TOK_ELSE) { |
| 5402 | next(); | 5403 | next(); |
| @@ -5406,10 +5407,12 @@ static void block(int *bsym, int *csym, int is_expr) · 3 unmodified lines | |||
| 5406 | gsym(a); | 5407 | gsym(a); |
| 5407 | block(bsym, csym, 0); | 5408 | block(bsym, csym, 0); |
| 5408 | gsym(d); /* patch else jmp */ | 5409 | gsym(d); /* patch else jmp */ |
| 5409 | nocode_wanted = saved_nocode_wanted; | 5410 | if (cond != 0) |
| 5411 | nocode_wanted = saved_nocode_wanted; | ||
| 5410 | } else | 5412 | } else |
| 5411 | gsym(a); | 5413 | gsym(a); |
| 5412 | } else if (tok == TOK_WHILE) { | 5414 | } else if (tok == TOK_WHILE) { |
| 5415 | int saved_nocode_wanted; | ||
| 5413 | nocode_wanted &= ~2; | 5416 | nocode_wanted &= ~2; |
| 5414 | next(); | 5417 | next(); |
| 5415 | d = ind; | 5418 | d = ind; |
| @@ -5420,7 +5423,9 @@ static void block(int *bsym, int *csym, int is_expr) · 4 unmodified lines | |||
| 5420 | a = gvtst(1, 0); | 5423 | a = gvtst(1, 0); |
| 5421 | b = 0; | 5424 | b = 0; |
| 5422 | ++local_scope; | 5425 | ++local_scope; |
| 5426 | saved_nocode_wanted = nocode_wanted; | ||
| 5423 | block(&a, &b, 0); | 5427 | block(&a, &b, 0); |
| 5428 | nocode_wanted = saved_nocode_wanted; | ||
| 5424 | --local_scope; | 5429 | --local_scope; |
| 5425 | if(!nocode_wanted) | 5430 | if(!nocode_wanted) |
| 5426 | gjmp_addr(d); | 5431 | gjmp_addr(d); |
| @@ -5556,6 +5561,7 @@ static void block(int *bsym, int *csym, int is_expr) · 129 unmodified lines | |||
| 5556 | /* jump unless last stmt in top-level block */ | 5561 | /* jump unless last stmt in top-level block */ |
| 5557 | if (tok != '}' || local_scope != 1) | 5562 | if (tok != '}' || local_scope != 1) |
| 5558 | rsym = gjmp(rsym); | 5563 | rsym = gjmp(rsym); |
| 5564 | nocode_wanted |= 2; | ||
| 5559 | } else if (tok == TOK_BREAK) { | 5565 | } else if (tok == TOK_BREAK) { |
| 5560 | /* compute jump */ | 5566 | /* compute jump */ |
| 5561 | if (!bsym) | 5567 | if (!bsym) |
| @@ -5563,6 +5569,7 @@ static void block(int *bsym, int *csym, int is_expr) · 1 unmodified line | |||
| 5563 | *bsym = gjmp(*bsym); | 5569 | *bsym = gjmp(*bsym); |
| 5564 | next(); | 5570 | next(); |
| 5565 | skip(';'); | 5571 | skip(';'); |
| 5572 | nocode_wanted |= 2; | ||
| 5566 | } else if (tok == TOK_CONTINUE) { | 5573 | } else if (tok == TOK_CONTINUE) { |
| 5567 | /* compute jump */ | 5574 | /* compute jump */ |
| 5568 | if (!csym) | 5575 | if (!csym) |
| @@ -5573,6 +5580,7 @@ static void block(int *bsym, int *csym, int is_expr) · 4 unmodified lines | |||
| 5573 | skip(';'); | 5580 | skip(';'); |
| 5574 | } else if (tok == TOK_FOR) { | 5581 | } else if (tok == TOK_FOR) { |
| 5575 | int e; | 5582 | int e; |
| 5583 | int saved_nocode_wanted; | ||
| 5576 | nocode_wanted &= ~2; | 5584 | nocode_wanted &= ~2; |
| 5577 | next(); | 5585 | next(); |
| 5578 | skip('('); | 5586 | skip('('); |
| @@ -5607,7 +5615,9 @@ static void block(int *bsym, int *csym, int is_expr) · 28 unmodified lines | |||
| 5607 | gsym(e); | 5615 | gsym(e); |
| 5608 | } | 5616 | } |
| 5609 | skip(')'); | 5617 | skip(')'); |
| 5618 | saved_nocode_wanted = nocode_wanted; | ||
| 5610 | block(&a, &b, 0); | 5619 | block(&a, &b, 0); |
| 5620 | nocode_wanted = saved_nocode_wanted; | ||
| 5611 | if(!nocode_wanted) | 5621 | if(!nocode_wanted) |
| 5612 | gjmp_addr(c); | 5622 | gjmp_addr(c); |
| 5613 | gsym(a); | 5623 | gsym(a); |
| @@ -5617,13 +5627,16 @@ static void block(int *bsym, int *csym, int is_expr) · 3 unmodified lines | |||
| 5617 | 5627 | ||
| 5618 | } else | 5628 | } else |
| 5619 | if (tok == TOK_DO) { | 5629 | if (tok == TOK_DO) { |
| 5630 | int saved_nocode_wanted; | ||
| 5620 | nocode_wanted &= ~2; | 5631 | nocode_wanted &= ~2; |
| 5621 | next(); | 5632 | next(); |
| 5622 | a = 0; | 5633 | a = 0; |
| 5623 | b = 0; | 5634 | b = 0; |
| 5624 | d = ind; | 5635 | d = ind; |
| 5625 | vla_sp_restore(); | 5636 | vla_sp_restore(); |
| 5637 | saved_nocode_wanted = nocode_wanted; | ||
| 5626 | block(&a, &b, 0); | 5638 | block(&a, &b, 0); |
| 5639 | nocode_wanted = saved_nocode_wanted; | ||
| 5627 | skip(TOK_WHILE); | 5640 | skip(TOK_WHILE); |
| 5628 | skip('('); | 5641 | skip('('); |
| 5629 | gsym(b); | 5642 | gsym(b); |
| @@ -5637,6 +5650,7 @@ static void block(int *bsym, int *csym, int is_expr) · 7 unmodified lines | |||
| 5637 | } else | 5650 | } else |
| 5638 | if (tok == TOK_SWITCH) { | 5651 | if (tok == TOK_SWITCH) { |
| 5639 | struct switch_t *saved, sw; | 5652 | struct switch_t *saved, sw; |
| 5653 | int saved_nocode_wanted = nocode_wanted; | ||
| 5640 | next(); | 5654 | next(); |
| 5641 | skip('('); | 5655 | skip('('); |
| 5642 | gexpr(); | 5656 | gexpr(); |
| @@ -5650,6 +5664,7 @@ static void block(int *bsym, int *csym, int is_expr) · 7 unmodified lines | |||
| 5650 | saved = cur_switch; | 5664 | saved = cur_switch; |
| 5651 | cur_switch = &sw; | 5665 | cur_switch = &sw; |
| 5652 | block(&a, csym, 0); | 5666 | block(&a, csym, 0); |
| 5667 | nocode_wanted = saved_nocode_wanted; | ||
| 5653 | a = gjmp(a); /* add implicit break */ | 5668 | a = gjmp(a); /* add implicit break */ |
| 5654 | /* case lookup */ | 5669 | /* case lookup */ |
| 5655 | gsym(b); | 5670 | gsym(b); |
| @@ -1184,6 +1184,57 @@ void optimize_out(void) · 1183 unmodified lines | |||
| 1184 | printf("oo:%d\n", defined_function()); | 1184 | printf("oo:%d\n", defined_function()); |
| 1185 | else | 1185 | else |
| 1186 | printf("oo:%d\n", undefined_function()); | 1186 | printf("oo:%d\n", undefined_function()); |
| 1187 | while (1) { | ||
| 1188 | printf("oow:%d\n", defined_function()); | ||
| 1189 | break; | ||
| 1190 | printf("oow:%d\n", undefined_function()); | ||
| 1191 | } | ||
| 1192 | j = 1; | ||
| 1193 | /* Following is a switch without {} block intentionally. */ | ||
| 1194 | switch (j) | ||
| 1195 | case 1: break; | ||
| 1196 | printf ("oos:%d\n", defined_function()); | ||
| 1197 | /* The following break shouldn't lead to disabled code after | ||
| 1198 | the while. */ | ||
| 1199 | while (1) | ||
| 1200 | break; | ||
| 1201 | printf ("ool1:%d\n", defined_function()); | ||
| 1202 | /* Same for the other types of loops. */ | ||
| 1203 | do | ||
| 1204 | break; | ||
| 1205 | while (1); | ||
| 1206 | printf ("ool2:%d\n", defined_function()); | ||
| 1207 | for (;;) | ||
| 1208 | break; | ||
| 1209 | printf ("ool3:%d\n", defined_function()); | ||
| 1210 | /* Normal {} blocks without controlling statements | ||
| 1211 | shouldn't reactivate code emission */ | ||
| 1212 | while (1) { | ||
| 1213 | { | ||
| 1214 | break; | ||
| 1215 | } | ||
| 1216 | printf ("ool4:%d\n", undefined_function()); | ||
| 1217 | } | ||
| 1218 | j = 1; | ||
| 1219 | while (j) { | ||
| 1220 | if (j == 0) | ||
| 1221 | break; /* this break shouldn't disable code outside the if. */ | ||
| 1222 | printf("ool5:%d\n", defined_function()); | ||
| 1223 | j--; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | j = 1; | ||
| 1227 | while (j) { | ||
| 1228 | if (1) | ||
| 1229 | j--; | ||
| 1230 | else | ||
| 1231 | breakhere: break; | ||
| 1232 | printf("ool6:%d\n", defined_function()); | ||
| 1233 | goto breakhere; | ||
| 1234 | } | ||
| 1235 | if (1) | ||
| 1236 | return; | ||
| 1237 | printf ("oor:%d\n", undefined_function()); | ||
| 1187 | } | 1238 | } |
| 1188 | 1239 | ||
| 1189 | int defined_function(void) | 1240 | int defined_function(void) |