From: Daniel Berlin Date: Tue, 3 Feb 2015 20:37:08 +0000 (+0000) Subject: Allow PRE to insert no-cost phi nodes X-Git-Tag: llvmorg-3.7.0-rc1~13203 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=487aed0d774132d1baf44ffbd7869755dfa8a9a7;p=platform%2Fupstream%2Fllvm.git Allow PRE to insert no-cost phi nodes llvm-svn: 228024 --- diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 7519b59..08c07cb 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -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(Op) || isa(Op) || isa(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, 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) - return false; - - // Don't do PRE across indirect branch. - if (isa(PREPred->getTerminator())) + if (NumWithout > 1 || NumWith == 0) return false; - // 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 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; - // 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(Op) || isa(Op) || isa(Op)) - continue; + if (NumWithout != 0) { + // Don't do PRE across indirect branch. + if (isa(PREPred->getTerminator())) + return false; - 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; } diff --git a/llvm/test/Transforms/GVN/pre-no-cost-phi.ll b/llvm/test/Transforms/GVN/pre-no-cost-phi.ll new file mode 100644 index 0000000..4c5afa1 --- /dev/null +++ b/llvm/test/Transforms/GVN/pre-no-cost-phi.ll @@ -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 +} + +