diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMGlobalMerge.cpp | 219 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/ARMTargetMachine.cpp | 3 | 
2 files changed, 2 insertions, 220 deletions
| diff --git a/llvm/lib/Target/ARM/ARMGlobalMerge.cpp b/llvm/lib/Target/ARM/ARMGlobalMerge.cpp deleted file mode 100644 index 5f863ea241c..00000000000 --- a/llvm/lib/Target/ARM/ARMGlobalMerge.cpp +++ /dev/null @@ -1,219 +0,0 @@ -//===-- ARMGlobalMerge.cpp - Internal globals merging  --------------------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This pass merges globals with internal linkage into one. This way all the -// globals which were merged into a biggest one can be addressed using offsets -// from the same base pointer (no need for separate base pointer for each of the -// global). Such a transformation can significantly reduce the register pressure -// when many globals are involved. -// -// For example, consider the code which touches several global variables at  -// once: -// -// static int foo[N], bar[N], baz[N]; -// -// for (i = 0; i < N; ++i) { -//    foo[i] = bar[i] * baz[i]; -// } -// -//  On ARM the addresses of 3 arrays should be kept in the registers, thus -//  this code has quite large register pressure (loop body): -// -//  ldr     r1, [r5], #4 -//  ldr     r2, [r6], #4 -//  mul     r1, r2, r1 -//  str     r1, [r0], #4 -// -//  Pass converts the code to something like: -// -//  static struct { -//    int foo[N]; -//    int bar[N]; -//    int baz[N]; -//  } merged; -// -//  for (i = 0; i < N; ++i) { -//    merged.foo[i] = merged.bar[i] * merged.baz[i]; -//  } -// -//  and in ARM code this becomes: -// -//  ldr     r0, [r5, #40] -//  ldr     r1, [r5, #80] -//  mul     r0, r1, r0 -//  str     r0, [r5], #4 -// -//  note that we saved 2 registers here almostly "for free". -// ===---------------------------------------------------------------------===// - -#define DEBUG_TYPE "arm-global-merge" -#include "ARM.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Attributes.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/GlobalVariable.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -using namespace llvm; - -namespace { -  class ARMGlobalMerge : public FunctionPass { -    /// TLI - Keep a pointer of a TargetLowering to consult for determining -    /// target type sizes. -    const TargetLowering *TLI; - -    bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, -                 Module &M, bool isConst) const; - -  public: -    static char ID;             // Pass identification, replacement for typeid. -    explicit ARMGlobalMerge(const TargetLowering *tli) -      : FunctionPass(ID), TLI(tli) {} - -    virtual bool doInitialization(Module &M); -    virtual bool runOnFunction(Function &F); - -    const char *getPassName() const { -      return "Merge internal globals"; -    } - -    virtual void getAnalysisUsage(AnalysisUsage &AU) const { -      AU.setPreservesCFG(); -      FunctionPass::getAnalysisUsage(AU); -    } - -    struct GlobalCmp { -      const TargetData *TD; - -      GlobalCmp(const TargetData *td) : TD(td) { } - -      bool operator()(const GlobalVariable *GV1, const GlobalVariable *GV2) { -        Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); -        Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); - -        return (TD->getTypeAllocSize(Ty1) < TD->getTypeAllocSize(Ty2)); -      } -    }; -  }; -} // end anonymous namespace - -char ARMGlobalMerge::ID = 0; - -bool ARMGlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, -                             Module &M, bool isConst) const { -  const TargetData *TD = TLI->getTargetData(); - -  // FIXME: Infer the maximum possible offset depending on the actual users -  // (these max offsets are different for the users inside Thumb or ARM -  // functions) -  unsigned MaxOffset = TLI->getMaximalGlobalOffset(); - -  // FIXME: Find better heuristics -  std::stable_sort(Globals.begin(), Globals.end(), GlobalCmp(TD)); - -  Type *Int32Ty = Type::getInt32Ty(M.getContext()); - -  for (size_t i = 0, e = Globals.size(); i != e; ) { -    size_t j = 0; -    uint64_t MergedSize = 0; -    std::vector<Type*> Tys; -    std::vector<Constant*> Inits; -    for (j = i; j != e; ++j) { -      Type *Ty = Globals[j]->getType()->getElementType(); -      MergedSize += TD->getTypeAllocSize(Ty); -      if (MergedSize > MaxOffset) { -        break; -      } -      Tys.push_back(Ty); -      Inits.push_back(Globals[j]->getInitializer()); -    } - -    StructType *MergedTy = StructType::get(M.getContext(), Tys); -    Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); -    GlobalVariable *MergedGV = new GlobalVariable(M, MergedTy, isConst, -                                                  GlobalValue::InternalLinkage, -                                                  MergedInit, "_MergedGlobals"); -    for (size_t k = i; k < j; ++k) { -      Constant *Idx[2] = { -        ConstantInt::get(Int32Ty, 0), -        ConstantInt::get(Int32Ty, k-i) -      }; -      Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); -      Globals[k]->replaceAllUsesWith(GEP); -      Globals[k]->eraseFromParent(); -    } -    i = j; -  } - -  return true; -} - - -bool ARMGlobalMerge::doInitialization(Module &M) { -  SmallVector<GlobalVariable*, 16> Globals, ConstGlobals, BSSGlobals; -  const TargetData *TD = TLI->getTargetData(); -  unsigned MaxOffset = TLI->getMaximalGlobalOffset(); -  bool Changed = false; - -  // Grab all non-const globals. -  for (Module::global_iterator I = M.global_begin(), -         E = M.global_end(); I != E; ++I) { -    // Merge is safe for "normal" internal globals only -    if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) -      continue; - -    // Ignore fancy-aligned globals for now. -    unsigned Alignment = I->getAlignment(); -    Type *Ty = I->getType()->getElementType(); -    if (Alignment > TD->getABITypeAlignment(Ty)) -      continue; - -    // Ignore all 'special' globals. -    if (I->getName().startswith("llvm.") || -        I->getName().startswith(".llvm.")) -      continue; - -    if (TD->getTypeAllocSize(Ty) < MaxOffset) { -      const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); -      if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) -        BSSGlobals.push_back(I); -      else if (I->isConstant()) -        ConstGlobals.push_back(I); -      else -        Globals.push_back(I); -    } -  } - -  if (Globals.size() > 1) -    Changed |= doMerge(Globals, M, false); -  if (BSSGlobals.size() > 1) -    Changed |= doMerge(BSSGlobals, M, false); - -  // FIXME: This currently breaks the EH processing due to way how the  -  // typeinfo detection works. We might want to detect the TIs and ignore  -  // them in the future. -  // if (ConstGlobals.size() > 1) -  //  Changed |= doMerge(ConstGlobals, M, true); - -  return Changed; -} - -bool ARMGlobalMerge::runOnFunction(Function &F) { -  return false; -} - -FunctionPass *llvm::createARMGlobalMergePass(const TargetLowering *tli) { -  return new ARMGlobalMerge(tli); -} diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp index 96b1e89b0df..cf1432d64f2 100644 --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -20,6 +20,7 @@  #include "llvm/Support/FormattedStream.h"  #include "llvm/Support/TargetRegistry.h"  #include "llvm/Target/TargetOptions.h" +#include "llvm/Transforms/Scalar.h"  using namespace llvm;  static cl::opt<bool> @@ -97,7 +98,7 @@ ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,  bool ARMBaseTargetMachine::addPreISel(PassManagerBase &PM,                                        CodeGenOpt::Level OptLevel) {    if (OptLevel != CodeGenOpt::None && EnableGlobalMerge) -    PM.add(createARMGlobalMergePass(getTargetLowering())); +    PM.add(createGlobalMergePass(getTargetLowering()));    return false;  } | 

