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

📄 tree-ssa.texi

📁 理解和实践操作系统的一本好书
💻 TEXI
📖 第 1 页 / 共 4 页
字号:
@c Copyright (c) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.@c Free Software Foundation, Inc.@c This is part of the GCC manual.@c For copying conditions, see the file gcc.texi.@c ---------------------------------------------------------------------@c Tree SSA@c ---------------------------------------------------------------------@node Tree SSA@chapter Analysis and Optimization of GIMPLE Trees@cindex Tree SSA@cindex Optimization infrastructure for GIMPLEGCC uses three main intermediate languages to represent the programduring compilation: GENERIC, GIMPLE and RTL@.  GENERIC is alanguage-independent representation generated by each front end.  Itis used to serve as an interface between the parser and optimizer.GENERIC is a common representation that is able to represent programswritten in all the languages supported by GCC@.GIMPLE and RTL are used to optimize the program.  GIMPLE is used fortarget and language independent optimizations (e.g., inlining,constant propagation, tail call elimination, redundancy elimination,etc).  Much like GENERIC, GIMPLE is a language independent, tree basedrepresentation.  However, it differs from GENERIC in that the GIMPLEgrammar is more restrictive: expressions contain no more than 3operands (except function calls), it has no control flow structuresand expressions with side-effects are only allowed on the right handside of assignments.  See the chapter describing GENERIC and GIMPLEfor more details.This chapter describes the data structures and functions used in theGIMPLE optimizers (also known as ``tree optimizers'' or ``middleend'').  In particular, it focuses on all the macros, data structures,functions and programming constructs needed to implement optimizationpasses for GIMPLE@.@menu* GENERIC::		A high-level language-independent representation.* GIMPLE::              A lower-level factored tree representation.* Annotations::		Attributes for statements and variables.* Statement Operands::	Variables referenced by GIMPLE statements.* SSA::			Static Single Assignment representation.* Alias analysis::	Representing aliased loads and stores.@end menu@node GENERIC@section GENERIC@cindex GENERICThe purpose of GENERIC is simply to provide a language-independent way ofrepresenting an entire function in trees.  To this end, it was necessary toadd a few new tree codes to the back end, but most everything was alreadythere.  If you can express it with the codes in @code{gcc/tree.def}, it'sGENERIC@.Early on, there was a great deal of debate about how to think aboutstatements in a tree IL@.  In GENERIC, a statement is defined as anyexpression whose value, if any, is ignored.  A statement will alwayshave @code{TREE_SIDE_EFFECTS} set (or it will be discarded), but anon-statement expression may also have side effects.  A@code{CALL_EXPR}, for instance.It would be possible for some local optimizations to work on theGENERIC form of a function; indeed, the adapted tree inliner worksfine on GENERIC, but the current compiler performs inlining afterlowering to GIMPLE (a restricted form described in the next section).Indeed, currently the frontends perform this lowering before handingoff to @code{tree_rest_of_compilation}, but this seems inelegant.If necessary, a front end can use some language-dependent tree codesin its GENERIC representation, so long as it provides a hook forconverting them to GIMPLE and doesn't expect them to work with any(hypothetical) optimizers that run before the conversion to GIMPLE@.The intermediate representation used while parsing C and C++ looksvery little like GENERIC, but the C and C++ gimplifier hooks areperfectly happy to take it as input and spit out GIMPLE@.@node GIMPLE@section GIMPLE@cindex GIMPLEGIMPLE is a simplified subset of GENERIC for use in optimization.  Theparticular subset chosen (and the name) was heavily influenced by theSIMPLE IL used by the McCAT compiler project at McGill University,though we have made some different choices.  For one thing, SIMPLEdoesn't support @code{goto}; a production compiler can't afford thatkind of restriction.GIMPLE retains much of the structure of the parse trees: lexicalscopes are represented as containers, rather than markers.  However,expressions are broken down into a 3-address form, using temporaryvariables to hold intermediate values.  Also, control structures arelowered to gotos.In GIMPLE no container node is ever used for its value; if a@code{COND_EXPR} or @code{BIND_EXPR} has a value, it is stored into atemporary within the controlled blocks, and that temporary is used inplace of the container.The compiler pass which lowers GENERIC to GIMPLE is referred to as the@samp{gimplifier}.  The gimplifier works recursively, replacing complexstatements with sequences of simple statements.@c Currently, the only way to@c tell whether or not an expression is in GIMPLE form is by recursively@c examining it; in the future there will probably be a flag to help avoid@c redundant work.  FIXME FIXME@menu* Interfaces::* Temporaries::* GIMPLE Expressions::* Statements::* GIMPLE Example::* Rough GIMPLE Grammar::@end menu@node Interfaces@subsection Interfaces@cindex gimplificationThe tree representation of a function is stored in@code{DECL_SAVED_TREE}.  It is lowered to GIMPLE by a call to@code{gimplify_function_tree}.If a front end wants to include language-specific tree codes in the treerepresentation which it provides to the back end, it must provide adefinition of @code{LANG_HOOKS_GIMPLIFY_EXPR} which knows how toconvert the front end trees to GIMPLE@.  Usually such a hook will involvemuch of the same code for expanding front end trees to RTL@.  This functioncan return fully lowered GIMPLE, or it can return GENERIC trees and let themain gimplifier lower them the rest of the way; this is often simpler.GIMPLE that is not fully lowered is known as ``high GIMPLE'' andconsists of the IL before the pass @code{pass_lower_cf}.  High GIMPLEstill contains lexical scopes and nested expressions, while low GIMPLEexposes all of the implicit jumps for control expressions like@code{COND_EXPR}.The C and C++ front ends currently convert directly from front endtrees to GIMPLE, and hand that off to the back end rather than firstconverting to GENERIC@.  Their gimplifier hooks know about all the@code{_STMT} nodes and how to convert them to GENERIC forms.  Therewas some work done on a genericization pass which would run first, butthe existence of @code{STMT_EXPR} meant that in order to convert allof the C statements into GENERIC equivalents would involve walking theentire tree anyway, so it was simpler to lower all the way.  Thismight change in the future if someone writes an optimization passwhich would work better with higher-level trees, but currently theoptimizers all expect GIMPLE@.A front end which wants to use the tree optimizers (and already hassome sort of whole-function tree representation) only needs to providea definition of @code{LANG_HOOKS_GIMPLIFY_EXPR}, call@code{gimplify_function_tree} to lower to GIMPLE, and then hand off to@code{tree_rest_of_compilation} to compile and output the function.You can tell the compiler to dump a C-like representation of the GIMPLEform with the flag @option{-fdump-tree-gimple}.@node Temporaries@subsection Temporaries@cindex TemporariesWhen gimplification encounters a subexpression which is too complex, itcreates a new temporary variable to hold the value of the subexpression,and adds a new statement to initialize it before the current statement.These special temporaries are known as @samp{expression temporaries}, and areallocated using @code{get_formal_tmp_var}.  The compiler tries toalways evaluate identical expressions into the same temporary, to simplifyelimination of redundant calculations.We can only use expression temporaries when we know that it will not bereevaluated before its value is used, and that it will not be otherwisemodified@footnote{These restrictions are derived from those in Morgan 4.8.}.Other temporaries can be allocated using@code{get_initialized_tmp_var} or @code{create_tmp_var}.Currently, an expression like @code{a = b + 5} is not reduced anyfurther.  We tried converting it to something like@smallexample  T1 = b + 5;  a = T1;@end smallexamplebut this bloated the representation for minimal benefit.  However, avariable which must live in memory cannot appear in an expression; itsvalue is explicitly loaded into a temporary first.  Similarly, storingthe value of an expression to a memory variable goes through atemporary.@node GIMPLE Expressions@subsection Expressions@cindex GIMPLE ExpressionsIn general, expressions in GIMPLE consist of an operation and theappropriate number of simple operands; these operands must either be aGIMPLE rvalue (@code{is_gimple_val}), i.e.@: a constant or a registervariable.  More complex operands are factored out into temporaries, sothat@smallexample  a = b + c + d@end smallexamplebecomes@smallexample  T1 = b + c;  a = T1 + d;@end smallexampleThe same rule holds for arguments to a @code{CALL_EXPR}.The target of an assignment is usually a variable, but can also be an@code{INDIRECT_REF} or a compound lvalue as described below.@menu* Compound Expressions::* Compound Lvalues::* Conditional Expressions::* Logical Operators::@end menu@node Compound Expressions@subsubsection Compound Expressions@cindex Compound ExpressionsThe left-hand side of a C comma expression is simply moved into a separatestatement.@node Compound Lvalues@subsubsection Compound Lvalues@cindex Compound LvaluesCurrently compound lvalues involving array and structure field referencesare not broken down; an expression like @code{a.b[2] = 42} is not reducedany further (though complex array subscripts are).  This restriction is aworkaround for limitations in later optimizers; if we were to convert thisto@smallexample  T1 = &a.b;  T1[2] = 42;@end smallexamplealias analysis would not remember that the reference to @code{T1[2]} cameby way of @code{a.b}, so it would think that the assignment could aliasanother member of @code{a}; this broke @code{struct-alias-1.c}.  Futureoptimizer improvements may make this limitation unnecessary.@node Conditional Expressions@subsubsection Conditional Expressions@cindex Conditional ExpressionsA C @code{?:} expression is converted into an @code{if} statement witheach branch assigning to the same temporary.  So,@smallexample  a = b ? c : d;@end smallexamplebecomes@smallexample  if (b)    T1 = c;  else    T1 = d;  a = T1;@end smallexampleTree level if-conversion pass re-introduces @code{?:} expression, if appropriate.It is used to vectorize loops with conditions using vector conditional operations.Note that in GIMPLE, @code{if} statements are also represented using@code{COND_EXPR}, as described below.@node Logical Operators@subsubsection Logical Operators@cindex Logical OperatorsExcept when they appear in the condition operand of a @code{COND_EXPR},logical `and' and `or' operators are simplified as follows:@code{a = b && c} becomes@smallexample  T1 = (bool)b;  if (T1)    T1 = (bool)c;  a = T1;@end smallexampleNote that @code{T1} in this example cannot be an expression temporary,because it has two different assignments.@node Statements@subsection Statements@cindex StatementsMost statements will be assignment statements, represented by@code{MODIFY_EXPR}.  A @code{CALL_EXPR} whose value is ignored canalso be a statement.  No other C expressions can appear at statement level;a reference to a volatile object is converted into a @code{MODIFY_EXPR}.In GIMPLE form, type of @code{MODIFY_EXPR} is not meaningful.  Instead, use typeof LHS or RHS@.There are also several varieties of complex statements.@menu* Blocks::* Statement Sequences::* Empty Statements::* Loops::* Selection Statements::* Jumps::* Cleanups::* GIMPLE Exception Handling::@end menu@node Blocks@subsubsection Blocks@cindex BlocksBlock scopes and the variables they declare in GENERIC and GIMPLE areexpressed using the @code{BIND_EXPR} code, which in previous versions ofGCC was primarily used for the C statement-expression extension.Variables in a block are collected into @code{BIND_EXPR_VARS} indeclaration order.  Any runtime initialization is moved out of@code{DECL_INITIAL} and into a statement in the controlled block.  Whengimplifying from C or C++, this initialization replaces the@code{DECL_STMT}.Variable-length arrays (VLAs) complicate this process, as their size oftenrefers to variables initialized earlier in the block.  To handle this, wecurrently split the block at that point, and move the VLA into a new, inner@code{BIND_EXPR}.  This strategy may change in the future.@code{DECL_SAVED_TREE} for a GIMPLE function will always be a@code{BIND_EXPR} which contains declarations for the temporary variablesused in the function.A C++ program will usually contain more @code{BIND_EXPR}s than there aresyntactic blocks in the source code, since several C++ constructs haveimplicit scopes associated with them.  On the other hand, although the C++front end uses pseudo-scopes to handle cleanups for objects withdestructors, these don't translate into the GIMPLE form; multipledeclarations at the same level use the same @code{BIND_EXPR}.@node Statement Sequences@subsubsection Statement Sequences@cindex Statement SequencesMultiple statements at the same nesting level are collected into a@code{STATEMENT_LIST}.  Statement lists are modified and traversedusing the interface in @samp{tree-iterator.h}.@node Empty Statements@subsubsection Empty Statements@cindex Empty StatementsWhenever possible, statements with no effect are discarded.  But if theyare nested within another construct which cannot be discarded for somereason, they are instead replaced with an empty statement, generated by@code{build_empty_stmt}.  Initially, all empty statements were shared,after the pattern of the Java front end, but this caused a lot of trouble inpractice.An empty statement is represented as @code{(void)0}.@node Loops@subsubsection Loops@cindex LoopsAt one time loops were expressed in GIMPLE using @code{LOOP_EXPR}, butnow they are lowered to explicit gotos.@node Selection Statements@subsubsection Selection Statements@cindex Selection StatementsA simple selection statement, such as the C @code{if} statement, isexpressed in GIMPLE using a void @code{COND_EXPR}.  If only one branch isused, the other is filled with an empty statement.Normally, the condition expression is reduced to a simple comparison.  Ifit is a shortcut (@code{&&} or @code{||}) expression, however, we try tobreak up the @code{if} into multiple @code{if}s so that the implied shortcutis taken directly, much like the transformation done by @code{do_jump} inthe RTL expander.A @code{SWITCH_EXPR} in GIMPLE contains the condition and a@code{TREE_VEC} of @code{CASE_LABEL_EXPR}s describing the case valuesand corresponding @code{LABEL_DECL}s to jump to.  The body of the@code{switch} is moved after the @code{SWITCH_EXPR}.@node Jumps@subsubsection Jumps@cindex JumpsOther jumps are expressed by either @code{GOTO_EXPR} or @code{RETURN_EXPR}.The operand of a @code{GOTO_EXPR} must be either a label or a variablecontaining the address to jump to.The operand of a @code{RETURN_EXPR} is either @code{NULL_TREE},@code{RESULT_DECL}, or a @code{MODIFY_EXPR} which sets the return value.  Itwould be nice to move the @code{MODIFY_EXPR} into a separate statement, but thespecial return semantics in @code{expand_return} make that difficult.  It maystill happen in the future, perhaps by moving most of that logic into@code{expand_assignment}.@node Cleanups@subsubsection Cleanups@cindex CleanupsDestructors for local C++ objects and similar dynamic cleanups arerepresented in GIMPLE by a @code{TRY_FINALLY_EXPR}.@code{TRY_FINALLY_EXPR} has two operands, both of which are a sequenceof statements to execute.  The first sequence is executed.  When itcompletes the second sequence is executed.The first sequence may complete in the following ways:@enumerate@item Execute the last statement in the sequence and fall off theend.@item Execute a goto statement (@code{GOTO_EXPR}) to an ordinarylabel outside the sequence.@item Execute a return statement (@code{RETURN_EXPR}).@item Throw an exception.  This is currently not explicitly represented inGIMPLE.

⌨️ 快捷键说明

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