diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index b856b4786573b..89f7641ef27f8 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -1257,6 +1257,9 @@ class SelectionDAG { /// stack arguments from being clobbered. LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain); + std::pair 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 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 a954dde9fb223..a04de6d5df443 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.td +++ b/llvm/include/llvm/IR/RuntimeLibcalls.td @@ -248,6 +248,7 @@ foreach FPTy = ["F32", "F64", "F128", "PPCF128"] in { } // Memory +def MEMCMP : RuntimeLibcall; def MEMCPY : RuntimeLibcall; def MEMMOVE : RuntimeLibcall; def MEMSET : RuntimeLibcall; @@ -1739,12 +1740,14 @@ defset list PPCRuntimeLibcalls = { } defset list PPC64AIXCallList = { + def ___memcmp64 : RuntimeLibcallImpl; def ___memmove64 : RuntimeLibcallImpl; def ___memset64 : RuntimeLibcallImpl; def ___bzero64 : RuntimeLibcallImpl; } defset list PPC32AIXCallList = { + def ___memcmp : RuntimeLibcallImpl; def ___memmove : RuntimeLibcallImpl; def ___memset : RuntimeLibcallImpl; def ___bzero : RuntimeLibcallImpl; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c1356239ad206..54446fa4a74cf 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -8820,6 +8820,45 @@ static void checkAddrSpaceIsValidForLibcall(const TargetLowering *TLI, Twine(AS)); } } +std::pair +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 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 ecd1ff87e7fbc..2dd28185326b7 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 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/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 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 + 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 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(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 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 EmitTargetCodeForMemchr(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 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)