-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/variable renaming #38
base: master
Are you sure you want to change the base?
Feature/variable renaming #38
Conversation
map[&T, set[&T]] dominanceTree = createDominanceTree(flowGraph); | ||
map[&T, set[&T]] dominanceFrontier = createDominanceFrontier(flowGraph, dominanceTree); | ||
FlowGraph phiFunctionFlowGraph = insertPhiFunctions(flowGraph, dominanceFrontier); | ||
result = applyVariableRenaming(phiFunctionFlowGraph); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applies each SSA's stages
public FlowGraph insertPhiFunctions(FlowGraph flowGraph, map[&T, set[&T]] dominanceFrontier) { | ||
newFlowGraph = { <origin, destination> | <origin, destination> <- flowGraph }; | ||
variableList = { getStmtVariable(graphNode) | <graphNode, _> <- flowGraph, isVariable(graphNode) }; | ||
|
||
for(Variable variable <- variableList) { | ||
F = {}; // set of basic blocks where φ is added | ||
W = {}; // set of basic blocks that contain definitions of v | ||
|
||
for(variableNode <- blocksWithVariable(flowGraph, variable)) { // d ∈ Defs(v) | ||
B = variableNode; | ||
W = W + {B}; | ||
}; | ||
|
||
while(size(W) != 0) { | ||
// remove a basic block X from W | ||
tuple[Node, set[Node]] elements = takeOneFrom(W); | ||
X = elements[0]; | ||
W = elements[1]; | ||
|
||
if(X in dominanceFrontier) { // Avoids NoSuchKey error | ||
frontierNodes = dominanceFrontier[X]; | ||
for(Y <- frontierNodes) { // Y : basic block ∈ DF(X ) | ||
if(size({Y} & F) == 0 && isJoinNode(flowGraph, Y)) { // Y \notin F && Y is a join node | ||
newFlowGraph = insertPhiFunction(newFlowGraph, Y, variable); // add v←φ(...) at entry of Y | ||
F = F + {Y}; // F ← F ∪ {Y} | ||
if(size([Y] & blocksWithVariable(flowGraph, variable)) == 0) { // Y \notin Defs(v) | ||
W = W + {Y}; // W ←W ∪{Y} | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
}; | ||
|
||
return newFlowGraph; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public FlowGraph applyVariableRenaming(FlowGraph flowGraph) { | ||
VARIABLE_VERSION_STACK = (); // Stack for each variable that holds the next variable to ve replaced | ||
VARIABLE_ASSIGNMENT_COUNT = (); // Counts how many assingments have been processed for a given variable | ||
REPLACED_NODES = {}; // Keep tracking of all nodes replaced in one execution | ||
LAST_VERSION_REPLACED = (); // Keep tracking of the new version of a given node | ||
|
||
ADJACENCIES_MATRIX = createAdjacenciesMatrix(flowGraph); // Mainly used to rebuild the renamed flow graph | ||
IDOM_TREE = createIdomTree(createDominanceTree(flowGraph)); // Used to traverse the flow graph | ||
|
||
map[Node, list[Node]] newBlockTree = replace(entryNode()); // Start algorithm | ||
|
||
// Rebuild renamed flowGraph | ||
FlowGraph newFlowGraph = {}; | ||
for(fatherNode <- newBlockTree) { | ||
newFlowGraph = newFlowGraph + { <fatherNode, nodeChild> | nodeChild <- ADJACENCIES_MATRIX[fatherNode]}; | ||
}; | ||
|
||
return newFlowGraph; | ||
} | ||
|
||
public map[Node, list[Node]] replace(Node X) { | ||
if((X == exitNode())) return ADJACENCIES_MATRIX; | ||
|
||
Node oldNode = X; | ||
|
||
// Deal with all nodes that aren't assigments bug uses a variable in some way | ||
if(isNonAssignmentStatementToRename(X)) { | ||
stmtNode(statement) = X; | ||
Node renamedStatement = stmtNode(replaceImmediateUse(statement)); | ||
renameNodeOcurrecies(X, renamedStatement); | ||
X = renamedStatement; | ||
}; | ||
|
||
// Deal will all nodes that are an assigment and are not renamed | ||
if(isOrdinaryAssignment(X) && !isRenamed(X)) { | ||
|
||
// Replace right hand side variables | ||
list[Immediate] rightHandNodeImmediates = getRightHandSideImmediates(X); | ||
for(rightHandSideImmediate <- rightHandNodeImmediates) { | ||
newAssignStmt = replaceRightVariableVersion(ADJACENCIES_MATRIX, rightHandSideImmediate, X); | ||
|
||
renameNodeOcurrecies(X, newAssignStmt); | ||
|
||
X = newAssignStmt; | ||
}; | ||
|
||
// Replace left hand side variables | ||
if(isLeftHandSideVariable(X)) { | ||
Variable V = getStmtVariable(X); | ||
Immediate localVariableImmediate = local(V[0]); | ||
|
||
int assingmentQuantity = returnAssignmentQuantity(localVariableImmediate); | ||
newAssignStmt = replaceLeftVariableVersion(ADJACENCIES_MATRIX, X, assingmentQuantity); | ||
|
||
renameNodeOcurrecies(X, newAssignStmt); | ||
|
||
stackVariableVersion(localVariableImmediate, assingmentQuantity); | ||
iterateAssignmentQuantity(localVariableImmediate); | ||
findAndAddPhiFunctionArgs(oldNode, newAssignStmt); // Search variable uses of replaced variable in phi-function and rename it | ||
|
||
X = newAssignStmt; | ||
}; | ||
} | ||
|
||
for(child <- IDOM_TREE[X]) { | ||
// We need to check the last version replaced because the renamed version was not beign reflected in the current `for` statement iteration, | ||
// so we need to check the last version replaced | ||
nodeToRename = LAST_VERSION_REPLACED[child]? ? LAST_VERSION_REPLACED[child] : child; | ||
replace(nodeToRename); | ||
}; | ||
|
||
if(!ignoreNode(oldNode) && isVariable(oldNode) && !isRenamed(X)) | ||
popOldNode(oldNode); | ||
|
||
return ADJACENCIES_MATRIX; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3329eef
to
0d3eebb
Compare
b7d7a04
to
45f0cf6
Compare
45f0cf6
to
e8a8731
Compare
This reverts commit 6267bbc.
This is a direct implementation of Cytron's Single Static Assignment Form. The code also uses some ideas and algorithms presented by the SSA book.
The implementation ignores two types of instructions:
invokeStmt
assign(fieldRef(_, _), _)
The code is composed into five main modules:
lang::jimple::toolkit::ssa::Generator
is responsible to call all the other modules to perform a complete SSA transformation, also validates if the ignored instructions are present;lang::jimple::toolkit::ssa::DominanceFrontier
is responsible to create the graph's dominance frontier;lang::jimple::toolkit::ssa::DominanceTree
is responsible to create the graph's dominance tree;lang::jimple::toolkit::ssa::PhiFunctionInsertion
it inserts the phi functions in the graph;lang::jimple::toolkit::ssa::VariableRenaming
it renames all the variables for different versions;