diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -3455,45 +3455,67 @@ if (!ignoreCallingConv(Func) && !IsCallingConvC) return nullptr; + Value *New; switch (Func) { case LibFunc_memcpy_chk: - return optimizeMemCpyChk(CI, Builder); + New = optimizeMemCpyChk(CI, Builder); + break; case LibFunc_mempcpy_chk: - return optimizeMemPCpyChk(CI, Builder); + New = optimizeMemPCpyChk(CI, Builder); + break; case LibFunc_memmove_chk: - return optimizeMemMoveChk(CI, Builder); + New = optimizeMemMoveChk(CI, Builder); + break; case LibFunc_memset_chk: - return optimizeMemSetChk(CI, Builder); + New = optimizeMemSetChk(CI, Builder); + break; case LibFunc_stpcpy_chk: case LibFunc_strcpy_chk: - return optimizeStrpCpyChk(CI, Builder, Func); + New = optimizeStrpCpyChk(CI, Builder, Func); + break; case LibFunc_strlen_chk: - return optimizeStrLenChk(CI, Builder); + New = optimizeStrLenChk(CI, Builder); + break; case LibFunc_stpncpy_chk: case LibFunc_strncpy_chk: - return optimizeStrpNCpyChk(CI, Builder, Func); + New = optimizeStrpNCpyChk(CI, Builder, Func); + break; case LibFunc_memccpy_chk: - return optimizeMemCCpyChk(CI, Builder); + New = optimizeMemCCpyChk(CI, Builder); + break; case LibFunc_snprintf_chk: - return optimizeSNPrintfChk(CI, Builder); + New = optimizeSNPrintfChk(CI, Builder); + break; case LibFunc_sprintf_chk: - return optimizeSPrintfChk(CI, Builder); + New = optimizeSPrintfChk(CI, Builder); + break; case LibFunc_strcat_chk: - return optimizeStrCatChk(CI, Builder); + New = optimizeStrCatChk(CI, Builder); + break; case LibFunc_strlcat_chk: - return optimizeStrLCat(CI, Builder); + New = optimizeStrLCat(CI, Builder); + break; case LibFunc_strncat_chk: - return optimizeStrNCatChk(CI, Builder); + New = optimizeStrNCatChk(CI, Builder); + break; case LibFunc_strlcpy_chk: - return optimizeStrLCpyChk(CI, Builder); + New = optimizeStrLCpyChk(CI, Builder); + break; case LibFunc_vsnprintf_chk: - return optimizeVSNPrintfChk(CI, Builder); + New = optimizeVSNPrintfChk(CI, Builder); + break; case LibFunc_vsprintf_chk: - return optimizeVSPrintfChk(CI, Builder); - default: + New = optimizeVSPrintfChk(CI, Builder); break; + default: + return nullptr; } - return nullptr; + + if (auto *SimplifiedCI = dyn_cast_or_null(New)) + if (CI->isTailCall() && !SimplifiedCI->isTailCall()) + SimplifiedCI->setTailCall(); + + return New; } FortifiedLibCallSimplifier::FortifiedLibCallSimplifier( diff --git a/llvm/test/Transforms/InstCombine/fortify-folding.ll b/llvm/test/Transforms/InstCombine/fortify-folding.ll --- a/llvm/test/Transforms/InstCombine/fortify-folding.ll +++ b/llvm/test/Transforms/InstCombine/fortify-folding.ll @@ -11,12 +11,12 @@ define i8* @test_memccpy() { ; CHECK-LABEL: @test_memccpy( -; CHECK-NEXT: [[MEMCCPY:%.*]] = call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60) +; CHECK-NEXT: [[MEMCCPY:%.*]] = tail call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60) ; CHECK-NEXT: ret i8* [[MEMCCPY]] ; %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 - %ret = call i8* @__memccpy_chk(i8* %dst, i8* %src, i32 0, i64 60, i64 -1) + %ret = tail call i8* @__memccpy_chk(i8* %dst, i8* %src, i32 0, i64 60, i64 -1) ret i8* %ret }