diff options
author | Josh Stone <jistone@redhat.com> | 2010-02-24 16:43:06 -0800 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2010-02-24 16:43:06 -0800 |
commit | a7e58d4c674003f192c4c8a834e80a3c23f9ec2e (patch) | |
tree | de1fe1e773a27384b8b2fc3b8f7c561fe1cdb070 /elaborate.cxx | |
parent | f4869658bae06af2e92091cebda75b59d00211d8 (diff) | |
download | systemtap-steved-a7e58d4c674003f192c4c8a834e80a3c23f9ec2e.tar.gz systemtap-steved-a7e58d4c674003f192c4c8a834e80a3c23f9ec2e.tar.xz systemtap-steved-a7e58d4c674003f192c4c8a834e80a3c23f9ec2e.zip |
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.
Diffstat (limited to 'elaborate.cxx')
-rw-r--r-- | elaborate.cxx | 88 |
1 files 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 |