[llvm] PowerPC: Stop reporting memcpy as an alias of memmove on AIX (PR #143836)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 19 19:50:19 PDT 2025
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/143836
>From bc991e7373c129a8e4d8429348e57802c5c32cb9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
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");
More information about the llvm-commits
mailing list