diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2010-02-23 20:38:56 -0500 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2010-02-23 20:38:56 -0500 |
commit | c7005ee1ba902de01a8863661a2031bfd45d3d40 (patch) | |
tree | e8a7bfa55c9afcfac71b5aafa5b54256f356c81a /elaborate.cxx | |
parent | 30263a7389d5c2712536b74656193708bbc64d49 (diff) | |
parent | 10328bcf86d49e5de83c5b22890204b5874740a9 (diff) | |
download | systemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.tar.gz systemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.tar.xz systemtap-steved-c7005ee1ba902de01a8863661a2031bfd45d3d40.zip |
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
* 'master' of ssh://sources.redhat.com/git/systemtap:
PR10719 part 1: Partial constant folding
Simplify null_statement construction
Fixed PR 11269 by properly handling mmap syscall 'fd' argument.
Removed rvalue operator check.
PR 10690 (partial fix). Handle '.=' operator in procfs probes.
Conflicts:
tapsets.h
Diffstat (limited to 'elaborate.cxx')
-rw-r--r-- | elaborate.cxx | 236 |
1 files changed, 230 insertions, 6 deletions
diff --git a/elaborate.cxx b/elaborate.cxx index 127e0bda..4e5c63c8 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2421,6 +2421,7 @@ dead_stmtexpr_remover::visit_foreach_loop (foreach_loop *s) if (s->block == 0) { + // XXX what if s->limit has side effects? if (session.verbose>2) clog << "Eliding side-effect-free foreach statement " << *s->tok << endl; s = 0; // yeah, baby @@ -2450,8 +2451,7 @@ dead_stmtexpr_remover::visit_for_loop (for_loop *s) else { // Can't elide this whole statement; put a null in there. - s->block = new null_statement(); - s->block->tok = s->tok; + s->block = new null_statement(s->tok); } } provide (s); @@ -2527,8 +2527,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) && ! s.timing) // PR10070 s.print_warning ("side-effect-free probe '" + p->name + "'", p->tok); - p->body = new null_statement(); - p->body->tok = p->tok; + p->body = new null_statement(p->tok); // XXX: possible duplicate warnings; see below } @@ -2552,8 +2551,7 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) if (! s.suppress_warnings) s.print_warning ("side-effect-free function '" + fn->name + "'", fn->tok); - fn->body = new null_statement(); - fn->body->tok = fn->tok; + fn->body = new null_statement(fn->tok); // XXX: the next iteration of the outer optimization loop may // take this new null_statement away again, and thus give us a @@ -2983,6 +2981,231 @@ void semantic_pass_opt5 (systemtap_session& s, bool& relaxed_p) } +struct const_folder: public update_visitor +{ + systemtap_session& session; + bool& relaxed_p; + + const_folder(systemtap_session& s, bool& r): + session(s), relaxed_p(r), last_number(0), last_string(0) {} + + literal_number* last_number; + literal_number* get_number(expression*& e); + void visit_literal_number (literal_number* e); + + literal_string* last_string; + literal_string* get_string(expression*& e); + void visit_literal_string (literal_string* e); + + void visit_if_statement (if_statement* s); + void visit_for_loop (for_loop* s); + void visit_foreach_loop (foreach_loop* s); + void visit_binary_expression (binary_expression* e); + void visit_unary_expression (unary_expression* e); + void visit_logical_or_expr (logical_or_expr* e); + void visit_logical_and_expr (logical_and_expr* e); + void visit_comparison (comparison* e); + void visit_concatenation (concatenation* e); + void visit_ternary_expression (ternary_expression* e); +}; + +literal_number* +const_folder::get_number(expression*& e) +{ + replace (e); + return (e == last_number) ? last_number : NULL; +} + +void +const_folder::visit_literal_number (literal_number* e) +{ + last_number = e; + provide (e); +} + +literal_string* +const_folder::get_string(expression*& e) +{ + replace (e); + return (e == last_string) ? last_string : NULL; +} + +void +const_folder::visit_literal_string (literal_string* e) +{ + last_string = e; + provide (e); +} + +void +const_folder::visit_if_statement (if_statement* s) +{ + literal_number* cond = get_number (s->condition); + if (!cond) + { + replace (s->thenblock); + replace (s->elseblock); + provide (s); + } + else + { + if (session.verbose>2) + clog << "Collapsing constant if-statement " << *s->tok << endl; + relaxed_p = false; + + statement* n = cond->value ? s->thenblock : s->elseblock; + if (n) + n->visit (this); + else + provide (new null_statement (s->tok)); + } +} + +void +const_folder::visit_for_loop (for_loop* s) +{ + literal_number* cond = get_number (s->cond); + if (!cond || cond->value) + { + replace (s->init); + replace (s->incr); + replace (s->block); + provide (s); + } + else + { + if (session.verbose>2) + clog << "Collapsing constantly-false for-loop " << *s->tok << endl; + relaxed_p = false; + + if (s->init) + s->init->visit (this); + else + provide (new null_statement (s->tok)); + } +} + +void +const_folder::visit_foreach_loop (foreach_loop* s) +{ + literal_number* limit = get_number (s->limit); + if (!limit || limit->value > 0) + { + for (unsigned i = 0; i < s->indexes.size(); ++i) + replace (s->indexes[i]); + replace (s->base); + replace (s->block); + provide (s); + } + else + { + if (session.verbose>2) + clog << "Collapsing constantly-limited foreach-loop " << *s->tok << endl; + relaxed_p = false; + + provide (new null_statement (s->tok)); + } +} + +void +const_folder::visit_binary_expression (binary_expression* e) +{ + // TODO + update_visitor::visit_binary_expression (e); +} + +void +const_folder::visit_unary_expression (unary_expression* e) +{ + literal_number* operand = get_number (e->operand); + if (!operand) + provide (e); + else + { + if (session.verbose>2) + clog << "Collapsing constant unary " << *e->tok << endl; + relaxed_p = false; + + literal_number* n = new literal_number (*operand); + n->tok = e->tok; + if (e->op == "+") + ; // nothing to do + else if (e->op == "-") + n->value = -n->value; + else if (e->op == "!") + n->value = !n->value; + else if (e->op == "~") + n->value = ~n->value; + else + throw semantic_error ("unsupported unary operator " + e->op); + n->visit (this); + } +} + +void +const_folder::visit_logical_or_expr (logical_or_expr* e) +{ + // TODO + update_visitor::visit_logical_or_expr (e); +} + +void +const_folder::visit_logical_and_expr (logical_and_expr* e) +{ + // TODO + update_visitor::visit_logical_and_expr (e); +} + +void +const_folder::visit_comparison (comparison* e) +{ + // TODO + update_visitor::visit_comparison (e); +} + +void +const_folder::visit_concatenation (concatenation* e) +{ + // TODO + update_visitor::visit_concatenation (e); +} + +void +const_folder::visit_ternary_expression (ternary_expression* e) +{ + literal_number* cond = get_number (e->cond); + if (!cond) + { + replace (e->truevalue); + replace (e->falsevalue); + provide (e); + } + else + { + if (session.verbose>2) + clog << "Collapsing constant ternary " << *e->tok << endl; + relaxed_p = false; + + expression* n = cond->value ? e->truevalue : e->falsevalue; + n->visit (this); + } +} + +static void semantic_pass_const_fold (systemtap_session& s, bool& relaxed_p) +{ + // Let's simplify statements with constant values. + + const_folder cf (s, relaxed_p); + // This instance may be reused for multiple probe/function body trims. + + for (unsigned i=0; i<s.probes.size(); i++) + cf.replace (s.probes[i]->body); + for (map<string,functiondecl*>::iterator it = s.functions.begin(); + it != s.functions.end(); it++) + cf.replace (it->second->body); +} + + struct duplicate_function_remover: public functioncall_traversing_visitor { systemtap_session& s; @@ -3107,6 +3330,7 @@ semantic_pass_optimize1 (systemtap_session& s) semantic_pass_opt3 (s, relaxed_p); semantic_pass_opt4 (s, relaxed_p); semantic_pass_opt5 (s, relaxed_p); + semantic_pass_const_fold (s, relaxed_p); iterations ++; } |