Add a new pass for doing late hoisting of floating-point and vector
authorDan Gohman <gohman@apple.com>
Wed, 16 Sep 2009 20:25:11 +0000 (20:25 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 16 Sep 2009 20:25:11 +0000 (20:25 +0000)
constants out of loops. These aren't covered by the regular LICM
pass, because in LLVM IR constants don't require separate
instructions. They're not always covered by the MachineLICM pass
either, because it doesn't know how to unfold folded constant-pool
loads. This is somewhat experimental at this point, and off by
default.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82076 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/LinkAllPasses.h
include/llvm/Transforms/Scalar.h
lib/CodeGen/LLVMTargetMachine.cpp
lib/Transforms/Scalar/CodeGenLICM.cpp [new file with mode: 0644]

index 208010602473dd886a9d4fc0e4a4c4f9454b6891..f5017116de082c1ec285ce72168bc6a658a4e223 100644 (file)
@@ -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();
index f193b8d9dd55c8a35381910127317f8b3f4687bd..093da644faebaf3160684e85e0cb803357d0d37d 100644 (file)
@@ -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();
   
 //===----------------------------------------------------------------------===//
 //
index 5b6cfdc989f0f133ae660f53800f31a756273429..94c6fa6b833333adaa5d85ade5294714c1b42b3b 100644 (file)
@@ -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 (file)
index 0000000..ef9f81e
--- /dev/null
@@ -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);
+}