From 8a2a3119395915cf57c771c2d555e1018628751c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 14 Dec 2001 16:52:21 +0000 Subject: [PATCH] initial checkin git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1480 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 lib/Transforms/Scalar/InstructionCombining.cpp diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp new file mode 100644 index 00000000000..87f8ed1897f --- /dev/null +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -0,0 +1,150 @@ +//===- 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 "../TransformInternals.h" +#include "llvm/Optimizations/ConstantHandling.h" +#include "llvm/Method.h" +#include "llvm/iMemory.h" + +using namespace opt; + +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(I->getOperand(0)) && !isa(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(I->getOperand(1))) { + if (I->getOpcode() == Instruction::Add) { + if (Instruction *IOp1 = dyn_cast(Op1)) { + if (IOp1->getOpcode() == Instruction::Add && + isa(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(IOp1->getOperand(1)); + + if (Val) { + I->setOperand(0, IOp1->getOperand(0)); + I->setOperand(1, Val); + LocalChange = true; + } + } + + } + } + } + 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(MAI->getPointerOperand()); + if (!Src) return 0; + + vector 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; +} + +bool InstructionCombining::CombineInstruction(Instruction *I) { + Instruction *Result = 0; + if (BinaryOperator *BOP = dyn_cast(I)) + Result = CombineBinOp(BOP); + else if (MemAccessInst *MAI = dyn_cast(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; +} + + +bool InstructionCombining::doit(Method *M) { + // Start the worklist out with all of the instructions in the method in it. + vector WorkList(M->inst_begin(), M->inst_end()); + + 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(*UI)) + WorkList.push_back(User); + } + } + + return false; +}