llvm-6502/lib/Transforms/Scalar/InstructionCombining.cpp
Chris Lattner 2fbfdcffd3 Change references to the Method class to be references to the Function
class.  The Method class is obsolete (renamed) and all references to it
are being converted over to Function.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2144 91177308-0d34-0410-b5e6-96231b3b80d8
2002-04-07 20:49:59 +00:00

182 lines
5.8 KiB
C++

//===- InstructionCombining.cpp - Combine multiple instructions -------------=//
//
// InstructionCombining - Combine instructions to form fewer, simple
// instructions. This pass does not modify the CFG, and has a tendancy to
// make instructions dead, so a subsequent DCE pass is useful.
//
// This pass combines things like:
// %Y = add int 1, %X
// %Z = add int 1, %Y
// into:
// %Z = add int 2, %X
//
// This is a simple worklist driven algorithm.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar/InstructionCombining.h"
#include "llvm/Transforms/Scalar/ConstantHandling.h"
#include "llvm/Function.h"
#include "llvm/iMemory.h"
#include "llvm/InstrTypes.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstIterator.h"
#include "../TransformInternals.h"
static Instruction *CombineBinOp(BinaryOperator *I) {
bool Changed = false;
// First thing we do is make sure that this instruction has a constant on the
// right hand side if it has any constant arguments.
//
if (isa<Constant>(I->getOperand(0)) && !isa<Constant>(I->getOperand(1)))
if (!I->swapOperands())
Changed = true;
bool LocalChange = true;
while (LocalChange) {
LocalChange = false;
Value *Op1 = I->getOperand(0);
if (Constant *Op2 = dyn_cast<Constant>(I->getOperand(1))) {
switch (I->getOpcode()) {
case Instruction::Add:
if (I->getType()->isIntegral() && cast<ConstantInt>(Op2)->equalsInt(0)){
// Eliminate 'add int %X, 0'
I->replaceAllUsesWith(Op1); // FIXME: This breaks the worklist
Changed = true;
return I;
}
if (Instruction *IOp1 = dyn_cast<Instruction>(Op1)) {
if (IOp1->getOpcode() == Instruction::Add &&
isa<Constant>(IOp1->getOperand(1))) {
// Fold:
// %Y = add int %X, 1
// %Z = add int %Y, 1
// into:
// %Z = add int %X, 2
//
// Constant fold both constants...
Constant *Val = *Op2 + *cast<Constant>(IOp1->getOperand(1));
if (Val) {
I->setOperand(0, IOp1->getOperand(0));
I->setOperand(1, Val);
LocalChange = true;
break;
}
}
}
break;
case Instruction::Mul:
if (I->getType()->isIntegral() && cast<ConstantInt>(Op2)->equalsInt(1)){
// Eliminate 'mul int %X, 1'
I->replaceAllUsesWith(Op1); // FIXME: This breaks the worklist
LocalChange = true;
break;
}
default:
break;
}
}
Changed |= LocalChange;
}
if (!Changed) return 0;
return I;
}
// Combine Indices - If the source pointer to this mem access instruction is a
// getelementptr instruction, combine the indices of the GEP into this
// instruction
//
static Instruction *CombineIndicies(MemAccessInst *MAI) {
GetElementPtrInst *Src =
dyn_cast<GetElementPtrInst>(MAI->getPointerOperand());
if (!Src) return 0;
std::vector<Value *> Indices;
// Only special case we have to watch out for is pointer arithmetic on the
// 0th index of MAI.
unsigned FirstIdx = MAI->getFirstIndexOperandNumber();
if (FirstIdx == MAI->getNumOperands() ||
(FirstIdx == MAI->getNumOperands()-1 &&
MAI->getOperand(FirstIdx) == ConstantUInt::get(Type::UIntTy, 0))) {
// Replace the index list on this MAI with the index on the getelementptr
Indices.insert(Indices.end(), Src->idx_begin(), Src->idx_end());
} else if (*MAI->idx_begin() == ConstantUInt::get(Type::UIntTy, 0)) {
// Otherwise we can do the fold if the first index of the GEP is a zero
Indices.insert(Indices.end(), Src->idx_begin(), Src->idx_end());
Indices.insert(Indices.end(), MAI->idx_begin()+1, MAI->idx_end());
}
if (Indices.empty()) return 0; // Can't do the fold?
switch (MAI->getOpcode()) {
case Instruction::GetElementPtr:
return new GetElementPtrInst(Src->getOperand(0), Indices, MAI->getName());
case Instruction::Load:
return new LoadInst(Src->getOperand(0), Indices, MAI->getName());
case Instruction::Store:
return new StoreInst(MAI->getOperand(0), Src->getOperand(0),
Indices, MAI->getName());
default:
assert(0 && "Unknown memaccessinst!");
break;
}
abort();
return 0;
}
static bool CombineInstruction(Instruction *I) {
Instruction *Result = 0;
if (BinaryOperator *BOP = dyn_cast<BinaryOperator>(I))
Result = CombineBinOp(BOP);
else if (MemAccessInst *MAI = dyn_cast<MemAccessInst>(I))
Result = CombineIndicies(MAI);
if (!Result) return false;
if (Result == I) return true;
// If we get to here, we are to replace I with Result.
ReplaceInstWithInst(I, Result);
return true;
}
static bool doInstCombining(Function *M) {
// Start the worklist out with all of the instructions in the function in it.
std::vector<Instruction*> WorkList(inst_begin(M), inst_end(M));
while (!WorkList.empty()) {
Instruction *I = WorkList.back(); // Get an instruction from the worklist
WorkList.pop_back();
// Now that we have an instruction, try combining it to simplify it...
if (CombineInstruction(I)) {
// The instruction was simplified, add all users of the instruction to
// the work lists because they might get more simplified now...
//
for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
UI != UE; ++UI)
if (Instruction *User = dyn_cast<Instruction>(*UI))
WorkList.push_back(User);
}
}
return false;
}
namespace {
struct InstructionCombining : public MethodPass {
virtual bool runOnMethod(Function *F) { return doInstCombining(F); }
};
}
Pass *createInstructionCombiningPass() {
return new InstructionCombining();
}