aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-11-02 05:57:39 +0000
committerChris Lattner <sabre@nondot.org>2003-11-02 05:57:39 +0000
commitbc61e661bd55343dac22c08c6c7be8855adc44c9 (patch)
tree64c88c1fd0d05748e29add98f972660917863ed8
parentfc424c39de129ec928a985ec1507067f1a1881b9 (diff)
Implement transmogriphication of allocation instructions
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9654 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp35
1 files changed, 33 insertions, 2 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index bc1a81967f..d5da0b3b54 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -34,14 +34,15 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Scalar.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Constants.h"
#include "llvm/ConstantHandling.h"
#include "llvm/DerivedTypes.h"
#include "llvm/GlobalVariable.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Support/InstIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/CallSite.h"
@@ -57,6 +58,7 @@ namespace {
public InstVisitor<InstCombiner, Instruction*> {
// Worklist of all of the instructions that need to be simplified.
std::vector<Instruction*> WorkList;
+ TargetData *TD;
void AddUsesToWorkList(Instruction &I) {
// The instruction was simplified, add all users of the instruction to
@@ -73,6 +75,7 @@ namespace {
virtual bool runOnFunction(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<TargetData>();
AU.setPreservesCFG();
}
@@ -1536,6 +1539,33 @@ Instruction *InstCombiner::visitCastInst(CastInst &CI) {
}
}
+ // If we are casting a malloc or alloca to a pointer to a type of the same
+ // size, rewrite the allocation instruction to allocate the "right" type.
+ //
+ if (AllocationInst *AI = dyn_cast<AllocationInst>(Src))
+ if (AI->hasOneUse())
+ if (const PointerType *PTy = dyn_cast<PointerType>(CI.getType())) {
+ // Get the type really allocated and the type casted to...
+ const Type *AllocElTy = AI->getAllocatedType();
+ unsigned AllocElTySize = TD->getTypeSize(AllocElTy);
+ const Type *CastElTy = PTy->getElementType();
+ unsigned CastElTySize = TD->getTypeSize(CastElTy);
+
+ // If the allocation is for an even multiple of the cast type size
+ if (AllocElTySize % CastElTySize == 0) {
+ Value *Amt = ConstantUInt::get(Type::UIntTy,
+ AllocElTySize/CastElTySize);
+ std::string Name = AI->getName(); AI->setName("");
+ AllocationInst *New;
+ if (isa<MallocInst>(AI))
+ New = new MallocInst(CastElTy, Amt, Name);
+ else
+ New = new AllocaInst(CastElTy, Amt, Name);
+ InsertNewInstBefore(New, CI);
+ return ReplaceInstUsesWith(CI, New);
+ }
+ }
+
// If the source value is an instruction with only this use, we can attempt to
// propagate the cast into the instruction. Also, only handle integral types
// for now.
@@ -1975,6 +2005,7 @@ void InstCombiner::removeFromWorkList(Instruction *I) {
bool InstCombiner::runOnFunction(Function &F) {
bool Changed = false;
+ TD = &getAnalysis<TargetData>();
WorkList.insert(WorkList.end(), inst_begin(F), inst_end(F));