From 3500d08b4b439399dd2e3227d23c1979b8f0634e Mon Sep 17 00:00:00 2001 From: George Burgess IV Date: Tue, 27 Dec 2016 06:32:14 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290588 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/MemoryBuiltins.cpp | 25 ++++++++++++++---------- test/Transforms/InstCombine/allocsize.ll | 13 ++++++++++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index d41af65d202..2d8274040d3 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -77,8 +77,8 @@ static const std::pair 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(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 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 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 Data = - getAllocationDataForFunction(Callee, AnyAlloc, TLI)) - return Data; + if (!IsNoBuiltinCall) + if (Optional Data = + getAllocationDataForFunction(Callee, AnyAlloc, TLI)) + return Data; Attribute Attr = Callee->getFnAttribute(Attribute::AllocSize); if (Attr == Attribute()) diff --git a/test/Transforms/InstCombine/allocsize.ll b/test/Transforms/InstCombine/allocsize.ll index 928c8a50249..ac1817c164f 100644 --- a/test/Transforms/InstCombine/allocsize.ll +++ b/test/Transforms/InstCombine/allocsize.ll @@ -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) } -- 2.49.0