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 | 5396 | nocode_wanted |= 2; |
| 5397 | 5397 | a = gvtst(1, 0); |
| 5398 | 5398 | block(bsym, csym, 0); |
| 5399 | − nocode_wanted = saved_nocode_wanted; | |
| 5399 | + if (cond != 1) | |
| 5400 | + nocode_wanted = saved_nocode_wanted; | |
| 5400 | 5401 | c = tok; |
| 5401 | 5402 | if (c == TOK_ELSE) { |
| 5402 | 5403 | next(); |
| @@ -5406,10 +5407,12 @@ static void block(int *bsym, int *csym, int is_expr) · 3 unmodified lines | ||
| 5406 | 5407 | gsym(a); |
| 5407 | 5408 | block(bsym, csym, 0); |
| 5408 | 5409 | gsym(d); /* patch else jmp */ |
| 5409 | − nocode_wanted = saved_nocode_wanted; | |
| 5410 | + if (cond != 0) | |
| 5411 | + nocode_wanted = saved_nocode_wanted; | |
| 5410 | 5412 | } else |
| 5411 | 5413 | gsym(a); |
| 5412 | 5414 | } else if (tok == TOK_WHILE) { |
| 5415 | + int saved_nocode_wanted; | |
| 5413 | 5416 | nocode_wanted &= ~2; |
| 5414 | 5417 | next(); |
| 5415 | 5418 | d = ind; |
| @@ -5420,7 +5423,9 @@ static void block(int *bsym, int *csym, int is_expr) · 4 unmodified lines | ||
| 5420 | 5423 | a = gvtst(1, 0); |
| 5421 | 5424 | b = 0; |
| 5422 | 5425 | ++local_scope; |
| 5426 | + saved_nocode_wanted = nocode_wanted; | |
| 5423 | 5427 | block(&a, &b, 0); |
| 5428 | + nocode_wanted = saved_nocode_wanted; | |
| 5424 | 5429 | --local_scope; |
| 5425 | 5430 | if(!nocode_wanted) |
| 5426 | 5431 | gjmp_addr(d); |
| @@ -5556,6 +5561,7 @@ static void block(int *bsym, int *csym, int is_expr) · 129 unmodified lines | ||
| 5556 | 5561 | /* jump unless last stmt in top-level block */ |
| 5557 | 5562 | if (tok != '}' || local_scope != 1) |
| 5558 | 5563 | rsym = gjmp(rsym); |
| 5564 | + nocode_wanted |= 2; | |
| 5559 | 5565 | } else if (tok == TOK_BREAK) { |
| 5560 | 5566 | /* compute jump */ |
| 5561 | 5567 | if (!bsym) |
| @@ -5563,6 +5569,7 @@ static void block(int *bsym, int *csym, int is_expr) · 1 unmodified line | ||
| 5563 | 5569 | *bsym = gjmp(*bsym); |
| 5564 | 5570 | next(); |
| 5565 | 5571 | skip(';'); |
| 5572 | + nocode_wanted |= 2; | |
| 5566 | 5573 | } else if (tok == TOK_CONTINUE) { |
| 5567 | 5574 | /* compute jump */ |
| 5568 | 5575 | if (!csym) |
| @@ -5573,6 +5580,7 @@ static void block(int *bsym, int *csym, int is_expr) · 4 unmodified lines | ||
| 5573 | 5580 | skip(';'); |
| 5574 | 5581 | } else if (tok == TOK_FOR) { |
| 5575 | 5582 | int e; |
| 5583 | + int saved_nocode_wanted; | |
| 5576 | 5584 | nocode_wanted &= ~2; |
| 5577 | 5585 | next(); |
| 5578 | 5586 | skip('('); |
| @@ -5607,7 +5615,9 @@ static void block(int *bsym, int *csym, int is_expr) · 28 unmodified lines | ||
| 5607 | 5615 | gsym(e); |
| 5608 | 5616 | } |
| 5609 | 5617 | skip(')'); |
| 5618 | + saved_nocode_wanted = nocode_wanted; | |
| 5610 | 5619 | block(&a, &b, 0); |
| 5620 | + nocode_wanted = saved_nocode_wanted; | |
| 5611 | 5621 | if(!nocode_wanted) |
| 5612 | 5622 | gjmp_addr(c); |
| 5613 | 5623 | gsym(a); |
| @@ -5617,13 +5627,16 @@ static void block(int *bsym, int *csym, int is_expr) · 3 unmodified lines | ||
| 5617 | 5627 | |
| 5618 | 5628 | } else |
| 5619 | 5629 | if (tok == TOK_DO) { |
| 5630 | + int saved_nocode_wanted; | |
| 5620 | 5631 | nocode_wanted &= ~2; |
| 5621 | 5632 | next(); |
| 5622 | 5633 | a = 0; |
| 5623 | 5634 | b = 0; |
| 5624 | 5635 | d = ind; |
| 5625 | 5636 | vla_sp_restore(); |
| 5637 | + saved_nocode_wanted = nocode_wanted; | |
| 5626 | 5638 | block(&a, &b, 0); |
| 5639 | + nocode_wanted = saved_nocode_wanted; | |
| 5627 | 5640 | skip(TOK_WHILE); |
| 5628 | 5641 | skip('('); |
| 5629 | 5642 | gsym(b); |
| @@ -5637,6 +5650,7 @@ static void block(int *bsym, int *csym, int is_expr) · 7 unmodified lines | ||
| 5637 | 5650 | } else |
| 5638 | 5651 | if (tok == TOK_SWITCH) { |
| 5639 | 5652 | struct switch_t *saved, sw; |
| 5653 | + int saved_nocode_wanted = nocode_wanted; | |
| 5640 | 5654 | next(); |
| 5641 | 5655 | skip('('); |
| 5642 | 5656 | gexpr(); |
| @@ -5650,6 +5664,7 @@ static void block(int *bsym, int *csym, int is_expr) · 7 unmodified lines | ||
| 5650 | 5664 | saved = cur_switch; |
| 5651 | 5665 | cur_switch = &sw; |
| 5652 | 5666 | block(&a, csym, 0); |
| 5667 | + nocode_wanted = saved_nocode_wanted; | |
| 5653 | 5668 | a = gjmp(a); /* add implicit break */ |
| 5654 | 5669 | /* case lookup */ |
| 5655 | 5670 | gsym(b); |
| @@ -1184,6 +1184,57 @@ void optimize_out(void) · 1183 unmodified lines | ||
| 1184 | 1184 | printf("oo:%d\n", defined_function()); |
| 1185 | 1185 | else |
| 1186 | 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 | 1240 | int defined_function(void) |