[llvm] r312799 - Fix a bug for rL312641.

Wei Mi via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 8 09:44:53 PDT 2017


Author: wmi
Date: Fri Sep  8 09:44:52 2017
New Revision: 312799

URL: http://llvm.org/viewvc/llvm-project?rev=312799&view=rev
Log:
Fix a bug for rL312641.

rL312641 Allowed llvm.memcpy/memset/memmove to be tail calls when parent
function return the intrinsics's first argument. However on arm-none-eabi
platform, llvm.memcpy will be expanded to __aeabi_memcpy which doesn't
have return value. The fix is to check the libcall name after expansion
to match "memcpy/memset/memmove" before allowing those intrinsic to be
tail calls.

Added:
    llvm/trunk/test/CodeGen/ARM/tailcall-mem-intrinsics.ll
Modified:
    llvm/trunk/lib/CodeGen/Analysis.cpp

Modified: llvm/trunk/lib/CodeGen/Analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Analysis.cpp?rev=312799&r1=312798&r2=312799&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/Analysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/Analysis.cpp Fri Sep  8 09:44:52 2017
@@ -565,13 +565,20 @@ bool llvm::returnTypeIsEligibleForTailCa
     return false;
 
   const Value *RetVal = Ret->getOperand(0), *CallVal = I;
-  // Intrinsic like llvm.memcpy has no return value, but will return the
-  // first argument if it is expanded as libcall.
+  // Intrinsic like llvm.memcpy has no return value, but the expanded
+  // libcall may or may not have return value. On most platforms, it
+  // will be expanded as memcpy in libc, which returns the first
+  // argument. On other platforms like arm-none-eabi, memcpy may be
+  // expanded as library call without return value, like __aeabi_memcpy.
   const CallInst *Call = cast<CallInst>(I);
   if (Function *F = Call->getCalledFunction()) {
     Intrinsic::ID IID = F->getIntrinsicID();
-    if ((IID == Intrinsic::memcpy || IID == Intrinsic::memmove ||
-         IID == Intrinsic::memset) &&
+    if (((IID == Intrinsic::memcpy &&
+          TLI.getLibcallName(RTLIB::MEMCPY) == StringRef("memcpy")) ||
+         (IID == Intrinsic::memmove &&
+          TLI.getLibcallName(RTLIB::MEMMOVE) == StringRef("memmove")) ||
+         (IID == Intrinsic::memset &&
+          TLI.getLibcallName(RTLIB::MEMSET) == StringRef("memset"))) &&
         RetVal == Call->getArgOperand(0))
       return true;
   }

Added: llvm/trunk/test/CodeGen/ARM/tailcall-mem-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/tailcall-mem-intrinsics.ll?rev=312799&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/tailcall-mem-intrinsics.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/tailcall-mem-intrinsics.ll Fri Sep  8 09:44:52 2017
@@ -0,0 +1,31 @@
+; RUN: llc -mtriple=arm-none-eabi < %s | FileCheck %s
+
+; CHECK-LABEL: tail_memcpy_ret
+; CHECK: bl	__aeabi_memcpy
+define i8* @tail_memcpy_ret(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
+entry:
+  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
+  ret i8* %p
+}
+
+; CHECK-LABEL: tail_memmove_ret
+; CHECK: bl	__aeabi_memmove
+define i8* @tail_memmove_ret(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
+entry:
+  tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i32 1, i1 false)
+  ret i8* %p
+}
+
+; CHECK-LABEL: tail_memset_ret
+; CHECK: bl	__aeabi_memset
+define i8* @tail_memset_ret(i8* nocapture %p, i8 %c, i32 %n) #0 {
+entry:
+  tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i32 1, i1 false)
+  ret i8* %p
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
+declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #0
+declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) #0
+
+attributes #0 = { nounwind }




More information about the llvm-commits mailing list