Index: src/IceCfgNode.cpp |
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp |
index 696a2f0b87ad9fb948535f3ded3d0ece2a0ccfe2..e3918720eb8d25e5bf875940867f869227629247 100644 |
--- a/src/IceCfgNode.cpp |
+++ b/src/IceCfgNode.cpp |
@@ -115,16 +115,41 @@ 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. |
assert(InsertionPoint != Insts.begin()); |
--InsertionPoint; |
+ // 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 |
+ 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; |
// Confirm that InsertionPoint is a terminator instruction. Calling |
// getTerminatorEdges() on a non-terminator instruction will cause |
// an llvm_unreachable(). |
jvoung (off chromium)
2014/09/10 17:17:43
Maybe this confirmation should be earlier than the
Jim Stichnoth
2014/09/10 18:29:16
Actually, the "Every block must..." comment was me
|
@@ -137,8 +162,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 +192,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); |
} |
} |