SystemZSelectionDAGInfo.cpp revision 19262ee0725a09b7c621a3d2eb66ba1513ae932a
1//===-- SystemZSelectionDAGInfo.cpp - SystemZ SelectionDAG Info -----------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the SystemZSelectionDAGInfo class.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "systemz-selectiondag-info"
15#include "SystemZTargetMachine.h"
16#include "llvm/CodeGen/SelectionDAG.h"
17
18using namespace llvm;
19
20SystemZSelectionDAGInfo::
21SystemZSelectionDAGInfo(const SystemZTargetMachine &TM)
22  : TargetSelectionDAGInfo(TM) {
23}
24
25SystemZSelectionDAGInfo::~SystemZSelectionDAGInfo() {
26}
27
28SDValue SystemZSelectionDAGInfo::
29EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
30                        SDValue Dst, SDValue Src, SDValue Size, unsigned Align,
31                        bool IsVolatile, bool AlwaysInline,
32                        MachinePointerInfo DstPtrInfo,
33                        MachinePointerInfo SrcPtrInfo) const {
34  if (IsVolatile)
35    return SDValue();
36
37  if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) {
38    uint64_t Bytes = CSize->getZExtValue();
39    if (Bytes >= 1 && Bytes <= 0x100) {
40      // A single MVC.
41      return DAG.getNode(SystemZISD::MVC, DL, MVT::Other,
42                         Chain, Dst, Src, Size);
43    }
44  }
45  return SDValue();
46}
47
48// Handle a memset of 1, 2, 4 or 8 bytes with the operands given by
49// Chain, Dst, ByteVal and Size.  These cases are expected to use
50// MVI, MVHHI, MVHI and MVGHI respectively.
51static SDValue memsetStore(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
52                           SDValue Dst, uint64_t ByteVal, uint64_t Size,
53                           unsigned Align,
54                           MachinePointerInfo DstPtrInfo) {
55  uint64_t StoreVal = ByteVal;
56  for (unsigned I = 1; I < Size; ++I)
57    StoreVal |= ByteVal << (I * 8);
58  return DAG.getStore(Chain, DL,
59                      DAG.getConstant(StoreVal, MVT::getIntegerVT(Size * 8)),
60                      Dst, DstPtrInfo, false, false, Align);
61}
62
63SDValue SystemZSelectionDAGInfo::
64EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
65                        SDValue Dst, SDValue Byte, SDValue Size,
66                        unsigned Align, bool IsVolatile,
67                        MachinePointerInfo DstPtrInfo) const {
68  EVT DstVT = Dst.getValueType();
69
70  if (IsVolatile)
71    return SDValue();
72
73  if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) {
74    uint64_t Bytes = CSize->getZExtValue();
75    if (Bytes == 0)
76      return SDValue();
77    if (ConstantSDNode *CByte = dyn_cast<ConstantSDNode>(Byte)) {
78      // Handle cases that can be done using at most two of
79      // MVI, MVHI, MVHHI and MVGHI.  The latter two can only be
80      // used if ByteVal is all zeros or all ones; in other casees,
81      // we can move at most 2 halfwords.
82      uint64_t ByteVal = CByte->getZExtValue();
83      if (ByteVal == 0 || ByteVal == 255 ?
84          Bytes <= 16 && CountPopulation_64(Bytes) <= 2 :
85          Bytes <= 4) {
86        unsigned Size1 = Bytes == 16 ? 8 : 1 << findLastSet(Bytes);
87        unsigned Size2 = Bytes - Size1;
88        SDValue Chain1 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size1,
89                                     Align, DstPtrInfo);
90        if (Size2 == 0)
91          return Chain1;
92        Dst = DAG.getNode(ISD::ADD, DL, DstVT, Dst,
93                          DAG.getConstant(Size1, DstVT));
94        DstPtrInfo = DstPtrInfo.getWithOffset(Size1);
95        SDValue Chain2 = memsetStore(DAG, DL, Chain, Dst, ByteVal, Size2,
96                                     std::min(Align, Size1), DstPtrInfo);
97        return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
98      }
99    } else {
100      // Handle one and two bytes using STC.
101      if (Bytes <= 2) {
102        SDValue Chain1 = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo,
103                                      false, false, Align);
104        if (Bytes == 1)
105          return Chain1;
106        SDValue Dst2 = DAG.getNode(ISD::ADD, DL, DstVT, Dst,
107                                   DAG.getConstant(1, DstVT));
108        SDValue Chain2 = DAG.getStore(Chain, DL, Byte, Dst2,
109                                      DstPtrInfo.getWithOffset(1),
110                                      false, false, 1);
111        return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chain1, Chain2);
112      }
113    }
114    assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already");
115    if (Bytes <= 0x101) {
116      // Copy the byte to the first location and then use MVC to copy
117      // it to the rest.
118      Chain = DAG.getStore(Chain, DL, Byte, Dst, DstPtrInfo,
119                           false, false, Align);
120      SDValue Dst2 = DAG.getNode(ISD::ADD, DL, DstVT, Dst,
121                                 DAG.getConstant(1, DstVT));
122      return DAG.getNode(SystemZISD::MVC, DL, MVT::Other, Chain, Dst2, Dst,
123                         DAG.getConstant(Bytes - 1, MVT::i32));
124    }
125  }
126  return SDValue();
127}
128
129// Convert the current CC value into an integer that is 0 if CC == 0,
130// less than zero if CC == 1 and greater than zero if CC >= 2.
131// The sequence starts with IPM, which puts CC into bits 29 and 28
132// of an integer and clears bits 30 and 31.
133static SDValue addIPMSequence(SDLoc DL, SDValue Glue, SelectionDAG &DAG) {
134  SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue);
135  SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM,
136                            DAG.getConstant(28, MVT::i32));
137  SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL,
138                             DAG.getConstant(31, MVT::i32));
139  return ROTL;
140}
141
142std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
143EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
144                        SDValue Src1, SDValue Src2, SDValue Size,
145                        MachinePointerInfo Op1PtrInfo,
146                        MachinePointerInfo Op2PtrInfo) const {
147  if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) {
148    uint64_t Bytes = CSize->getZExtValue();
149    if (Bytes >= 1 && Bytes <= 0x100) {
150      // A single CLC.
151      SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue);
152      Chain = DAG.getNode(SystemZISD::CLC, DL, VTs, Chain,
153                          Src1, Src2, Size);
154      SDValue Glue = Chain.getValue(1);
155      return std::make_pair(addIPMSequence(DL, Glue, DAG), Chain);
156    }
157  }
158  return std::make_pair(SDValue(), SDValue());
159}
160
161std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
162EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
163                        SDValue Dest, SDValue Src,
164                        MachinePointerInfo DestPtrInfo,
165                        MachinePointerInfo SrcPtrInfo, bool isStpcpy) const {
166  SDVTList VTs = DAG.getVTList(Dest.getValueType(), MVT::Other);
167  SDValue EndDest = DAG.getNode(SystemZISD::STPCPY, DL, VTs, Chain, Dest, Src,
168                                DAG.getConstant(0, MVT::i32));
169  return std::make_pair(isStpcpy ? EndDest : Dest, EndDest.getValue(1));
170}
171
172std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
173EmitTargetCodeForStrcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
174                        SDValue Src1, SDValue Src2,
175                        MachinePointerInfo Op1PtrInfo,
176                        MachinePointerInfo Op2PtrInfo) const {
177  SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::Other, MVT::Glue);
178  SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2,
179                               DAG.getConstant(0, MVT::i32));
180  Chain = Unused.getValue(1);
181  SDValue Glue = Chain.getValue(2);
182  return std::make_pair(addIPMSequence(DL, Glue, DAG), Chain);
183}
184
185// Search from Src for a null character, stopping once Src reaches Limit.
186// Return a pair of values, the first being the number of nonnull characters
187// and the second being the out chain.
188//
189// This can be used for strlen by setting Limit to 0.
190static std::pair<SDValue, SDValue> getBoundedStrlen(SelectionDAG &DAG, SDLoc DL,
191                                                    SDValue Chain, SDValue Src,
192                                                    SDValue Limit) {
193  EVT PtrVT = Src.getValueType();
194  SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other, MVT::Glue);
195  SDValue End = DAG.getNode(SystemZISD::SEARCH_STRING, DL, VTs, Chain,
196                            Limit, Src, DAG.getConstant(0, MVT::i32));
197  Chain = End.getValue(1);
198  SDValue Len = DAG.getNode(ISD::SUB, DL, PtrVT, End, Src);
199  return std::make_pair(Len, Chain);
200}
201
202std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
203EmitTargetCodeForStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
204                        SDValue Src, MachinePointerInfo SrcPtrInfo) const {
205  EVT PtrVT = Src.getValueType();
206  return getBoundedStrlen(DAG, DL, Chain, Src, DAG.getConstant(0, PtrVT));
207}
208
209std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::
210EmitTargetCodeForStrnlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain,
211                         SDValue Src, SDValue MaxLength,
212                         MachinePointerInfo SrcPtrInfo) const {
213  EVT PtrVT = Src.getValueType();
214  MaxLength = DAG.getZExtOrTrunc(MaxLength, DL, PtrVT);
215  SDValue Limit = DAG.getNode(ISD::ADD, DL, PtrVT, Src, MaxLength);
216  return getBoundedStrlen(DAG, DL, Chain, Src, Limit);
217}
218