summaryrefslogtreecommitdiffstats
path: root/elaborate.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2010-02-24 16:43:06 -0800
committerJosh Stone <jistone@redhat.com>2010-02-24 16:43:06 -0800
commita7e58d4c674003f192c4c8a834e80a3c23f9ec2e (patch)
treede1fe1e773a27384b8b2fc3b8f7c561fe1cdb070 /elaborate.cxx
parentf4869658bae06af2e92091cebda75b59d00211d8 (diff)
downloadsystemtap-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.cxx88
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