📄 tree-ssa.texi
字号:
@end smallexampleNotice that @code{VDEF} operands have two copies of the referencedvariable. This indicates that this is not a killing definition ofthat variable. In this case we refer to it as a @dfn{may definition}or @dfn{aliased store}. The presence of the second copy of thevariable in the @code{VDEF} operand will become important when thefunction is converted into SSA form. This will be used to link allthe non-killing definitions to prevent optimizations from makingincorrect assumptions about them.Operands are updated as soon as the statement is finished via a callto @code{update_stmt}. If statement elements are changed via@code{SET_USE} or @code{SET_DEF}, then no further action is required(i.e., those macros take care of updating the statement). If changesare made by manipulating the statement's tree directly, then a callmust be made to @code{update_stmt} when complete. Calling one of the@code{bsi_insert} routines or @code{bsi_replace} performs an implicitcall to @code{update_stmt}.@subsection Operand Iterators And Access Routines@cindex Operand Iterators @cindex Operand Access RoutinesOperands are collected by @file{tree-ssa-operands.c}. They are storedinside each statement's annotation and can be accessed through either theoperand iterators or an access routine.The following access routines are available for examining operands:@enumerate@item @code{SINGLE_SSA_@{USE,DEF,TREE@}_OPERAND}: These accessors will return NULL unless there is exactly one operand matching the specified flags. If there is exactly one operand, the operand is returned as either a @code{tree}, @code{def_operand_p}, or @code{use_operand_p}.@smallexampletree t = SINGLE_SSA_TREE_OPERAND (stmt, flags);use_operand_p u = SINGLE_SSA_USE_OPERAND (stmt, SSA_ALL_VIRTUAL_USES);def_operand_p d = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_ALL_DEFS);@end smallexample@item @code{ZERO_SSA_OPERANDS}: This macro returns true if there are no operands matching the specified flags.@smallexampleif (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) return;@end smallexample@item @code{NUM_SSA_OPERANDS}: This macro Returns the number of operands matching 'flags'. This actually executes a loop to perform the count, so only use this if it is really needed.@smallexampleint count = NUM_SSA_OPERANDS (stmt, flags)@end smallexample@end enumerateIf you wish to iterate over some or all operands, use the@code{FOR_EACH_SSA_@{USE,DEF,TREE@}_OPERAND} iterator. For example, to printall the operands for a statement:@smallexamplevoidprint_ops (tree stmt)@{ ssa_op_iter; tree var; FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_OPERANDS) print_generic_expr (stderr, var, TDF_SLIM);@}@end smallexampleHow to choose the appropriate iterator:@enumerate@item Determine whether you are need to see the operand pointers, or just the trees, and choose the appropriate macro:@smallexampleNeed Macro:---- -------use_operand_p FOR_EACH_SSA_USE_OPERANDdef_operand_p FOR_EACH_SSA_DEF_OPERANDtree FOR_EACH_SSA_TREE_OPERAND@end smallexample@item You need to declare a variable of the type you are interested in, and an ssa_op_iter structure which serves as the loop controlling variable.@item Determine which operands you wish to use, and specify the flags of those you are interested in. They are documented in @file{tree-ssa-operands.h}:@smallexample#define SSA_OP_USE 0x01 /* @r{Real USE operands.} */#define SSA_OP_DEF 0x02 /* @r{Real DEF operands.} */#define SSA_OP_VUSE 0x04 /* @r{VUSE operands.} */#define SSA_OP_VMAYUSE 0x08 /* @r{USE portion of VDEFS.} */#define SSA_OP_VDEF 0x10 /* @r{DEF portion of VDEFS.} *//* @r{These are commonly grouped operand flags.} */#define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE | SSA_OP_VMAYUSE)#define SSA_OP_VIRTUAL_DEFS (SSA_OP_VDEF)#define SSA_OP_ALL_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)#define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF)#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS)@end smallexample@end enumerateSo if you want to look at the use pointers for all the @code{USE} and@code{VUSE} operands, you would do something like:@smallexample use_operand_p use_p; ssa_op_iter iter; FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, (SSA_OP_USE | SSA_OP_VUSE)) @{ process_use_ptr (use_p); @}@end smallexampleThe @code{TREE} macro is basically the same as the @code{USE} and@code{DEF} macros, only with the use or def dereferenced via@code{USE_FROM_PTR (use_p)} and @code{DEF_FROM_PTR (def_p)}. Since wearen't using operand pointers, use and defs flags can be mixed.@smallexample tree var; ssa_op_iter iter; FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_VUSE) @{ print_generic_expr (stderr, var, TDF_SLIM); @}@end smallexample@code{VDEF}s are broken into two flags, one for the@code{DEF} portion (@code{SSA_OP_VDEF}) and one for the USE portion(@code{SSA_OP_VMAYUSE}). If all you want to look at are the@code{VDEF}s together, there is a fourth iterator macro for this,which returns both a def_operand_p and a use_operand_p for each@code{VDEF} in the statement. Note that you don't need any flags forthis one.@smallexample use_operand_p use_p; def_operand_p def_p; ssa_op_iter iter; FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter) @{ my_code; @}@end smallexampleThere are many examples in the code as well, as well as thedocumentation in @file{tree-ssa-operands.h}.There are also a couple of variants on the stmt iterators regarding PHInodes.@code{FOR_EACH_PHI_ARG} Works exactly like @code{FOR_EACH_SSA_USE_OPERAND}, except it works over @code{PHI} arguments instead of statement operands.@smallexample/* Look at every virtual PHI use. */FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_VIRTUAL_USES)@{ my_code;@}/* Look at every real PHI use. */FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_USES) my_code;/* Look at every every PHI use. */FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_ALL_USES) my_code;@end smallexample@code{FOR_EACH_PHI_OR_STMT_@{USE,DEF@}} works exactly like @code{FOR_EACH_SSA_@{USE,DEF@}_OPERAND}, except it will function oneither a statement or a @code{PHI} node. These should be used when it isappropriate but they are not quite as efficient as the individual @code{FOR_EACH_PHI} and @code{FOR_EACH_SSA} routines.@smallexampleFOR_EACH_PHI_OR_STMT_USE (use_operand_p, stmt, iter, flags) @{ my_code; @}FOR_EACH_PHI_OR_STMT_DEF (def_operand_p, phi, iter, flags) @{ my_code; @}@end smallexample@subsection Immediate Uses@cindex Immediate UsesImmediate use information is now always available. Using the immediate use iterators, you may examine every use of any @code{SSA_NAME}. For instance,to change each use of @code{ssa_var} to @code{ssa_var2} and call fold_stmt oneach stmt after that is done:@smallexample use_operand_p imm_use_p; imm_use_iterator iterator; tree ssa_var, stmt; FOR_EACH_IMM_USE_STMT (stmt, iterator, ssa_var) @{ FOR_EACH_IMM_USE_ON_STMT (imm_use_p, iterator) SET_USE (imm_use_p, ssa_var_2); fold_stmt (stmt); @}@end smallexampleThere are 2 iterators which can be used. @code{FOR_EACH_IMM_USE_FAST} isused when the immediate uses are not changed, i.e., you are looking at theuses, but not setting them. If they do get changed, then care must be taken that things are not changed under the iterators, so use the @code{FOR_EACH_IMM_USE_STMT} and @code{FOR_EACH_IMM_USE_ON_STMT} iterators. They attempt to preserve the sanity of the use list by moving all the uses for a statement into a controlled position, and then iterating over those uses. Then the optimization can manipulate the stmt when all the uses have beenprocessed. This is a little slower than the FAST version since it adds a placeholder element and must sort through the list a bit for each statement. This placeholder element must be also be removed if the loop is terminated early. The macro @code{BREAK_FROM_IMM_USE_SAFE} is provided to do this :@smallexample FOR_EACH_IMM_USE_STMT (stmt, iterator, ssa_var) @{ if (stmt == last_stmt) BREAK_FROM_SAFE_IMM_USE (iter); FOR_EACH_IMM_USE_ON_STMT (imm_use_p, iterator) SET_USE (imm_use_p, ssa_var_2); fold_stmt (stmt); @}@end smallexampleThere are checks in @code{verify_ssa} which verify that the immediate use listis up to date, as well as checking that an optimization didn't break from the loop without using this macro. It is safe to simply 'break'; from a @code{FOR_EACH_IMM_USE_FAST} traverse.Some useful functions and macros:@enumerate@item @code{has_zero_uses (ssa_var)} : Returns true if there are no uses of@code{ssa_var}.@item @code{has_single_use (ssa_var)} : Returns true if there is only a single use of @code{ssa_var}.@item @code{single_imm_use (ssa_var, use_operand_p *ptr, tree *stmt)} :Returns true if there is only a single use of @code{ssa_var}, and also returnsthe use pointer and statement it occurs in in the second and third parameters.@item @code{num_imm_uses (ssa_var)} : Returns the number of immediate uses of@code{ssa_var}. It is better not to use this if possible since it simplyutilizes a loop to count the uses.@item @code{PHI_ARG_INDEX_FROM_USE (use_p)} : Given a use within a @code{PHI}node, return the index number for the use. An assert is triggered if the useisn't located in a @code{PHI} node.@item @code{USE_STMT (use_p)} : Return the statement a use occurs in.@end enumerateNote that uses are not put into an immediate use list until their statement isactually inserted into the instruction stream via a @code{bsi_*} routine. It is also still possible to utilize lazy updating of statements, but this should be used only when absolutely required. Both alias analysis and the dominator optimizations currently do this. When lazy updating is being used, the immediate use information is out of date and cannot be used reliably. Lazy updating is achieved by simply markingstatements modified via calls to @code{mark_stmt_modified} instead of @code{update_stmt}. When lazy updating is no longer required, all the modified statements must have @code{update_stmt} called in order to bring them up to date. This must be done before the optimization is finished, or @code{verify_ssa} will trigger an abort.This is done with a simple loop over the instruction stream:@smallexample block_stmt_iterator bsi; basic_block bb; FOR_EACH_BB (bb) @{ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) update_stmt_if_modified (bsi_stmt (bsi)); @}@end smallexample@node SSA@section Static Single Assignment@cindex SSA@cindex static single assignmentMost of the tree optimizers rely on the data flow information providedby the Static Single Assignment (SSA) form. We implement the SSA formas described in @cite{R. Cytron, J. Ferrante, B. Rosen, M. Wegman, andK. Zadeck. Efficiently Computing Static Single Assignment Form and theControl Dependence Graph. ACM Transactions on Programming Languagesand Systems, 13(4):451-490, October 1991}.The SSA form is based on the premise that program variables areassigned in exactly one location in the program. Multiple assignmentsto the same variable create new versions of that variable. Naturally,actual programs are seldom in SSA form initially because variablestend to be assigned multiple times. The compiler modifies the programrepresentation so that every time a variable is assigned in the code,a new version of the variable is created. Different versions of thesame variable are distinguished by subscripting the variable name withits version number. Variables used in the right-hand side ofexpressions are renamed so that their version number matches that ofthe most recent assignment.We represent variable versions using @code{SSA_NAME} nodes. Therenaming process in @file{tree-ssa.c} wraps every real andvirtual operand with an @code{SSA_NAME} node which containsthe version number and the statement that created the@code{SSA_NAME}. Only definitions and virtual definitions maycreate new @code{SSA_NAME} nodes.@cindex PHI nodesSometimes, flow of control makes it impossible to determine themost recent version of a variable. In these cases, the compilerinserts an artificial definition for that variable called@dfn{PHI function} or @dfn{PHI node}. This new definition mergesall the incoming versions of the variable to create a new namefor it. For instance,@smallexampleif (@dots{}) a_1 = 5;else if (@dots{}) a_2 = 2;else a_3 = 13;# a_4 = PHI <a_1, a_2, a_3>return a_4;@end smallexampleSince it is not possible to determine which of the three brancheswill be taken at runtime, we don't know which of @code{a_1},@code{a_2} or @code{a_3} to use at the return statement. So, theSSA renamer creates a new version @code{a_4} which is assignedthe result of ``merging'' @code{a_1}, @code{a_2} and @code{a_3}.Hence, PHI nodes mean ``one of these operands. I don't knowwhich''.The following macros can be used to examine PHI nodes@defmac PHI_RESULT (@var{phi})Returns the @code{SSA_NAME} created by PHI node @var{phi} (i.e.,@var{phi}'s LHS)@.@end defmac@defmac PHI_NUM_ARGS (@var{phi})Returns the number of arguments in @var{phi}. This number is exactlythe number of incoming edges to the basic block holding @var{phi}@.@end defmac@defmac PHI_ARG_ELT (@var{phi}, @var{i})Returns a tuple representing the @var{i}th argument of @var{phi}@.Each element of this tuple contains an @code{SSA_NAME} @var{var} andthe incoming edge through which @var{var} flows.@end defmac@defmac PHI_ARG_EDGE (@var{phi}, @var{i})Returns the incoming edge for the @var{i}th argument of @var{phi}.@end defmac@defmac PHI_ARG_DEF (@var{phi}, @var{i})Returns the @code{SSA_NAME} for the @var{i}th argument of @var{phi}.@end defmac@subsection Preserving the SSA form@findex update_ssa@cindex preserving SSA formSome optimization passes make changes to the function thatinvalidate the SSA property. This can happen when a pass hasadded new symbols or changed the program so that variables thatwere previously aliased aren't anymore. Whenever something like thishappens, the affected symbols must be renamed into SSA form again. Transformations that emit new code or replicate existing statementswill also need to update the SSA form@.Since GCC implements two different SSA forms for register and virtualvariables, keeping the SSA form up to date depends on whether you areupdating register or virtual names. In both cases, the general ideabehind incremental SSA updates is similar: when new SSA names arecreated, they typically are meant to replace other existing names inthe program@.For instance, given the following code:@smallexample 1 L0: 2 x_1 = PHI (0, x_5) 3 if (x_1 < 10) 4 if (x_1 > 7) 5 y_2 = 0 6 else 7 y_3 = x_1 + x_7 8 endif 9 x_5 = x_1 + 1 10 goto L0; 11 endif@end smallexampleSuppose that we insert new names @code{x_10} and @code{x_11} (lines@code{4} and @code{8})@.@smallexample 1 L0: 2 x_1 = PHI (0, x_5) 3 if (x_1 < 10)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -