]> granicus.if.org Git - llvm/commitdiff
[Analysis] Ignore `nobuiltin` on `allocsize` function calls.
authorGeorge Burgess IV <george.burgess.iv@gmail.com>
Tue, 27 Dec 2016 06:32:14 +0000 (06:32 +0000)
committerGeorge Burgess IV <george.burgess.iv@gmail.com>
Tue, 27 Dec 2016 06:32:14 +0000 (06:32 +0000)
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
test/Transforms/InstCombine/allocsize.ll

index d41af65d202ebda1a116fd061fbec06c5d2e4590..2d8274040d393c06c77cdf496867275bf4664c71 100644 (file)
@@ -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())
index 928c8a50249cccfbe165fadb2674d4897aa37b3f..ac1817c164f741f513d768a70c3b0d0d393bd4c2 100644 (file)
@@ -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) }