mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
6000e253d4
GEPs (more than one non-zero index) into simple GEPs (at most one non-zero index). In some simple experiments using this it's not uncommon to see 3% overall code size wins, because it exposes redundancies that can be eliminated, however it's tricky to use because instcombine aggressively undoes the work that this pass does. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85144 91177308-0d34-0410-b5e6-96231b3b80d8
82 lines
2.9 KiB
C++
82 lines
2.9 KiB
C++
//===- 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();
|
|
}
|