#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; 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;
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();
if (NumOps <= 2)
continue;
bool FirstIndexIsZero = isa<ConstantInt>(GEP->getOperand(1)) &&
cast<ConstantInt>(GEP->getOperand(1))->isZero();
if (NumOps == 3 && FirstIndexIsZero)
continue;
Value *NewGEP = FirstIndexIsZero ?
GEP->getOperand(0) :
GetElementPtrInst::Create(GEP->getOperand(0), GEP->getOperand(1),
"tmp", GEP);
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();
}