Chromium Code Reviews| 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); |
| } |
| } |