mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
Auto-upgrade free instructions to calls to the builtin free function.
Update all analysis passes and transforms to treat free calls just like FreeInst. Remove RaiseAllocations and all its tests since FreeInst no longer needs to be raised. llvm-svn: 84987
This commit is contained in:
parent
0e5c6b3b69
commit
e8998896f5
@ -158,7 +158,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print " <p>\n" if !
|
||||
<tr><td><a href="#memcpyopt">-memcpyopt</a></td><td>Optimize use of memcpy and friends</td></tr>
|
||||
<tr><td><a href="#mergereturn">-mergereturn</a></td><td>Unify function exit nodes</td></tr>
|
||||
<tr><td><a href="#prune-eh">-prune-eh</a></td><td>Remove unused exception handling info</td></tr>
|
||||
<tr><td><a href="#raiseallocs">-raiseallocs</a></td><td>Raise allocations from calls to instructions</td></tr>
|
||||
<tr><td><a href="#reassociate">-reassociate</a></td><td>Reassociate expressions</td></tr>
|
||||
<tr><td><a href="#reg2mem">-reg2mem</a></td><td>Demote all values to stack slots</td></tr>
|
||||
<tr><td><a href="#scalarrepl">-scalarrepl</a></td><td>Scalar Replacement of Aggregates</td></tr>
|
||||
@ -1502,17 +1501,6 @@ if (X < 3) {</pre>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-------------------------------------------------------------------------- -->
|
||||
<div class="doc_subsection">
|
||||
<a name="raiseallocs">Raise allocations from calls to instructions</a>
|
||||
</div>
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Converts <tt>@malloc</tt> and <tt>@free</tt> calls to <tt>malloc</tt> and
|
||||
<tt>free</tt> instructions.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-------------------------------------------------------------------------- -->
|
||||
<div class="doc_subsection">
|
||||
<a name="reassociate">Reassociate expressions</a>
|
||||
|
@ -54,7 +54,7 @@ void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createPruneEHPass function. */
|
||||
void LLVMAddPruneEHPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createRaiseAllocationsPass function. */
|
||||
// FIXME: Remove in LLVM 3.0.
|
||||
void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createStripDeadPrototypesPass function. */
|
||||
|
@ -27,8 +27,8 @@ class Value;
|
||||
// malloc Call Utility Functions.
|
||||
//
|
||||
|
||||
/// isMalloc - Returns true if the the value is either a malloc call or a
|
||||
/// bitcast of the result of a malloc call
|
||||
/// isMalloc - Returns true if the value is either a malloc call or a bitcast of
|
||||
/// the result of a malloc call
|
||||
bool isMalloc(const Value* I);
|
||||
|
||||
/// extractMallocCall - Returns the corresponding CallInst if the instruction
|
||||
@ -80,6 +80,13 @@ const Type* getMallocAllocatedType(const CallInst* CI);
|
||||
Value* getMallocArraySize(CallInst* CI, LLVMContext &Context,
|
||||
const TargetData* TD);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// free Call Utility Functions.
|
||||
//
|
||||
|
||||
/// isFreeCall - Returns true if the the value is a call to the builtin free()
|
||||
bool isFreeCall(const Value* I);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -956,6 +956,9 @@ public:
|
||||
const Type *IntPtrTy, const Type *AllocTy,
|
||||
Value *ArraySize = 0, Function* MallocF = 0,
|
||||
const Twine &Name = "");
|
||||
/// CreateFree - Generate the IR for a call to the builtin free function.
|
||||
static void CreateFree(Value* Source, Instruction *InsertBefore);
|
||||
static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd);
|
||||
|
||||
~CallInst();
|
||||
|
||||
|
@ -107,7 +107,6 @@ namespace {
|
||||
(void) llvm::createPostDomPrinterPass();
|
||||
(void) llvm::createPostDomOnlyViewerPass();
|
||||
(void) llvm::createPostDomViewerPass();
|
||||
(void) llvm::createRaiseAllocationsPass();
|
||||
(void) llvm::createReassociatePass();
|
||||
(void) llvm::createSCCPPass();
|
||||
(void) llvm::createScalarReplAggregatesPass();
|
||||
|
@ -96,8 +96,6 @@ namespace llvm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (UnitAtATime)
|
||||
PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
|
||||
PM->add(createCFGSimplificationPass()); // Clean up disgusting code
|
||||
if (UnitAtATime) {
|
||||
PM->add(createGlobalOptimizerPass()); // Optimize out global vars
|
||||
|
@ -68,13 +68,6 @@ ModulePass *createConstantMergePass();
|
||||
ModulePass *createGlobalOptimizerPass();
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// createRaiseAllocationsPass - Return a new pass that transforms malloc and
|
||||
/// free function calls into malloc and free instructions.
|
||||
///
|
||||
ModulePass *createRaiseAllocationsPass();
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// createDeadTypeEliminationPass - Return a new pass that eliminates symbol
|
||||
/// table entries for types that are never used.
|
||||
|
@ -1017,6 +1017,8 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) {
|
||||
}
|
||||
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(*UI)) {
|
||||
if (AnalyzeUsesOfFunction(GEP)) return true;
|
||||
} else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) {
|
||||
return false;
|
||||
} else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
|
||||
// Make sure that this is just the function being called, not that it is
|
||||
// passing into the function.
|
||||
@ -1038,8 +1040,6 @@ bool Andersens::AnalyzeUsesOfFunction(Value *V) {
|
||||
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
||||
return true; // Allow comparison against null.
|
||||
} else if (isa<FreeInst>(*UI)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
@ -240,6 +240,8 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
} else if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI)) {
|
||||
if (AnalyzeUsesOfPointer(BCI, Readers, Writers, OkayStoreDest))
|
||||
return true;
|
||||
} else if (isa<FreeInst>(*UI) || isFreeCall(*UI)) {
|
||||
Writers.push_back(cast<Instruction>(*UI)->getParent()->getParent());
|
||||
} else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
|
||||
// Make sure that this is just the function being called, not that it is
|
||||
// passing into the function.
|
||||
@ -261,8 +263,6 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
} else if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
|
||||
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
|
||||
return true; // Allow comparison against null.
|
||||
} else if (FreeInst *F = dyn_cast<FreeInst>(*UI)) {
|
||||
Writers.push_back(F->getParent()->getParent());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@ -439,7 +439,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
if (cast<StoreInst>(*II).isVolatile())
|
||||
// Treat volatile stores as reading memory somewhere.
|
||||
FunctionEffect |= Ref;
|
||||
} else if (isMalloc(&cast<Instruction>(*II)) || isa<FreeInst>(*II)) {
|
||||
} else if (isMalloc(&cast<Instruction>(*II)) || isa<FreeInst>(*II) ||
|
||||
isFreeCall(&cast<Instruction>(*II))) {
|
||||
FunctionEffect |= ModRef;
|
||||
}
|
||||
|
||||
|
@ -263,3 +263,29 @@ Value* llvm::getMallocArraySize(CallInst* CI, LLVMContext &Context,
|
||||
assert(BO && "getMallocArraySize not constant but not multiplication either");
|
||||
return BO->getOperand(0);
|
||||
}
|
||||
|
||||
/// isFreeCall - Returns true if the the value is a call to the builtin free()
|
||||
bool llvm::isFreeCall(const Value* I) {
|
||||
const CallInst *CI = dyn_cast<CallInst>(I);
|
||||
if (!CI)
|
||||
return false;
|
||||
|
||||
const Module* M = CI->getParent()->getParent()->getParent();
|
||||
Function *FreeFunc = M->getFunction("free");
|
||||
|
||||
if (CI->getOperand(0) != FreeFunc)
|
||||
return false;
|
||||
|
||||
// Check free prototype.
|
||||
// FIXME: workaround for PR5130, this will be obsolete when a nobuiltin
|
||||
// attribute will exist.
|
||||
const FunctionType *FTy = FreeFunc->getFunctionType();
|
||||
if (FTy->getReturnType() != Type::getVoidTy(M->getContext()))
|
||||
return false;
|
||||
if (FTy->getNumParams() != 1)
|
||||
return false;
|
||||
if (FTy->param_begin()->get() != Type::getInt8PtrTy(M->getContext()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -118,6 +118,10 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
|
||||
|
||||
// FreeInsts erase the entire structure
|
||||
PointerSize = ~0ULL;
|
||||
} else if (isFreeCall(Inst)) {
|
||||
Pointer = Inst->getOperand(0);
|
||||
// calls to free() erase the entire structure
|
||||
PointerSize = ~0ULL;
|
||||
} else if (isa<CallInst>(Inst) || isa<InvokeInst>(Inst)) {
|
||||
// Debug intrinsics don't cause dependences.
|
||||
if (isa<DbgInfoIntrinsic>(Inst)) continue;
|
||||
@ -314,6 +318,10 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
|
||||
MemPtr = LI->getPointerOperand();
|
||||
MemSize = AA->getTypeStoreSize(LI->getType());
|
||||
}
|
||||
} else if (isFreeCall(QueryInst)) {
|
||||
MemPtr = QueryInst->getOperand(0);
|
||||
// calls to free() erase the entire structure, not just a field.
|
||||
MemSize = ~0UL;
|
||||
} else if (isa<CallInst>(QueryInst) || isa<InvokeInst>(QueryInst)) {
|
||||
CallSite QueryCS = CallSite::get(QueryInst);
|
||||
bool isReadOnly = AA->onlyReadsMemory(QueryCS);
|
||||
|
@ -2800,7 +2800,7 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
// Memory.
|
||||
case lltok::kw_alloca: return ParseAlloc(Inst, PFS);
|
||||
case lltok::kw_malloc: return ParseAlloc(Inst, PFS, BB, false);
|
||||
case lltok::kw_free: return ParseFree(Inst, PFS);
|
||||
case lltok::kw_free: return ParseFree(Inst, PFS, BB);
|
||||
case lltok::kw_load: return ParseLoad(Inst, PFS, false);
|
||||
case lltok::kw_store: return ParseStore(Inst, PFS, false);
|
||||
case lltok::kw_volatile:
|
||||
@ -3496,12 +3496,13 @@ bool LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS,
|
||||
|
||||
/// ParseFree
|
||||
/// ::= 'free' TypeAndValue
|
||||
bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS,
|
||||
BasicBlock* BB) {
|
||||
Value *Val; LocTy Loc;
|
||||
if (ParseTypeAndValue(Val, Loc, PFS)) return true;
|
||||
if (!isa<PointerType>(Val->getType()))
|
||||
return Error(Loc, "operand to free must be a pointer");
|
||||
Inst = new FreeInst(Val);
|
||||
Inst = CallInst::CreateFree(Val, BB);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -280,7 +280,7 @@ namespace llvm {
|
||||
bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail);
|
||||
bool ParseAlloc(Instruction *&I, PerFunctionState &PFS,
|
||||
BasicBlock *BB = 0, bool isAlloca = true);
|
||||
bool ParseFree(Instruction *&I, PerFunctionState &PFS);
|
||||
bool ParseFree(Instruction *&I, PerFunctionState &PFS, BasicBlock *BB);
|
||||
bool ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
|
||||
bool ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
|
||||
bool ParseGetResult(Instruction *&I, PerFunctionState &PFS);
|
||||
|
@ -2073,7 +2073,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
|
||||
if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
|
||||
OpNum != Record.size())
|
||||
return Error("Invalid FREE record");
|
||||
I = new FreeInst(Op);
|
||||
if (!CurBB) return Error("Invalid free instruction with no BB");
|
||||
I = CallInst::CreateFree(Op, CurBB);
|
||||
InstructionList.push_back(I);
|
||||
break;
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ add_llvm_library(LLVMipo
|
||||
PartialInlining.cpp
|
||||
PartialSpecialization.cpp
|
||||
PruneEH.cpp
|
||||
RaiseAllocations.cpp
|
||||
StripDeadPrototypes.cpp
|
||||
StripSymbols.cpp
|
||||
StructRetPromotion.cpp
|
||||
|
@ -1364,10 +1364,11 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV,
|
||||
OrigBB->getParent());
|
||||
BasicBlock *NextBlock = BasicBlock::Create(Context, "next",
|
||||
OrigBB->getParent());
|
||||
BranchInst::Create(FreeBlock, NextBlock, Cmp, NullPtrBlock);
|
||||
Instruction *BI = BranchInst::Create(FreeBlock, NextBlock,
|
||||
Cmp, NullPtrBlock);
|
||||
|
||||
// Fill in FreeBlock.
|
||||
new FreeInst(GVVal, FreeBlock);
|
||||
CallInst::CreateFree(GVVal, BI);
|
||||
new StoreInst(Constant::getNullValue(GVVal->getType()), FieldGlobals[i],
|
||||
FreeBlock);
|
||||
BranchInst::Create(NextBlock, FreeBlock);
|
||||
|
@ -63,7 +63,7 @@ void LLVMAddPruneEHPass(LLVMPassManagerRef PM) {
|
||||
}
|
||||
|
||||
void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createRaiseAllocationsPass());
|
||||
// FIXME: Remove in LLVM 3.0.
|
||||
}
|
||||
|
||||
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
|
||||
|
@ -1,173 +0,0 @@
|
||||
//===- RaiseAllocations.cpp - Convert @free calls to insts ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the RaiseAllocations pass which convert free calls to free
|
||||
// instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "raiseallocs"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumRaised, "Number of allocations raised");
|
||||
|
||||
namespace {
|
||||
// RaiseAllocations - Turn @free calls into the appropriate
|
||||
// instruction.
|
||||
//
|
||||
class VISIBILITY_HIDDEN RaiseAllocations : public ModulePass {
|
||||
Function *FreeFunc; // Functions in the module we are processing
|
||||
// Initialized by doPassInitializationVirt
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
RaiseAllocations()
|
||||
: ModulePass(&ID), FreeFunc(0) {}
|
||||
|
||||
// doPassInitialization - For the raise allocations pass, this finds a
|
||||
// declaration for free if it exists.
|
||||
//
|
||||
void doInitialization(Module &M);
|
||||
|
||||
// run - This method does the actual work of converting instructions over.
|
||||
//
|
||||
bool runOnModule(Module &M);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
char RaiseAllocations::ID = 0;
|
||||
static RegisterPass<RaiseAllocations>
|
||||
X("raiseallocs", "Raise allocations from calls to instructions");
|
||||
|
||||
// createRaiseAllocationsPass - The interface to this file...
|
||||
ModulePass *llvm::createRaiseAllocationsPass() {
|
||||
return new RaiseAllocations();
|
||||
}
|
||||
|
||||
|
||||
// If the module has a symbol table, they might be referring to the free
|
||||
// function. If this is the case, grab the method pointers that the module is
|
||||
// using.
|
||||
//
|
||||
// Lookup @free in the symbol table, for later use. If they don't
|
||||
// exist, or are not external, we do not worry about converting calls to that
|
||||
// function into the appropriate instruction.
|
||||
//
|
||||
void RaiseAllocations::doInitialization(Module &M) {
|
||||
// Get free prototype if it exists!
|
||||
FreeFunc = M.getFunction("free");
|
||||
if (FreeFunc) {
|
||||
const FunctionType* TyWeHave = FreeFunc->getFunctionType();
|
||||
|
||||
// Get the expected prototype for void free(i8*)
|
||||
const FunctionType *Free1Type =
|
||||
FunctionType::get(Type::getVoidTy(M.getContext()),
|
||||
std::vector<const Type*>(1, PointerType::getUnqual(
|
||||
Type::getInt8Ty(M.getContext()))),
|
||||
false);
|
||||
|
||||
if (TyWeHave != Free1Type) {
|
||||
// Check to see if the prototype was forgotten, giving us
|
||||
// void (...) * free
|
||||
// This handles the common forward declaration of: 'void free();'
|
||||
const FunctionType* Free2Type =
|
||||
FunctionType::get(Type::getVoidTy(M.getContext()), true);
|
||||
|
||||
if (TyWeHave != Free2Type) {
|
||||
// One last try, check to see if we can find free as
|
||||
// int (...)* free. This handles the case where NOTHING was declared.
|
||||
const FunctionType* Free3Type =
|
||||
FunctionType::get(Type::getInt32Ty(M.getContext()), true);
|
||||
|
||||
if (TyWeHave != Free3Type) {
|
||||
// Give up.
|
||||
FreeFunc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't mess with locally defined versions of these functions...
|
||||
if (FreeFunc && !FreeFunc->isDeclaration()) FreeFunc = 0;
|
||||
}
|
||||
|
||||
// run - Transform calls into instructions...
|
||||
//
|
||||
bool RaiseAllocations::runOnModule(Module &M) {
|
||||
// Find the free prototype...
|
||||
doInitialization(M);
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
// Process all free calls...
|
||||
if (FreeFunc) {
|
||||
std::vector<User*> Users(FreeFunc->use_begin(), FreeFunc->use_end());
|
||||
std::vector<Value*> EqPointers; // Values equal to FreeFunc
|
||||
|
||||
while (!Users.empty()) {
|
||||
User *U = Users.back();
|
||||
Users.pop_back();
|
||||
|
||||
if (Instruction *I = dyn_cast<Instruction>(U)) {
|
||||
if (isa<InvokeInst>(I))
|
||||
continue;
|
||||
CallSite CS = CallSite::get(I);
|
||||
if (CS.getInstruction() && !CS.arg_empty() &&
|
||||
(CS.getCalledFunction() == FreeFunc ||
|
||||
std::find(EqPointers.begin(), EqPointers.end(),
|
||||
CS.getCalledValue()) != EqPointers.end())) {
|
||||
|
||||
// If no prototype was provided for free, we may need to cast the
|
||||
// source pointer. This should be really uncommon, but it's necessary
|
||||
// just in case we are dealing with weird code like this:
|
||||
// free((long)ptr);
|
||||
//
|
||||
Value *Source = *CS.arg_begin();
|
||||
if (!isa<PointerType>(Source->getType()))
|
||||
Source = new IntToPtrInst(Source,
|
||||
Type::getInt8PtrTy(M.getContext()),
|
||||
"FreePtrCast", I);
|
||||
new FreeInst(Source, I);
|
||||
|
||||
// If the old instruction was an invoke, add an unconditional branch
|
||||
// before the invoke, which will become the new terminator.
|
||||
if (InvokeInst *II = dyn_cast<InvokeInst>(I))
|
||||
BranchInst::Create(II->getNormalDest(), I);
|
||||
|
||||
// Delete the old call site
|
||||
if (I->getType() != Type::getVoidTy(M.getContext()))
|
||||
I->replaceAllUsesWith(UndefValue::get(I->getType()));
|
||||
I->eraseFromParent();
|
||||
Changed = true;
|
||||
++NumRaised;
|
||||
}
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(U)) {
|
||||
Users.insert(Users.end(), GV->use_begin(), GV->use_end());
|
||||
EqPointers.push_back(GV);
|
||||
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
|
||||
if (CE->isCast()) {
|
||||
Users.insert(Users.end(), CE->use_begin(), CE->use_end());
|
||||
EqPointers.push_back(CE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Analysis/MallocHelper.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
@ -49,7 +50,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool runOnBasicBlock(BasicBlock &BB);
|
||||
bool handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep);
|
||||
bool handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep);
|
||||
bool handleEndBlock(BasicBlock &BB);
|
||||
bool RemoveUndeadPointers(Value* Ptr, uint64_t killPointerSize,
|
||||
BasicBlock::iterator& BBI,
|
||||
@ -88,7 +89,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||
Instruction *Inst = BBI++;
|
||||
|
||||
// If we find a store or a free, get its memory dependence.
|
||||
if (!isa<StoreInst>(Inst) && !isa<FreeInst>(Inst))
|
||||
if (!isa<StoreInst>(Inst) && !isa<FreeInst>(Inst) && !isFreeCall(Inst))
|
||||
continue;
|
||||
|
||||
// Don't molest volatile stores or do queries that will return "clobber".
|
||||
@ -103,8 +104,8 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||
if (InstDep.isNonLocal()) continue;
|
||||
|
||||
// Handle frees whose dependencies are non-trivial.
|
||||
if (FreeInst *FI = dyn_cast<FreeInst>(Inst)) {
|
||||
MadeChange |= handleFreeWithNonTrivialDependency(FI, InstDep);
|
||||
if (isa<FreeInst>(Inst) || isFreeCall(Inst)) {
|
||||
MadeChange |= handleFreeWithNonTrivialDependency(Inst, InstDep);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -165,7 +166,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
|
||||
|
||||
/// handleFreeWithNonTrivialDependency - Handle frees of entire structures whose
|
||||
/// dependency is a store to a field of that structure.
|
||||
bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) {
|
||||
bool DSE::handleFreeWithNonTrivialDependency(Instruction *F, MemDepResult Dep) {
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
|
||||
StoreInst *Dependency = dyn_cast_or_null<StoreInst>(Dep.getInst());
|
||||
@ -175,7 +176,8 @@ bool DSE::handleFreeWithNonTrivialDependency(FreeInst *F, MemDepResult Dep) {
|
||||
Value *DepPointer = Dependency->getPointerOperand()->getUnderlyingObject();
|
||||
|
||||
// Check for aliasing.
|
||||
if (AA.alias(F->getPointerOperand(), 1, DepPointer, 1) !=
|
||||
Value* FreeVal = isa<FreeInst>(F) ? F->getOperand(0) : F->getOperand(1);
|
||||
if (AA.alias(FreeVal, 1, DepPointer, 1) !=
|
||||
AliasAnalysis::MustAlias)
|
||||
return false;
|
||||
|
||||
|
@ -286,6 +286,7 @@ namespace {
|
||||
Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP);
|
||||
Instruction *visitAllocaInst(AllocaInst &AI);
|
||||
Instruction *visitFreeInst(FreeInst &FI);
|
||||
Instruction *visitFree(Instruction &FI);
|
||||
Instruction *visitLoadInst(LoadInst &LI);
|
||||
Instruction *visitStoreInst(StoreInst &SI);
|
||||
Instruction *visitBranchInst(BranchInst &BI);
|
||||
@ -9747,6 +9748,9 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) {
|
||||
/// the heavy lifting.
|
||||
///
|
||||
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||
if (isFreeCall(&CI))
|
||||
return visitFree(CI);
|
||||
|
||||
// If the caller function is nounwind, mark the call as nounwind, even if the
|
||||
// callee isn't.
|
||||
if (CI.getParent()->getParent()->doesNotThrow() &&
|
||||
@ -11337,6 +11341,42 @@ Instruction *InstCombiner::visitFreeInst(FreeInst &FI) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFree(Instruction &FI) {
|
||||
Value *Op = FI.getOperand(1);
|
||||
|
||||
// free undef -> unreachable.
|
||||
if (isa<UndefValue>(Op)) {
|
||||
// Insert a new store to null because we cannot modify the CFG here.
|
||||
new StoreInst(ConstantInt::getTrue(*Context),
|
||||
UndefValue::get(Type::getInt1PtrTy(*Context)), &FI);
|
||||
return EraseInstFromFunction(FI);
|
||||
}
|
||||
|
||||
// If we have 'free null' delete the instruction. This can happen in stl code
|
||||
// when lots of inlining happens.
|
||||
if (isa<ConstantPointerNull>(Op))
|
||||
return EraseInstFromFunction(FI);
|
||||
|
||||
// FIXME: Bring back free (gep X, 0,0,0,0) into free(X) transform
|
||||
|
||||
if (isMalloc(Op)) {
|
||||
if (CallInst* CI = extractMallocCallFromBitCast(Op)) {
|
||||
if (Op->hasOneUse() && CI->hasOneUse()) {
|
||||
EraseInstFromFunction(FI);
|
||||
EraseInstFromFunction(*CI);
|
||||
return EraseInstFromFunction(*cast<Instruction>(Op));
|
||||
}
|
||||
} else {
|
||||
// Op is a call to malloc
|
||||
if (Op->hasOneUse()) {
|
||||
EraseInstFromFunction(FI);
|
||||
return EraseInstFromFunction(*cast<Instruction>(Op));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// InstCombineLoadCast - Fold 'load (cast P)' -> cast (load P)' when possible.
|
||||
static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI,
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/MallocHelper.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
@ -401,6 +402,8 @@ private:
|
||||
void visitLoadInst (LoadInst &I);
|
||||
void visitGetElementPtrInst(GetElementPtrInst &I);
|
||||
void visitCallInst (CallInst &I) {
|
||||
if (isFreeCall(&I))
|
||||
return;
|
||||
visitCallSite(CallSite::get(&I));
|
||||
}
|
||||
void visitInvokeInst (InvokeInst &II) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/DebugInfo.h"
|
||||
#include "llvm/Analysis/MallocHelper.h"
|
||||
#include "llvm/Analysis/ProfileInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Support/GetElementPtrTypeIterator.h"
|
||||
@ -59,7 +60,7 @@ bool llvm::isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom) {
|
||||
|
||||
// If we see a free or a call which may write to memory (i.e. which might do
|
||||
// a free) the pointer could be marked invalid.
|
||||
if (isa<FreeInst>(BBI) ||
|
||||
if (isa<FreeInst>(BBI) || isFreeCall(BBI) ||
|
||||
(isa<CallInst>(BBI) && BBI->mayWriteToMemory() &&
|
||||
!isa<DbgInfoIntrinsic>(BBI)))
|
||||
return false;
|
||||
|
@ -102,12 +102,8 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
||||
// Loop over all of the instructions, looking for free instructions
|
||||
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
|
||||
if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
|
||||
Value *PtrCast =
|
||||
new BitCastInst(FI->getOperand(0),
|
||||
Type::getInt8PtrTy(BB.getContext()), "", I);
|
||||
|
||||
// Insert a call to the free function...
|
||||
CallInst::Create(FreeFunc, PtrCast, "", I)->setTailCall();
|
||||
CallInst::CreateFree(FI->getOperand(0), I);
|
||||
|
||||
// Delete the old free instruction
|
||||
I = --BBIL.erase(I);
|
||||
|
@ -559,6 +559,51 @@ Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
|
||||
ArraySize, MallocF, Name);
|
||||
}
|
||||
|
||||
static Instruction* createFree(Value* Source, Instruction *InsertBefore,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
|
||||
"createFree needs either InsertBefore or InsertAtEnd");
|
||||
assert(isa<PointerType>(Source->getType()) &&
|
||||
"Can not free something of nonpointer type!");
|
||||
|
||||
BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
|
||||
Module* M = BB->getParent()->getParent();
|
||||
|
||||
const Type *VoidTy = Type::getVoidTy(M->getContext());
|
||||
const Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
|
||||
// prototype free as "void free(void*)"
|
||||
Constant *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL);
|
||||
|
||||
CallInst* Result = NULL;
|
||||
Value *PtrCast = Source;
|
||||
if (InsertBefore) {
|
||||
if (Source->getType() != IntPtrTy)
|
||||
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertBefore);
|
||||
Result = CallInst::Create(FreeFunc, PtrCast, "", InsertBefore);
|
||||
} else {
|
||||
if (Source->getType() != IntPtrTy)
|
||||
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertAtEnd);
|
||||
Result = CallInst::Create(FreeFunc, PtrCast, "");
|
||||
}
|
||||
Result->setTailCall();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// CreateFree - Generate the IR for a call to the builtin free function.
|
||||
void CallInst::CreateFree(Value* Source, Instruction *InsertBefore) {
|
||||
createFree(Source, InsertBefore, NULL);
|
||||
}
|
||||
|
||||
/// CreateFree - Generate the IR for a call to the builtin free function.
|
||||
/// Note: This function does not add the call to the basic block, that is the
|
||||
/// responsibility of the caller.
|
||||
Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) {
|
||||
Instruction* FreeCall = createFree(Source, NULL, InsertAtEnd);
|
||||
assert(FreeCall && "CreateFree did not create a CallInst");
|
||||
return FreeCall;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// InvokeInst Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1,11 +1,13 @@
|
||||
; RUN: opt < %s -instcombine -S | grep {ret i32 0}
|
||||
; RUN: opt < %s -instcombine -globaldce -S | not grep malloc
|
||||
; RUN: opt < %s -instcombine -globaldce -S | FileCheck %s
|
||||
; PR1201
|
||||
define i32 @main(i32 %argc, i8** %argv) {
|
||||
%c_19 = alloca i8* ; <i8**> [#uses=2]
|
||||
%malloc_206 = malloc i8, i32 10 ; <i8*> [#uses=1]
|
||||
; CHECK-NOT: malloc
|
||||
store i8* %malloc_206, i8** %c_19
|
||||
%tmp_207 = load i8** %c_19 ; <i8*> [#uses=1]
|
||||
free i8* %tmp_207
|
||||
; CHECK-NOT: free
|
||||
ret i32 0
|
||||
; CHECK: ret i32 0
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
; RUN: opt < %s -raiseallocs -disable-output
|
||||
|
||||
define void @main() {
|
||||
%tmp.13 = call i32 (...)* @free( i32 32 ) ; <i32> [#uses=1]
|
||||
%tmp.14 = inttoptr i32 %tmp.13 to i32* ; <i32*> [#uses=0]
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @free(...)
|
||||
|
@ -1,17 +0,0 @@
|
||||
; RUN: opt < %s -raiseallocs -stats -disable-output |& \
|
||||
; RUN: not grep {Number of allocations raised}
|
||||
define void @foo() {
|
||||
entry:
|
||||
%buffer = alloca i16*
|
||||
%tmp = load i16** %buffer, align 8
|
||||
invoke i32(...)* @free(i16* %tmp)
|
||||
to label %invcont unwind label %unwind
|
||||
invcont:
|
||||
br label %finally
|
||||
unwind:
|
||||
br label %finally
|
||||
finally:
|
||||
ret void
|
||||
}
|
||||
declare i32 @free(...)
|
||||
|
@ -1,11 +0,0 @@
|
||||
; This situation can occur due to the funcresolve pass.
|
||||
;
|
||||
; RUN: opt < %s -raiseallocs -S | not grep call
|
||||
|
||||
declare void @free(i8*)
|
||||
|
||||
define void @test(i32* %P) {
|
||||
call void bitcast (void (i8*)* @free to void (i32*)*)( i32* %P )
|
||||
ret void
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
load_lib llvm.exp
|
||||
|
||||
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
|
@ -70,7 +70,7 @@ dis2="$llvm2/Debug/bin/llvm-dis"
|
||||
opt1="$llvm1/Debug/bin/opt"
|
||||
opt2="$llvm2/Debug/bin/opt"
|
||||
|
||||
all_switches="-verify -lowersetjmp -raiseallocs -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -scalarrepl -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify"
|
||||
all_switches="-verify -lowersetjmp -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -prune-eh -inline -simplify-libcalls -argpromotion -tailduplicate -simplifycfg -scalarrepl -instcombine -predsimplify -condprop -tailcallelim -simplifycfg -reassociate -licm -loop-unswitch -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -condprop -dse -dce -simplifycfg -deadtypeelim -constmerge -internalize -ipsccp -globalopt -constmerge -deadargelim -inline -prune-eh -globalopt -globaldce -argpromotion -instcombine -predsimplify -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -dse -instcombine -simplifycfg -verify"
|
||||
|
||||
#counter=0
|
||||
function tryit {
|
||||
|
Loading…
Reference in New Issue
Block a user