[phc-internals] [phc commit] r1405 - in branches/saturn:
src/analyse test/subjects/optimization
codesite-noreply at google.com
codesite-noreply at google.com
Wed Jul 2 12:32:23 IST 2008
Author: paul.biggar
Date: Wed Jul 2 04:30:08 2008
New Revision: 1405
Added:
branches/saturn/src/analyse/address_taken.clp
branches/saturn/test/subjects/optimization/address_taken.php
Log:
Add address_taken alias-analysis. Strictly speaking, there are no
addresses in PHP, but the name is standard, and its conceptually
similar to address-taken analysis in C. Basically, anything which might
be aliased is added to the same alias-set. Assignments to variables in
the alias-set can't be dead. This isn't fully tested since the XML
broke recently, but I'm committing it so I can merge changes to the XML.
Added: branches/saturn/src/analyse/address_taken.clp
==============================================================================
--- (empty file)
+++ branches/saturn/src/analyse/address_taken.clp Wed Jul 2 04:30:08 2008
@@ -0,0 +1,155 @@
+% A very simple address-taken alias-analysis. Any variable which is
+% referenced, or may be referenced, is marked as is_alias. There is
just one
+% alias-set, an they all alias each other. Anything is the alias set is
+% ignored for scalar optimizations.
+
+
+type alias = alias_var {string}
+ | alias_bottom.
+
+predicate is_alias (VAR_NAME:string) succeeds [zero,once].
+is_alias (_) :- in_alias_set (alias_bottom).
+is_alias (VAR_NAME) :- in_alias_set (alias_var{VAR_NAME}).
+
+predicate alias_handled (BB:t_cfg_node).
+
+% No aliases
+alias_handled (BB) :- cfg_node (BB),
+ ( BB = nentry{_}
+ ; BB = nexit{_},
+ ; BB = nbranch{_,_,_}
+ ; BB = nblock{statement_Assign_var {assign_var {_, _, false, _}}},
+ ; BB = nblock{statement_Assign_array {assign_array {_, _, _, false, _}}}
+ ; BB = nblock{statement_Push_array {push_array {_, _, _, false, _}}}
+ ; BB = nblock{statement_Pre_op {pre_op {_, _, _}}}
+ ; BB = nblock {statement_Foreach_reset{foreach_reset{_, _, _}}}
+ ; BB = nblock {statement_Foreach_end{foreach_end{_, _, _}}}
+ ; BB = nblock {statement_Foreach_next{foreach_next{_, _, _}}}
+
+
+predicate aliased (t_VARIABLE_NAME).
+aliased (vARIABLE_NAME{_, VAR_NAME}), +in_alias_set (alias_var{VAR_NAME}).
+
+
+
+% Assign_vars - $x =& $y; $x aliases $y;
+cfg_node (BB), BB = nblock{statement_Assign_var {
+ assign_var {_, LHS, true, EXPR}}},
+ +aliased (LHS),
+ +alias_expr (BB, EXPR).
+
+% Assign array - $x[$y] =& $z. $z is aliased. $x is not.
+cfg_node (BB), BB = nblock{statement_Assign_array {
+ assign_array {_, _, _, true, RHS}}},
+ +aliased (RHS), +alias_handled (BB).
+
+% Assign array - $x[] =& $z. $z is aliased. $x is not.
+cfg_node (BB), BB = nblock{statement_Push_array {
+ push_array {_, _, true, RHS}}},
+ +aliased (RHS), +alias_handled (BB).
+
+% Eval_expr - RHS may be aliased
+cfg_node (BB), BB = nblock{statement_Eval_expr{
+ eval_expr{_, EXPR}}},
+ +alias_expr (BB, EXPR).
+
+% Return - Since we don't know if the statement is return by
reference, we must assume it references.
+cfg_node (BB), BB = nblock{statement_Return{
+ return {_, EXPR}}},
+ +alias_expr (BB, EXPR).
+
+% Globals (VARIABLE_NAME) - Any global must be aliased
+cfg_node (BB), BB = nblock{statement_Global {
+ global {_, variable_name_VARIABLE_NAME{VAR}}}},
+ +alias_expr (BB, VAR), +alias_handled (BB).
+
+% Globals (REFLECTION) - Everything is aliased
+% cannot say any variable is defined. So nothing happens.
+cfg_node (BB), BB = nblock{statement_Global {
+ global {_, variable_name_Reflection {_}}}},
+ +aliased (BB, alias_bottom),
+ +alias_handled (BB).
+
+
+
+
+
+% Expression handling
+predicate alias_expr (BB:t_cfg_node, EXPR:t_Expr).
+
+% No aliases
+alias_handled (BB) :- alias_expr (BB, EXPR),
+ % Not allowed in MIR:
+ % literal,
+ % cast,
+ % unary_op,
+ % bin_op,
+ % constants
+ % Index_array: $x =& $y[$z] or return $y[$z] - Nothing is aliased here
+ EXPR = expr_Index_array {index_array{_, _, _}}),
+ EXPR = expr_Foreach_has_key{foreach_has_key{_, ARRAY, _}}
+ EXPR = expr_Foreach_get_key{foreach_get_key{_, ARRAY, _}}
+ EXPR = expr_Foreach_get_val{foreach_get_val{_, ARRAY, _, _}}
+ EXPR = expr_Target_expr {target_expr{_, _, _}}
+
+
+% Variable: $x =& $y; $y is aliased.
+alias_expr (BB, expr_Variable{variable{_, VAR_NAME}}),
+ +aliased (BB, VAR_NAME),
+ +alias_handled (BB).
+
+% Variable_variable: $x =& $$y - Everything is aliased.
+alias_expr (BB, expr_Variable_variable {variable_variable{_, _}}),
+ +alised (BB, alias_bottom),
+ +alias_handled (BB).
+
+% Method invocation - all parameters can be aliased
+alias_expr (BB, expr_Method_invocation {method_invocation {_, _, _, PARAMS}}),
+ +alias_actual_params (BB, PARAMS).
+
+% Actual parameters (part of Method_invocation)
+% $t->$x[$i]
+% $t->$$r[$i]
+% $x is aliased unless $t or $i exists
+% $r means everything is aliased unless $t or $i
+predicate alias_actual_params (BB:t_cfg_node, list[t_Actual_parameter]).
+
+% No target, empty list, VARIABLE_NAME
+alias_actual_params (BB, [PARAM|TAIL]),
+ PARAM = actual_parameter {_, no, _,
variable_name_VARIABLE_NAME{VAR_NAME}, []},
+ +aliased_var (BB, VAR),
+ +alias_actual_params (BB, TAIL).
+
+% No target, empty list, Reflection
+alias_actual_params (BB, [PARAM|TAIL]),
+ PARAM = actual_parameter {_, no, _, variable_name_Reflection {_}, []},
+ +aliased (BB, alias_bottom),
+ +alias_actual_params (BB, TAIL).
+
+% Everything else - No aliases
+alias_actual_params (BB, [PARAM|TAIL]),
+ PARAM = actual_parameter {_, _, _, _, _},
+ +aliased_var (BB, VAR),
+ +alias_actual_params (BB, TAIL).
+
+% All params must be handled to get this far
+alias_actual_params (BB, []),
+ +alias_handled (BB).
+
+
+
+
+% Make sure all rules are alias_handled
+predicate alias_handled (BB:t_cfg_node).
+predicate error (BB:t_cfg_node).
+error (BB) :-
+ cfg_node (BB),
+ ~alias_handled (BB),
+ tostring (BB, BB_STR),
+ ((BB = nblock {B}, to_node (any{B}, NODE), mir()->source_rep (get_id
(NODE), SOURCE))
+ ;
+ (BB \= nblock{_}, SOURCE = "SOURCE NOT AVAILABLE")),
+ str_cat_list (["Error, not alias_handled: ", BB_STR, " - ", SOURCE], ERROR),
+ +print (ERROR).
+
+assert ~error (_).
Added: branches/saturn/test/subjects/optimization/address_taken.php
==============================================================================
--- (empty file)
+++ branches/saturn/test/subjects/optimization/address_taken.php Wed
Jul 2 04:30:08 2008
@@ -0,0 +1,19 @@
+<?php
+
+ // Test conditions of address-taken aliasing.
+
+ // The assumption is that $x = $y; does not create move $x or $y into an
+ // alias-set if they are not already in one. However, $x =& $y adds
$y and
+ // $x to the same alias-set.
+
+ $z = 6;
+ $y = &$z; // y and z in same set.
+ var_dump ($y);
+ $x = $y; // x not in same set
+ var_dump ($x, $y);
+ $x = 5; // this assignment doesnt touch $y
+ var_dump ($x, $y);
+
+ // This means we can treat address-of as aliasing (even if its not
strictly an address-of operator).
+
+?>
More information about the phc-internals
mailing list