[phc-internals] [phc commit] r1147 - trunk/src/codegen
codesite-noreply at google.com
codesite-noreply at google.com
Sun Apr 6 03:56:32 IST 2008
Author: paul.biggar
Date: Sat Apr 5 19:55:32 2008
New Revision: 1147
Modified:
trunk/src/codegen/Copy_propagation.cpp
trunk/src/codegen/Copy_propagation.h
trunk/src/codegen/Dead_code_elimination.cpp
trunk/src/codegen/Dead_code_elimination.h
trunk/src/codegen/Use_def_counter.cpp
trunk/src/codegen/Use_def_counter.h
Log:
Fix the Dead_code and copy_propagation passes to work at the global
scope, as well as in functions. This is almost a complete rewrite of
the use-def portion.
The use_def_counter now uses a stack to avoid the nested-functions
problem. Instead of the nasty hack of being passed a string to int map,
it now annotates each variable with
in a function with its uses and defs. That is really the point of the
attrs maps anyway. These are cleared by the use of the pass, in Clear_use_defs.
We also remove an assertion, where I assumed that left-hand sides of
replaceable statements are unique. This doesn't work in the case of If
statements with the same lhs in bo
th branches. This occurs when trinary elements are lowered.
Fortunately, this doesn't affect correctness.
Modified: trunk/src/codegen/Copy_propagation.cpp
==============================================================================
--- trunk/src/codegen/Copy_propagation.cpp (original)
+++ trunk/src/codegen/Copy_propagation.cpp Sat Apr 5 19:55:32 2008
@@ -58,40 +58,21 @@
using namespace HIR;
Copy_propagation::Copy_propagation ()
-: in_method (false)
{
}
-void Copy_propagation::pre_method (Method* in, List<Method*>* out)
+void Copy_propagation::children_php_script (PHP_script* in)
{
-
- // each function is separate
- replaceable.clear ();
- use_counts.clear ();
- def_counts.clear ();
-
// count uses and defs
- in->visit (new Use_def_counter (use_counts, def_counts));
+ in->visit (new Use_def_counter);
- in_method = true;
+ Transform::children_php_script (in);
- out->push_back (in);
+ in->visit (new Clear_use_defs);
}
-void Copy_propagation::post_method (Method* in, List<Method*>* out)
-{
- in_method = false;
- out->push_back (in);
-}
void Copy_propagation::pre_eval_expr (Eval_expr* in, List<Statement*>* out)
{
- // only method, not the global part
- if (!in_method)
- {
- out->push_back (in);
- return;
- }
-
debug (in);
// get useful variables
@@ -109,22 +90,19 @@
if (lhs->attrs->is_true ("phc.codegen.compiler_generated"))
{
cdebug << "lhs is compiler generated" << endl;
- assert (replaceable.find (slhs) == replaceable.end ());
replaceable [slhs] = assignment;
}
- cdebug << "use counts" << endl;
- print_map (use_counts);
- cdebug << "def counts" << endl;
- print_map (def_counts);
-
// be conservative
if (replaceable.find (srhs) != replaceable.end ()
- && use_counts [srhs] == 1
- && def_counts [srhs] == 1)
+ && rhs->attrs->get_integer ("phc.use_defs.use_count")->value () == 1
+ && rhs->attrs->get_integer ("phc.use_defs.def_count")->value () == 1)
{
cdebug << "r s is replacable" << endl;
- replaceable [srhs]->variable = new Variable (NULL, new
VARIABLE_NAME (s(slhs)), new List<Expr*>);
+ replaceable [srhs]->variable = new Variable (
+ NULL,
+ new VARIABLE_NAME (s(slhs)),
+ new List<Expr*>);
// note lack of out->push_back (in);
iterate_again = true;
Modified: trunk/src/codegen/Copy_propagation.h
==============================================================================
--- trunk/src/codegen/Copy_propagation.h (original)
+++ trunk/src/codegen/Copy_propagation.h Sat Apr 5 19:55:32 2008
@@ -91,20 +91,17 @@
#include "Fix_point.h"
#include <map>
+#include "Use_def_counter.h"
class Copy_propagation : public Fix_point
{
private:
- map<string, int> use_counts;
- map<string, int> def_counts;
map<string, HIR::Assignment*> replaceable;
- bool in_method;
public:
Copy_propagation ();
- void pre_method (HIR::Method* in, List<HIR::Method*>* out);
- void post_method (HIR::Method* in, List<HIR::Method*>* out);
+ void children_php_script (HIR::PHP_script* in);
void pre_eval_expr (HIR::Eval_expr* in, List<HIR::Statement*>* out);
};
Modified: trunk/src/codegen/Dead_code_elimination.cpp
==============================================================================
--- trunk/src/codegen/Dead_code_elimination.cpp (original)
+++ trunk/src/codegen/Dead_code_elimination.cpp Sat Apr 5 19:55:32 2008
@@ -25,51 +25,33 @@
using namespace HIR;
Dead_code_elimination::Dead_code_elimination ()
-: in_method (false)
{
}
-void Dead_code_elimination::pre_method (Method* in, List<Method*>* out)
+void Dead_code_elimination::children_php_script (PHP_script* in)
{
- // each function is separate
- use_counts.clear ();
- def_counts.clear ();
+ in->visit (new Use_def_counter ());
- // count uses and defs
- in->visit (new Use_def_counter (use_counts, def_counts));
+ Transform::children_php_script (in);
- in_method = true;
-
- out->push_back (in);
-}
-
-void Dead_code_elimination::post_method (Method* in, List<Method*>* out)
-{
- in_method = false;
- out->push_back (in);
+ in->visit (new Clear_use_defs);
}
void Dead_code_elimination::pre_eval_expr (Eval_expr* in,
List<Statement*>* out)
{
- // only method, not the global part
- if (!in_method)
- {
- cdebug << "Ignore non-method" << endl;;
- out->push_back (in);
- return;
- }
-
// get useful variables
VARIABLE_NAME *lhs, *rhs;
Assignment* assignment;
if (extract_simple_assignment (in, lhs, rhs, assignment))
{
cdebug << "is simple assignment" << endl;
+ xdebug (lhs);
+ xdebug (rhs);
// Remove statement
if (lhs->attrs->is_true ("phc.codegen.compiler_generated")
- && use_counts [*lhs->value] == 0
- && def_counts [*lhs->value] == 1)
+ && lhs->attrs->get_integer ("phc.use_defs.use_count")->value() == 0
+ && lhs->attrs->get_integer ("phc.use_defs.def_count")->value() == 1)
{
cdebug << "removing statement" << endl;
@@ -83,5 +65,6 @@
debug (in);
}
}
+
out->push_back (in);
}
Modified: trunk/src/codegen/Dead_code_elimination.h
==============================================================================
--- trunk/src/codegen/Dead_code_elimination.h (original)
+++ trunk/src/codegen/Dead_code_elimination.h Sat Apr 5 19:55:32 2008
@@ -22,20 +22,14 @@
#include "Fix_point.h"
#include <map>
+#include <stack>
class Dead_code_elimination : public Fix_point
{
-private:
- map<string, int> use_counts;
- map<string, int> def_counts;
- map<string, HIR::Assignment*> replaceable;
- bool in_method;
-
public:
Dead_code_elimination ();
- void pre_method (HIR::Method* in, List<HIR::Method*>* out);
- void post_method (HIR::Method* in, List<HIR::Method*>* out);
+ void children_php_script (HIR::PHP_script* in);
void pre_eval_expr (HIR::Eval_expr* in, List<HIR::Statement*>* out);
};
Modified: trunk/src/codegen/Use_def_counter.cpp
==============================================================================
--- trunk/src/codegen/Use_def_counter.cpp (original)
+++ trunk/src/codegen/Use_def_counter.cpp Sat Apr 5 19:55:32 2008
@@ -21,6 +21,10 @@
#include "HIR_visitor.h"
using namespace HIR;
+
+
+// Some convenience analysistions for passes which use this.
+
VARIABLE_NAME* simple_var (Expr* in)
{
Variable* var = dynamic_cast<Variable*> (in);
@@ -35,15 +39,6 @@
return dynamic_cast<VARIABLE_NAME*> (var->variable_name);
}
-void print_map (map<string, int>& in)
-{
- map<string, int>::const_iterator i;
- for(i = in.begin(); i != in.end(); i++)
- cdebug << (*i).first << ": " << (*i).second << endl;
-}
-
-
-
bool extract_simple_assignment (Eval_expr* in, VARIABLE_NAME*& lhs,
VARIABLE_NAME*& rhs, Assignment*& assignment)
{
assignment = dynamic_cast<Assignment*> (in->expr);
@@ -62,52 +57,106 @@
-Use_def_counter::Use_def_counter (map<string, int>& uses, map<string,
int>& defs)
-: uses (uses)
-, defs (defs)
-, occurences ()
+Use_def_counter::Use_def_counter ()
+: analysis_defs ()
+, analysis_occurences ()
{
}
+
+/* The entry points are the php script, and method entries */
+void Use_def_counter::init_analysis ()
+{
+ analysis_defs.push (new map<string, int>);
+ analysis_occurences.push (new map<string, int>);
+}
+
+void Use_def_counter::children_php_script (PHP_script* in)
+{
+ init_analysis ();
+
+ // continue the visitor
+ Visitor::children_php_script (in);
+
+ finish_analysis (in->statements);
+}
+
void Use_def_counter::pre_method (Method* in)
{
- uses.clear ();
- defs.clear ();
- occurences.clear ();
+ init_analysis ();
}
+
+
+/* Count defs and uses */
void Use_def_counter::pre_assignment (Assignment* in)
{
if (VARIABLE_NAME* var_name = simple_var (in->variable))
- defs [*var_name->value] ++;
+ (*analysis_defs.top()) [*var_name->value] ++;
}
void Use_def_counter::pre_variable_name (VARIABLE_NAME* in)
{
- occurences [*in->value] ++;
+ (*analysis_occurences.top()) [*in->value] ++;
}
-
+/* Exit points are after methods, and after the script completes */
void Use_def_counter::post_method (Method* in)
{
- // our exit point - work out the uses from the occurences and
- // the defs
+ finish_analysis (in->statements);
+}
+
+class Add_attributes : public HIR::Visitor
+{
+private:
+ map<string, int>* uses;
+ map<string, int>* defs;
+public:
+ Add_attributes (map<string, int>* uses, map<string, int>* defs)
+ : uses (uses)
+ , defs (defs)
+ {
+ }
+
+ void children_method (Method* in)
+ {
+ // Do not descend into functions
+ }
- // first if either occurences or defs are missing a variable,
- // add it.
+ void pre_variable_name (VARIABLE_NAME* in)
+ {
+ in->attrs->set ("phc.use_defs.use_count", new Integer ((*uses) [*in->value]));
+ in->attrs->set ("phc.use_defs.def_count", new Integer ((*defs) [*in->value]));
+ }
+};
+
+void Use_def_counter::finish_analysis (List<HIR::Statement*>* in)
+{
+ map<string, int>* defs = analysis_defs.top ();
+ map<string, int>* occurences = analysis_occurences.top ();
+ map<string, int>* uses = new map <string, int> ();
+
+ analysis_occurences.pop ();
+ analysis_defs.pop ();
+
+
+ // If either occurences or defs are missing a variable, add it.
map<string, int>::const_iterator i;
- for(i = defs.begin(); i != defs.end(); i++)
- if (occurences.find ((*i).first) == defs.end ())
- occurences [(*i).first] = 0;
+ for(i = defs->begin(); i != defs->end(); i++)
+ if (occurences->find ((*i).first) == defs->end ())
+ (*occurences) [(*i).first] = 0;
- for(i = occurences.begin(); i != occurences.end(); i++)
- if (defs.find ((*i).first) == defs.end ())
- defs [(*i).first] = 0;
+ for(i = occurences->begin(); i != occurences->end(); i++)
+ if (defs->find ((*i).first) == defs->end ())
+ (*defs) [(*i).first] = 0;
- for(i = occurences.begin(); i != occurences.end(); i++)
+ for(i = occurences->begin(); i != occurences->end(); i++)
{
string key = (*i).first;
- uses [key] = occurences [key] - defs [key];
+ (*uses) [key] = (*occurences) [key] - (*defs) [key];
}
+
+ (new Add_attributes (uses, defs))->visit_statement_list (in);
}
+
Modified: trunk/src/codegen/Use_def_counter.h
==============================================================================
--- trunk/src/codegen/Use_def_counter.h (original)
+++ trunk/src/codegen/Use_def_counter.h Sat Apr 5 19:55:32 2008
@@ -17,29 +17,50 @@
*
*/
+#ifndef PHC_USE_DEF_COUNTER
+#define PHC_USE_DEF_COUNTER
+
#include "process_ir/General.h"
#include "HIR_visitor.h"
+#include "stack"
+#include "map"
+#include "HIR.h"
-using namespace HIR;
-VARIABLE_NAME* simple_var (Expr* in);
-void print_map (map<string, int>& in);
-bool extract_simple_assignment (Eval_expr* in, VARIABLE_NAME*& lhs,
VARIABLE_NAME*& rhs, Assignment*& assignment);
+HIR::VARIABLE_NAME* simple_var (HIR::Expr* in);
+bool extract_simple_assignment (HIR::Eval_expr* in,
HIR::VARIABLE_NAME*& lhs, HIR::VARIABLE_NAME*& rhs, HIR::Assignment*& assignment);
/* Entering at the method level, count the total occurences of a
* variable, and the number of defintions, and the uses is the
* difference of the two. */
class Use_def_counter : public HIR::Visitor
{
- map<string, int>& uses;
- map<string, int>& defs;
- map<string, int> occurences;
- bool ignore_methods; // for global
+ // For analysis
+private:
+ stack< map<string, int>* > analysis_defs;
+ stack< map<string, int>* > analysis_occurences;
+
+ void pre_method (HIR::Method* in);
+ void pre_assignment (HIR::Assignment* in);
+ void pre_variable_name (HIR::VARIABLE_NAME* in);
+ void post_method (HIR::Method* in);
+ void children_php_script (HIR::PHP_script* in);
+
+ // start analysing a new method
+ void init_analysis ();
+ void finish_analysis (List<HIR::Statement*>* in);
public:
- Use_def_counter (map<string, int>& uses, map<string, int>& defs);
+ Use_def_counter ();
+};
- void pre_method (Method* in);
- void pre_assignment (Assignment* in);
- void pre_variable_name (VARIABLE_NAME* in);
- void post_method (Method* in);
+
+class Clear_use_defs : public HIR::Visitor
+{
+ void pre_node (HIR::Node* in)
+ {
+ in->attrs->erase_with_prefix ("phc.use_defs");
+ }
};
+
+#endif // PHC_USE_DEF_COUNTER
+
More information about the phc-internals
mailing list