aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-09-19 18:38:12 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:12 +0100
commit31c7ea0165882eaf09040ea7edfc37cc38f0a032 (patch)
treed1dad07537700b756d612c68b414d243202a9529 /tests
parentb303a00ce01876dfa2ba3fe532db04d200168b9d (diff)
downloadtinycc-31c7ea0165882eaf09040ea7edfc37cc38f0a032.tar.gz
tinycc-31c7ea0165882eaf09040ea7edfc37cc38f0a032.tar.bz2
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.
Diffstat (limited to 'tests')
-rw-r--r--tests/tcctest.c27
-rw-r--r--tests/tests2/87_dead_code.c122
-rw-r--r--tests/tests2/87_dead_code.expect18
3 files changed, 167 insertions, 0 deletions
diff --git a/tests/tcctest.c b/tests/tcctest.c
index d1f6c9b..8031af4 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -88,6 +88,7 @@ void struct_test();
void array_test();
void expr_ptr_test();
void bool_test();
+void optimize_out();
void expr2_test();
void constant_expr_test();
void expr_cmp_test();
@@ -695,6 +696,7 @@ int main(int argc, char **argv)
array_test();
expr_ptr_test();
bool_test();
+ optimize_out();
expr2_test();
constant_expr_test();
expr_cmp_test();
@@ -1165,6 +1167,31 @@ void bool_test()
printf ("bits = 0x%x\n", calc_vm_flags (0x1));
}
+extern int undefined_function(void);
+extern int defined_function(void);
+
+void optimize_out(void)
+{
+ int i = 0 ? undefined_function() : defined_function();
+ printf ("oo:%d\n", i);
+ int j = 1 ? defined_function() : undefined_function();
+ printf ("oo:%d\n", j);
+ if (0)
+ printf("oo:%d\n", undefined_function());
+ else
+ printf("oo:%d\n", defined_function());
+ if (1)
+ printf("oo:%d\n", defined_function());
+ else
+ printf("oo:%d\n", undefined_function());
+}
+
+int defined_function(void)
+{
+ static int i = 40;
+ return i++;
+}
+
/* GCC accepts that */
static int tab_reinit[];
static int tab_reinit[10];
diff --git a/tests/tests2/87_dead_code.c b/tests/tests2/87_dead_code.c
new file mode 100644
index 0000000..92983f5
--- /dev/null
+++ b/tests/tests2/87_dead_code.c
@@ -0,0 +1,122 @@
+/* This checks various ways of dead code inside if statements
+ where there are non-obvious ways of how the code is actually
+ not dead due to reachable by labels. */
+extern int printf (const char *, ...);
+static void kb_wait_1(void)
+{
+ unsigned long timeout = 2;
+ do {
+ /* Here the else arm is a statement expression that's supposed
+ to be suppressed. The label inside the while would unsuppress
+ code generation again if not handled correctly. And that
+ would wreak havok to the cond-expression because there's no
+ jump-around emitted, the whole statement expression really
+ needs to not generate code (perhaps except useless forward jumps). */
+ (1 ?
+ printf("timeout=%ld\n", timeout) :
+ ({
+ int i = 1;
+ while (1)
+ while (i--)
+ some_label:
+ printf("error\n");
+ goto some_label;
+ })
+ );
+ timeout--;
+ } while (timeout);
+}
+int main (void)
+{
+ int i = 1;
+ kb_wait_1();
+
+ /* Simple test of dead code at first sight which isn't actually dead. */
+ if (0) {
+yeah:
+ printf ("yeah\n");
+ } else {
+ printf ("boo\n");
+ }
+ if (i--)
+ goto yeah;
+
+ /* Some more non-obvious uses where the problems are loops, so that even
+ the first loop statements aren't actually dead. */
+ i = 1;
+ if (0) {
+ while (i--) {
+ printf ("once\n");
+enterloop:
+ printf ("twice\n");
+ }
+ }
+ if (i >= 0)
+ goto enterloop;
+
+ /* The same with statement expressions. One might be tempted to
+ handle them specially by counting if inside statement exprs and
+ not unsuppressing code at loops at all then.
+ See kb_wait_1 for the other side of the medal where that wouldn't work. */
+ i = ({
+ int j = 1;
+ if (0) {
+ while (j--) {
+ printf ("SEonce\n");
+ enterexprloop:
+ printf ("SEtwice\n");
+ }
+ }
+ if (j >= 0)
+ goto enterexprloop;
+ j; });
+
+ /* The other two loop forms: */
+ i = 1;
+ if (0) {
+ for (i = 1; i--;) {
+ printf ("once2\n");
+enterloop2:
+ printf ("twice2\n");
+ }
+ }
+ if (i > 0)
+ goto enterloop2;
+
+ i = 1;
+ if (0) {
+ do {
+ printf ("once3\n");
+enterloop3:
+ printf ("twice3\n");
+ } while (i--);
+ }
+ if (i > 0)
+ goto enterloop3;
+
+ /* And check that case and default labels have the same effect
+ of disabling code suppression. */
+ i = 41;
+ switch (i) {
+ if (0) {
+ printf ("error\n");
+ case 42:
+ printf ("error2\n");
+ case 41:
+ printf ("caseok\n");
+ }
+ }
+
+ i = 41;
+ switch (i) {
+ if (0) {
+ printf ("error3\n");
+ default:
+ printf ("caseok2\n");
+ break;
+ case 42:
+ printf ("error4\n");
+ }
+ }
+ return 0;
+}
diff --git a/tests/tests2/87_dead_code.expect b/tests/tests2/87_dead_code.expect
new file mode 100644
index 0000000..0b3ec1d
--- /dev/null
+++ b/tests/tests2/87_dead_code.expect
@@ -0,0 +1,18 @@
+timeout=2
+timeout=1
+boo
+yeah
+twice
+once
+twice
+SEtwice
+SEonce
+SEtwice
+twice2
+once2
+twice2
+twice3
+once3
+twice3
+caseok
+caseok2