diff options
-rw-r--r-- | include/llvm/LinkAllPasses.h | 1 | ||||
-rw-r--r-- | include/llvm/Transforms/Scalar.h | 5 | ||||
-rw-r--r-- | lib/CodeGen/LLVMTargetMachine.cpp | 7 | ||||
-rw-r--r-- | lib/Transforms/Scalar/CodeGenLICM.cpp | 117 |
4 files changed, 129 insertions, 1 deletions
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 2080106024..f5017116de 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -120,6 +120,7 @@ namespace { (void) llvm::createIndMemRemPass(); (void) llvm::createInstCountPass(); (void) llvm::createPredicateSimplifierPass(); + (void) llvm::createCodeGenLICMPass(); (void) llvm::createCodeGenPreparePass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index f193b8d9dd..093da644fa 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -329,6 +329,11 @@ FunctionPass *createSimplifyHalfPowrLibCallsPass(); // FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); +//===----------------------------------------------------------------------===// +// +// CodeGenLICM - This pass performs late LICM; hoisting constants out of loops. +// +Pass *createCodeGenLICMPass(); //===----------------------------------------------------------------------===// // diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 5b6cfdc989..94c6fa6b83 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -39,6 +39,8 @@ static cl::opt<bool> PrintEmittedAsm("print-emitted-asm", cl::Hidden, cl::desc("Dump emitter generated instructions as assembly")); static cl::opt<bool> PrintGCInfo("print-gc", cl::Hidden, cl::desc("Dump garbage collector data")); +static cl::opt<bool> HoistConstants("hoist-constants", cl::Hidden, + cl::desc("Hoist constants out of loops")); static cl::opt<bool> VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); @@ -259,8 +261,11 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // Make sure that no unreachable blocks are instruction selected. PM.add(createUnreachableBlockEliminationPass()); - if (OptLevel != CodeGenOpt::None) + if (OptLevel != CodeGenOpt::None) { + if (HoistConstants) + PM.add(createCodeGenLICMPass()); PM.add(createCodeGenPreparePass(getTargetLowering())); + } PM.add(createStackProtectorPass(getTargetLowering())); diff --git a/lib/Transforms/Scalar/CodeGenLICM.cpp b/lib/Transforms/Scalar/CodeGenLICM.cpp new file mode 100644 index 0000000000..ef9f81e266 --- /dev/null +++ b/lib/Transforms/Scalar/CodeGenLICM.cpp @@ -0,0 +1,117 @@ +//===- CodeGenLICM.cpp - LICM a function for code generation --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This function performs late LICM, hoisting constants out of loops that +// are not valid immediates. It should not be followed by instcombine, +// because instcombine would quickly stuff the constants back into the loop. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "codegen-licm" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/LLVMContext.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/IVUsers.h" +#include "llvm/ADT/DenseMap.h" +using namespace llvm; + +namespace { + class CodeGenLICM : public LoopPass { + virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + public: + static char ID; // Pass identification, replacement for typeid + explicit CodeGenLICM() : LoopPass(&ID) {} + }; +} + +char CodeGenLICM::ID = 0; +static RegisterPass<CodeGenLICM> X("codegen-licm", + "hoist constants out of loops"); + +Pass *llvm::createCodeGenLICMPass() { + return new CodeGenLICM(); +} + +bool CodeGenLICM::runOnLoop(Loop *L, LPPassManager &) { + bool Changed = false; + + // Only visit outermost loops. + if (L->getParentLoop()) return Changed; + + Instruction *PreheaderTerm = L->getLoopPreheader()->getTerminator(); + DenseMap<Constant *, BitCastInst *> HoistedConstants; + + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + for (BasicBlock::iterator BBI = BB->begin(), BBE = BB->end(); + BBI != BBE; ++BBI) { + Instruction *I = BBI; + // Don't bother hoisting constants out of loop-header phi nodes. + if (BB == L->getHeader() && isa<PHINode>(I)) + continue; + // TODO: For now, skip all intrinsic instructions, because some of them + // can require their operands to be constants, and we don't want to + // break that. + if (isa<IntrinsicInst>(I)) + continue; + // LLVM represents fneg as -0.0-x; don't hoist the -0.0 out. + if (BinaryOperator::isFNeg(I) || + BinaryOperator::isNeg(I) || + BinaryOperator::isNot(I)) + continue; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + // Don't hoist out switch case constants. + if (isa<SwitchInst>(I) && i == 1) + break; + // Don't hoist out shuffle masks. + if (isa<ShuffleVectorInst>(I) && i == 2) + break; + Value *Op = I->getOperand(i); + Constant *C = dyn_cast<Constant>(Op); + if (!C) continue; + // TODO: Ask the target which constants are legal. This would allow + // us to add support for hoisting ConstantInts and GlobalValues too. + if (isa<ConstantFP>(C) || + isa<ConstantVector>(C) || + isa<ConstantAggregateZero>(C)) { + BitCastInst *&BC = HoistedConstants[C]; + if (!BC) + BC = new BitCastInst(C, C->getType(), "hoist", PreheaderTerm); + I->setOperand(i, BC); + Changed = true; + } + } + } + } + + return Changed; +} + +void CodeGenLICM::getAnalysisUsage(AnalysisUsage &AU) const { + // This pass preserves just about everything. List some popular things here. + AU.setPreservesCFG(); + AU.addPreservedID(LoopSimplifyID); + AU.addPreserved<LoopInfo>(); + AU.addPreserved<AliasAnalysis>(); + AU.addPreserved<DominanceFrontier>(); + AU.addPreserved<DominatorTree>(); + AU.addPreserved<ScalarEvolution>(); + AU.addPreserved<IVUsers>(); + + // Hoisting requires a loop preheader. + AU.addRequiredID(LoopSimplifyID); +} |