forked from OSchip/llvm-project
[MemoryBuiltins] Add getFreedOperand() function (NFCI)
We currently assume in a number of places that free-like functions free their first argument. This is true for all hardcoded free-like functions, but with the new attribute-based design, the freed argument is supposed to be indicated by the allocptr attribute. To make sure we handle this correctly once allockind(free) is respected, add a getFreedOperand() helper which returns the freed argument, rather than just indicating whether the call frees *some* argument. This migrates most but not all users of isFreeCall() to the new API. The remaining users are a bit more tricky.
This commit is contained in:
parent
d2a4d6bf9c
commit
c81dff3c30
llvm
include/llvm/Analysis
lib
|
@ -80,12 +80,11 @@ bool isReallocLikeFn(const Function *F, const TargetLibraryInfo *TLI);
|
|||
/// isLibFreeFunction - Returns true if the function is a builtin free()
|
||||
bool isLibFreeFunction(const Function *F, const LibFunc TLIFn);
|
||||
|
||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||
const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
/// Returns true if the value is a call to a free function.
|
||||
bool isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
|
||||
inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
|
||||
}
|
||||
/// If this if a call to a free function, return the freed operand.
|
||||
Value *getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Properties of allocation functions
|
||||
|
|
|
@ -361,7 +361,7 @@ bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V,
|
|||
if (Call->isDataOperand(&U)) {
|
||||
// Detect calls to free.
|
||||
if (Call->isArgOperand(&U) &&
|
||||
isFreeCall(I, &GetTLI(*Call->getFunction()))) {
|
||||
getFreedOperand(Call, &GetTLI(*Call->getFunction())) == U) {
|
||||
if (Writers)
|
||||
Writers->insert(Call->getParent()->getParent());
|
||||
} else {
|
||||
|
|
|
@ -531,20 +531,25 @@ bool llvm::isLibFreeFunction(const Function *F, const LibFunc TLIFn) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
||||
bool llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
||||
bool IsNoBuiltinCall;
|
||||
const Function *Callee = getCalledFunction(I, IsNoBuiltinCall);
|
||||
if (Callee == nullptr || IsNoBuiltinCall)
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
LibFunc TLIFn;
|
||||
if (!TLI || !TLI->getLibFunc(*Callee, TLIFn) || !TLI->has(TLIFn))
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
return isLibFreeFunction(Callee, TLIFn) ? dyn_cast<CallInst>(I) : nullptr;
|
||||
return isLibFreeFunction(Callee, TLIFn);
|
||||
}
|
||||
|
||||
Value *llvm::getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI) {
|
||||
// All currently supported free functions free the first argument.
|
||||
if (isFreeCall(CB, TLI))
|
||||
return CB->getArgOperand(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions to compute size of objects.
|
||||
|
|
|
@ -139,10 +139,12 @@ static ModRefInfo GetLocation(const Instruction *Inst, MemoryLocation &Loc,
|
|||
return ModRefInfo::ModRef;
|
||||
}
|
||||
|
||||
if (const CallInst *CI = isFreeCall(Inst, &TLI)) {
|
||||
// calls to free() deallocate the entire structure
|
||||
Loc = MemoryLocation::getAfter(CI->getArgOperand(0));
|
||||
return ModRefInfo::Mod;
|
||||
if (const CallBase *CB = dyn_cast<CallBase>(Inst)) {
|
||||
if (Value *FreedOp = getFreedOperand(CB, &TLI)) {
|
||||
// calls to free() deallocate the entire structure
|
||||
Loc = MemoryLocation::getAfter(FreedOp);
|
||||
return ModRefInfo::Mod;
|
||||
}
|
||||
}
|
||||
|
||||
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
|
||||
|
|
|
@ -1372,7 +1372,7 @@ struct AAPointerInfoFloating : public AAPointerInfoImpl {
|
|||
if (auto *CB = dyn_cast<CallBase>(Usr)) {
|
||||
if (CB->isLifetimeStartOrEnd())
|
||||
return true;
|
||||
if (TLI && isFreeCall(CB, TLI))
|
||||
if (getFreedOperand(CB, TLI) == U)
|
||||
return true;
|
||||
if (CB->isArgOperand(&U)) {
|
||||
unsigned ArgNo = CB->getArgOperandNo(&U);
|
||||
|
|
|
@ -1140,8 +1140,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
|
|||
if (Value *V = simplifyCall(&CI, SQ.getWithInstruction(&CI)))
|
||||
return replaceInstUsesWith(CI, V);
|
||||
|
||||
if (isFreeCall(&CI, &TLI))
|
||||
return visitFree(CI);
|
||||
if (Value *FreedOp = getFreedOperand(&CI, &TLI))
|
||||
return visitFree(CI, FreedOp);
|
||||
|
||||
// If the caller function (i.e. us, the function that contains this CallInst)
|
||||
// is nounwind, mark the call as nounwind, even if the callee isn't.
|
||||
|
|
|
@ -152,7 +152,7 @@ public:
|
|||
Instruction *visitGEPOfBitcast(BitCastInst *BCI, GetElementPtrInst &GEP);
|
||||
Instruction *visitAllocaInst(AllocaInst &AI);
|
||||
Instruction *visitAllocSite(Instruction &FI);
|
||||
Instruction *visitFree(CallInst &FI);
|
||||
Instruction *visitFree(CallInst &FI, Value *FreedOp);
|
||||
Instruction *visitLoadInst(LoadInst &LI);
|
||||
Instruction *visitStoreInst(StoreInst &SI);
|
||||
Instruction *visitAtomicRMWInst(AtomicRMWInst &SI);
|
||||
|
|
|
@ -3034,9 +3034,7 @@ static Instruction *tryToMoveFreeBeforeNullTest(CallInst &FI,
|
|||
return &FI;
|
||||
}
|
||||
|
||||
Instruction *InstCombinerImpl::visitFree(CallInst &FI) {
|
||||
Value *Op = FI.getArgOperand(0);
|
||||
|
||||
Instruction *InstCombinerImpl::visitFree(CallInst &FI, Value *Op) {
|
||||
// free undef -> unreachable.
|
||||
if (isa<UndefValue>(Op)) {
|
||||
// Leave a marker since we can't modify the CFG here.
|
||||
|
|
|
@ -1108,9 +1108,8 @@ struct DSEState {
|
|||
return {std::make_pair(MemoryLocation(Ptr, Len), false)};
|
||||
|
||||
if (auto *CB = dyn_cast<CallBase>(I)) {
|
||||
if (isFreeCall(I, &TLI))
|
||||
return {std::make_pair(MemoryLocation::getAfter(CB->getArgOperand(0)),
|
||||
true)};
|
||||
if (Value *FreedOp = getFreedOperand(CB, &TLI))
|
||||
return {std::make_pair(MemoryLocation::getAfter(FreedOp), true)};
|
||||
}
|
||||
|
||||
return None;
|
||||
|
|
|
@ -493,13 +493,13 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
|
|||
}
|
||||
}
|
||||
|
||||
if (CallInst *CI = isFreeCall(I, TLI))
|
||||
if (Constant *C = dyn_cast<Constant>(CI->getArgOperand(0)))
|
||||
return C->isNullValue() || isa<UndefValue>(C);
|
||||
|
||||
if (auto *Call = dyn_cast<CallBase>(I))
|
||||
if (auto *Call = dyn_cast<CallBase>(I)) {
|
||||
if (Value *FreedOp = getFreedOperand(Call, TLI))
|
||||
if (Constant *C = dyn_cast<Constant>(FreedOp))
|
||||
return C->isNullValue() || isa<UndefValue>(C);
|
||||
if (isMathLibCallNoop(Call, TLI))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Non-volatile atomic loads from constants can be removed.
|
||||
if (auto *LI = dyn_cast<LoadInst>(I))
|
||||
|
|
Loading…
Reference in New Issue