diff options
author | Wei Mi <wmi@google.com> | 2017-09-08 16:44:52 +0000 |
---|---|---|
committer | Wei Mi <wmi@google.com> | 2017-09-08 16:44:52 +0000 |
commit | 5d84d9b35ccae7fc17acc08a15658bbc2884555e (patch) | |
tree | 81ce263c07bacfb7531ae7353d723b17d724a166 | |
parent | e85a7e7cd5aa8471d4bd93605162f911c2cbf947 (diff) | |
download | bcm5719-llvm-5d84d9b35ccae7fc17acc08a15658bbc2884555e.tar.gz bcm5719-llvm-5d84d9b35ccae7fc17acc08a15658bbc2884555e.zip |
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.
llvm-svn: 312799
-rw-r--r-- | llvm/lib/CodeGen/Analysis.cpp | 15 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/tailcall-mem-intrinsics.ll | 31 |
2 files changed, 42 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp index f561577e1e2..876cca4bc7a 100644 --- a/llvm/lib/CodeGen/Analysis.cpp +++ b/llvm/lib/CodeGen/Analysis.cpp @@ -565,13 +565,20 @@ bool llvm::returnTypeIsEligibleForTailCall(const Function *F, 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; } diff --git a/llvm/test/CodeGen/ARM/tailcall-mem-intrinsics.ll b/llvm/test/CodeGen/ARM/tailcall-mem-intrinsics.ll new file mode 100644 index 00000000000..6744efa8ab8 --- /dev/null +++ b/llvm/test/CodeGen/ARM/tailcall-mem-intrinsics.ll @@ -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 } |