[PATCH] Detect deallocation calls even if the deallocation function has a definition

Richard Smith richard at metafoo.co.uk
Thu Dec 4 16:11:50 PST 2014


When Clang emits a call to a C++14 sized deallocation function, it emits a
weak definition of that function in case the underlying C++ ABI library
doesn't provide it:

  call _ZdlPvm(i8* %p, i64 8) builtin

// ...

  define linkonce void @_ZdlPvm(i8* %p, i64) nobuiltin {
    call void @_ZdlPvm(i8* %p)
    ret void
  }

However, LLVM's detection of deallocation functions is broken by this: it
assumes that if we have a definition of the deallocation function, then
it's not really a deallocation function. I'm not sure why this is the case.
The check was added in response to this review comment:


http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20091102/090282.html

The attached patch removes this condition (and thus avoids the optimization
regression in C++14 mode), but I'm wary about removing a check that I don't
understand, so I was wondering if anyone knew the justification for having
this test?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141204/6bc97f44/attachment.html>
-------------- next part --------------
Index: lib/Analysis/MemoryBuiltins.cpp
===================================================================
--- lib/Analysis/MemoryBuiltins.cpp	(revision 223063)
+++ lib/Analysis/MemoryBuiltins.cpp	(working copy)
@@ -319,7 +319,7 @@
   if (!CI || isa<IntrinsicInst>(CI))
     return nullptr;
   Function *Callee = CI->getCalledFunction();
-  if (Callee == nullptr || !Callee->isDeclaration())
+  if (Callee == nullptr)
     return nullptr;
 
   StringRef FnName = Callee->getName();
Index: test/Transforms/InstCombine/malloc-free-delete.ll
===================================================================
--- test/Transforms/InstCombine/malloc-free-delete.ll	(revision 223063)
+++ test/Transforms/InstCombine/malloc-free-delete.ll	(working copy)
@@ -146,17 +146,36 @@
 }
 
 declare i8* @_Znwm(i64) nobuiltin
-declare void @_ZdlPvm(i8*, i64) nobuiltin
 declare i8* @_Znwj(i32) nobuiltin
-declare void @_ZdlPvj(i8*, i32) nobuiltin
 declare i8* @_Znam(i64) nobuiltin
-declare void @_ZdaPvm(i8*, i64) nobuiltin
 declare i8* @_Znaj(i32) nobuiltin
-declare void @_ZdaPvj(i8*, i32) nobuiltin
+declare void @_ZdlPv(i8*) nobuiltin
+declare void @_ZdaPv(i8*) nobuiltin
 
+define linkonce void @_ZdlPvm(i8* %p, i64) nobuiltin {
+  call void @_ZdlPv(i8* %p)
+  ret void
+}
+define linkonce void @_ZdlPvj(i8* %p, i32) nobuiltin {
+  call void @_ZdlPv(i8* %p)
+  ret void
+}
+define linkonce void @_ZdaPvm(i8* %p, i64) nobuiltin {
+  call void @_ZdaPv(i8* %p)
+  ret void
+}
+define linkonce void @_ZdaPvj(i8* %p, i32) nobuiltin {
+  call void @_ZdaPv(i8* %p)
+  ret void
+}
+
 ; CHECK-LABEL: @test8(
 define void @test8() {
   ; CHECK-NOT: call
+  %nw = call i8* @_Znwm(i64 32) builtin
+  call void @_ZdlPv(i8* %nw) builtin
+  %na = call i8* @_Znam(i64 32) builtin
+  call void @_ZdaPv(i8* %na) builtin
   %nwm = call i8* @_Znwm(i64 32) builtin
   call void @_ZdlPvm(i8* %nwm, i64 32) builtin
   %nwj = call i8* @_Znwj(i32 32) builtin


More information about the llvm-commits mailing list