[llvm] [PowerPC][AIX] Using milicode for memcmp instead of libcall (PR #147093)
zhijian lin via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 9 11:15:32 PDT 2025
https://github.com/diggerlin updated https://github.com/llvm/llvm-project/pull/147093
>From 16a43afcf4769d6b2fd06d4502be11f2920ccb5a Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Fri, 27 Jun 2025 21:02:33 +0000
Subject: [PATCH 1/3] implement milicode memcmp
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index ecd1ff87e7fbc..5bc71bdbccf43 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9065,8 +9065,15 @@ bool SelectionDAGBuilder::visitMemCmpBCmpCall(const CallInst &I) {
// memcmp(S1,S2,2) != 0 -> (*(short*)LHS != *(short*)RHS) != 0
// memcmp(S1,S2,4) != 0 -> (*(int*)LHS != *(int*)RHS) != 0
- if (!CSize || !isOnlyUsedInZeroEqualityComparison(&I))
+ if (!CSize || !isOnlyUsedInZeroEqualityComparison(&I)) {
+ const Triple& TheTriple = TM.getTargetTriple();
+ if(TheTriple.isOSAIX()) {
+ if (Function *F = I.getCalledFunction()) {
+ F->setName(TheTriple.isArch32Bit() ? "___memcmp" : "___memcmp64");
+ }
+ }
return false;
+ }
// If the target has a fast compare for the given size, it will return a
// preferred load type for that size. Require that the load VT is legal and
>From c97352653a6c2cbe3cdfa66adbfd90d5c7b0f4f9 Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Fri, 4 Jul 2025 18:02:53 +0000
Subject: [PATCH 2/3] modify test case based on new behavious
---
llvm/test/CodeGen/PowerPC/memintr32.ll | 2 +-
llvm/test/CodeGen/PowerPC/memintr64.ll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/PowerPC/memintr32.ll b/llvm/test/CodeGen/PowerPC/memintr32.ll
index c07a5af17e48a..4f0a9960a546d 100644
--- a/llvm/test/CodeGen/PowerPC/memintr32.ll
+++ b/llvm/test/CodeGen/PowerPC/memintr32.ll
@@ -11,7 +11,7 @@ define i32 @memcmp_test(ptr nocapture noundef readonly %ptr1, ptr nocapture noun
; CHECK-AIX-32-P9-NEXT: mflr r0
; CHECK-AIX-32-P9-NEXT: stwu r1, -64(r1)
; CHECK-AIX-32-P9-NEXT: stw r0, 72(r1)
-; CHECK-AIX-32-P9-NEXT: bl .memcmp[PR]
+; CHECK-AIX-32-P9-NEXT: bl .___memcmp[PR]
; CHECK-AIX-32-P9-NEXT: nop
; CHECK-AIX-32-P9-NEXT: addi r1, r1, 64
; CHECK-AIX-32-P9-NEXT: lwz r0, 8(r1)
diff --git a/llvm/test/CodeGen/PowerPC/memintr64.ll b/llvm/test/CodeGen/PowerPC/memintr64.ll
index b3a6650b8f6e6..0b0e556e89b51 100644
--- a/llvm/test/CodeGen/PowerPC/memintr64.ll
+++ b/llvm/test/CodeGen/PowerPC/memintr64.ll
@@ -39,7 +39,7 @@ define noundef i32 @_Z11memcmp_testPKvS0_m(ptr noundef readonly captures(none) %
; CHECK-AIX-64-P9-NEXT: mflr r0
; CHECK-AIX-64-P9-NEXT: stdu r1, -112(r1)
; CHECK-AIX-64-P9-NEXT: std r0, 128(r1)
-; CHECK-AIX-64-P9-NEXT: bl .memcmp[PR]
+; CHECK-AIX-64-P9-NEXT: bl .___memcmp64[PR]
; CHECK-AIX-64-P9-NEXT: nop
; CHECK-AIX-64-P9-NEXT: addi r1, r1, 112
; CHECK-AIX-64-P9-NEXT: ld r0, 16(r1)
>From 91fb8a7a45a1a6fa54c5755afde9be1e96c800eb Mon Sep 17 00:00:00 2001
From: zhijian <zhijian at ca.ibm.com>
Date: Wed, 9 Jul 2025 18:18:51 +0000
Subject: [PATCH 3/3] address comment
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 3 ++
.../llvm/CodeGen/SelectionDAGTargetInfo.h | 5 +--
llvm/include/llvm/IR/RuntimeLibcalls.td | 3 ++
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 39 +++++++++++++++++++
.../SelectionDAG/SelectionDAGBuilder.cpp | 2 +-
llvm/lib/IR/RuntimeLibcalls.cpp | 2 +
.../Target/PowerPC/PPCSelectionDAGInfo.cpp | 6 +++
llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h | 5 +++
.../SystemZ/SystemZSelectionDAGInfo.cpp | 3 +-
.../Target/SystemZ/SystemZSelectionDAGInfo.h | 3 +-
10 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index a98e46c587273..f9f2d57831ce2 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1253,6 +1253,9 @@ class SelectionDAG {
/// stack arguments from being clobbered.
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain);
+ std::pair<SDValue, SDValue> getMemcmp(SDValue Chain, const SDLoc &dl,
+ SDValue Dst, SDValue Src, SDValue Size,
+ const CallInst *CI);
/* \p CI if not null is the memset call being lowered.
* \p OverrideTailCall is an optional parameter that can be used to override
* the tail call optimization decision. */
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h b/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
index 463f0ec350d9c..c071de43e2be1 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h
@@ -24,7 +24,7 @@
namespace llvm {
class SelectionDAG;
-
+class CallInst;
//===----------------------------------------------------------------------===//
/// Targets can subclass this to parameterize the
/// SelectionDAG lowering and instruction selection process.
@@ -118,8 +118,7 @@ class SelectionDAGTargetInfo {
virtual std::pair<SDValue, SDValue>
EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
SDValue Op1, SDValue Op2, SDValue Op3,
- MachinePointerInfo Op1PtrInfo,
- MachinePointerInfo Op2PtrInfo) const {
+ const CallInst *CI) const {
return std::make_pair(SDValue(), SDValue());
}
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 1b54be8dca418..750b2b15668f6 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -241,6 +241,7 @@ foreach FPTy = ["F32", "F64", "F128", "PPCF128"] in {
}
// Memory
+def MEMCMP : RuntimeLibcall;
def MEMCPY : RuntimeLibcall;
def MEMMOVE : RuntimeLibcall;
def MEMSET : RuntimeLibcall;
@@ -1485,11 +1486,13 @@ def __gtkf2 : PPCRuntimeLibcallImpl<OGT_F128>;
def __unordkf2 : PPCRuntimeLibcallImpl<UO_F128>;
// PPC64 && Subtarget.isAIXABI()
+def ___memcmp64 : RuntimeLibcallImpl<MEMCPY>;
def ___memmove64 : RuntimeLibcallImpl<MEMCPY>;
def ___memset64 : RuntimeLibcallImpl<MEMSET>;
def ___bzero64 : RuntimeLibcallImpl<BZERO>;
// !PPC64 && Subtarget.isAIXABI()
+def ___memcmp : RuntimeLibcallImpl<MEMCMP>;
def ___memmove : RuntimeLibcallImpl<MEMMOVE>;
def ___memset : RuntimeLibcallImpl<MEMSET>;
def ___bzero : RuntimeLibcallImpl<BZERO>;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 2a3c8e2b011ad..cd63706f6e423 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -8743,6 +8743,45 @@ static void checkAddrSpaceIsValidForLibcall(const TargetLowering *TLI,
Twine(AS));
}
}
+std::pair<SDValue, SDValue>
+SelectionDAG::getMemcmp(SDValue Chain, const SDLoc &dl, SDValue Mem0,
+ SDValue Mem1, SDValue Size, const CallInst *CI) {
+
+ const char *LibCallName = TLI->getLibcallName(RTLIB::MEMCMP);
+ if (LibCallName == nullptr)
+ return std::make_pair(SDValue(), SDValue());
+ // Emit a library call.
+ TargetLowering::ArgListTy Args;
+ TargetLowering::ArgListEntry Entry;
+ Entry.Ty = PointerType::getUnqual(*getContext());
+ Entry.Node = Mem0;
+ Args.push_back(Entry);
+ Entry.Node = Mem1;
+ Args.push_back(Entry);
+
+ Entry.Ty = getDataLayout().getIntPtrType(*getContext());
+ Entry.Node = Size;
+ Args.push_back(Entry);
+
+ // FIXME: pass in SDLoc
+ TargetLowering::CallLoweringInfo CLI(*this);
+ bool IsTailCall = false;
+ bool ReturnsFirstArg = CI && funcReturnsFirstArgOfCall(*CI);
+ IsTailCall = CI && CI->isTailCall() &&
+ isInTailCallPosition(*CI, getTarget(), ReturnsFirstArg);
+
+ CLI.setDebugLoc(dl)
+ .setChain(Chain)
+ .setLibCallee(
+ TLI->getLibcallCallingConv(RTLIB::MEMCMP),
+ Type::getInt32Ty(*getContext()),
+ getExternalSymbol(LibCallName, TLI->getPointerTy(getDataLayout())),
+ std::move(Args))
+ .setTailCall(IsTailCall);
+
+ std::pair<SDValue, SDValue> CallResult = TLI->LowerCallTo(CLI);
+ return CallResult;
+}
SDValue SelectionDAG::getMemcpy(
SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size,
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 5bc71bdbccf43..25b93fa23a7d1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9056,7 +9056,7 @@ bool SelectionDAGBuilder::visitMemCmpBCmpCall(const CallInst &I) {
const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
std::pair<SDValue, SDValue> Res = TSI.EmitTargetCodeForMemcmp(
DAG, getCurSDLoc(), DAG.getRoot(), getValue(LHS), getValue(RHS),
- getValue(Size), MachinePointerInfo(LHS), MachinePointerInfo(RHS));
+ getValue(Size), &I);
if (Res.first.getNode()) {
processIntegerCallValue(I, Res.first, true);
PendingLoads.push_back(Res.second);
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 712f1a48d0b7b..9cee314709607 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -376,11 +376,13 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
// TODO: Tablegen predicate support
if (TT.isOSAIX()) {
if (TT.isPPC64()) {
+ setLibcallImpl(RTLIB::MEMCMP, RTLIB::___memcmp64);
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove64);
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset64);
setLibcallImpl(RTLIB::BZERO, RTLIB::___bzero64);
} else {
+ setLibcallImpl(RTLIB::MEMCMP, RTLIB::___memcmp);
setLibcallImpl(RTLIB::MEMCPY, RTLIB::Unsupported);
setLibcallImpl(RTLIB::MEMMOVE, RTLIB::___memmove);
setLibcallImpl(RTLIB::MEMSET, RTLIB::___memset);
diff --git a/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp b/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp
index 95de9f39b86e8..4039fedd0cb5c 100644
--- a/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp
@@ -22,3 +22,9 @@ bool PPCSelectionDAGInfo::isTargetStrictFPOpcode(unsigned Opcode) const {
return Opcode >= PPCISD::FIRST_STRICTFP_OPCODE &&
Opcode <= PPCISD::LAST_STRICTFP_OPCODE;
}
+
+std::pair<SDValue, SDValue> PPCSelectionDAGInfo::EmitTargetCodeForMemcmp(
+ SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1, SDValue Op2,
+ SDValue Op3, const CallInst *CI) const {
+ return DAG.getMemcmp(Chain, dl, Op1, Op2, Op3, CI);
+}
diff --git a/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h b/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h
index 08e2ddbf1c4ca..5635c6aea7e2e 100644
--- a/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h
@@ -20,6 +20,11 @@ class PPCSelectionDAGInfo : public SelectionDAGTargetInfo {
bool isTargetMemoryOpcode(unsigned Opcode) const override;
bool isTargetStrictFPOpcode(unsigned Opcode) const override;
+
+ std::pair<SDValue, SDValue>
+ EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
+ SDValue Op1, SDValue Op2, SDValue Op3,
+ const CallInst *CI) const;
};
} // namespace llvm
diff --git a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
index d76babec73dd4..afe838ac973e6 100644
--- a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp
@@ -181,8 +181,7 @@ static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,
std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(
SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,
- SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo,
- MachinePointerInfo Op2PtrInfo) const {
+ SDValue Src2, SDValue Size, const CallInst *CI) const {
SDValue CCReg;
// Swap operands to invert CC == 1 vs. CC == 2 cases.
if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {
diff --git a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
index c928f343e5710..5a1e0cd108e77 100644
--- a/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h
@@ -41,8 +41,7 @@ class SystemZSelectionDAGInfo : public SelectionDAGTargetInfo {
std::pair<SDValue, SDValue>
EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
SDValue Src1, SDValue Src2, SDValue Size,
- MachinePointerInfo Op1PtrInfo,
- MachinePointerInfo Op2PtrInfo) const override;
+ const CallInst *CI) const override;
std::pair<SDValue, SDValue>
EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
More information about the llvm-commits
mailing list