Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: src/IceCfgNode.cpp

Issue 560773002: Subzero: Fix Phi lowering. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes, plus a new TODO Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/llvm2ice.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceCfgNode.cpp
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 696a2f0b87ad9fb948535f3ded3d0ece2a0ccfe2..f6b4a98b46bae12bbeb9fccf87b0587999654089 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -115,20 +115,62 @@ void CfgNode::placePhiLoads() {
// critical edges, add the assignments, and lower them. This should
// reduce the amount of shuffling at the end of each block.
void CfgNode::placePhiStores() {
- // Find the insertion point. TODO: After branch/compare fusing is
- // implemented, try not to insert Phi stores between the compare and
- // conditional branch instructions, otherwise the branch/compare
- // pattern matching may fail. However, the branch/compare sequence
- // will have to be broken if the compare result is read (by the
- // assignment) before it is written (by the compare).
+ // Find the insertion point.
InstList::iterator InsertionPoint = Insts.end();
- // Every block must end in a terminator instruction.
+ // Every block must end in a terminator instruction, and therefore
+ // must have at least one instruction, so it's valid to decrement
+ // InsertionPoint (but assert just in case).
assert(InsertionPoint != Insts.begin());
--InsertionPoint;
// Confirm that InsertionPoint is a terminator instruction. Calling
// getTerminatorEdges() on a non-terminator instruction will cause
// an llvm_unreachable().
(void)(*InsertionPoint)->getTerminatorEdges();
+ // SafeInsertionPoint is always immediately before the terminator
+ // instruction. If the block ends in a compare and conditional
+ // branch, it's better to place the Phi store before the compare so
+ // as not to interfere with compare/branch fusing. However, if the
+ // compare instruction's dest operand is the same as the new
+ // assignment statement's source operand, this can't be done due to
+ // data dependences, so we need to fall back to the
+ // SafeInsertionPoint. To illustrate:
+ // ; <label>:95
+ // %97 = load i8* %96, align 1
+ // %98 = icmp ne i8 %97, 0
+ // br i1 %98, label %99, label %2132
+ // ; <label>:99
+ // %100 = phi i8 [ %97, %95 ], [ %110, %108 ]
+ // %101 = phi i1 [ %98, %95 ], [ %111, %108 ]
+ // would be Phi-lowered as:
+ // ; <label>:95
+ // %97 = load i8* %96, align 1
+ // %100_phi = %97 ; can be at InsertionPoint
+ // %98 = icmp ne i8 %97, 0
+ // %101_phi = %98 ; must be at SafeInsertionPoint
+ // br i1 %98, label %99, label %2132
+ // ; <label>:99
+ // %100 = %100_phi
+ // %101 = %101_phi
+ //
+ // TODO(stichnot): It may be possible to bypass this whole
+ // SafeInsertionPoint mechanism. If a source basic block ends in a
+ // conditional branch:
+ // labelSource:
+ // ...
+ // br i1 %foo, label %labelTrue, label %labelFalse
+ // and a branch target has a Phi involving the branch operand:
+ // labelTrue:
+ // %bar = phi i1 [ %foo, %labelSource ], ...
+ // then we actually know the constant i1 value of the Phi operand:
+ // labelTrue:
+ // %bar = phi i1 [ true, %labelSource ], ...
+ // It seems that this optimization should be done by clang or opt,
+ // but we could also do it here.
+ InstList::iterator SafeInsertionPoint = InsertionPoint;
+ // Keep track of the dest variable of a compare instruction, so that
+ // we insert the new instruction at the SafeInsertionPoint if the
+ // compare's dest matches the Phi-lowered assignment's source.
+ Variable *CmpInstDest = NULL;
// If the current insertion point is at a conditional branch
// instruction, and the previous instruction is a compare
// instruction, then we move the insertion point before the compare
@@ -137,8 +179,10 @@ void CfgNode::placePhiStores() {
if (!Branch->isUnconditional()) {
if (InsertionPoint != Insts.begin()) {
--InsertionPoint;
- if (!llvm::isa<InstIcmp>(*InsertionPoint) &&
- !llvm::isa<InstFcmp>(*InsertionPoint)) {
+ if (llvm::isa<InstIcmp>(*InsertionPoint) ||
+ llvm::isa<InstFcmp>(*InsertionPoint)) {
+ CmpInstDest = (*InsertionPoint)->getDest();
+ } else {
++InsertionPoint;
}
}
@@ -165,7 +209,10 @@ void CfgNode::placePhiStores() {
Dest->setPreferredRegister(Src, AllowOverlap);
Src->setPreferredRegister(Dest, AllowOverlap);
}
- Insts.insert(InsertionPoint, NewInst);
+ if (CmpInstDest == Operand)
+ Insts.insert(SafeInsertionPoint, NewInst);
+ else
+ Insts.insert(InsertionPoint, NewInst);
NewInst->updateVars(this);
}
}
« no previous file with comments | « no previous file | src/llvm2ice.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698