| 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);
|
| }
|
| }
|
|
|