[llvm] r312641 - [TailCall] Allow llvm.memcpy/memset/memmove to be tail calls when parent

Wei Mi via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 6 09:05:18 PDT 2017


Author: wmi
Date: Wed Sep  6 09:05:17 2017
New Revision: 312641

URL: http://llvm.org/viewvc/llvm-project?rev=312641&view=rev
Log:
[TailCall] Allow llvm.memcpy/memset/memmove to be tail calls when parent
function return the intrinsics's first argument.

llvm.memcpy/memset/memmove return void but they will return the first
argument after they are expanded as libcalls. Now if the parent function
has any return value, llvm.memcpy cannot be turned into tail call after
expansion.

The patch is to handle that case in SelectionDAGBuilder so when caller
function return the same value as the first argument of llvm.memcpy,
tail call is allowed.

Differential Revision: https://reviews.llvm.org/D37406

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

Modified: llvm/trunk/lib/CodeGen/Analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Analysis.cpp?rev=312641&r1=312640&r2=312641&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/Analysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/Analysis.cpp Wed Sep  6 09:05:17 2017
@@ -565,6 +565,17 @@ 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.
+  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) &&
+        RetVal == Call->getArgOperand(0))
+      return true;
+  }
+
   SmallVector<unsigned, 4> RetPath, CallPath;
   SmallVector<CompositeType *, 4> RetSubTypes, CallSubTypes;
 

Modified: llvm/trunk/test/CodeGen/X86/tailcall-mem-intrinsics.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tailcall-mem-intrinsics.ll?rev=312641&r1=312640&r2=312641&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/tailcall-mem-intrinsics.ll (original)
+++ llvm/trunk/test/CodeGen/X86/tailcall-mem-intrinsics.ll Wed Sep  6 09:05:17 2017
@@ -24,6 +24,30 @@ entry:
   ret void
 }
 
+; CHECK-LABEL: tail_memcpy_ret
+; CHECK: jmp 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: jmp 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: jmp 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




More information about the llvm-commits mailing list