diff options
| author | Michael Matz <matz@suse.de> | 2016-09-26 21:21:42 +0200 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-15 17:47:12 +0100 |
| commit | fb933ae0eb25af6b03c0098902d215fa7fe7fdbd (patch) | |
| tree | 8bcd595af55636c03344da4fd8679d322f1e9f45 | |
| parent | ca435dc2e36c685a225933283841ab3a827c3316 (diff) | |
| download | tinycc-fb933ae0eb25af6b03c0098902d215fa7fe7fdbd.tar.gz tinycc-fb933ae0eb25af6b03c0098902d215fa7fe7fdbd.tar.bz2 | |
opt: constprop also 'cond && 0'
We didn't handle constants in logical expressions when they weren't
the first operand. Some reordering in the loop structure is enough
to handle them.
| -rw-r--r-- | tccgen.c | 136 | ||||
| -rw-r--r-- | tests/tcctest.c | 39 |
2 files changed, 113 insertions, 62 deletions
@@ -4909,37 +4909,43 @@ static void expr_land(void) { expr_or(); if (tok == TOK_LAND) { - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - CType ctb, cti; - ctb.t = VT_BOOL; - cti.t = VT_INT; - next(); - gen_cast(&ctb); - if (vtop->c.i) { - vpop(); - expr_land(); - gen_cast(&ctb); - } else { - int saved_nocode_wanted = nocode_wanted; - nocode_wanted = 1; - expr_land(); - vpop(); - nocode_wanted = saved_nocode_wanted; - } - gen_cast(&cti); - } else { - int t = 0; - save_regs(1); - for(;;) { - t = gvtst(1, t); - if (tok != TOK_LAND) { - vseti(VT_JMPI, t); - break; - } - next(); - expr_or(); - } - } + int t = 0; + for(;;) { + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + CType ctb; + ctb.t = VT_BOOL; + gen_cast(&ctb); + if (vtop->c.i) { + vpop(); + } else { + int saved_nocode_wanted = nocode_wanted; + nocode_wanted = 1; + while (tok == TOK_LAND) { + next(); + expr_or(); + vpop(); + } + if (t) + gsym(t); + nocode_wanted = saved_nocode_wanted; + gen_cast(&int_type); + break; + } + } else { + if (!t) + save_regs(1); + t = gvtst(1, t); + } + if (tok != TOK_LAND) { + if (t) + vseti(VT_JMPI, t); + else + vpushi(1); + break; + } + next(); + expr_or(); + } } } @@ -4947,37 +4953,43 @@ static void expr_lor(void) { expr_land(); if (tok == TOK_LOR) { - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - CType ctb, cti; - ctb.t = VT_BOOL; - cti.t = VT_INT; - next(); - gen_cast(&ctb); - if (vtop->c.i) { - int saved_nocode_wanted = nocode_wanted; - nocode_wanted = 1; - expr_lor(); - vpop(); - nocode_wanted = saved_nocode_wanted; - } else { - vpop(); - expr_lor(); - gen_cast(&ctb); - } - gen_cast(&cti); - } else { - int t = 0; - save_regs(1); - for(;;) { - t = gvtst(0, t); - if (tok != TOK_LOR) { - vseti(VT_JMP, t); - break; - } - next(); - expr_land(); - } - } + int t = 0; + for(;;) { + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + CType ctb; + ctb.t = VT_BOOL; + gen_cast(&ctb); + if (!vtop->c.i) { + vpop(); + } else { + int saved_nocode_wanted = nocode_wanted; + nocode_wanted = 1; + while (tok == TOK_LOR) { + next(); + expr_land(); + vpop(); + } + if (t) + gsym(t); + nocode_wanted = saved_nocode_wanted; + gen_cast(&int_type); + break; + } + } else { + if (!t) + save_regs(1); + t = gvtst(0, t); + } + if (tok != TOK_LOR) { + if (t) + vseti(VT_JMP, t); + else + vpushi(0); + break; + } + next(); + expr_land(); + } } } diff --git a/tests/tcctest.c b/tests/tcctest.c index a0ddc84..ff88688 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1232,6 +1232,38 @@ void optimize_out(void) printf("ool6:%d\n", defined_function()); goto breakhere; } + + /* Test that constants in logical && are optimized: */ + i = 0 && undefined_function(); + i = defined_function() && 0 && undefined_function(); + if (0 && undefined_function()) + undefined_function(); + if (defined_function() && 0) + undefined_function(); + if (0 && 0) + undefined_function(); + if (defined_function() && 0 && undefined_function()) + undefined_function(); + /* The same for || : */ + i = 1 || undefined_function(); + i = defined_function() || 1 || undefined_function(); + if (1 || undefined_function()) + ; + else + undefined_function(); + if (defined_function() || 1) + ; + else + undefined_function(); + if (1 || 1) + ; + else + undefined_function(); + if (defined_function() || 1 || undefined_function()) + ; + else + undefined_function(); + if (1) return; printf ("oor:%d\n", undefined_function()); @@ -2544,6 +2576,13 @@ void sizeof_test(void) /* And as direct sizeof argument (as unary expression): */ printf("sizeof (struct {short i; short j;}){4,5} = %d\n", sizeof (struct {short i; short j;}){4,5} ); + + /* sizeof(x && y) should be sizeof(int), even if constant + evaluating is possible. */ + printf("sizeof(t && 0) = %d\n", sizeof(t && 0)); + printf("sizeof(1 && 1) = %d\n", sizeof(1 && 1)); + printf("sizeof(t || 1) = %d\n", sizeof(t || 1)); + printf("sizeof(0 || 0) = %d\n", sizeof(0 || 0)); } void typeof_test(void) |
