brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.5 KiB · 88feba8 Raw
285 lines · cpp
1//===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the SystemZSelectionDAGInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "SystemZSelectionDAGInfo.h"14#include "SystemZTargetMachine.h"15#include "llvm/CodeGen/SelectionDAG.h"16 17#define GET_SDNODE_DESC18#include "SystemZGenSDNodeInfo.inc"19 20using namespace llvm;21 22#define DEBUG_TYPE "systemz-selectiondag-info"23 24SystemZSelectionDAGInfo::SystemZSelectionDAGInfo()25    : SelectionDAGGenTargetInfo(SystemZGenSDNodeInfo) {}26 27const char *SystemZSelectionDAGInfo::getTargetNodeName(unsigned Opcode) const {28  switch (static_cast<SystemZISD::NodeType>(Opcode)) {29  case SystemZISD::GET_CCMASK:30    return "SystemZISD::GET_CCMASK";31  }32 33  return SelectionDAGGenTargetInfo::getTargetNodeName(Opcode);34}35 36static unsigned getMemMemLenAdj(unsigned Op) {37  return Op == SystemZISD::MEMSET_MVC ? 2 : 1;38}39 40static SDValue createMemMemNode(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,41                                SDValue Chain, SDValue Dst, SDValue Src,42                                SDValue LenAdj, SDValue Byte) {43  SDVTList VTs = Op == SystemZISD::CLC ? DAG.getVTList(MVT::i32, MVT::Other)44                                       : DAG.getVTList(MVT::Other);45  SmallVector<SDValue, 6> Ops;46  if (Op == SystemZISD::MEMSET_MVC)47    Ops = { Chain, Dst, LenAdj, Byte };48  else49    Ops = { Chain, Dst, Src, LenAdj };50  return DAG.getNode(Op, DL, VTs, Ops);51}52 53// Emit a mem-mem operation after subtracting one (or two for memset) from54// size, which will be added back during pseudo expansion. As the Reg case55// emitted here may be converted by DAGCombiner into having an Imm length,56// they are both emitted the same way.57static SDValue emitMemMemImm(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,58                             SDValue Chain, SDValue Dst, SDValue Src,59                             uint64_t Size, SDValue Byte = SDValue()) {60  unsigned Adj = getMemMemLenAdj(Op);61  assert(Size >= Adj && "Adjusted length overflow.");62  SDValue LenAdj = DAG.getConstant(Size - Adj, DL, Dst.getValueType());63  return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);64}65 66static SDValue emitMemMemReg(SelectionDAG &DAG, const SDLoc &DL, unsigned Op,67                             SDValue Chain, SDValue Dst, SDValue Src,68                             SDValue Size, SDValue Byte = SDValue()) {69  int64_t Adj = getMemMemLenAdj(Op);70  SDValue LenAdj = DAG.getNode(ISD::ADD, DL, MVT::i64,71                               DAG.getZExtOrTrunc(Size, DL, MVT::i64),72                               DAG.getSignedConstant(0 - Adj, DL, MVT::i64));73  return createMemMemNode(DAG, DL, Op, Chain, Dst, Src, LenAdj, Byte);74}75 76SDValue SystemZSelectionDAGInfo::EmitTargetCodeForMemcpy(77    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst, SDValue Src,78    SDValue Size, Align Alignment, bool IsVolatile, bool AlwaysInline,79    MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {80  if (IsVolatile)81    return SDValue();82 83  if (auto *CSize = dyn_cast<ConstantSDNode>(Size))84    return emitMemMemImm(DAG, DL, SystemZISD::MVC, Chain, Dst, Src,85                         CSize->getZExtValue());86 87  return emitMemMemReg(DAG, DL, SystemZISD::MVC, Chain, Dst, Src, Size);88}89 90// Handle a memset of 1, 2, 4 or 8 bytes with the operands given by91// Chain, Dst, ByteVal and Size.  These cases are expected to use92// MVI, MVHHI, MVHI and MVGHI respectively.93static SDValue memsetStore(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain,94                           SDValue Dst, uint64_t ByteVal, uint64_t Size,95                           Align Alignment, MachinePointerInfo DstPtrInfo) {96  uint64_t StoreVal = ByteVal;97  for (unsigned I = 1; I < Size; ++I)98    StoreVal |= ByteVal << (I * 8);99  return DAG.getStore(100      Chain, DL, DAG.getConstant(StoreVal, DL, MVT::getIntegerVT(Size * 8)),101      Dst, DstPtrInfo, Alignment);102}103 104SDValue SystemZSelectionDAGInfo::EmitTargetCodeForMemset(105    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dst,106    SDValue Byte, SDValue Size, Align Alignment, bool IsVolatile,107    bool AlwaysInline, MachinePointerInfo DstPtrInfo) const {108  EVT PtrVT = Dst.getValueType();109 110  if (IsVolatile)111    return SDValue();112 113  auto *CByte = dyn_cast<ConstantSDNode>(Byte);114  if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {115    uint64_t Bytes = CSize->getZExtValue();116    if (Bytes == 0)117      return SDValue();118    if (CByte) {119      // Handle cases that can be done using at most two of120      // MVI, MVHI, MVHHI and MVGHI.  The latter two can only be121      // used if ByteVal is all zeros or all ones; in other cases,122      // we can move at most 2 halfwords.123      uint64_t ByteVal = CByte->getZExtValue();124      if (ByteVal == 0 || ByteVal == 255125              ? Bytes <= 16 && llvm::popcount(Bytes) <= 2126              : Bytes <= 4) {127        unsigned Size1 = Bytes == 16 ? 8 : llvm::bit_floor(Bytes);128        unsigned Size2 = Bytes - Size1;129        SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1,130                                     Alignment, DstPtrInfo);131        if (Size2 == 0)132          return Chain1;133        Dst = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,134                          DAG.getConstant(Size1, DL, PtrVT));135        DstPtrInfo = DstPtrInfo.getWithOffset(Size1);136        SDValue Chain2 =137            memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2,138                        std::min(Alignment, Align(Size1)), DstPtrInfo);139        return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);140      }141    } else {142      // Handle one and two bytes using STC.143      if (Bytes <= 2) {144        SDValue Chain1 =145            DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo, Alignment);146        if (Bytes == 1)147          return Chain1;148        SDValue Dst2 = DAG.getNode(ISD::ADD, DL, PtrVT, Dst,149                                   DAG.getConstant(1, DL, PtrVT));150        SDValue Chain2 = DAG.getStore(Chain, DL, Byte, Dst2,151                                      DstPtrInfo.getWithOffset(1), Align(1));152        return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);153      }154    }155    assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already");156 157    // Handle the special case of a memset of 0, which can use XC.158    if (CByte && CByte->getZExtValue() == 0)159      return emitMemMemImm(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Bytes);160 161    return emitMemMemImm(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),162                         Bytes, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));163  }164 165  // Variable length166  if (CByte && CByte->getZExtValue() == 0)167    // Handle the special case of a variable length memset of 0 with XC.168    return emitMemMemReg(DAG, DL, SystemZISD::XC, Chain, Dst, Dst, Size);169 170  return emitMemMemReg(DAG, DL, SystemZISD::MEMSET_MVC, Chain, Dst, SDValue(),171                       Size, DAG.getAnyExtOrTrunc(Byte, DL, MVT::i32));172}173 174// Convert the current CC value into an integer that is 0 if CC == 0,175// greater than zero if CC == 1 and less than zero if CC >= 2.176// The sequence starts with IPM, which puts CC into bits 29 and 28177// of an integer and clears bits 30 and 31.178static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg,179                              SelectionDAG &DAG) {180  SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);181  SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM,182                            DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32));183  SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL,184                            DAG.getConstant(30, DL, MVT::i32));185  return SRA;186}187 188std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp(189    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,190    SDValue Src2, SDValue Size, const CallInst *CI) const {191  SDValue CCReg;192  // Swap operands to invert CC == 1 vs. CC == 2 cases.193  if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) {194    uint64_t Bytes = CSize->getZExtValue();195    assert(Bytes > 0 && "Caller should have handled 0-size case");196    CCReg = emitMemMemImm(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Bytes);197  } else198    CCReg = emitMemMemReg(DAG, DL, SystemZISD::CLC, Chain, Src2, Src1, Size);199  Chain = CCReg.getValue(1);200  return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);201}202 203std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemchr(204    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,205    SDValue Char, SDValue Length, MachinePointerInfo SrcPtrInfo) const {206  // Use SRST to find the character.  End is its address on success.207  EVT PtrVT = Src.getValueType();208  SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);209  Length = DAG.getZExtOrTrunc(Length, DL, PtrVT);210  Char = DAG.getZExtOrTrunc(Char, DL, MVT::i32);211  Char = DAG.getNode(ISD::AND, DL, MVT::i32, Char,212                     DAG.getConstant(255, DL, MVT::i32));213  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, Length);214  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,215                            Limit, Src, Char);216  SDValue CCReg = End.getValue(1);217  Chain = End.getValue(2);218 219  // Now select between End and null, depending on whether the character220  // was found.221  SDValue Ops[] = {222      End, DAG.getConstant(0, DL, PtrVT),223      DAG.getTargetConstant(SystemZ::CCMASK_SRST, DL, MVT::i32),224      DAG.getTargetConstant(SystemZ::CCMASK_SRST_FOUND, DL, MVT::i32), CCReg};225  End = DAG.getNode(SystemZISD::SELECT_CCMASK, DL, PtrVT, Ops);226  return std::make_pair(End, Chain);227}228 229std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcpy(230    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Dest,231    SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo,232    bool isStpcpy) const {233  SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other);234  SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src,235                                DAG.getConstant(0, DL, MVT::i32));236  return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1));237}238 239std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp(240    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src1,241    SDValue Src2, MachinePointerInfo Op1PtrInfo,242    MachinePointerInfo Op2PtrInfo) const {243  SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other);244  // Swap operands to invert CC == 1 vs. CC == 2 cases.245  SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1,246                               DAG.getConstant(0, DL, MVT::i32));247  SDValue CCReg = Unused.getValue(1);248  Chain = Unused.getValue(2);249  return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain);250}251 252// Search from Src for a null character, stopping once Src reaches Limit.253// Return a pair of values, the first being the number of nonnull characters254// and the second being the out chain.255//256// This can be used for strlen by setting Limit to 0.257static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG,258                                                    const SDLoc &DL,259                                                    SDValue Chain, SDValue Src,260                                                    SDValue Limit) {261  EVT PtrVT = Src.getValueType();262  SDVTList VTs = DAG.getVTList(PtrVT, MVT::i32, MVT::Other);263  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,264                            Limit, Src, DAG.getConstant(0, DL, MVT::i32));265  Chain = End.getValue(2);266  SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src);267  return std::make_pair(Len, Chain);268}269 270std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrlen(271    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,272    const CallInst *CI) const {273  EVT PtrVT = Src.getValueType();274  return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, DL, PtrVT));275}276 277std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrnlen(278    SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, SDValue Src,279    SDValue MaxLength, MachinePointerInfo SrcPtrInfo) const {280  EVT PtrVT = Src.getValueType();281  MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT);282  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength);283  return getBoundedStrlen(DAG, DL, Chain, Src, Limit);284}285