summaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar/CodeGenLICM.cpp
blob: 10f950e135dade7ce2905d145f4aa8f9875ee7f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//===- 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/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;
      // 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("scalar-evolution");
  AU.addPreserved("iv-users");
  AU.addPreserved("lda");
  AU.addPreserved("live-values");

  // Hoisting requires a loop preheader.
  AU.addRequiredID(LoopSimplifyID);
}
OpenPOWER on IntegriCloud