Skip to content

Commit be6c4d9

Browse files
authored
[PowerPC] using milicode call for strlen instead of lib call (#153600)
AIX has "millicode" routines, which are functions loaded at boot time into fixed addresses in kernel memory. This allows them to be customized for the processor. The __strlen routine is a millicode implementation; we use millicode for the strlen function instead of a library call to improve performance.
1 parent 084872a commit be6c4d9

File tree

11 files changed

+50
-9
lines changed

11 files changed

+50
-9
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,9 @@ class SelectionDAG {
12591259
std::pair<SDValue, SDValue> getMemcmp(SDValue Chain, const SDLoc &dl,
12601260
SDValue Dst, SDValue Src, SDValue Size,
12611261
const CallInst *CI);
1262+
LLVM_ABI std::pair<SDValue, SDValue>
1263+
getStrlen(SDValue Chain, const SDLoc &dl, SDValue Src, const CallInst *CI);
1264+
12621265
/* \p CI if not null is the memset call being lowered.
12631266
* \p OverrideTailCall is an optional parameter that can be used to override
12641267
* the tail call optimization decision. */

llvm/include/llvm/CodeGen/SelectionDAGTargetInfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ class SelectionDAGTargetInfo {
162162

163163
virtual std::pair<SDValue, SDValue>
164164
EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
165-
SDValue Src, MachinePointerInfo SrcPtrInfo) const {
165+
SDValue Src, const CallInst *CI) const {
166166
return std::make_pair(SDValue(), SDValue());
167167
}
168168

llvm/include/llvm/IR/RuntimeLibcalls.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ def MEMMOVE : RuntimeLibcall;
297297
def MEMSET : RuntimeLibcall;
298298
def CALLOC : RuntimeLibcall;
299299
def BZERO : RuntimeLibcall;
300+
def STRLEN : RuntimeLibcall;
300301

301302
// Element-wise unordered-atomic memory of different sizes
302303
foreach MemSize = [1, 2, 4, 8, 16] in {
@@ -2272,13 +2273,15 @@ defset list<RuntimeLibcallImpl> PPC64AIXCallList = {
22722273
def ___memmove64 : RuntimeLibcallImpl<MEMCPY>;
22732274
def ___memset64 : RuntimeLibcallImpl<MEMSET>;
22742275
def ___bzero64 : RuntimeLibcallImpl<BZERO>;
2276+
def ___strlen64 : RuntimeLibcallImpl<STRLEN>;
22752277
}
22762278

22772279
defset list<RuntimeLibcallImpl> PPC32AIXCallList = {
22782280
def ___memcmp : RuntimeLibcallImpl<MEMCMP>;
22792281
def ___memmove : RuntimeLibcallImpl<MEMMOVE>;
22802282
def ___memset : RuntimeLibcallImpl<MEMSET>;
22812283
def ___bzero : RuntimeLibcallImpl<BZERO>;
2284+
def ___strlen : RuntimeLibcallImpl<STRLEN>;
22822285
}
22832286

22842287
defvar PPCOverrides = !foreach(entry, PPCRuntimeLibcalls, entry.Provides);

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9140,6 +9140,33 @@ SelectionDAG::getMemcmp(SDValue Chain, const SDLoc &dl, SDValue Mem0,
91409140
return TLI->LowerCallTo(CLI);
91419141
}
91429142

9143+
std::pair<SDValue, SDValue> SelectionDAG::getStrlen(SDValue Chain,
9144+
const SDLoc &dl,
9145+
SDValue Src,
9146+
const CallInst *CI) {
9147+
const char *LibCallName = TLI->getLibcallName(RTLIB::STRLEN);
9148+
if (!LibCallName)
9149+
return {};
9150+
9151+
// Emit a library call.
9152+
TargetLowering::ArgListTy Args = {
9153+
{Src, PointerType::getUnqual(*getContext())}};
9154+
9155+
TargetLowering::CallLoweringInfo CLI(*this);
9156+
bool IsTailCall =
9157+
isInTailCallPositionWrapper(CI, this, /*AllowReturnsFirstArg*/ true);
9158+
9159+
CLI.setDebugLoc(dl)
9160+
.setChain(Chain)
9161+
.setLibCallee(TLI->getLibcallCallingConv(RTLIB::STRLEN), CI->getType(),
9162+
getExternalSymbol(
9163+
LibCallName, TLI->getProgramPointerTy(getDataLayout())),
9164+
std::move(Args))
9165+
.setTailCall(IsTailCall);
9166+
9167+
return TLI->LowerCallTo(CLI);
9168+
}
9169+
91439170
SDValue SelectionDAG::getMemcpy(
91449171
SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size,
91459172
Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI,

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9330,9 +9330,8 @@ bool SelectionDAGBuilder::visitStrLenCall(const CallInst &I) {
93309330
const Value *Arg0 = I.getArgOperand(0);
93319331

93329332
const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
9333-
std::pair<SDValue, SDValue> Res =
9334-
TSI.EmitTargetCodeForStrlen(DAG, getCurSDLoc(), DAG.getRoot(),
9335-
getValue(Arg0), MachinePointerInfo(Arg0));
9333+
std::pair<SDValue, SDValue> Res = TSI.EmitTargetCodeForStrlen(
9334+
DAG, getCurSDLoc(), DAG.getRoot(), getValue(Arg0), &I);
93369335
if (Res.first.getNode()) {
93379336
processIntegerCallValue(I, Res.first, false);
93389337
PendingLoads.push_back(Res.second);

llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,10 @@ std::pair<SDValue, SDValue> PPCSelectionDAGInfo::EmitTargetCodeForMemcmp(
2828
SDValue Op3, const CallInst *CI) const {
2929
return DAG.getMemcmp(Chain, dl, Op1, Op2, Op3, CI);
3030
}
31+
32+
std::pair<SDValue, SDValue>
33+
PPCSelectionDAGInfo::EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL,
34+
SDValue Chain, SDValue Src,
35+
const CallInst *CI) const {
36+
return DAG.getStrlen(Chain, DL, Src, CI);
37+
}

llvm/lib/Target/PowerPC/PPCSelectionDAGInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ class PPCSelectionDAGInfo : public SelectionDAGTargetInfo {
2525
EmitTargetCodeForMemcmp(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain,
2626
SDValue Op1, SDValue Op2, SDValue Op3,
2727
const CallInst *CI) const override;
28+
std::pair<SDValue, SDValue>
29+
EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
30+
SDValue Src, const CallInst *CI) const override;
2831
};
2932

3033
} // namespace llvm

llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG,
263263

264264
std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrlen(
265265
SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,
266-
MachinePointerInfo SrcPtrInfo) const {
266+
const CallInst *CI) const {
267267
EVT PtrVT = Src.getValueType();
268268
return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT));
269269
}

llvm/lib/Target/SystemZ/SystemZSelectionDAGInfo.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ class SystemZSelectionDAGInfo : public SelectionDAGTargetInfo {
6161

6262
std::pair<SDValue, SDValue>
6363
EmitTargetCodeForStrlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,
64-
SDValue Src,
65-
MachinePointerInfo SrcPtrInfo) const override;
64+
SDValue Src, const CallInst *CI) const override;
6665

6766
std::pair<SDValue, SDValue>
6867
EmitTargetCodeForStrnlen(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,

llvm/test/CodeGen/PowerPC/milicode32.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ define i32 @strlen_test(ptr noundef %str) nounwind {
4242
; CHECK-AIX-32-P9-NEXT: stwu r1, -64(r1)
4343
; CHECK-AIX-32-P9-NEXT: stw r0, 72(r1)
4444
; CHECK-AIX-32-P9-NEXT: stw r3, 60(r1)
45-
; CHECK-AIX-32-P9-NEXT: bl .strlen[PR]
45+
; CHECK-AIX-32-P9-NEXT: bl .___strlen[PR]
4646
; CHECK-AIX-32-P9-NEXT: nop
4747
; CHECK-AIX-32-P9-NEXT: addi r1, r1, 64
4848
; CHECK-AIX-32-P9-NEXT: lwz r0, 8(r1)

0 commit comments

Comments
 (0)