From fb933ae0eb25af6b03c0098902d215fa7fe7fdbd Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 26 Sep 2016 21:21:42 +0200 Subject: [PATCH] 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. --- tccgen.c | 136 ++++++++++++++++++++++++++---------------------- tests/tcctest.c | 39 ++++++++++++++ 2 files changed, 113 insertions(+), 62 deletions(-) diff --git a/tccgen.c b/tccgen.c index c9d43b4..056ee4e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -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)