From bc991e7373c129a8e4d8429348e57802c5c32cb9 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 12 Jun 2025 14:37:22 +0900 Subject: [PATCH] PowerPC: Stop reporting memcpy as an alias of memmove on AIX Instead of reporting ___memmove as an implementation of memcpy, make it unavailable and let the lowering logic consider memmove as a fallback path. This avoids a special case 1:N mapping for libcall implementations. --- llvm/include/llvm/CodeGen/TargetLowering.h | 2 ++ llvm/include/llvm/IR/RuntimeLibcalls.h | 10 ++++++++++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 6 +++++- llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp | 11 +++++++++-- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 15 ++++++++------- llvm/lib/IR/RuntimeLibcalls.cpp | 2 +- 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index dd44afd0855a5..727526055e592 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3572,6 +3572,8 @@ class LLVM_ABI TargetLoweringBase { return Libcalls.getLibcallName(Call); } + const char *getMemcpyName() const { return Libcalls.getMemcpyName(); } + /// Override the default CondCode to be used to test the result of the /// comparison libcall against zero. /// FIXME: This should be removed diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h index 71f38bedf17e0..b7660e1e3c3d8 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -106,6 +106,16 @@ struct RuntimeLibcallsInfo { SoftFloatCompareLibcallPredicates[Call] = Pred; } + /// Return a function name compatible with RTLIB::MEMCPY, or nullptr if fully + /// unsupported. + const char *getMemcpyName() const { + if (const char *Memcpy = getLibcallName(RTLIB::MEMCPY)) + return Memcpy; + + // Fallback to memmove if memcpy isn't available. + return getLibcallName(RTLIB::MEMMOVE); + } + private: /// Stores the name each libcall. const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL + 1] = {nullptr}; diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 028bffd1bf5a7..74228df99bb75 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -672,26 +672,30 @@ llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering(); RTLIB::Libcall RTLibcall; unsigned Opc = MI.getOpcode(); + const char *Name; switch (Opc) { case TargetOpcode::G_BZERO: RTLibcall = RTLIB::BZERO; + Name = TLI.getLibcallName(RTLibcall); break; case TargetOpcode::G_MEMCPY: RTLibcall = RTLIB::MEMCPY; + Name = TLI.getMemcpyName(); Args[0].Flags[0].setReturned(); break; case TargetOpcode::G_MEMMOVE: RTLibcall = RTLIB::MEMMOVE; + Name = TLI.getLibcallName(RTLibcall); Args[0].Flags[0].setReturned(); break; case TargetOpcode::G_MEMSET: RTLibcall = RTLIB::MEMSET; + Name = TLI.getLibcallName(RTLibcall); Args[0].Flags[0].setReturned(); break; default: llvm_unreachable("unsupported opcode"); } - const char *Name = TLI.getLibcallName(RTLibcall); // Unsupported libcall on the target. if (!Name) { diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 6f52b7cac1d46..9d1d70b1cb234 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -231,6 +231,14 @@ static bool canEmitLibcall(const TargetMachine *TM, Function *F, return TLI->getLibcallName(LC) != nullptr; } +static bool canEmitMemcpy(const TargetMachine *TM, Function *F) { + // TODO: Should this consider the address space of the memcpy? + if (!TM) + return true; + const TargetLowering *TLI = TM->getSubtargetImpl(*F)->getTargetLowering(); + return TLI->getMemcpyName() != nullptr; +} + // Return a value appropriate for use with the memset_pattern16 libcall, if // possible and if we know how. (Adapted from equivalent helper in // LoopIdiomRecognize). @@ -300,8 +308,7 @@ bool PreISelIntrinsicLowering::expandMemIntrinsicUses(Function &F) const { Function *ParentFunc = Memcpy->getFunction(); const TargetTransformInfo &TTI = LookupTTI(*ParentFunc); if (shouldExpandMemIntrinsicWithSize(Memcpy->getLength(), TTI)) { - if (UseMemIntrinsicLibFunc && - canEmitLibcall(TM, ParentFunc, RTLIB::MEMCPY)) + if (UseMemIntrinsicLibFunc && canEmitMemcpy(TM, ParentFunc)) break; // TODO: For optsize, emit the loop into a separate function diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 5d8db8be9731f..30ee6a99b9dfc 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -8776,11 +8776,12 @@ SDValue SelectionDAG::getMemcpy( // FIXME: pass in SDLoc TargetLowering::CallLoweringInfo CLI(*this); bool IsTailCall = false; + const char *MemCpyName = TLI->getMemcpyName(); + if (OverrideTailCall.has_value()) { IsTailCall = *OverrideTailCall; } else { - bool LowersToMemcpy = - TLI->getLibcallName(RTLIB::MEMCPY) == StringRef("memcpy"); + bool LowersToMemcpy = StringRef(MemCpyName) == StringRef("memcpy"); bool ReturnsFirstArg = CI && funcReturnsFirstArgOfCall(*CI); IsTailCall = CI && CI->isTailCall() && isInTailCallPosition(*CI, getTarget(), @@ -8789,11 +8790,11 @@ SDValue SelectionDAG::getMemcpy( CLI.setDebugLoc(dl) .setChain(Chain) - .setLibCallee(TLI->getLibcallCallingConv(RTLIB::MEMCPY), - Dst.getValueType().getTypeForEVT(*getContext()), - getExternalSymbol(TLI->getLibcallName(RTLIB::MEMCPY), - TLI->getPointerTy(getDataLayout())), - std::move(Args)) + .setLibCallee( + TLI->getLibcallCallingConv(RTLIB::MEMCPY), + Dst.getValueType().getTypeForEVT(*getContext()), + getExternalSymbol(MemCpyName, TLI->getPointerTy(getDataLayout())), + std::move(Args)) .setDiscardResult() .setTailCall(IsTailCall); diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index ad2904d6d2ea6..627c9fa8fac2a 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -416,7 +416,7 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, if (TT.isOSAIX()) { bool isPPC64 = TT.isPPC64(); - setLibcallName(RTLIB::MEMCPY, isPPC64 ? "___memmove64" : "___memmove"); + setLibcallName(RTLIB::MEMCPY, nullptr); setLibcallName(RTLIB::MEMMOVE, isPPC64 ? "___memmove64" : "___memmove"); setLibcallName(RTLIB::MEMSET, isPPC64 ? "___memset64" : "___memset"); setLibcallName(RTLIB::BZERO, isPPC64 ? "___bzero64" : "___bzero");