From a7e58d4c674003f192c4c8a834e80a3c23f9ec2e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Feb 2010 16:43:06 -0800 Subject: PR10719 cont'd: const-fold logical ops We can compute results between two literals, we can short-circuit some literals on the left ("0&&x", "1||x"), and we can simplify literals on the right if the left has no side effect ("x&&0", "x||1"). * elaborate.cxx (const_folder::visit_logical_or_expr): Implement. (const_folder::visit_logical_and_expr): Implement. --- elaborate.cxx | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/elaborate.cxx b/elaborate.cxx index 81e6fdcb..d74051a9 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -3158,15 +3158,95 @@ const_folder::visit_unary_expression (unary_expression* e) void const_folder::visit_logical_or_expr (logical_or_expr* e) { - // TODO - update_visitor::visit_logical_or_expr (e); + int64_t value; + literal_number* left = get_number (e->left); + literal_number* right = get_number (e->right); + + if (left && right) + value = left->value || right->value; + + else if ((left && left->value) || (right && right->value)) + { + // If the const is on the left, we get to short-circuit the right + // immediately. Otherwise, we can only eliminate the LHS if it's pure. + if (right) + { + varuse_collecting_visitor vu(session); + e->left->visit(&vu); + if (!vu.side_effect_free()) + { + provide (e); + return; + } + } + + value = 1; + } + + // We might also get rid of useless "0||x" and "x||0", except it does + // normalize x to 0 or 1. We could change it to "!!x", but it's not clear + // that this would gain us much. + + else + { + provide (e); + return; + } + + if (session.verbose>2) + clog << "Collapsing constant logical-OR " << *e->tok << endl; + relaxed_p = false; + + literal_number* n = new literal_number(value); + n->tok = e->tok; + n->visit (this); } void const_folder::visit_logical_and_expr (logical_and_expr* e) { - // TODO - update_visitor::visit_logical_and_expr (e); + int64_t value; + literal_number* left = get_number (e->left); + literal_number* right = get_number (e->right); + + if (left && right) + value = left->value && right->value; + + else if ((left && !left->value) || (right && !right->value)) + { + // If the const is on the left, we get to short-circuit the right + // immediately. Otherwise, we can only eliminate the LHS if it's pure. + if (right) + { + varuse_collecting_visitor vu(session); + e->left->visit(&vu); + if (!vu.side_effect_free()) + { + provide (e); + return; + } + } + + value = 0; + } + + // We might also get rid of useless "1&&x" and "x&&1", except it does + // normalize x to 0 or 1. We could change it to "!!x", but it's not clear + // that this would gain us much. + + else + { + provide (e); + return; + } + + if (session.verbose>2) + clog << "Collapsing constant logical-AND " << *e->tok << endl; + relaxed_p = false; + + literal_number* n = new literal_number(value); + n->tok = e->tok; + n->visit (this); } void -- cgit