History

opt: Start optimizing dead code a bit

If a condition is always zero/non-zero we can omit the then or else code. This is complicated a bit by having to deal with labels that might make such code reachable without us yet knowing during parsing.

Michael Matz committed 10 years ago

Commit 31c7ea01 parent b303a004 files · +182 −2Browse files

Showing the changes to tests (3 of 4 files). Show all

Unified · Split

3 files
  1. tests/tcctest.c +27 −0
  2. tests/tests2/87_dead_code.c +122 −0
  3. tests/tests2/87_dead_code.expect +18 −0
tests/tcctest.c+27−0
@@ -88,6 +88,7 @@ void struct_test(); · 87 unmodified lines
8888 void array_test();
8989 void expr_ptr_test();
9090 void bool_test();
91+void optimize_out();
9192 void expr2_test();
9293 void constant_expr_test();
9394 void expr_cmp_test();
@@ -695,6 +696,7 @@ int main(int argc, char **argv) · 601 unmodified lines
695696 array_test();
696697 expr_ptr_test();
697698 bool_test();
699+ optimize_out();
698700 expr2_test();
699701 constant_expr_test();
700702 expr_cmp_test();
@@ -1165,6 +1167,31 @@ void bool_test() · 464 unmodified lines
11651167 printf ("bits = 0x%x\n", calc_vm_flags (0x1));
11661168 }
11671169
1170+extern int undefined_function(void);
1171+extern int defined_function(void);
1172+
1173+void optimize_out(void)
1174+{
1175+ int i = 0 ? undefined_function() : defined_function();
1176+ printf ("oo:%d\n", i);
1177+ int j = 1 ? defined_function() : undefined_function();
1178+ printf ("oo:%d\n", j);
1179+ if (0)
1180+ printf("oo:%d\n", undefined_function());
1181+ else
1182+ printf("oo:%d\n", defined_function());
1183+ if (1)
1184+ printf("oo:%d\n", defined_function());
1185+ else
1186+ printf("oo:%d\n", undefined_function());
1187+}
1188+
1189+int defined_function(void)
1190+{
1191+ static int i = 40;
1192+ return i++;
1193+}
1194+
11681195 /* GCC accepts that */
11691196 static int tab_reinit[];
11701197 static int tab_reinit[10];
tests/tests2/87_dead_code.c+122−0
@@ -0,0 +1,122 @@
1+/* This checks various ways of dead code inside if statements
2+ where there are non-obvious ways of how the code is actually
3+ not dead due to reachable by labels. */
4+extern int printf (const char *, ...);
5+static void kb_wait_1(void)
6+{
7+ unsigned long timeout = 2;
8+ do {
9+ /* Here the else arm is a statement expression that's supposed
10+ to be suppressed. The label inside the while would unsuppress
11+ code generation again if not handled correctly. And that
12+ would wreak havok to the cond-expression because there's no
13+ jump-around emitted, the whole statement expression really
14+ needs to not generate code (perhaps except useless forward jumps). */
15+ (1 ?
16+ printf("timeout=%ld\n", timeout) :
17+ ({
18+ int i = 1;
19+ while (1)
20+ while (i--)
21+ some_label:
22+ printf("error\n");
23+ goto some_label;
24+ })
25+ );
26+ timeout--;
27+ } while (timeout);
28+}
29+int main (void)
30+{
31+ int i = 1;
32+ kb_wait_1();
33+
34+ /* Simple test of dead code at first sight which isn't actually dead. */
35+ if (0) {
36+yeah:
37+ printf ("yeah\n");
38+ } else {
39+ printf ("boo\n");
40+ }
41+ if (i--)
42+ goto yeah;
43+
44+ /* Some more non-obvious uses where the problems are loops, so that even
45+ the first loop statements aren't actually dead. */
46+ i = 1;
47+ if (0) {
48+ while (i--) {
49+ printf ("once\n");
50+enterloop:
51+ printf ("twice\n");
52+ }
53+ }
54+ if (i >= 0)
55+ goto enterloop;
56+
57+ /* The same with statement expressions. One might be tempted to
58+ handle them specially by counting if inside statement exprs and
59+ not unsuppressing code at loops at all then.
60+ See kb_wait_1 for the other side of the medal where that wouldn't work. */
61+ i = ({
62+ int j = 1;
63+ if (0) {
64+ while (j--) {
65+ printf ("SEonce\n");
66+ enterexprloop:
67+ printf ("SEtwice\n");
68+ }
69+ }
70+ if (j >= 0)
71+ goto enterexprloop;
72+ j; });
73+
74+ /* The other two loop forms: */
75+ i = 1;
76+ if (0) {
77+ for (i = 1; i--;) {
78+ printf ("once2\n");
79+enterloop2:
80+ printf ("twice2\n");
81+ }
82+ }
83+ if (i > 0)
84+ goto enterloop2;
85+
86+ i = 1;
87+ if (0) {
88+ do {
89+ printf ("once3\n");
90+enterloop3:
91+ printf ("twice3\n");
92+ } while (i--);
93+ }
94+ if (i > 0)
95+ goto enterloop3;
96+
97+ /* And check that case and default labels have the same effect
98+ of disabling code suppression. */
99+ i = 41;
100+ switch (i) {
101+ if (0) {
102+ printf ("error\n");
103+ case 42:
104+ printf ("error2\n");
105+ case 41:
106+ printf ("caseok\n");
107+ }
108+ }
109+
110+ i = 41;
111+ switch (i) {
112+ if (0) {
113+ printf ("error3\n");
114+ default:
115+ printf ("caseok2\n");
116+ break;
117+ case 42:
118+ printf ("error4\n");
119+ }
120+ }
121+ return 0;
122+}
tests/tests2/87_dead_code.expect+18−0
@@ -0,0 +1,18 @@
1+timeout=2
2+timeout=1
3+boo
4+yeah
5+twice
6+once
7+twice
8+SEtwice
9+SEonce
10+SEtwice
11+twice2
12+once2
13+twice2
14+twice3
15+once3
16+twice3
17+caseok
18+caseok2

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t