[Analysis] Ignore `nobuiltin` on `allocsize` function calls.
We currently ignore the `allocsize` attribute on functions calls with the `nobuiltin` attribute when trying to lower `@llvm.objectsize`. We shouldn't care about `nobuiltin` here: `allocsize` is explicitly added by the user, not inferred based on a function's symbol. llvm-svn: 290588
This commit is contained in:
parent
f0071ccd08
commit
ed16024a9b
|
@ -77,8 +77,8 @@ static const std::pair<LibFunc::Func, AllocFnsTy> AllocationFnData[] = {
|
|||
// TODO: Handle "int posix_memalign(void **, size_t, size_t)"
|
||||
};
|
||||
|
||||
|
||||
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
|
||||
static Function *getCalledFunction(const Value *V, bool LookThroughBitCast,
|
||||
bool &IsNoBuiltin) {
|
||||
// Don't care about intrinsics in this case.
|
||||
if (isa<IntrinsicInst>(V))
|
||||
return nullptr;
|
||||
|
@ -90,8 +90,7 @@ static Function *getCalledFunction(const Value *V, bool LookThroughBitCast) {
|
|||
if (!CS.getInstruction())
|
||||
return nullptr;
|
||||
|
||||
if (CS.isNoBuiltin())
|
||||
return nullptr;
|
||||
IsNoBuiltin = CS.isNoBuiltin();
|
||||
|
||||
Function *Callee = CS.getCalledFunction();
|
||||
if (!Callee || !Callee->isDeclaration())
|
||||
|
@ -143,22 +142,28 @@ getAllocationDataForFunction(const Function *Callee, AllocType AllocTy,
|
|||
static Optional<AllocFnsTy> getAllocationData(const Value *V, AllocType AllocTy,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false) {
|
||||
if (const Function *Callee = getCalledFunction(V, LookThroughBitCast))
|
||||
return getAllocationDataForFunction(Callee, AllocTy, TLI);
|
||||
bool IsNoBuiltinCall;
|
||||
if (const Function *Callee =
|
||||
getCalledFunction(V, LookThroughBitCast, IsNoBuiltinCall))
|
||||
if (!IsNoBuiltinCall)
|
||||
return getAllocationDataForFunction(Callee, AllocTy, TLI);
|
||||
return None;
|
||||
}
|
||||
|
||||
static Optional<AllocFnsTy> getAllocationSize(const Value *V,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
const Function *Callee = getCalledFunction(V, /*LookThroughBitCast=*/false);
|
||||
bool IsNoBuiltinCall;
|
||||
const Function *Callee =
|
||||
getCalledFunction(V, /*LookThroughBitCast=*/false, IsNoBuiltinCall);
|
||||
if (!Callee)
|
||||
return None;
|
||||
|
||||
// Prefer to use existing information over allocsize. This will give us an
|
||||
// accurate AllocTy.
|
||||
if (Optional<AllocFnsTy> Data =
|
||||
getAllocationDataForFunction(Callee, AnyAlloc, TLI))
|
||||
return Data;
|
||||
if (!IsNoBuiltinCall)
|
||||
if (Optional<AllocFnsTy> Data =
|
||||
getAllocationDataForFunction(Callee, AnyAlloc, TLI))
|
||||
return Data;
|
||||
|
||||
Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize);
|
||||
if (Attr == Attribute())
|
||||
|
|
|
@ -134,6 +134,19 @@ define void @test_overflow(i8** %p, i32* %r) {
|
|||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @test_nobuiltin
|
||||
; We had a bug where `nobuiltin` would cause `allocsize` to be ignored in
|
||||
; @llvm.objectsize calculations.
|
||||
define void @test_nobuiltin(i8** %p, i64* %r) {
|
||||
%1 = call i8* @my_malloc(i8* null, i32 100) nobuiltin
|
||||
store i8* %1, i8** %p, align 8
|
||||
|
||||
%2 = call i64 @llvm.objectsize.i64.p0i8(i8* %1, i1 false)
|
||||
; CHECK: store i64 100
|
||||
store i64 %2, i64* %r, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { allocsize(1) }
|
||||
attributes #1 = { allocsize(2, 3) }
|
||||
|
||||
|
|
Loading…
Reference in New Issue