⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree-ssa.texi

📁 理解和实践操作系统的一本好书
💻 TEXI
📖 第 1 页 / 共 4 页
字号:
     4	  x_10 = @dots{}     5	  if (x_1 > 7)     6	    y_2 = 0     7	  else     8	    x_11 = @dots{}     9	    y_3 = x_1 + x_7     10	  endif     11	  x_5 = x_1 + 1     12	  goto L0;     13	endif@end smallexampleWe want to replace all the uses of @code{x_1} with the new definitionsof @code{x_10} and @code{x_11}.  Note that the only uses that shouldbe replaced are those at lines @code{5}, @code{9} and @code{11}.Also, the use of @code{x_7} at line @code{9} should @emph{not} bereplaced (this is why we cannot just mark symbol @code{x} forrenaming)@.Additionally, we may need to insert a PHI node at line @code{11}because that is a merge point for @code{x_10} and @code{x_11}.  So theuse of @code{x_1} at line @code{11} will be replaced with the new PHInode.  The insertion of PHI nodes is optional.  They are not strictlynecessary to preserve the SSA form, and depending on what the callerinserted, they may not even be useful for the optimizers@.Updating the SSA form is a two step process.  First, the pass has toidentify which names need to be updated and/or which symbols need tobe renamed into SSA form for the first time.  When new names areintroduced to replace existing names in the program, the mappingbetween the old and the new names are registered by calling@code{register_new_name_mapping} (note that if your pass creates newcode by duplicating basic blocks, the call to @code{tree_duplicate_bb}will set up the necessary mappings automatically).  On the other hand,if your pass exposes a new symbol that should be put in SSA form forthe first time, the new symbol should be registered with@code{mark_sym_for_renaming}.After the replacement mappings have been registered and new symbolsmarked for renaming, a call to @code{update_ssa} makes the registeredchanges.  This can be done with an explicit call or by creating@code{TODO} flags in the @code{tree_opt_pass} structure for your pass.There are several @code{TODO} flags that control the behavior of@code{update_ssa}:@itemize @bullet@item @code{TODO_update_ssa}.  Update the SSA form inserting PHI nodes      for newly exposed symbols and virtual names marked for updating.      When updating real names, only insert PHI nodes for a real name      @code{O_j} in blocks reached by all the new and old definitions for      @code{O_j}.  If the iterated dominance frontier for @code{O_j}      is not pruned, we may end up inserting PHI nodes in blocks that      have one or more edges with no incoming definition for      @code{O_j}.  This would lead to uninitialized warnings for      @code{O_j}'s symbol@.@item @code{TODO_update_ssa_no_phi}.  Update the SSA form without      inserting any new PHI nodes at all.  This is used by passes that      have either inserted all the PHI nodes themselves or passes that      need only to patch use-def and def-def chains for virtuals      (e.g., DCE)@.@item @code{TODO_update_ssa_full_phi}.  Insert PHI nodes everywhere      they are needed.  No pruning of the IDF is done.  This is used      by passes that need the PHI nodes for @code{O_j} even if it      means that some arguments will come from the default definition      of @code{O_j}'s symbol (e.g., @code{pass_linear_transform})@.      WARNING: If you need to use this flag, chances are that your      pass may be doing something wrong.  Inserting PHI nodes for an      old name where not all edges carry a new replacement may lead to      silent codegen errors or spurious uninitialized warnings@.@item @code{TODO_update_ssa_only_virtuals}.  Passes that update the      SSA form on their own may want to delegate the updating of      virtual names to the generic updater.  Since FUD chains are      easier to maintain, this simplifies the work they need to do.      NOTE: If this flag is used, any OLD->NEW mappings for real names      are explicitly destroyed and only the symbols marked for      renaming are processed@.@end itemize@subsection Preserving the virtual SSA form@cindex preserving virtual SSA formThe virtual SSA form is harder to preserve than the non-virtual SSA formmainly because the set of virtual operands for a statement may change atwhat some would consider unexpected times.  In general, statementmodifications should be bracketed between calls to@code{push_stmt_changes} and @code{pop_stmt_changes}.  For example,@smallexample    munge_stmt (tree stmt)    @{       push_stmt_changes (&stmt);       @dots{} rewrite STMT @dots{}       pop_stmt_changes (&stmt);    @}@end smallexampleThe call to @code{push_stmt_changes} saves the current state of thestatement operands and the call to @code{pop_stmt_changes} comparesthe saved state with the current one and does the appropriate symbolmarking for the SSA renamer.It is possible to modify several statements at a time, provided that@code{push_stmt_changes} and @code{pop_stmt_changes} are called inLIFO order, as when processing a stack of statements.Additionally, if the pass discovers that it did not need to makechanges to the statement after calling @code{push_stmt_changes}, itcan simply discard the topmost change buffer by calling@code{discard_stmt_changes}.  This will avoid the expensive operandre-scan operation and the buffer comparison that determines if symbolsneed to be marked for renaming.@subsection Examining @code{SSA_NAME} nodes@cindex examining SSA_NAMEsThe following macros can be used to examine @code{SSA_NAME} nodes@defmac SSA_NAME_DEF_STMT (@var{var})Returns the statement @var{s} that creates the @code{SSA_NAME}@var{var}.  If @var{s} is an empty statement (i.e., @code{IS_EMPTY_STMT(@var{s})} returns @code{true}), it means that the first reference tothis variable is a USE or a VUSE@.@end defmac@defmac SSA_NAME_VERSION (@var{var})Returns the version number of the @code{SSA_NAME} object @var{var}.@end defmac@subsection Walking use-def chains@deftypefn {Tree SSA function} void walk_use_def_chains (@var{var}, @var{fn}, @var{data})Walks use-def chains starting at the @code{SSA_NAME} node @var{var}.Calls function @var{fn} at each reaching definition found.  Function@var{FN} takes three arguments: @var{var}, its defining statement(@var{def_stmt}) and a generic pointer to whatever state informationthat @var{fn} may want to maintain (@var{data}).  Function @var{fn} isable to stop the walk by returning @code{true}, otherwise in order tocontinue the walk, @var{fn} should return @code{false}.Note, that if @var{def_stmt} is a @code{PHI} node, the semantics areslightly different.  For each argument @var{arg} of the PHI node, thisfunction will:@enumerate@item	Walk the use-def chains for @var{arg}.@item	Call @code{FN (@var{arg}, @var{phi}, @var{data})}.@end enumerateNote how the first argument to @var{fn} is no longer the originalvariable @var{var}, but the PHI argument currently being examined.If @var{fn} wants to get at @var{var}, it should call@code{PHI_RESULT} (@var{phi}).@end deftypefn@subsection Walking the dominator tree@deftypefn {Tree SSA function} void walk_dominator_tree (@var{walk_data}, @var{bb})This function walks the dominator tree for the current CFG calling aset of callback functions defined in @var{struct dom_walk_data} in@file{domwalk.h}.  The call back functions you need to define give youhooks to execute custom code at various points during traversal:@enumerate@item Once to initialize any local data needed while processing      @var{bb} and its children.  This local data is pushed into an      internal stack which is automatically pushed and popped as the      walker traverses the dominator tree.@item Once before traversing all the statements in the @var{bb}.@item Once for every statement inside @var{bb}.@item Once after traversing all the statements and before recursing      into @var{bb}'s dominator children.@item It then recurses into all the dominator children of @var{bb}.@item After recursing into all the dominator children of @var{bb} it      can, optionally, traverse every statement in @var{bb} again      (i.e., repeating steps 2 and 3).@item Once after walking the statements in @var{bb} and @var{bb}'s      dominator children.  At this stage, the block local data stack      is popped.@end enumerate@end deftypefn@node Alias analysis@section Alias analysis@cindex alias@cindex flow-sensitive alias analysis@cindex flow-insensitive alias analysisAlias analysis proceeds in 4 main phases:@enumerate@item   Structural alias analysis.This phase walks the types for structure variables, and determines whichof the fields can overlap using offset and size of each field.  For eachfield, a ``subvariable'' called a ``Structure field tag'' (SFT)@ iscreated, which represents that field as a separate variable.  Allaccesses that could possibly overlap with a given field will havevirtual operands for the SFT of that field.@smallexamplestruct foo@{  int a;  int b;@}struct foo temp;int bar (void)@{  int tmp1, tmp2, tmp3;  SFT.0_2 = VDEF <SFT.0_1>  temp.a = 5;  SFT.1_4 = VDEF <SFT.1_3>  temp.b = 6;    VUSE <SFT.1_4>  tmp1_5 = temp.b;  VUSE <SFT.0_2>  tmp2_6 = temp.a;  tmp3_7 = tmp1_5 + tmp2_6;  return tmp3_7;@}@end smallexampleIf you copy the symbol tag for a variable for some reason, you probablyalso want to copy the subvariables for that variable.@item	Points-to and escape analysis.This phase walks the use-def chains in the SSA web looking forthree things:	@itemize @bullet	@item	Assignments of the form @code{P_i = &VAR}	@item	Assignments of the form P_i = malloc()	@item	Pointers and ADDR_EXPR that escape the current function.	@end itemizeThe concept of `escaping' is the same one used in the Java world.When a pointer or an ADDR_EXPR escapes, it means that it has beenexposed outside of the current function.  So, assignment toglobal variables, function arguments and returning a pointer areall escape sites.This is where we are currently limited.  Since not everything isrenamed into SSA, we lose track of escape properties when apointer is stashed inside a field in a structure, for instance.In those cases, we are assuming that the pointer does escape.We use escape analysis to determine whether a variable iscall-clobbered.  Simply put, if an ADDR_EXPR escapes, then thevariable is call-clobbered.  If a pointer P_i escapes, then allthe variables pointed-to by P_i (and its memory tag) also escape.@item	Compute flow-sensitive aliasesWe have two classes of memory tags.  Memory tags associated withthe pointed-to data type of the pointers in the program.  Thesetags are called ``symbol memory tag'' (SMT)@.  The other class arethose associated with SSA_NAMEs, called ``name memory tag'' (NMT)@.The basic idea is that when adding operands for an INDIRECT_REF*P_i, we will first check whether P_i has a name tag, if it doeswe use it, because that will have more precise aliasinginformation.  Otherwise, we use the standard symbol tag.In this phase, we go through all the pointers we found inpoints-to analysis and create alias sets for the name memory tagsassociated with each pointer P_i.  If P_i escapes, we markcall-clobbered the variables it points to and its tag.@item	Compute flow-insensitive aliasesThis pass will compare the alias set of every symbol memory tag andevery addressable variable found in the program.  Given a symbolmemory tag SMT and an addressable variable V@.  If the alias setsof SMT and V conflict (as computed by may_alias_p), then V ismarked as an alias tag and added to the alias set of SMT@.Every language that wishes to perform language-specific alias analysisshould define a function that computes, given a @code{tree}node, an alias set for the node.  Nodes in different alias sets are notallowed to alias.  For an example, see the C front-end function@code{c_get_alias_set}.@end enumerateFor instance, consider the following function:@smallexamplefoo (int i)@{  int *p, *q, a, b;  if (i > 10)    p = &a;  else    q = &b;  *p = 3;  *q = 5;  a = b + 2;  return *p;@}@end smallexampleAfter aliasing analysis has finished, the symbol memory tag forpointer @code{p} will have two aliases, namely variables @code{a} and@code{b}.Every time pointer @code{p} is dereferenced, we want to mark theoperation as a potential reference to @code{a} and @code{b}.@smallexamplefoo (int i)@{  int *p, a, b;  if (i_2 > 10)    p_4 = &a;  else    p_6 = &b;  # p_1 = PHI <p_4(1), p_6(2)>;  # a_7 = VDEF <a_3>;  # b_8 = VDEF <b_5>;  *p_1 = 3;  # a_9 = VDEF <a_7>  # VUSE <b_8>  a_9 = b_8 + 2;  # VUSE <a_9>;  # VUSE <b_8>;  return *p_1;@}@end smallexampleIn certain cases, the list of may aliases for a pointer may growtoo large.  This may cause an explosion in the number of virtualoperands inserted in the code.  Resulting in increased memoryconsumption and compilation time.When the number of virtual operands needed to represent aliasedloads and stores grows too large (configurable with @option{--parammax-aliased-vops}), alias sets are grouped to avoid severecompile-time slow downs and memory consumption.  The aliasgrouping heuristic proceeds as follows:@enumerate@item Sort the list of pointers in decreasing number of contributedvirtual operands.@item Take the first pointer from the list and reverse the roleof the memory tag and its aliases.  Usually, whenever analiased variable Vi is found to alias with a memory tagT, we add Vi to the may-aliases set for T@.  Meaning thatafter alias analysis, we will have:@smallexamplemay-aliases(T) = @{ V1, V2, V3, @dots{}, Vn @}@end smallexampleThis means that every statement that references T, will get@code{n} virtual operands for each of the Vi tags.  But, whenalias grouping is enabled, we make T an alias tag and add itto the alias set of all the Vi variables:@smallexamplemay-aliases(V1) = @{ T @}may-aliases(V2) = @{ T @}@dots{}may-aliases(Vn) = @{ T @}@end smallexampleThis has two effects: (a) statements referencing T will only geta single virtual operand, and, (b) all the variables Vi will nowappear to alias each other.  So, we lose alias precision toimprove compile time.  But, in theory, a program with such a highlevel of aliasing should not be very optimizable in the firstplace.@item Since variables may be in the alias set of more than onememory tag, the grouping done in step (2) needs to be extendedto all the memory tags that have a non-empty intersection withthe may-aliases set of tag T@.  For instance, if we originallyhad these may-aliases sets:@smallexamplemay-aliases(T) = @{ V1, V2, V3 @}may-aliases(R) = @{ V2, V4 @}@end smallexampleIn step (2) we would have reverted the aliases for T as:@smallexamplemay-aliases(V1) = @{ T @}may-aliases(V2) = @{ T @}may-aliases(V3) = @{ T @}@end smallexampleBut note that now V2 is no longer aliased with R@.  We couldadd R to may-aliases(V2), but we are in the process ofgrouping aliases to reduce virtual operands so what we do isadd V4 to the grouping to obtain:@smallexamplemay-aliases(V1) = @{ T @}may-aliases(V2) = @{ T @}may-aliases(V3) = @{ T @}may-aliases(V4) = @{ T @}@end smallexample@item If the total number of virtual operands due to aliasing isstill above the threshold set by max-alias-vops, go back to (2).@end enumerate

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -