1*0b57cec5SDimitry Andric //===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the SystemZSelectionDAGInfo class. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "SystemZTargetMachine.h" 14*0b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric using namespace llvm; 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-selectiondag-info" 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric // Decide whether it is best to use a loop or straight-line code for 21*0b57cec5SDimitry Andric // a block operation of Size bytes with source address Src and destination 22*0b57cec5SDimitry Andric // address Dest. Sequence is the opcode to use for straight-line code 23*0b57cec5SDimitry Andric // (such as MVC) and Loop is the opcode to use for loops (such as MVC_LOOP). 24*0b57cec5SDimitry Andric // Return the chain for the completed operation. 25*0b57cec5SDimitry Andric static SDValue emitMemMem(SelectionDAG &DAG, const SDLoc &DL, unsigned Sequence, 26*0b57cec5SDimitry Andric unsigned Loop, SDValue Chain, SDValue Dst, 27*0b57cec5SDimitry Andric SDValue Src, uint64_t Size) { 28*0b57cec5SDimitry Andric EVT PtrVT = Src.getValueType(); 29*0b57cec5SDimitry Andric // The heuristic we use is to prefer loops for anything that would 30*0b57cec5SDimitry Andric // require 7 or more MVCs. With these kinds of sizes there isn't 31*0b57cec5SDimitry Andric // much to choose between straight-line code and looping code, 32*0b57cec5SDimitry Andric // since the time will be dominated by the MVCs themselves. 33*0b57cec5SDimitry Andric // However, the loop has 4 or 5 instructions (depending on whether 34*0b57cec5SDimitry Andric // the base addresses can be proved equal), so there doesn't seem 35*0b57cec5SDimitry Andric // much point using a loop for 5 * 256 bytes or fewer. Anything in 36*0b57cec5SDimitry Andric // the range (5 * 256, 6 * 256) will need another instruction after 37*0b57cec5SDimitry Andric // the loop, so it doesn't seem worth using a loop then either. 38*0b57cec5SDimitry Andric // The next value up, 6 * 256, can be implemented in the same 39*0b57cec5SDimitry Andric // number of straight-line MVCs as 6 * 256 - 1. 40*0b57cec5SDimitry Andric if (Size > 6 * 256) 41*0b57cec5SDimitry Andric return DAG.getNode(Loop, DL, MVT::Other, Chain, Dst, Src, 42*0b57cec5SDimitry Andric DAG.getConstant(Size, DL, PtrVT), 43*0b57cec5SDimitry Andric DAG.getConstant(Size / 256, DL, PtrVT)); 44*0b57cec5SDimitry Andric return DAG.getNode(Sequence, DL, MVT::Other, Chain, Dst, Src, 45*0b57cec5SDimitry Andric DAG.getConstant(Size, DL, PtrVT)); 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric SDValue SystemZSelectionDAGInfo::EmitTargetCodeForMemcpy( 49*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src, 50*0b57cec5SDimitry Andric SDValue Size, unsigned Align, bool IsVolatile, bool AlwaysInline, 51*0b57cec5SDimitry Andric MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const { 52*0b57cec5SDimitry Andric if (IsVolatile) 53*0b57cec5SDimitry Andric return SDValue(); 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) 56*0b57cec5SDimitry Andric return emitMemMem(DAG, DL, SystemZISD::MVC, SystemZISD::MVC_LOOP, 57*0b57cec5SDimitry Andric Chain, Dst, Src, CSize->getZExtValue()); 58*0b57cec5SDimitry Andric return SDValue(); 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric // Handle a memset of 1, 2, 4 or 8 bytes with the operands given by 62*0b57cec5SDimitry Andric // Chain, Dst, ByteVal and Size. These cases are expected to use 63*0b57cec5SDimitry Andric // MVI, MVHHI, MVHI and MVGHI respectively. 64*0b57cec5SDimitry Andric static SDValue memsetStore(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 65*0b57cec5SDimitry Andric SDValue Dst, uint64_t ByteVal, uint64_t Size, 66*0b57cec5SDimitry Andric unsigned Align, MachinePointerInfo DstPtrInfo) { 67*0b57cec5SDimitry Andric uint64_t StoreVal = ByteVal; 68*0b57cec5SDimitry Andric for (unsigned I = 1; I < Size; ++I) 69*0b57cec5SDimitry Andric StoreVal |= ByteVal << (I * 8); 70*0b57cec5SDimitry Andric return DAG.getStore( 71*0b57cec5SDimitry Andric Chain, DL, DAG.getConstant(StoreVal, DL, MVT::getIntegerVT(Size * 8)), 72*0b57cec5SDimitry Andric Dst, DstPtrInfo, Align); 73*0b57cec5SDimitry Andric } 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric SDValue SystemZSelectionDAGInfo::EmitTargetCodeForMemset( 76*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, 77*0b57cec5SDimitry Andric SDValue Byte, SDValue Size, unsigned Align, bool IsVolatile, 78*0b57cec5SDimitry Andric MachinePointerInfo DstPtrInfo) const { 79*0b57cec5SDimitry Andric EVT PtrVT = Dst.getValueType(); 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric if (IsVolatile) 82*0b57cec5SDimitry Andric return SDValue(); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { 85*0b57cec5SDimitry Andric uint64_t Bytes = CSize->getZExtValue(); 86*0b57cec5SDimitry Andric if (Bytes == 0) 87*0b57cec5SDimitry Andric return SDValue(); 88*0b57cec5SDimitry Andric if (auto *CByte = dyn_cast<ConstantSDNode>(Byte)) { 89*0b57cec5SDimitry Andric // Handle cases that can be done using at most two of 90*0b57cec5SDimitry Andric // MVI, MVHI, MVHHI and MVGHI. The latter two can only be 91*0b57cec5SDimitry Andric // used if ByteVal is all zeros or all ones; in other casees, 92*0b57cec5SDimitry Andric // we can move at most 2 halfwords. 93*0b57cec5SDimitry Andric uint64_t ByteVal = CByte->getZExtValue(); 94*0b57cec5SDimitry Andric if (ByteVal == 0 || ByteVal == 255 ? 95*0b57cec5SDimitry Andric Bytes <= 16 && countPopulation(Bytes) <= 2 : 96*0b57cec5SDimitry Andric Bytes <= 4) { 97*0b57cec5SDimitry Andric unsigned Size1 = Bytes == 16 ? 8 : 1 << findLastSet(Bytes); 98*0b57cec5SDimitry Andric unsigned Size2 = Bytes - Size1; 99*0b57cec5SDimitry Andric SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1, 100*0b57cec5SDimitry Andric Align, DstPtrInfo); 101*0b57cec5SDimitry Andric if (Size2 == 0) 102*0b57cec5SDimitry Andric return Chain1; 103*0b57cec5SDimitry Andric Dst = DAG.getNode(ISD::ADD, DL, PtrVT, Dst, 104*0b57cec5SDimitry Andric DAG.getConstant(Size1, DL, PtrVT)); 105*0b57cec5SDimitry Andric DstPtrInfo = DstPtrInfo.getWithOffset(Size1); 106*0b57cec5SDimitry Andric SDValue Chain2 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2, 107*0b57cec5SDimitry Andric std::min(Align, Size1), DstPtrInfo); 108*0b57cec5SDimitry Andric return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2); 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric } else { 111*0b57cec5SDimitry Andric // Handle one and two bytes using STC. 112*0b57cec5SDimitry Andric if (Bytes <= 2) { 113*0b57cec5SDimitry Andric SDValue Chain1 = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo, Align); 114*0b57cec5SDimitry Andric if (Bytes == 1) 115*0b57cec5SDimitry Andric return Chain1; 116*0b57cec5SDimitry Andric SDValue Dst2 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst, 117*0b57cec5SDimitry Andric DAG.getConstant(1, DL, PtrVT)); 118*0b57cec5SDimitry Andric SDValue Chain2 = 119*0b57cec5SDimitry Andric DAG.getStore(Chain, DL, Byte, Dst2, DstPtrInfo.getWithOffset(1), 120*0b57cec5SDimitry Andric /* Alignment = */ 1); 121*0b57cec5SDimitry Andric return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2); 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric } 124*0b57cec5SDimitry Andric assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already"); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric // Handle the special case of a memset of 0, which can use XC. 127*0b57cec5SDimitry Andric auto *CByte = dyn_cast<ConstantSDNode>(Byte); 128*0b57cec5SDimitry Andric if (CByte && CByte->getZExtValue() == 0) 129*0b57cec5SDimitry Andric return emitMemMem(DAG, DL, SystemZISD::XC, SystemZISD::XC_LOOP, 130*0b57cec5SDimitry Andric Chain, Dst, Dst, Bytes); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric // Copy the byte to the first location and then use MVC to copy 133*0b57cec5SDimitry Andric // it to the rest. 134*0b57cec5SDimitry Andric Chain = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo, Align); 135*0b57cec5SDimitry Andric SDValue DstPlus1 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst, 136*0b57cec5SDimitry Andric DAG.getConstant(1, DL, PtrVT)); 137*0b57cec5SDimitry Andric return emitMemMem(DAG, DL, SystemZISD::MVC, SystemZISD::MVC_LOOP, 138*0b57cec5SDimitry Andric Chain, DstPlus1, Dst, Bytes - 1); 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric return SDValue(); 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric // Use CLC to compare [Src1, Src1 + Size) with [Src2, Src2 + Size), 144*0b57cec5SDimitry Andric // deciding whether to use a loop or straight-line code. 145*0b57cec5SDimitry Andric static SDValue emitCLC(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, 146*0b57cec5SDimitry Andric SDValue Src1, SDValue Src2, uint64_t Size) { 147*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other); 148*0b57cec5SDimitry Andric EVT PtrVT = Src1.getValueType(); 149*0b57cec5SDimitry Andric // A two-CLC sequence is a clear win over a loop, not least because it 150*0b57cec5SDimitry Andric // needs only one branch. A three-CLC sequence needs the same number 151*0b57cec5SDimitry Andric // of branches as a loop (i.e. 2), but is shorter. That brings us to 152*0b57cec5SDimitry Andric // lengths greater than 768 bytes. It seems relatively likely that 153*0b57cec5SDimitry Andric // a difference will be found within the first 768 bytes, so we just 154*0b57cec5SDimitry Andric // optimize for the smallest number of branch instructions, in order 155*0b57cec5SDimitry Andric // to avoid polluting the prediction buffer too much. A loop only ever 156*0b57cec5SDimitry Andric // needs 2 branches, whereas a straight-line sequence would need 3 or more. 157*0b57cec5SDimitry Andric if (Size > 3 * 256) 158*0b57cec5SDimitry Andric return DAG.getNode(SystemZISD::CLC_LOOP, DL, VTs, Chain, Src1, Src2, 159*0b57cec5SDimitry Andric DAG.getConstant(Size, DL, PtrVT), 160*0b57cec5SDimitry Andric DAG.getConstant(Size / 256, DL, PtrVT)); 161*0b57cec5SDimitry Andric return DAG.getNode(SystemZISD::CLC, DL, VTs, Chain, Src1, Src2, 162*0b57cec5SDimitry Andric DAG.getConstant(Size, DL, PtrVT)); 163*0b57cec5SDimitry Andric } 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric // Convert the current CC value into an integer that is 0 if CC == 0, 166*0b57cec5SDimitry Andric // greater than zero if CC == 1 and less than zero if CC >= 2. 167*0b57cec5SDimitry Andric // The sequence starts with IPM, which puts CC into bits 29 and 28 168*0b57cec5SDimitry Andric // of an integer and clears bits 30 and 31. 169*0b57cec5SDimitry Andric static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg, 170*0b57cec5SDimitry Andric SelectionDAG &DAG) { 171*0b57cec5SDimitry Andric SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); 172*0b57cec5SDimitry Andric SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM, 173*0b57cec5SDimitry Andric DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32)); 174*0b57cec5SDimitry Andric SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL, 175*0b57cec5SDimitry Andric DAG.getConstant(30, DL, MVT::i32)); 176*0b57cec5SDimitry Andric return SRA; 177*0b57cec5SDimitry Andric } 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( 180*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, 181*0b57cec5SDimitry Andric SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo, 182*0b57cec5SDimitry Andric MachinePointerInfo Op2PtrInfo) const { 183*0b57cec5SDimitry Andric if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { 184*0b57cec5SDimitry Andric uint64_t Bytes = CSize->getZExtValue(); 185*0b57cec5SDimitry Andric assert(Bytes > 0 && "Caller should have handled 0-size case"); 186*0b57cec5SDimitry Andric // Swap operands to invert CC == 1 vs. CC == 2 cases. 187*0b57cec5SDimitry Andric SDValue CCReg = emitCLC(DAG, DL, Chain, Src2, Src1, Bytes); 188*0b57cec5SDimitry Andric Chain = CCReg.getValue(1); 189*0b57cec5SDimitry Andric return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain); 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric return std::make_pair(SDValue(), SDValue()); 192*0b57cec5SDimitry Andric } 193*0b57cec5SDimitry Andric 194*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemchr( 195*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, 196*0b57cec5SDimitry Andric SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const { 197*0b57cec5SDimitry Andric // Use SRST to find the character. End is its address on success. 198*0b57cec5SDimitry Andric EVT PtrVT = Src.getValueType(); 199*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other); 200*0b57cec5SDimitry Andric Length = DAG.getZExtOrTrunc(Length, DL, PtrVT); 201*0b57cec5SDimitry Andric Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32); 202*0b57cec5SDimitry Andric Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char, 203*0b57cec5SDimitry Andric DAG.getConstant(255, DL, MVT::i32)); 204*0b57cec5SDimitry Andric SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length); 205*0b57cec5SDimitry Andric SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain, 206*0b57cec5SDimitry Andric Limit, Src, Char); 207*0b57cec5SDimitry Andric SDValue CCReg = End.getValue(1); 208*0b57cec5SDimitry Andric Chain = End.getValue(2); 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric // Now select between End and null, depending on whether the character 211*0b57cec5SDimitry Andric // was found. 212*0b57cec5SDimitry Andric SDValue Ops[] = {End, DAG.getConstant(0, DL, PtrVT), 213*0b57cec5SDimitry Andric DAG.getConstant(SystemZ::CCMASK_SRST, DL, MVT::i32), 214*0b57cec5SDimitry Andric DAG.getConstant(SystemZ::CCMASK_SRST_FOUND, DL, MVT::i32), 215*0b57cec5SDimitry Andric CCReg}; 216*0b57cec5SDimitry Andric End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, PtrVT, Ops); 217*0b57cec5SDimitry Andric return std::make_pair(End, Chain); 218*0b57cec5SDimitry Andric } 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcpy( 221*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dest, 222*0b57cec5SDimitry Andric SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo, 223*0b57cec5SDimitry Andric bool isStpcpy) const { 224*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other); 225*0b57cec5SDimitry Andric SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src, 226*0b57cec5SDimitry Andric DAG.getConstant(0, DL, MVT::i32)); 227*0b57cec5SDimitry Andric return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1)); 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp( 231*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1, 232*0b57cec5SDimitry Andric SDValue Src2, MachinePointerInfo Op1PtrInfo, 233*0b57cec5SDimitry Andric MachinePointerInfo Op2PtrInfo) const { 234*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other); 235*0b57cec5SDimitry Andric // Swap operands to invert CC == 1 vs. CC == 2 cases. 236*0b57cec5SDimitry Andric SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1, 237*0b57cec5SDimitry Andric DAG.getConstant(0, DL, MVT::i32)); 238*0b57cec5SDimitry Andric SDValue CCReg = Unused.getValue(1); 239*0b57cec5SDimitry Andric Chain = Unused.getValue(2); 240*0b57cec5SDimitry Andric return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain); 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric 243*0b57cec5SDimitry Andric // Search from Src for a null character, stopping once Src reaches Limit. 244*0b57cec5SDimitry Andric // Return a pair of values, the first being the number of nonnull characters 245*0b57cec5SDimitry Andric // and the second being the out chain. 246*0b57cec5SDimitry Andric // 247*0b57cec5SDimitry Andric // This can be used for strlen by setting Limit to 0. 248*0b57cec5SDimitry Andric static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG, 249*0b57cec5SDimitry Andric const SDLoc &DL, 250*0b57cec5SDimitry Andric SDValue Chain, SDValue Src, 251*0b57cec5SDimitry Andric SDValue Limit) { 252*0b57cec5SDimitry Andric EVT PtrVT = Src.getValueType(); 253*0b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other); 254*0b57cec5SDimitry Andric SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain, 255*0b57cec5SDimitry Andric Limit, Src, DAG.getConstant(0, DL, MVT::i32)); 256*0b57cec5SDimitry Andric Chain = End.getValue(2); 257*0b57cec5SDimitry Andric SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src); 258*0b57cec5SDimitry Andric return std::make_pair(Len, Chain); 259*0b57cec5SDimitry Andric } 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrlen( 262*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, 263*0b57cec5SDimitry Andric MachinePointerInfo SrcPtrInfo) const { 264*0b57cec5SDimitry Andric EVT PtrVT = Src.getValueType(); 265*0b57cec5SDimitry Andric return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT)); 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrnlen( 269*0b57cec5SDimitry Andric SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src, 270*0b57cec5SDimitry Andric SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const { 271*0b57cec5SDimitry Andric EVT PtrVT = Src.getValueType(); 272*0b57cec5SDimitry Andric MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT); 273*0b57cec5SDimitry Andric SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength); 274*0b57cec5SDimitry Andric return getBoundedStrlen(DAG, DL, Chain, Src, Limit); 275*0b57cec5SDimitry Andric } 276