diff options
author | Chris Lattner <sabre@nondot.org> | 2003-09-11 16:45:55 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2003-09-11 16:45:55 +0000 |
commit | 38aec325604635380421a27e39ab06d55ed2458d (patch) | |
tree | 207cb17b79d4fd46084656a4319a6ee0841d58e8 /lib/Transforms | |
parent | 473205250de3289cda13b18e31c3f2fceb6e2e6a (diff) |
Integrate functionality of the mem2reg pass directly into this pass to make
the combination more effective
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8471 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/ScalarReplAggregates.cpp | 69 |
1 files changed, 62 insertions, 7 deletions
diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 864f8764aa..d2a098c428 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -3,29 +3,43 @@ // This transformation implements the well known scalar replacement of // aggregates transformation. This xform breaks up alloca instructions of // aggregate type (structure or array) into individual alloca instructions for -// each member (if possible). +// each member (if possible). Then, if possible, it transforms the individual +// alloca instructions into nice clean scalar SSA form. +// +// This combines a simple SRoA algorithm with the Mem2Reg algorithm because +// often interact, especially for C++ programs. As such, iterating between +// SRoA, then Mem2Reg until we run out of things to promote works well. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" #include "llvm/Function.h" #include "llvm/Pass.h" #include "llvm/iMemory.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Constants.h" +#include "llvm/Analysis/Dominators.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/Utils/PromoteMemToReg.h" #include "Support/Debug.h" #include "Support/Statistic.h" #include "Support/StringExtras.h" namespace { Statistic<> NumReplaced("scalarrepl", "Number of alloca's broken up"); + Statistic<> NumPromoted("scalarrepl", "Number of alloca's promoted"); struct SROA : public FunctionPass { bool runOnFunction(Function &F); + bool performScalarRepl(Function &F); + bool performPromotion(Function &F); + // getAnalysisUsage - This pass does not require any passes, but we know it // will not alter the CFG, so say so. virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<DominanceFrontier>(); + AU.addRequired<TargetData>(); AU.setPreservesCFG(); } @@ -43,11 +57,52 @@ namespace { Pass *createScalarReplAggregatesPass() { return new SROA(); } -// runOnFunction - This algorithm is a simple worklist driven algorithm, which -// runs on all of the malloc/alloca instructions in the function, removing them -// if they are only used by getelementptr instructions. -// bool SROA::runOnFunction(Function &F) { + bool Changed = false, LocalChange; + do { + LocalChange = performScalarRepl(F); + LocalChange |= performPromotion(F); + Changed |= LocalChange; + } while (LocalChange); + + return Changed; +} + + +bool SROA::performPromotion(Function &F) { + std::vector<AllocaInst*> Allocas; + const TargetData &TD = getAnalysis<TargetData>(); + + BasicBlock &BB = F.getEntryNode(); // Get the entry node for the function + + bool Changed = false; + + while (1) { + Allocas.clear(); + + // Find allocas that are safe to promote, by looking at all instructions in + // the entry node + for (BasicBlock::iterator I = BB.begin(), E = --BB.end(); I != E; ++I) + if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) // Is it an alloca? + if (isAllocaPromotable(AI, TD)) + Allocas.push_back(AI); + + if (Allocas.empty()) break; + + PromoteMemToReg(Allocas, getAnalysis<DominanceFrontier>(), TD); + NumPromoted += Allocas.size(); + Changed = true; + } + + return Changed; +} + + +// performScalarRepl - This algorithm is a simple worklist driven algorithm, +// which runs on all of the malloc/alloca instructions in the function, removing +// them if they are only used by getelementptr instructions. +// +bool SROA::performScalarRepl(Function &F) { std::vector<AllocationInst*> WorkList; // Scan the entry basic block, adding any alloca's and mallocs to the worklist |