//===- GEPSplitter.cpp - Split complex GEPs into simple ones --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This function breaks GEPs with more than 2 non-zero operands into smaller
// GEPs each with no more than 2 non-zero operands. This exposes redundancy
// between GEPs with common initial operand sequences.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "split-geps"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Constants.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
using namespace llvm;

namespace {
  class GEPSplitter : public FunctionPass {
    virtual bool runOnFunction(Function &F);
    virtual void getAnalysisUsage(AnalysisUsage &AU) const;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit GEPSplitter() : FunctionPass(&ID) {}
  };
}

char GEPSplitter::ID = 0;
static RegisterPass<GEPSplitter> X("split-geps",
                                   "split complex GEPs into simple GEPs");

FunctionPass *llvm::createGEPSplitterPass() {
  return new GEPSplitter();
}

bool GEPSplitter::runOnFunction(Function &F) {
  bool Changed = false;

  // Visit each GEP instruction.
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
    for (BasicBlock::iterator II = I->begin(), IE = I->end(); II != IE; )
      if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(II++)) {
        unsigned NumOps = GEP->getNumOperands();
        // Ignore GEPs which are already simple.
        if (NumOps <= 2)
          continue;
        bool FirstIndexIsZero = isa<ConstantInt>(GEP->getOperand(1)) &&
                                cast<ConstantInt>(GEP->getOperand(1))->isZero();
        if (NumOps == 3 && FirstIndexIsZero)
          continue;
        // The first index is special and gets expanded with a 2-operand GEP
        // (unless it's zero, in which case we can skip this).
        Value *NewGEP = FirstIndexIsZero ?
          GEP->getOperand(0) :
          GetElementPtrInst::Create(GEP->getOperand(0), GEP->getOperand(1),
                                    "tmp", GEP);
        // All remaining indices get expanded with a 3-operand GEP with zero
        // as the second operand.
        Value *Idxs[2];
        Idxs[0] = ConstantInt::get(Type::getInt64Ty(F.getContext()), 0);
        for (unsigned i = 2; i != NumOps; ++i) {
          Idxs[1] = GEP->getOperand(i);
          NewGEP = GetElementPtrInst::Create(NewGEP, Idxs, Idxs+2, "tmp", GEP);
        }
        GEP->replaceAllUsesWith(NewGEP);
        GEP->eraseFromParent();
        Changed = true;
      }

  return Changed;
}

void GEPSplitter::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesCFG();
}
