[llvm] [CGP] Consider arguments and ret values in `dupRetToEnableTailCallOpts` (PR #76613)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 7 01:40:33 PST 2024


================
@@ -2620,8 +2621,58 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB,
       // Make sure the phi value is indeed produced by the tail call.
       if (CI && CI->hasOneUse() && CI->getParent() == PredBB &&
           TLI->mayBeEmittedAsTailCall(CI) &&
-          attributesPermitTailCall(F, CI, RetI, *TLI))
+          attributesPermitTailCall(F, CI, RetI, *TLI)) {
         TailCallBBs.push_back(PredBB);
+      } else {
+        /// Consider the cases in which the phi value is indirectly produced by
+        /// the tail call, for example when encountering memset(), memmove(),
+        /// strcpy(), whose return value may have been optimized out. In such
+        /// cases, the value needs to be the first function argument.
+        /// @code
+        /// bb0:
+        ///   tail call void @llvm.memset.p0.i64(ptr %0, i8 0, i64 %1)
+        ///   br label %return
+        /// return:
+        ///   %phi = phi ptr [ %0, %bb0 ], [ %2, %entry ]
+        /// @endcode
+        if (PredBB && PredBB->getSingleSuccessor() == BB)
+          CI = dyn_cast_or_null<CallInst>(
+              PredBB->getTerminator()->getPrevNonDebugInstruction(true));
+
+        auto IsIntrinsicOrLibFuncToBeTailCalled = [&](const auto *CI) {
+          if (CI && CI->use_empty() && CI->hasArgument(IncomingVal) &&
+              IncomingVal == CI->getArgOperand(0)) {
+            if (const auto *II = dyn_cast<IntrinsicInst>(CI))
+              switch (II->getIntrinsicID()) {
+              case Intrinsic::memset:
+              case Intrinsic::memcpy:
+              case Intrinsic::memmove:
+                return true;
+              default:
+                return false;
+              }
+
+            LibFunc LF;
+            Function *Callee = CI->getCalledFunction();
+            if (Callee && TLInfo && TLInfo->getLibFunc(*Callee, LF))
+              switch (LF) {
+              case LibFunc_strcpy:
+              case LibFunc_strncpy:
+              case LibFunc_strcat:
+              case LibFunc_strncat:
+                return true;
+              default:
+                return false;
+              }
+          }
+          return false;
+        };
+
+        if (IsIntrinsicOrLibFuncToBeTailCalled(CI) &&
+            TLI->mayBeEmittedAsTailCall(CI) &&
+            attributesPermitTailCall(F, CI, RetI, *TLI))
+          TailCallBBs.push_back(PredBB);
+      }
----------------
nikic wrote:

Why are these extra checks only needed in the PN branch, but not the !PN branch?

https://github.com/llvm/llvm-project/pull/76613


More information about the llvm-commits mailing list