From: Justin Bogner Date: Fri, 22 Apr 2016 19:54:10 +0000 (+0000) Subject: PM: Port SinkingPass to the new pass manager X-Git-Tag: llvmorg-3.9.0-rc1~8265 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b93949089e8cd8e192c0293811f9cbd801af27b6;p=platform%2Fupstream%2Fllvm.git PM: Port SinkingPass to the new pass manager llvm-svn: 267199 --- diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 0b0d8da..638071f 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -274,7 +274,7 @@ void initializeSimpleInlinerPass(PassRegistry&); void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); -void initializeSinkingPass(PassRegistry&); +void initializeSinkingLegacyPassPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); void initializeSlotIndexesPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Scalar/Sink.h b/llvm/include/llvm/Transforms/Scalar/Sink.h new file mode 100644 index 0000000..1144c62 --- /dev/null +++ b/llvm/include/llvm/Transforms/Scalar/Sink.h @@ -0,0 +1,30 @@ +//===-- Sink.h - Code Sinking -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass moves instructions into successor blocks, when possible, so that +// they aren't executed on paths where their results aren't needed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_SINK_H +#define LLVM_TRANSFORMS_SCALAR_SINK_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Move instructions into successor blocks when possible. +class SinkingPass : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, AnalysisManager &AM); +}; +} + +#endif // LLVM_TRANSFORMS_SCALAR_SINK_H diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index eccc47d..6d6993b 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -58,6 +58,7 @@ #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/SROA.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" +#include "llvm/Transforms/Scalar/Sink.h" #include using namespace llvm; diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 9e20395..8215eac 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -113,6 +113,7 @@ FUNCTION_PASS("print", LoopPrinterPass(dbgs())) FUNCTION_PASS("print", RegionInfoPrinterPass(dbgs())) FUNCTION_PASS("print", ScalarEvolutionPrinterPass(dbgs())) FUNCTION_PASS("simplify-cfg", SimplifyCFGPass()) +FUNCTION_PASS("sink", SinkingPass()) FUNCTION_PASS("sroa", SROA()) FUNCTION_PASS("verify", VerifierPass()) FUNCTION_PASS("verify", DominatorTreeVerifierPass()) diff --git a/llvm/lib/Transforms/Scalar/Scalar.cpp b/llvm/lib/Transforms/Scalar/Scalar.cpp index 84e0f28be..1f18bb4 100644 --- a/llvm/lib/Transforms/Scalar/Scalar.cpp +++ b/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -77,7 +77,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeSROA_SSAUpPass(Registry); initializeCFGSimplifyPassPass(Registry); initializeStructurizeCFGPass(Registry); - initializeSinkingPass(Registry); + initializeSinkingLegacyPassPass(Registry); initializeTailCallElimPass(Registry); initializeSeparateConstOffsetFromGEPPass(Registry); initializeSpeculativeExecutionPass(Registry); diff --git a/llvm/lib/Transforms/Scalar/Sink.cpp b/llvm/lib/Transforms/Scalar/Sink.cpp index e586032..c5f29fa 100644 --- a/llvm/lib/Transforms/Scalar/Sink.cpp +++ b/llvm/lib/Transforms/Scalar/Sink.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/Sink.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/LoopInfo.h" @@ -24,6 +24,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Scalar.h" using namespace llvm; #define DEBUG_TYPE "sink" @@ -31,50 +32,10 @@ using namespace llvm; STATISTIC(NumSunk, "Number of instructions sunk"); STATISTIC(NumSinkIter, "Number of sinking iterations"); -namespace { - class Sinking : public FunctionPass { - DominatorTree *DT; - LoopInfo *LI; - AliasAnalysis *AA; - - public: - static char ID; // Pass identification - Sinking() : FunctionPass(ID) { - initializeSinkingPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - FunctionPass::getAnalysisUsage(AU); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); - AU.addPreserved(); - } - private: - bool ProcessBlock(BasicBlock &BB); - bool SinkInstruction(Instruction *I, SmallPtrSetImpl &Stores); - bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB) const; - bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo) const; - }; -} // end anonymous namespace - -char Sinking::ID = 0; -INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false) - -FunctionPass *llvm::createSinkingPass() { return new Sinking(); } - /// AllUsesDominatedByBlock - Return true if all uses of the specified value /// occur in blocks dominated by the specified block. -bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, - BasicBlock *BB) const { +static bool AllUsesDominatedByBlock(Instruction *Inst, BasicBlock *BB, + DominatorTree &DT) { // Ignoring debug uses is necessary so debug info doesn't affect the code. // This may leave a referencing dbg_value in the original block, before // the definition of the vreg. Dwarf generator handles this although the @@ -90,13 +51,13 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst, UseBlock = PN->getIncomingBlock(Num); } // Check that it dominates. - if (!DT->dominates(BB, UseBlock)) + if (!DT.dominates(BB, UseBlock)) return false; } return true; } -static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, +static bool isSafeToMove(Instruction *Inst, AliasAnalysis &AA, SmallPtrSetImpl &Stores) { if (Inst->mayWriteToMemory()) { @@ -107,7 +68,7 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, if (LoadInst *L = dyn_cast(Inst)) { MemoryLocation Loc = MemoryLocation::get(L); for (Instruction *S : Stores) - if (AA->getModRefInfo(S, Loc) & MRI_Mod) + if (AA.getModRefInfo(S, Loc) & MRI_Mod) return false; } @@ -127,8 +88,8 @@ static bool isSafeToMove(Instruction *Inst, AliasAnalysis *AA, /// IsAcceptableTarget - Return true if it is possible to sink the instruction /// in the specified basic block. -bool Sinking::IsAcceptableTarget(Instruction *Inst, - BasicBlock *SuccToSinkTo) const { +static bool IsAcceptableTarget(Instruction *Inst, BasicBlock *SuccToSinkTo, + DominatorTree &DT, LoopInfo &LI) { assert(Inst && "Instruction to be sunk is null"); assert(SuccToSinkTo && "Candidate sink target is null"); @@ -154,25 +115,26 @@ bool Sinking::IsAcceptableTarget(Instruction *Inst, // We don't want to sink across a critical edge if we don't dominate the // successor. We could be introducing calculations to new code paths. - if (!DT->dominates(Inst->getParent(), SuccToSinkTo)) + if (!DT.dominates(Inst->getParent(), SuccToSinkTo)) return false; // Don't sink instructions into a loop. - Loop *succ = LI->getLoopFor(SuccToSinkTo); - Loop *cur = LI->getLoopFor(Inst->getParent()); + Loop *succ = LI.getLoopFor(SuccToSinkTo); + Loop *cur = LI.getLoopFor(Inst->getParent()); if (succ != nullptr && succ != cur) return false; } // Finally, check that all the uses of the instruction are actually // dominated by the candidate - return AllUsesDominatedByBlock(Inst, SuccToSinkTo); + return AllUsesDominatedByBlock(Inst, SuccToSinkTo, DT); } /// SinkInstruction - Determine whether it is safe to sink the specified machine /// instruction out of its current block into a successor. -bool Sinking::SinkInstruction(Instruction *Inst, - SmallPtrSetImpl &Stores) { +static bool SinkInstruction(Instruction *Inst, + SmallPtrSetImpl &Stores, + DominatorTree &DT, LoopInfo &LI, AAResults &AA) { // Don't sink static alloca instructions. CodeGen assumes allocas outside the // entry block are dynamically sized stack objects. @@ -199,12 +161,12 @@ bool Sinking::SinkInstruction(Instruction *Inst, // Instructions can only be sunk if all their uses are in blocks // dominated by one of the successors. // Look at all the postdominators and see if we can sink it in one. - DomTreeNode *DTN = DT->getNode(Inst->getParent()); + DomTreeNode *DTN = DT.getNode(Inst->getParent()); for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); I != E && SuccToSinkTo == nullptr; ++I) { BasicBlock *Candidate = (*I)->getBlock(); if ((*I)->getIDom()->getBlock() == Inst->getParent() && - IsAcceptableTarget(Inst, Candidate)) + IsAcceptableTarget(Inst, Candidate, DT, LI)) SuccToSinkTo = Candidate; } @@ -212,7 +174,7 @@ bool Sinking::SinkInstruction(Instruction *Inst, // decide which one we should sink to, if any. for (succ_iterator I = succ_begin(Inst->getParent()), E = succ_end(Inst->getParent()); I != E && !SuccToSinkTo; ++I) { - if (IsAcceptableTarget(Inst, *I)) + if (IsAcceptableTarget(Inst, *I, DT, LI)) SuccToSinkTo = *I; } @@ -231,14 +193,15 @@ bool Sinking::SinkInstruction(Instruction *Inst, return true; } -bool Sinking::ProcessBlock(BasicBlock &BB) { +static bool ProcessBlock(BasicBlock &BB, DominatorTree &DT, LoopInfo &LI, + AAResults &AA) { // Can't sink anything out of a block that has less than two successors. if (BB.getTerminator()->getNumSuccessors() <= 1) return false; // Don't bother sinking code out of unreachable blocks. In addition to being // unprofitable, it can also lead to infinite looping, because in an // unreachable loop there may be nowhere to stop. - if (!DT->isReachableFromEntry(&BB)) return false; + if (!DT.isReachableFromEntry(&BB)) return false; bool MadeChange = false; @@ -259,7 +222,7 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { if (isa(Inst)) continue; - if (SinkInstruction(Inst, Stores)) { + if (SinkInstruction(Inst, Stores, DT, LI, AA)) { ++NumSunk; MadeChange = true; } @@ -270,11 +233,8 @@ bool Sinking::ProcessBlock(BasicBlock &BB) { return MadeChange; } -bool Sinking::runOnFunction(Function &F) { - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis().getLoopInfo(); - AA = &getAnalysis().getAAResults(); - +static bool iterativelySinkInstructions(Function &F, DominatorTree &DT, + LoopInfo &LI, AAResults &AA) { bool MadeChange, EverMadeChange = false; do { @@ -283,10 +243,61 @@ bool Sinking::runOnFunction(Function &F) { // Process all basic blocks. for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - MadeChange |= ProcessBlock(*I); + MadeChange |= ProcessBlock(*I, DT, LI, AA); EverMadeChange |= MadeChange; NumSinkIter++; } while (MadeChange); return EverMadeChange; } + +PreservedAnalyses SinkingPass::run(Function &F, AnalysisManager &AM) { + auto &DT = AM.getResult(F); + auto &LI = AM.getResult(F); + auto &AA = AM.getResult(F); + + if (!iterativelySinkInstructions(F, DT, LI, AA)) + return PreservedAnalyses::all(); + + auto PA = PreservedAnalyses(); + PA.preserve(); + PA.preserve(); + return PA; +} + +namespace { + class SinkingLegacyPass : public FunctionPass { + public: + static char ID; // Pass identification + SinkingLegacyPass() : FunctionPass(ID) { + initializeSinkingLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + auto &DT = getAnalysis().getDomTree(); + auto &LI = getAnalysis().getLoopInfo(); + auto &AA = getAnalysis().getAAResults(); + + return iterativelySinkInstructions(F, DT, LI, AA); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + AU.addPreserved(); + } + }; +} // end anonymous namespace + +char SinkingLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(SinkingLegacyPass, "sink", "Code sinking", false, false) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +INITIALIZE_PASS_END(SinkingLegacyPass, "sink", "Code sinking", false, false) + +FunctionPass *llvm::createSinkingPass() { return new SinkingLegacyPass(); } diff --git a/llvm/test/Transforms/Sink/basic.ll b/llvm/test/Transforms/Sink/basic.ll index 1bbf161..8ff4126 100644 --- a/llvm/test/Transforms/Sink/basic.ll +++ b/llvm/test/Transforms/Sink/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -basicaa -sink -S | FileCheck %s +; RUN: opt < %s -aa-pipeline='basic-aa' -passes='sink' -S | FileCheck %s @A = external global i32 @B = external global i32 diff --git a/llvm/test/Transforms/Sink/convergent.ll b/llvm/test/Transforms/Sink/convergent.ll index 49207db..b209e67 100644 --- a/llvm/test/Transforms/Sink/convergent.ll +++ b/llvm/test/Transforms/Sink/convergent.ll @@ -21,4 +21,3 @@ end: } declare i32 @bar() readonly convergent -