aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-09-26 21:21:42 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:12 +0100
commitfb933ae0eb25af6b03c0098902d215fa7fe7fdbd (patch)
tree8bcd595af55636c03344da4fd8679d322f1e9f45
parentca435dc2e36c685a225933283841ab3a827c3316 (diff)
downloadtinycc-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.c136
-rw-r--r--tests/tcctest.c39
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)