Update documentation.

This commit is contained in:
chriseth 2022-11-29 11:56:58 +01:00
parent c7bb117d50
commit 90a147d371
2 changed files with 29 additions and 25 deletions

View File

@ -62,28 +62,34 @@ struct Dialect;
* Detailed rules:
*
* The AST is traversed twice: in an information gathering step and in the
* actual removal step. During information gathering, we maintain a
* mapping from assignment statements to the three states
* "unused", "undecided" and "used".
* When an assignment is visited, it is added to the mapping in the "undecided" state
* (see remark about for loops below) and every other assignment to the same variable
* that is still in the "undecided" state is changed to "unused".
* When a variable is referenced, the state of any assignment to that variable still
* in the "undecided" state is changed to "used".
* At points where control flow splits, a copy
* of the mapping is handed over to each branch. At points where control flow
* joins, the two mappings coming from the two branches are combined in the following way:
* Statements that are only in one mapping or have the same state are used unchanged.
* Conflicting values are resolved in the following way:
* "unused", "undecided" -> "undecided"
* "unused", "used" -> "used"
* "undecided, "used" -> "used".
* actual removal step. During information gathering, assignment statements
* can be marked as "potentially unused" or as "used".
*
* When an assignment is visited, it is stored in the "set of all stores" and
* added to the branch-dependent "active" sets for the assigned variables. This active
* set for a variable contains all statements where that variable was last assigned to, i.e.
* where a read from that variable could read from.
* Furthermore, all other active sets for the assigned variables are cleared.
*
* When a reference to a variable is visited, the active assignments to that variable
* in the current branch are marked as "used". This mark is permanent.
* Also, the active set for this variable in the current branch is cleared.
*
* At points where control-flow splits, we maintain a copy of the active set
* (all other data structures are shared across branches).
*
* At control-flow joins, we combine the sets of active stores for each variable.
*
* In the example above, the active set right after the assignment "b := mload(a)" (but before
* the control-flow join) is "b := mload(a)"; the assignment "b := 2" was removed.
* After the control-flow join it will contain both "b := mload(a)" and "b := 2", coming from
* the two branches.
*
* For for-loops, the condition, body and post-part are visited twice, taking
* the joining control-flow at the condition into account.
* In other words, we create three control flow paths: Zero runs of the loop,
* one run and two runs and then combine them at the end.
* Running at most twice is enough because there are only three different states.
* Running at most twice is enough because this takes into account all possible control-flow connections.
*
* Since this algorithm has exponential runtime in the nesting depth of for loops,
* a shortcut is taken at a certain nesting level: We only use the zero- and
@ -95,12 +101,7 @@ struct Dialect;
*
* At ``leave`` statements, all return variables are set to "used".
*
* When a variable goes out of scope, all statements still in the "undecided"
* state are changed to "unused", unless the variable is the return
* parameter of a function - there, the state changes to "used".
*
* In the second traversal, all assignments that are in the "unused" state are removed.
*
* In the second traversal, all assignments that are not marked as "used" are removed.
*
* This step is usually run right after the SSA transform to complete
* the generation of the pseudo-SSA.

View File

@ -38,8 +38,11 @@ struct Dialect;
*
* The class tracks the state of abstract "stores" (assignments or mstore/sstore
* statements) across the control-flow. It is the job of the derived class to create
* the stores and track references, but the base class adjusts their "used state" at
* control-flow splits and joins.
* the stores and track references, but the base class manages control-flow splits and joins.
*
* In general, active stores are those where it has not yet been determined if they are used
* or not. Those are split and joined at control-flow forks. Once a store has been deemed
* used, it is removed from the active set and marked as used and this will never change.
*
* Prerequisite: Disambiguator, ForLoopInitRewriter.
*/