blob: 77042eaedddc2b58083c205f0e43bfb1e79b763b [file] [log] [blame]
//===-- MergeGEP.cpp - Merge GEPs for indexing in arrays ------------ ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mergegep"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/Constants.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Debug.h"
#include <vector>
using namespace llvm;
namespace {
class MergeGEP : public ModulePass {
public:
static char ID;
MergeGEP() : ModulePass(&ID) {}
bool runOnModule(Module& M) {
bool changed = false;
bool found;
do {
found = false;
for (Module::iterator F = M.begin(); F != M.end(); ++F){
for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {
if(!(isa<GetElementPtrInst>(I)))
continue;
GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
if(!isa<ArrayType>(GEP->getType()->getElementType()))
continue;
std::vector<GetElementPtrInst*> worklist;
for (Value::use_iterator UI = GEP->use_begin(),
UE = GEP->use_end(); UI != UE; ++UI){
if(!isa<GetElementPtrInst>(UI))
break;
GetElementPtrInst *GEPUse = cast<GetElementPtrInst>(UI);
worklist.push_back(GEPUse);
}
while(!worklist.empty()){
GetElementPtrInst *GEPUse = worklist.back();
worklist.pop_back();
SmallVector<Value*, 8> Indices;
Indices.append(GEP->op_begin()+1, GEP->op_end());
Indices.append(GEPUse->idx_begin()+1, GEPUse->idx_end());
GetElementPtrInst *GEPNew = GetElementPtrInst::Create(GEP->getOperand(0),
Indices.begin(),
Indices.end(),
GEPUse->getName()+ "moda",
GEPUse);
GEPUse->replaceAllUsesWith(GEPNew);
GEPUse->eraseFromParent();
found = true;
changed = true;
}
}
}
std::vector<GetElementPtrInst*> worklist;
for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {
if(!(isa<GetElementPtrInst>(I)))
continue;
GetElementPtrInst *GEP1 = cast<GetElementPtrInst>(I);
if(!isa<ArrayType>(GEP1->getType()->getElementType()))
continue;
if (Constant *C = dyn_cast<Constant>(GEP1->getOperand(0))) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
worklist.push_back(GEP1);
}
}
}
}
}
while(!worklist.empty()) {
GetElementPtrInst *GEP1 = worklist.back();
worklist.pop_back();
Constant *C = cast<Constant>(GEP1->getOperand(0));
ConstantExpr *CE = cast<ConstantExpr>(C);
SmallVector<Value*, 8> Indices;
Indices.append(CE->op_begin()+1, CE->op_end());
Indices.append(GEP1->idx_begin()+1, GEP1->idx_end());
GetElementPtrInst *GEPNew = GetElementPtrInst::Create(CE->getOperand(0),
Indices.begin(),
Indices.end(),
GEP1->getName()+ "modb",
GEP1);
GEP1->replaceAllUsesWith(GEPNew);
GEP1->eraseFromParent();
changed = true;
found = true;
}
}
}while(found);
return changed;
}
};
}
char MergeGEP::ID = 0;
static RegisterPass<MergeGEP>
X("mergegep", "Merge GEPs for arrays in structs");