parent
b61cd95431
commit
487aed0d77
|
@ -711,6 +711,8 @@ namespace {
|
|||
bool iterateOnFunction(Function &F);
|
||||
bool performPRE(Function &F);
|
||||
bool performScalarPRE(Instruction *I);
|
||||
bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
||||
unsigned int ValNo);
|
||||
Value *findLeader(const BasicBlock *BB, uint32_t num);
|
||||
void cleanupGlobalSets();
|
||||
void verifyRemoved(const Instruction *I) const;
|
||||
|
@ -2454,6 +2456,43 @@ bool GVN::processBlock(BasicBlock *BB) {
|
|||
return ChangedFunction;
|
||||
}
|
||||
|
||||
// Instantiate an expression in a predecessor that lacked it.
|
||||
bool GVN::performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
||||
unsigned int ValNo) {
|
||||
// Because we are going top-down through the block, all value numbers
|
||||
// will be available in the predecessor by the time we need them. Any
|
||||
// that weren't originally present will have been instantiated earlier
|
||||
// in this loop.
|
||||
bool success = true;
|
||||
for (unsigned i = 0, e = Instr->getNumOperands(); i != e; ++i) {
|
||||
Value *Op = Instr->getOperand(i);
|
||||
if (isa<Argument>(Op) || isa<Constant>(Op) || isa<GlobalValue>(Op))
|
||||
continue;
|
||||
|
||||
if (Value *V = findLeader(Pred, VN.lookup(Op))) {
|
||||
Instr->setOperand(i, V);
|
||||
} else {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail out if we encounter an operand that is not available in
|
||||
// the PRE predecessor. This is typically because of loads which
|
||||
// are not value numbered precisely.
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
Instr->insertBefore(Pred->getTerminator());
|
||||
Instr->setName(Instr->getName() + ".pre");
|
||||
Instr->setDebugLoc(Instr->getDebugLoc());
|
||||
VN.add(Instr, ValNo);
|
||||
|
||||
// Update the availability map to include the new instruction.
|
||||
addToLeaderTable(ValNo, Instr, Pred);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GVN::performScalarPRE(Instruction *CurInst) {
|
||||
SmallVector<std::pair<Value*, BasicBlock*>, 8> predMap;
|
||||
|
||||
|
@ -2520,60 +2559,43 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
|
|||
|
||||
// Don't do PRE when it might increase code size, i.e. when
|
||||
// we would need to insert instructions in more than one pred.
|
||||
if (NumWithout != 1 || NumWith == 0)
|
||||
if (NumWithout > 1 || NumWith == 0)
|
||||
return false;
|
||||
|
||||
// Don't do PRE across indirect branch.
|
||||
if (isa<IndirectBrInst>(PREPred->getTerminator()))
|
||||
return false;
|
||||
// We may have a case where all predecessors have the instruction,
|
||||
// and we just need to insert a phi node. Otherwise, perform
|
||||
// insertion.
|
||||
Instruction *PREInstr = nullptr;
|
||||
|
||||
// We can't do PRE safely on a critical edge, so instead we schedule
|
||||
// the edge to be split and perform the PRE the next time we iterate
|
||||
// on the function.
|
||||
unsigned SuccNum = GetSuccessorNumber(PREPred, CurrentBlock);
|
||||
if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) {
|
||||
toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum));
|
||||
return false;
|
||||
}
|
||||
if (NumWithout != 0) {
|
||||
// Don't do PRE across indirect branch.
|
||||
if (isa<IndirectBrInst>(PREPred->getTerminator()))
|
||||
return false;
|
||||
|
||||
// Instantiate the expression in the predecessor that lacked it.
|
||||
// Because we are going top-down through the block, all value numbers
|
||||
// will be available in the predecessor by the time we need them. Any
|
||||
// that weren't originally present will have been instantiated earlier
|
||||
// in this loop.
|
||||
Instruction *PREInstr = CurInst->clone();
|
||||
bool success = true;
|
||||
for (unsigned i = 0, e = CurInst->getNumOperands(); i != e; ++i) {
|
||||
Value *Op = PREInstr->getOperand(i);
|
||||
if (isa<Argument>(Op) || isa<Constant>(Op) || isa<GlobalValue>(Op))
|
||||
continue;
|
||||
|
||||
if (Value *V = findLeader(PREPred, VN.lookup(Op))) {
|
||||
PREInstr->setOperand(i, V);
|
||||
} else {
|
||||
success = false;
|
||||
break;
|
||||
// We can't do PRE safely on a critical edge, so instead we schedule
|
||||
// the edge to be split and perform the PRE the next time we iterate
|
||||
// on the function.
|
||||
unsigned SuccNum = GetSuccessorNumber(PREPred, CurrentBlock);
|
||||
if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) {
|
||||
toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum));
|
||||
return false;
|
||||
}
|
||||
// We need to insert somewhere, so let's give it a shot
|
||||
PREInstr = CurInst->clone();
|
||||
if (!performScalarPREInsertion(PREInstr, PREPred, ValNo)) {
|
||||
// If we failed insertion, make sure we remove the instruction.
|
||||
DEBUG(verifyRemoved(PREInstr));
|
||||
delete PREInstr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fail out if we encounter an operand that is not available in
|
||||
// the PRE predecessor. This is typically because of loads which
|
||||
// are not value numbered precisely.
|
||||
if (!success) {
|
||||
DEBUG(verifyRemoved(PREInstr));
|
||||
delete PREInstr;
|
||||
return false;
|
||||
}
|
||||
// Either we should have filled in the PRE instruction, or we should
|
||||
// not have needed insertions.
|
||||
assert (PREInstr != nullptr || NumWithout == 0);
|
||||
|
||||
PREInstr->insertBefore(PREPred->getTerminator());
|
||||
PREInstr->setName(CurInst->getName() + ".pre");
|
||||
PREInstr->setDebugLoc(CurInst->getDebugLoc());
|
||||
VN.add(PREInstr, ValNo);
|
||||
++NumGVNPRE;
|
||||
|
||||
// Update the availability map to include the new instruction.
|
||||
addToLeaderTable(ValNo, PREInstr, PREPred);
|
||||
|
||||
// Create a PHI to make the value available in this block.
|
||||
PHINode *Phi =
|
||||
PHINode::Create(CurInst->getType(), predMap.size(),
|
||||
|
@ -2609,6 +2631,8 @@ bool GVN::performScalarPRE(Instruction *CurInst) {
|
|||
MD->removeInstruction(CurInst);
|
||||
DEBUG(verifyRemoved(CurInst));
|
||||
CurInst->eraseFromParent();
|
||||
++NumGVNInstr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
; RUN: opt < %s -gvn -S | FileCheck %s
|
||||
; This testcase tests insertion of no-cost phis. That is,
|
||||
; when the value is already available in every predecessor,
|
||||
; and we just need to insert a phi node to merge the available values.
|
||||
|
||||
@c = global i32 0, align 4
|
||||
@d = global i32 0, align 4
|
||||
|
||||
|
||||
define i32 @mai(i32 %foo, i32 %a, i32 %b) {
|
||||
%1 = icmp ne i32 %foo, 0
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
|
||||
bb1:
|
||||
%2 = add nsw i32 %a, %b
|
||||
store i32 %2, i32* @c, align 4
|
||||
br label %mergeblock
|
||||
|
||||
bb2:
|
||||
%3 = add nsw i32 %a, %b
|
||||
store i32 %3, i32* @d, align 4
|
||||
br label %mergeblock
|
||||
|
||||
mergeblock:
|
||||
; CHECK: pre-phi = phi i32 [ %3, %bb2 ], [ %2, %bb1 ]
|
||||
; CHECK-NEXT: ret i32 %.pre-phi
|
||||
%4 = add nsw i32 %a, %b
|
||||
ret i32 %4
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue