1*9880d681SAndroid Build Coastguard Worker //===-- SystemZISelDAGToDAG.cpp - A dag to dag inst selector for SystemZ --===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file defines an instruction selector for the SystemZ target.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "SystemZTargetMachine.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Worker using namespace llvm;
21*9880d681SAndroid Build Coastguard Worker
22*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "systemz-isel"
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Worker namespace {
25*9880d681SAndroid Build Coastguard Worker // Used to build addressing modes.
26*9880d681SAndroid Build Coastguard Worker struct SystemZAddressingMode {
27*9880d681SAndroid Build Coastguard Worker // The shape of the address.
28*9880d681SAndroid Build Coastguard Worker enum AddrForm {
29*9880d681SAndroid Build Coastguard Worker // base+displacement
30*9880d681SAndroid Build Coastguard Worker FormBD,
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker // base+displacement+index for load and store operands
33*9880d681SAndroid Build Coastguard Worker FormBDXNormal,
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker // base+displacement+index for load address operands
36*9880d681SAndroid Build Coastguard Worker FormBDXLA,
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker // base+displacement+index+ADJDYNALLOC
39*9880d681SAndroid Build Coastguard Worker FormBDXDynAlloc
40*9880d681SAndroid Build Coastguard Worker };
41*9880d681SAndroid Build Coastguard Worker AddrForm Form;
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker // The type of displacement. The enum names here correspond directly
44*9880d681SAndroid Build Coastguard Worker // to the definitions in SystemZOperand.td. We could split them into
45*9880d681SAndroid Build Coastguard Worker // flags -- single/pair, 128-bit, etc. -- but it hardly seems worth it.
46*9880d681SAndroid Build Coastguard Worker enum DispRange {
47*9880d681SAndroid Build Coastguard Worker Disp12Only,
48*9880d681SAndroid Build Coastguard Worker Disp12Pair,
49*9880d681SAndroid Build Coastguard Worker Disp20Only,
50*9880d681SAndroid Build Coastguard Worker Disp20Only128,
51*9880d681SAndroid Build Coastguard Worker Disp20Pair
52*9880d681SAndroid Build Coastguard Worker };
53*9880d681SAndroid Build Coastguard Worker DispRange DR;
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker // The parts of the address. The address is equivalent to:
56*9880d681SAndroid Build Coastguard Worker //
57*9880d681SAndroid Build Coastguard Worker // Base + Disp + Index + (IncludesDynAlloc ? ADJDYNALLOC : 0)
58*9880d681SAndroid Build Coastguard Worker SDValue Base;
59*9880d681SAndroid Build Coastguard Worker int64_t Disp;
60*9880d681SAndroid Build Coastguard Worker SDValue Index;
61*9880d681SAndroid Build Coastguard Worker bool IncludesDynAlloc;
62*9880d681SAndroid Build Coastguard Worker
SystemZAddressingMode__anon3fc4e5930111::SystemZAddressingMode63*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode(AddrForm form, DispRange dr)
64*9880d681SAndroid Build Coastguard Worker : Form(form), DR(dr), Base(), Disp(0), Index(),
65*9880d681SAndroid Build Coastguard Worker IncludesDynAlloc(false) {}
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker // True if the address can have an index register.
hasIndexField__anon3fc4e5930111::SystemZAddressingMode68*9880d681SAndroid Build Coastguard Worker bool hasIndexField() { return Form != FormBD; }
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker // True if the address can (and must) include ADJDYNALLOC.
isDynAlloc__anon3fc4e5930111::SystemZAddressingMode71*9880d681SAndroid Build Coastguard Worker bool isDynAlloc() { return Form == FormBDXDynAlloc; }
72*9880d681SAndroid Build Coastguard Worker
dump__anon3fc4e5930111::SystemZAddressingMode73*9880d681SAndroid Build Coastguard Worker void dump() {
74*9880d681SAndroid Build Coastguard Worker errs() << "SystemZAddressingMode " << this << '\n';
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker errs() << " Base ";
77*9880d681SAndroid Build Coastguard Worker if (Base.getNode())
78*9880d681SAndroid Build Coastguard Worker Base.getNode()->dump();
79*9880d681SAndroid Build Coastguard Worker else
80*9880d681SAndroid Build Coastguard Worker errs() << "null\n";
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker if (hasIndexField()) {
83*9880d681SAndroid Build Coastguard Worker errs() << " Index ";
84*9880d681SAndroid Build Coastguard Worker if (Index.getNode())
85*9880d681SAndroid Build Coastguard Worker Index.getNode()->dump();
86*9880d681SAndroid Build Coastguard Worker else
87*9880d681SAndroid Build Coastguard Worker errs() << "null\n";
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker errs() << " Disp " << Disp;
91*9880d681SAndroid Build Coastguard Worker if (IncludesDynAlloc)
92*9880d681SAndroid Build Coastguard Worker errs() << " + ADJDYNALLOC";
93*9880d681SAndroid Build Coastguard Worker errs() << '\n';
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker };
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker // Return a mask with Count low bits set.
allOnes(unsigned int Count)98*9880d681SAndroid Build Coastguard Worker static uint64_t allOnes(unsigned int Count) {
99*9880d681SAndroid Build Coastguard Worker assert(Count <= 64);
100*9880d681SAndroid Build Coastguard Worker if (Count > 63)
101*9880d681SAndroid Build Coastguard Worker return UINT64_MAX;
102*9880d681SAndroid Build Coastguard Worker return (uint64_t(1) << Count) - 1;
103*9880d681SAndroid Build Coastguard Worker }
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker // Represents operands 2 to 5 of the ROTATE AND ... SELECTED BITS operation
106*9880d681SAndroid Build Coastguard Worker // given by Opcode. The operands are: Input (R2), Start (I3), End (I4) and
107*9880d681SAndroid Build Coastguard Worker // Rotate (I5). The combined operand value is effectively:
108*9880d681SAndroid Build Coastguard Worker //
109*9880d681SAndroid Build Coastguard Worker // (or (rotl Input, Rotate), ~Mask)
110*9880d681SAndroid Build Coastguard Worker //
111*9880d681SAndroid Build Coastguard Worker // for RNSBG and:
112*9880d681SAndroid Build Coastguard Worker //
113*9880d681SAndroid Build Coastguard Worker // (and (rotl Input, Rotate), Mask)
114*9880d681SAndroid Build Coastguard Worker //
115*9880d681SAndroid Build Coastguard Worker // otherwise. The output value has BitSize bits, although Input may be
116*9880d681SAndroid Build Coastguard Worker // narrower (in which case the upper bits are don't care), or wider (in which
117*9880d681SAndroid Build Coastguard Worker // case the result will be truncated as part of the operation).
118*9880d681SAndroid Build Coastguard Worker struct RxSBGOperands {
RxSBGOperands__anon3fc4e5930111::RxSBGOperands119*9880d681SAndroid Build Coastguard Worker RxSBGOperands(unsigned Op, SDValue N)
120*9880d681SAndroid Build Coastguard Worker : Opcode(Op), BitSize(N.getValueType().getSizeInBits()),
121*9880d681SAndroid Build Coastguard Worker Mask(allOnes(BitSize)), Input(N), Start(64 - BitSize), End(63),
122*9880d681SAndroid Build Coastguard Worker Rotate(0) {}
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker unsigned Opcode;
125*9880d681SAndroid Build Coastguard Worker unsigned BitSize;
126*9880d681SAndroid Build Coastguard Worker uint64_t Mask;
127*9880d681SAndroid Build Coastguard Worker SDValue Input;
128*9880d681SAndroid Build Coastguard Worker unsigned Start;
129*9880d681SAndroid Build Coastguard Worker unsigned End;
130*9880d681SAndroid Build Coastguard Worker unsigned Rotate;
131*9880d681SAndroid Build Coastguard Worker };
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker class SystemZDAGToDAGISel : public SelectionDAGISel {
134*9880d681SAndroid Build Coastguard Worker const SystemZSubtarget *Subtarget;
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker // Used by SystemZOperands.td to create integer constants.
getImm(const SDNode * Node,uint64_t Imm) const137*9880d681SAndroid Build Coastguard Worker inline SDValue getImm(const SDNode *Node, uint64_t Imm) const {
138*9880d681SAndroid Build Coastguard Worker return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0));
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
getTargetMachine() const141*9880d681SAndroid Build Coastguard Worker const SystemZTargetMachine &getTargetMachine() const {
142*9880d681SAndroid Build Coastguard Worker return static_cast<const SystemZTargetMachine &>(TM);
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker
getInstrInfo() const145*9880d681SAndroid Build Coastguard Worker const SystemZInstrInfo *getInstrInfo() const {
146*9880d681SAndroid Build Coastguard Worker return Subtarget->getInstrInfo();
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker // Try to fold more of the base or index of AM into AM, where IsBase
150*9880d681SAndroid Build Coastguard Worker // selects between the base and index.
151*9880d681SAndroid Build Coastguard Worker bool expandAddress(SystemZAddressingMode &AM, bool IsBase) const;
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker // Try to describe N in AM, returning true on success.
154*9880d681SAndroid Build Coastguard Worker bool selectAddress(SDValue N, SystemZAddressingMode &AM) const;
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker // Extract individual target operands from matched address AM.
157*9880d681SAndroid Build Coastguard Worker void getAddressOperands(const SystemZAddressingMode &AM, EVT VT,
158*9880d681SAndroid Build Coastguard Worker SDValue &Base, SDValue &Disp) const;
159*9880d681SAndroid Build Coastguard Worker void getAddressOperands(const SystemZAddressingMode &AM, EVT VT,
160*9880d681SAndroid Build Coastguard Worker SDValue &Base, SDValue &Disp, SDValue &Index) const;
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker // Try to match Addr as a FormBD address with displacement type DR.
163*9880d681SAndroid Build Coastguard Worker // Return true on success, storing the base and displacement in
164*9880d681SAndroid Build Coastguard Worker // Base and Disp respectively.
165*9880d681SAndroid Build Coastguard Worker bool selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
166*9880d681SAndroid Build Coastguard Worker SDValue &Base, SDValue &Disp) const;
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker // Try to match Addr as a FormBDX address with displacement type DR.
169*9880d681SAndroid Build Coastguard Worker // Return true on success and if the result had no index. Store the
170*9880d681SAndroid Build Coastguard Worker // base and displacement in Base and Disp respectively.
171*9880d681SAndroid Build Coastguard Worker bool selectMVIAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
172*9880d681SAndroid Build Coastguard Worker SDValue &Base, SDValue &Disp) const;
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker // Try to match Addr as a FormBDX* address of form Form with
175*9880d681SAndroid Build Coastguard Worker // displacement type DR. Return true on success, storing the base,
176*9880d681SAndroid Build Coastguard Worker // displacement and index in Base, Disp and Index respectively.
177*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
178*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::DispRange DR, SDValue Addr,
179*9880d681SAndroid Build Coastguard Worker SDValue &Base, SDValue &Disp, SDValue &Index) const;
180*9880d681SAndroid Build Coastguard Worker
181*9880d681SAndroid Build Coastguard Worker // PC-relative address matching routines used by SystemZOperands.td.
selectPCRelAddress(SDValue Addr,SDValue & Target) const182*9880d681SAndroid Build Coastguard Worker bool selectPCRelAddress(SDValue Addr, SDValue &Target) const {
183*9880d681SAndroid Build Coastguard Worker if (SystemZISD::isPCREL(Addr.getOpcode())) {
184*9880d681SAndroid Build Coastguard Worker Target = Addr.getOperand(0);
185*9880d681SAndroid Build Coastguard Worker return true;
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker return false;
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker
190*9880d681SAndroid Build Coastguard Worker // BD matching routines used by SystemZOperands.td.
selectBDAddr12Only(SDValue Addr,SDValue & Base,SDValue & Disp) const191*9880d681SAndroid Build Coastguard Worker bool selectBDAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp) const {
192*9880d681SAndroid Build Coastguard Worker return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr, Base, Disp);
193*9880d681SAndroid Build Coastguard Worker }
selectBDAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const194*9880d681SAndroid Build Coastguard Worker bool selectBDAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
195*9880d681SAndroid Build Coastguard Worker return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp);
196*9880d681SAndroid Build Coastguard Worker }
selectBDAddr20Only(SDValue Addr,SDValue & Base,SDValue & Disp) const197*9880d681SAndroid Build Coastguard Worker bool selectBDAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp) const {
198*9880d681SAndroid Build Coastguard Worker return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr, Base, Disp);
199*9880d681SAndroid Build Coastguard Worker }
selectBDAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const200*9880d681SAndroid Build Coastguard Worker bool selectBDAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
201*9880d681SAndroid Build Coastguard Worker return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker // MVI matching routines used by SystemZOperands.td.
selectMVIAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const205*9880d681SAndroid Build Coastguard Worker bool selectMVIAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
206*9880d681SAndroid Build Coastguard Worker return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp);
207*9880d681SAndroid Build Coastguard Worker }
selectMVIAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const208*9880d681SAndroid Build Coastguard Worker bool selectMVIAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
209*9880d681SAndroid Build Coastguard Worker return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker
212*9880d681SAndroid Build Coastguard Worker // BDX matching routines used by SystemZOperands.td.
selectBDXAddr12Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const213*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp,
214*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
215*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
216*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp12Only,
217*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
218*9880d681SAndroid Build Coastguard Worker }
selectBDXAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const219*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
220*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
221*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
222*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp12Pair,
223*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
224*9880d681SAndroid Build Coastguard Worker }
selectDynAlloc12Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const225*9880d681SAndroid Build Coastguard Worker bool selectDynAlloc12Only(SDValue Addr, SDValue &Base, SDValue &Disp,
226*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
227*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
228*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp12Only,
229*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
230*9880d681SAndroid Build Coastguard Worker }
selectBDXAddr20Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const231*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp,
232*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
233*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
234*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp20Only,
235*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
236*9880d681SAndroid Build Coastguard Worker }
selectBDXAddr20Only128(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const237*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr20Only128(SDValue Addr, SDValue &Base, SDValue &Disp,
238*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
239*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
240*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp20Only128,
241*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
242*9880d681SAndroid Build Coastguard Worker }
selectBDXAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const243*9880d681SAndroid Build Coastguard Worker bool selectBDXAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
244*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
245*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
246*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp20Pair,
247*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
248*9880d681SAndroid Build Coastguard Worker }
selectLAAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const249*9880d681SAndroid Build Coastguard Worker bool selectLAAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
250*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
251*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
252*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp12Pair,
253*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
254*9880d681SAndroid Build Coastguard Worker }
selectLAAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const255*9880d681SAndroid Build Coastguard Worker bool selectLAAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
256*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
257*9880d681SAndroid Build Coastguard Worker return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
258*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::Disp20Pair,
259*9880d681SAndroid Build Coastguard Worker Addr, Base, Disp, Index);
260*9880d681SAndroid Build Coastguard Worker }
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker // Try to match Addr as an address with a base, 12-bit displacement
263*9880d681SAndroid Build Coastguard Worker // and index, where the index is element Elem of a vector.
264*9880d681SAndroid Build Coastguard Worker // Return true on success, storing the base, displacement and vector
265*9880d681SAndroid Build Coastguard Worker // in Base, Disp and Index respectively.
266*9880d681SAndroid Build Coastguard Worker bool selectBDVAddr12Only(SDValue Addr, SDValue Elem, SDValue &Base,
267*9880d681SAndroid Build Coastguard Worker SDValue &Disp, SDValue &Index) const;
268*9880d681SAndroid Build Coastguard Worker
269*9880d681SAndroid Build Coastguard Worker // Check whether (or Op (and X InsertMask)) is effectively an insertion
270*9880d681SAndroid Build Coastguard Worker // of X into bits InsertMask of some Y != Op. Return true if so and
271*9880d681SAndroid Build Coastguard Worker // set Op to that Y.
272*9880d681SAndroid Build Coastguard Worker bool detectOrAndInsertion(SDValue &Op, uint64_t InsertMask) const;
273*9880d681SAndroid Build Coastguard Worker
274*9880d681SAndroid Build Coastguard Worker // Try to update RxSBG so that only the bits of RxSBG.Input in Mask are used.
275*9880d681SAndroid Build Coastguard Worker // Return true on success.
276*9880d681SAndroid Build Coastguard Worker bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) const;
277*9880d681SAndroid Build Coastguard Worker
278*9880d681SAndroid Build Coastguard Worker // Try to fold some of RxSBG.Input into other fields of RxSBG.
279*9880d681SAndroid Build Coastguard Worker // Return true on success.
280*9880d681SAndroid Build Coastguard Worker bool expandRxSBG(RxSBGOperands &RxSBG) const;
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker // Return an undefined value of type VT.
283*9880d681SAndroid Build Coastguard Worker SDValue getUNDEF(const SDLoc &DL, EVT VT) const;
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard Worker // Convert N to VT, if it isn't already.
286*9880d681SAndroid Build Coastguard Worker SDValue convertTo(const SDLoc &DL, EVT VT, SDValue N) const;
287*9880d681SAndroid Build Coastguard Worker
288*9880d681SAndroid Build Coastguard Worker // Try to implement AND or shift node N using RISBG with the zero flag set.
289*9880d681SAndroid Build Coastguard Worker // Return the selected node on success, otherwise return null.
290*9880d681SAndroid Build Coastguard Worker bool tryRISBGZero(SDNode *N);
291*9880d681SAndroid Build Coastguard Worker
292*9880d681SAndroid Build Coastguard Worker // Try to use RISBG or Opcode to implement OR or XOR node N.
293*9880d681SAndroid Build Coastguard Worker // Return the selected node on success, otherwise return null.
294*9880d681SAndroid Build Coastguard Worker bool tryRxSBG(SDNode *N, unsigned Opcode);
295*9880d681SAndroid Build Coastguard Worker
296*9880d681SAndroid Build Coastguard Worker // If Op0 is null, then Node is a constant that can be loaded using:
297*9880d681SAndroid Build Coastguard Worker //
298*9880d681SAndroid Build Coastguard Worker // (Opcode UpperVal LowerVal)
299*9880d681SAndroid Build Coastguard Worker //
300*9880d681SAndroid Build Coastguard Worker // If Op0 is nonnull, then Node can be implemented using:
301*9880d681SAndroid Build Coastguard Worker //
302*9880d681SAndroid Build Coastguard Worker // (Opcode (Opcode Op0 UpperVal) LowerVal)
303*9880d681SAndroid Build Coastguard Worker void splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0,
304*9880d681SAndroid Build Coastguard Worker uint64_t UpperVal, uint64_t LowerVal);
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker // Try to use gather instruction Opcode to implement vector insertion N.
307*9880d681SAndroid Build Coastguard Worker bool tryGather(SDNode *N, unsigned Opcode);
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker // Try to use scatter instruction Opcode to implement store Store.
310*9880d681SAndroid Build Coastguard Worker bool tryScatter(StoreSDNode *Store, unsigned Opcode);
311*9880d681SAndroid Build Coastguard Worker
312*9880d681SAndroid Build Coastguard Worker // Return true if Load and Store are loads and stores of the same size
313*9880d681SAndroid Build Coastguard Worker // and are guaranteed not to overlap. Such operations can be implemented
314*9880d681SAndroid Build Coastguard Worker // using block (SS-format) instructions.
315*9880d681SAndroid Build Coastguard Worker //
316*9880d681SAndroid Build Coastguard Worker // Partial overlap would lead to incorrect code, since the block operations
317*9880d681SAndroid Build Coastguard Worker // are logically bytewise, even though they have a fast path for the
318*9880d681SAndroid Build Coastguard Worker // non-overlapping case. We also need to avoid full overlap (i.e. two
319*9880d681SAndroid Build Coastguard Worker // addresses that might be equal at run time) because although that case
320*9880d681SAndroid Build Coastguard Worker // would be handled correctly, it might be implemented by millicode.
321*9880d681SAndroid Build Coastguard Worker bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load) const;
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker // N is a (store (load Y), X) pattern. Return true if it can use an MVC
324*9880d681SAndroid Build Coastguard Worker // from Y to X.
325*9880d681SAndroid Build Coastguard Worker bool storeLoadCanUseMVC(SDNode *N) const;
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Worker // N is a (store (op (load A[0]), (load A[1])), X) pattern. Return true
328*9880d681SAndroid Build Coastguard Worker // if A[1 - I] == X and if N can use a block operation like NC from A[I]
329*9880d681SAndroid Build Coastguard Worker // to X.
330*9880d681SAndroid Build Coastguard Worker bool storeLoadCanUseBlockBinary(SDNode *N, unsigned I) const;
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker public:
SystemZDAGToDAGISel(SystemZTargetMachine & TM,CodeGenOpt::Level OptLevel)333*9880d681SAndroid Build Coastguard Worker SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
334*9880d681SAndroid Build Coastguard Worker : SelectionDAGISel(TM, OptLevel) {}
335*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)336*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override {
337*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<SystemZSubtarget>();
338*9880d681SAndroid Build Coastguard Worker return SelectionDAGISel::runOnMachineFunction(MF);
339*9880d681SAndroid Build Coastguard Worker }
340*9880d681SAndroid Build Coastguard Worker
341*9880d681SAndroid Build Coastguard Worker // Override MachineFunctionPass.
getPassName() const342*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
343*9880d681SAndroid Build Coastguard Worker return "SystemZ DAG->DAG Pattern Instruction Selection";
344*9880d681SAndroid Build Coastguard Worker }
345*9880d681SAndroid Build Coastguard Worker
346*9880d681SAndroid Build Coastguard Worker // Override SelectionDAGISel.
347*9880d681SAndroid Build Coastguard Worker void Select(SDNode *Node) override;
348*9880d681SAndroid Build Coastguard Worker bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
349*9880d681SAndroid Build Coastguard Worker std::vector<SDValue> &OutOps) override;
350*9880d681SAndroid Build Coastguard Worker
351*9880d681SAndroid Build Coastguard Worker // Include the pieces autogenerated from the target description.
352*9880d681SAndroid Build Coastguard Worker #include "SystemZGenDAGISel.inc"
353*9880d681SAndroid Build Coastguard Worker };
354*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
355*9880d681SAndroid Build Coastguard Worker
createSystemZISelDag(SystemZTargetMachine & TM,CodeGenOpt::Level OptLevel)356*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createSystemZISelDag(SystemZTargetMachine &TM,
357*9880d681SAndroid Build Coastguard Worker CodeGenOpt::Level OptLevel) {
358*9880d681SAndroid Build Coastguard Worker return new SystemZDAGToDAGISel(TM, OptLevel);
359*9880d681SAndroid Build Coastguard Worker }
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker // Return true if Val should be selected as a displacement for an address
362*9880d681SAndroid Build Coastguard Worker // with range DR. Here we're interested in the range of both the instruction
363*9880d681SAndroid Build Coastguard Worker // described by DR and of any pairing instruction.
selectDisp(SystemZAddressingMode::DispRange DR,int64_t Val)364*9880d681SAndroid Build Coastguard Worker static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
365*9880d681SAndroid Build Coastguard Worker switch (DR) {
366*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp12Only:
367*9880d681SAndroid Build Coastguard Worker return isUInt<12>(Val);
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp12Pair:
370*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Only:
371*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Pair:
372*9880d681SAndroid Build Coastguard Worker return isInt<20>(Val);
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Only128:
375*9880d681SAndroid Build Coastguard Worker return isInt<20>(Val) && isInt<20>(Val + 8);
376*9880d681SAndroid Build Coastguard Worker }
377*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled displacement range");
378*9880d681SAndroid Build Coastguard Worker }
379*9880d681SAndroid Build Coastguard Worker
380*9880d681SAndroid Build Coastguard Worker // Change the base or index in AM to Value, where IsBase selects
381*9880d681SAndroid Build Coastguard Worker // between the base and index.
changeComponent(SystemZAddressingMode & AM,bool IsBase,SDValue Value)382*9880d681SAndroid Build Coastguard Worker static void changeComponent(SystemZAddressingMode &AM, bool IsBase,
383*9880d681SAndroid Build Coastguard Worker SDValue Value) {
384*9880d681SAndroid Build Coastguard Worker if (IsBase)
385*9880d681SAndroid Build Coastguard Worker AM.Base = Value;
386*9880d681SAndroid Build Coastguard Worker else
387*9880d681SAndroid Build Coastguard Worker AM.Index = Value;
388*9880d681SAndroid Build Coastguard Worker }
389*9880d681SAndroid Build Coastguard Worker
390*9880d681SAndroid Build Coastguard Worker // The base or index of AM is equivalent to Value + ADJDYNALLOC,
391*9880d681SAndroid Build Coastguard Worker // where IsBase selects between the base and index. Try to fold the
392*9880d681SAndroid Build Coastguard Worker // ADJDYNALLOC into AM.
expandAdjDynAlloc(SystemZAddressingMode & AM,bool IsBase,SDValue Value)393*9880d681SAndroid Build Coastguard Worker static bool expandAdjDynAlloc(SystemZAddressingMode &AM, bool IsBase,
394*9880d681SAndroid Build Coastguard Worker SDValue Value) {
395*9880d681SAndroid Build Coastguard Worker if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
396*9880d681SAndroid Build Coastguard Worker changeComponent(AM, IsBase, Value);
397*9880d681SAndroid Build Coastguard Worker AM.IncludesDynAlloc = true;
398*9880d681SAndroid Build Coastguard Worker return true;
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker return false;
401*9880d681SAndroid Build Coastguard Worker }
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker // The base of AM is equivalent to Base + Index. Try to use Index as
404*9880d681SAndroid Build Coastguard Worker // the index register.
expandIndex(SystemZAddressingMode & AM,SDValue Base,SDValue Index)405*9880d681SAndroid Build Coastguard Worker static bool expandIndex(SystemZAddressingMode &AM, SDValue Base,
406*9880d681SAndroid Build Coastguard Worker SDValue Index) {
407*9880d681SAndroid Build Coastguard Worker if (AM.hasIndexField() && !AM.Index.getNode()) {
408*9880d681SAndroid Build Coastguard Worker AM.Base = Base;
409*9880d681SAndroid Build Coastguard Worker AM.Index = Index;
410*9880d681SAndroid Build Coastguard Worker return true;
411*9880d681SAndroid Build Coastguard Worker }
412*9880d681SAndroid Build Coastguard Worker return false;
413*9880d681SAndroid Build Coastguard Worker }
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker // The base or index of AM is equivalent to Op0 + Op1, where IsBase selects
416*9880d681SAndroid Build Coastguard Worker // between the base and index. Try to fold Op1 into AM's displacement.
expandDisp(SystemZAddressingMode & AM,bool IsBase,SDValue Op0,uint64_t Op1)417*9880d681SAndroid Build Coastguard Worker static bool expandDisp(SystemZAddressingMode &AM, bool IsBase,
418*9880d681SAndroid Build Coastguard Worker SDValue Op0, uint64_t Op1) {
419*9880d681SAndroid Build Coastguard Worker // First try adjusting the displacement.
420*9880d681SAndroid Build Coastguard Worker int64_t TestDisp = AM.Disp + Op1;
421*9880d681SAndroid Build Coastguard Worker if (selectDisp(AM.DR, TestDisp)) {
422*9880d681SAndroid Build Coastguard Worker changeComponent(AM, IsBase, Op0);
423*9880d681SAndroid Build Coastguard Worker AM.Disp = TestDisp;
424*9880d681SAndroid Build Coastguard Worker return true;
425*9880d681SAndroid Build Coastguard Worker }
426*9880d681SAndroid Build Coastguard Worker
427*9880d681SAndroid Build Coastguard Worker // We could consider forcing the displacement into a register and
428*9880d681SAndroid Build Coastguard Worker // using it as an index, but it would need to be carefully tuned.
429*9880d681SAndroid Build Coastguard Worker return false;
430*9880d681SAndroid Build Coastguard Worker }
431*9880d681SAndroid Build Coastguard Worker
expandAddress(SystemZAddressingMode & AM,bool IsBase) const432*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
433*9880d681SAndroid Build Coastguard Worker bool IsBase) const {
434*9880d681SAndroid Build Coastguard Worker SDValue N = IsBase ? AM.Base : AM.Index;
435*9880d681SAndroid Build Coastguard Worker unsigned Opcode = N.getOpcode();
436*9880d681SAndroid Build Coastguard Worker if (Opcode == ISD::TRUNCATE) {
437*9880d681SAndroid Build Coastguard Worker N = N.getOperand(0);
438*9880d681SAndroid Build Coastguard Worker Opcode = N.getOpcode();
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker if (Opcode == ISD::ADD || CurDAG->isBaseWithConstantOffset(N)) {
441*9880d681SAndroid Build Coastguard Worker SDValue Op0 = N.getOperand(0);
442*9880d681SAndroid Build Coastguard Worker SDValue Op1 = N.getOperand(1);
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker unsigned Op0Code = Op0->getOpcode();
445*9880d681SAndroid Build Coastguard Worker unsigned Op1Code = Op1->getOpcode();
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker if (Op0Code == SystemZISD::ADJDYNALLOC)
448*9880d681SAndroid Build Coastguard Worker return expandAdjDynAlloc(AM, IsBase, Op1);
449*9880d681SAndroid Build Coastguard Worker if (Op1Code == SystemZISD::ADJDYNALLOC)
450*9880d681SAndroid Build Coastguard Worker return expandAdjDynAlloc(AM, IsBase, Op0);
451*9880d681SAndroid Build Coastguard Worker
452*9880d681SAndroid Build Coastguard Worker if (Op0Code == ISD::Constant)
453*9880d681SAndroid Build Coastguard Worker return expandDisp(AM, IsBase, Op1,
454*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Op0)->getSExtValue());
455*9880d681SAndroid Build Coastguard Worker if (Op1Code == ISD::Constant)
456*9880d681SAndroid Build Coastguard Worker return expandDisp(AM, IsBase, Op0,
457*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Op1)->getSExtValue());
458*9880d681SAndroid Build Coastguard Worker
459*9880d681SAndroid Build Coastguard Worker if (IsBase && expandIndex(AM, Op0, Op1))
460*9880d681SAndroid Build Coastguard Worker return true;
461*9880d681SAndroid Build Coastguard Worker }
462*9880d681SAndroid Build Coastguard Worker if (Opcode == SystemZISD::PCREL_OFFSET) {
463*9880d681SAndroid Build Coastguard Worker SDValue Full = N.getOperand(0);
464*9880d681SAndroid Build Coastguard Worker SDValue Base = N.getOperand(1);
465*9880d681SAndroid Build Coastguard Worker SDValue Anchor = Base.getOperand(0);
466*9880d681SAndroid Build Coastguard Worker uint64_t Offset = (cast<GlobalAddressSDNode>(Full)->getOffset() -
467*9880d681SAndroid Build Coastguard Worker cast<GlobalAddressSDNode>(Anchor)->getOffset());
468*9880d681SAndroid Build Coastguard Worker return expandDisp(AM, IsBase, Base, Offset);
469*9880d681SAndroid Build Coastguard Worker }
470*9880d681SAndroid Build Coastguard Worker return false;
471*9880d681SAndroid Build Coastguard Worker }
472*9880d681SAndroid Build Coastguard Worker
473*9880d681SAndroid Build Coastguard Worker // Return true if an instruction with displacement range DR should be
474*9880d681SAndroid Build Coastguard Worker // used for displacement value Val. selectDisp(DR, Val) must already hold.
isValidDisp(SystemZAddressingMode::DispRange DR,int64_t Val)475*9880d681SAndroid Build Coastguard Worker static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
476*9880d681SAndroid Build Coastguard Worker assert(selectDisp(DR, Val) && "Invalid displacement");
477*9880d681SAndroid Build Coastguard Worker switch (DR) {
478*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp12Only:
479*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Only:
480*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Only128:
481*9880d681SAndroid Build Coastguard Worker return true;
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp12Pair:
484*9880d681SAndroid Build Coastguard Worker // Use the other instruction if the displacement is too large.
485*9880d681SAndroid Build Coastguard Worker return isUInt<12>(Val);
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker case SystemZAddressingMode::Disp20Pair:
488*9880d681SAndroid Build Coastguard Worker // Use the other instruction if the displacement is small enough.
489*9880d681SAndroid Build Coastguard Worker return !isUInt<12>(Val);
490*9880d681SAndroid Build Coastguard Worker }
491*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled displacement range");
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker
494*9880d681SAndroid Build Coastguard Worker // Return true if Base + Disp + Index should be performed by LA(Y).
shouldUseLA(SDNode * Base,int64_t Disp,SDNode * Index)495*9880d681SAndroid Build Coastguard Worker static bool shouldUseLA(SDNode *Base, int64_t Disp, SDNode *Index) {
496*9880d681SAndroid Build Coastguard Worker // Don't use LA(Y) for constants.
497*9880d681SAndroid Build Coastguard Worker if (!Base)
498*9880d681SAndroid Build Coastguard Worker return false;
499*9880d681SAndroid Build Coastguard Worker
500*9880d681SAndroid Build Coastguard Worker // Always use LA(Y) for frame addresses, since we know that the destination
501*9880d681SAndroid Build Coastguard Worker // register is almost always (perhaps always) going to be different from
502*9880d681SAndroid Build Coastguard Worker // the frame register.
503*9880d681SAndroid Build Coastguard Worker if (Base->getOpcode() == ISD::FrameIndex)
504*9880d681SAndroid Build Coastguard Worker return true;
505*9880d681SAndroid Build Coastguard Worker
506*9880d681SAndroid Build Coastguard Worker if (Disp) {
507*9880d681SAndroid Build Coastguard Worker // Always use LA(Y) if there is a base, displacement and index.
508*9880d681SAndroid Build Coastguard Worker if (Index)
509*9880d681SAndroid Build Coastguard Worker return true;
510*9880d681SAndroid Build Coastguard Worker
511*9880d681SAndroid Build Coastguard Worker // Always use LA if the displacement is small enough. It should always
512*9880d681SAndroid Build Coastguard Worker // be no worse than AGHI (and better if it avoids a move).
513*9880d681SAndroid Build Coastguard Worker if (isUInt<12>(Disp))
514*9880d681SAndroid Build Coastguard Worker return true;
515*9880d681SAndroid Build Coastguard Worker
516*9880d681SAndroid Build Coastguard Worker // For similar reasons, always use LAY if the constant is too big for AGHI.
517*9880d681SAndroid Build Coastguard Worker // LAY should be no worse than AGFI.
518*9880d681SAndroid Build Coastguard Worker if (!isInt<16>(Disp))
519*9880d681SAndroid Build Coastguard Worker return true;
520*9880d681SAndroid Build Coastguard Worker } else {
521*9880d681SAndroid Build Coastguard Worker // Don't use LA for plain registers.
522*9880d681SAndroid Build Coastguard Worker if (!Index)
523*9880d681SAndroid Build Coastguard Worker return false;
524*9880d681SAndroid Build Coastguard Worker
525*9880d681SAndroid Build Coastguard Worker // Don't use LA for plain addition if the index operand is only used
526*9880d681SAndroid Build Coastguard Worker // once. It should be a natural two-operand addition in that case.
527*9880d681SAndroid Build Coastguard Worker if (Index->hasOneUse())
528*9880d681SAndroid Build Coastguard Worker return false;
529*9880d681SAndroid Build Coastguard Worker
530*9880d681SAndroid Build Coastguard Worker // Prefer addition if the second operation is sign-extended, in the
531*9880d681SAndroid Build Coastguard Worker // hope of using AGF.
532*9880d681SAndroid Build Coastguard Worker unsigned IndexOpcode = Index->getOpcode();
533*9880d681SAndroid Build Coastguard Worker if (IndexOpcode == ISD::SIGN_EXTEND ||
534*9880d681SAndroid Build Coastguard Worker IndexOpcode == ISD::SIGN_EXTEND_INREG)
535*9880d681SAndroid Build Coastguard Worker return false;
536*9880d681SAndroid Build Coastguard Worker }
537*9880d681SAndroid Build Coastguard Worker
538*9880d681SAndroid Build Coastguard Worker // Don't use LA for two-operand addition if either operand is only
539*9880d681SAndroid Build Coastguard Worker // used once. The addition instructions are better in that case.
540*9880d681SAndroid Build Coastguard Worker if (Base->hasOneUse())
541*9880d681SAndroid Build Coastguard Worker return false;
542*9880d681SAndroid Build Coastguard Worker
543*9880d681SAndroid Build Coastguard Worker return true;
544*9880d681SAndroid Build Coastguard Worker }
545*9880d681SAndroid Build Coastguard Worker
546*9880d681SAndroid Build Coastguard Worker // Return true if Addr is suitable for AM, updating AM if so.
selectAddress(SDValue Addr,SystemZAddressingMode & AM) const547*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::selectAddress(SDValue Addr,
548*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode &AM) const {
549*9880d681SAndroid Build Coastguard Worker // Start out assuming that the address will need to be loaded separately,
550*9880d681SAndroid Build Coastguard Worker // then try to extend it as much as we can.
551*9880d681SAndroid Build Coastguard Worker AM.Base = Addr;
552*9880d681SAndroid Build Coastguard Worker
553*9880d681SAndroid Build Coastguard Worker // First try treating the address as a constant.
554*9880d681SAndroid Build Coastguard Worker if (Addr.getOpcode() == ISD::Constant &&
555*9880d681SAndroid Build Coastguard Worker expandDisp(AM, true, SDValue(),
556*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Addr)->getSExtValue()))
557*9880d681SAndroid Build Coastguard Worker ;
558*9880d681SAndroid Build Coastguard Worker // Also see if it's a bare ADJDYNALLOC.
559*9880d681SAndroid Build Coastguard Worker else if (Addr.getOpcode() == SystemZISD::ADJDYNALLOC &&
560*9880d681SAndroid Build Coastguard Worker expandAdjDynAlloc(AM, true, SDValue()))
561*9880d681SAndroid Build Coastguard Worker ;
562*9880d681SAndroid Build Coastguard Worker else
563*9880d681SAndroid Build Coastguard Worker // Otherwise try expanding each component.
564*9880d681SAndroid Build Coastguard Worker while (expandAddress(AM, true) ||
565*9880d681SAndroid Build Coastguard Worker (AM.Index.getNode() && expandAddress(AM, false)))
566*9880d681SAndroid Build Coastguard Worker continue;
567*9880d681SAndroid Build Coastguard Worker
568*9880d681SAndroid Build Coastguard Worker // Reject cases where it isn't profitable to use LA(Y).
569*9880d681SAndroid Build Coastguard Worker if (AM.Form == SystemZAddressingMode::FormBDXLA &&
570*9880d681SAndroid Build Coastguard Worker !shouldUseLA(AM.Base.getNode(), AM.Disp, AM.Index.getNode()))
571*9880d681SAndroid Build Coastguard Worker return false;
572*9880d681SAndroid Build Coastguard Worker
573*9880d681SAndroid Build Coastguard Worker // Reject cases where the other instruction in a pair should be used.
574*9880d681SAndroid Build Coastguard Worker if (!isValidDisp(AM.DR, AM.Disp))
575*9880d681SAndroid Build Coastguard Worker return false;
576*9880d681SAndroid Build Coastguard Worker
577*9880d681SAndroid Build Coastguard Worker // Make sure that ADJDYNALLOC is included where necessary.
578*9880d681SAndroid Build Coastguard Worker if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
579*9880d681SAndroid Build Coastguard Worker return false;
580*9880d681SAndroid Build Coastguard Worker
581*9880d681SAndroid Build Coastguard Worker DEBUG(AM.dump());
582*9880d681SAndroid Build Coastguard Worker return true;
583*9880d681SAndroid Build Coastguard Worker }
584*9880d681SAndroid Build Coastguard Worker
585*9880d681SAndroid Build Coastguard Worker // Insert a node into the DAG at least before Pos. This will reposition
586*9880d681SAndroid Build Coastguard Worker // the node as needed, and will assign it a node ID that is <= Pos's ID.
587*9880d681SAndroid Build Coastguard Worker // Note that this does *not* preserve the uniqueness of node IDs!
588*9880d681SAndroid Build Coastguard Worker // The selection DAG must no longer depend on their uniqueness when this
589*9880d681SAndroid Build Coastguard Worker // function is used.
insertDAGNode(SelectionDAG * DAG,SDNode * Pos,SDValue N)590*9880d681SAndroid Build Coastguard Worker static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N) {
591*9880d681SAndroid Build Coastguard Worker if (N.getNode()->getNodeId() == -1 ||
592*9880d681SAndroid Build Coastguard Worker N.getNode()->getNodeId() > Pos->getNodeId()) {
593*9880d681SAndroid Build Coastguard Worker DAG->RepositionNode(Pos->getIterator(), N.getNode());
594*9880d681SAndroid Build Coastguard Worker N.getNode()->setNodeId(Pos->getNodeId());
595*9880d681SAndroid Build Coastguard Worker }
596*9880d681SAndroid Build Coastguard Worker }
597*9880d681SAndroid Build Coastguard Worker
getAddressOperands(const SystemZAddressingMode & AM,EVT VT,SDValue & Base,SDValue & Disp) const598*9880d681SAndroid Build Coastguard Worker void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM,
599*9880d681SAndroid Build Coastguard Worker EVT VT, SDValue &Base,
600*9880d681SAndroid Build Coastguard Worker SDValue &Disp) const {
601*9880d681SAndroid Build Coastguard Worker Base = AM.Base;
602*9880d681SAndroid Build Coastguard Worker if (!Base.getNode())
603*9880d681SAndroid Build Coastguard Worker // Register 0 means "no base". This is mostly useful for shifts.
604*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getRegister(0, VT);
605*9880d681SAndroid Build Coastguard Worker else if (Base.getOpcode() == ISD::FrameIndex) {
606*9880d681SAndroid Build Coastguard Worker // Lower a FrameIndex to a TargetFrameIndex.
607*9880d681SAndroid Build Coastguard Worker int64_t FrameIndex = cast<FrameIndexSDNode>(Base)->getIndex();
608*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
609*9880d681SAndroid Build Coastguard Worker } else if (Base.getValueType() != VT) {
610*9880d681SAndroid Build Coastguard Worker // Truncate values from i64 to i32, for shifts.
611*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::i32 && Base.getValueType() == MVT::i64 &&
612*9880d681SAndroid Build Coastguard Worker "Unexpected truncation");
613*9880d681SAndroid Build Coastguard Worker SDLoc DL(Base);
614*9880d681SAndroid Build Coastguard Worker SDValue Trunc = CurDAG->getNode(ISD::TRUNCATE, DL, VT, Base);
615*9880d681SAndroid Build Coastguard Worker insertDAGNode(CurDAG, Base.getNode(), Trunc);
616*9880d681SAndroid Build Coastguard Worker Base = Trunc;
617*9880d681SAndroid Build Coastguard Worker }
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker // Lower the displacement to a TargetConstant.
620*9880d681SAndroid Build Coastguard Worker Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(Base), VT);
621*9880d681SAndroid Build Coastguard Worker }
622*9880d681SAndroid Build Coastguard Worker
getAddressOperands(const SystemZAddressingMode & AM,EVT VT,SDValue & Base,SDValue & Disp,SDValue & Index) const623*9880d681SAndroid Build Coastguard Worker void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM,
624*9880d681SAndroid Build Coastguard Worker EVT VT, SDValue &Base,
625*9880d681SAndroid Build Coastguard Worker SDValue &Disp,
626*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
627*9880d681SAndroid Build Coastguard Worker getAddressOperands(AM, VT, Base, Disp);
628*9880d681SAndroid Build Coastguard Worker
629*9880d681SAndroid Build Coastguard Worker Index = AM.Index;
630*9880d681SAndroid Build Coastguard Worker if (!Index.getNode())
631*9880d681SAndroid Build Coastguard Worker // Register 0 means "no index".
632*9880d681SAndroid Build Coastguard Worker Index = CurDAG->getRegister(0, VT);
633*9880d681SAndroid Build Coastguard Worker }
634*9880d681SAndroid Build Coastguard Worker
selectBDAddr(SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp) const635*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
636*9880d681SAndroid Build Coastguard Worker SDValue Addr, SDValue &Base,
637*9880d681SAndroid Build Coastguard Worker SDValue &Disp) const {
638*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
639*9880d681SAndroid Build Coastguard Worker if (!selectAddress(Addr, AM))
640*9880d681SAndroid Build Coastguard Worker return false;
641*9880d681SAndroid Build Coastguard Worker
642*9880d681SAndroid Build Coastguard Worker getAddressOperands(AM, Addr.getValueType(), Base, Disp);
643*9880d681SAndroid Build Coastguard Worker return true;
644*9880d681SAndroid Build Coastguard Worker }
645*9880d681SAndroid Build Coastguard Worker
selectMVIAddr(SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp) const646*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
647*9880d681SAndroid Build Coastguard Worker SDValue Addr, SDValue &Base,
648*9880d681SAndroid Build Coastguard Worker SDValue &Disp) const {
649*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
650*9880d681SAndroid Build Coastguard Worker if (!selectAddress(Addr, AM) || AM.Index.getNode())
651*9880d681SAndroid Build Coastguard Worker return false;
652*9880d681SAndroid Build Coastguard Worker
653*9880d681SAndroid Build Coastguard Worker getAddressOperands(AM, Addr.getValueType(), Base, Disp);
654*9880d681SAndroid Build Coastguard Worker return true;
655*9880d681SAndroid Build Coastguard Worker }
656*9880d681SAndroid Build Coastguard Worker
selectBDXAddr(SystemZAddressingMode::AddrForm Form,SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const657*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
658*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::DispRange DR,
659*9880d681SAndroid Build Coastguard Worker SDValue Addr, SDValue &Base,
660*9880d681SAndroid Build Coastguard Worker SDValue &Disp, SDValue &Index) const {
661*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode AM(Form, DR);
662*9880d681SAndroid Build Coastguard Worker if (!selectAddress(Addr, AM))
663*9880d681SAndroid Build Coastguard Worker return false;
664*9880d681SAndroid Build Coastguard Worker
665*9880d681SAndroid Build Coastguard Worker getAddressOperands(AM, Addr.getValueType(), Base, Disp, Index);
666*9880d681SAndroid Build Coastguard Worker return true;
667*9880d681SAndroid Build Coastguard Worker }
668*9880d681SAndroid Build Coastguard Worker
selectBDVAddr12Only(SDValue Addr,SDValue Elem,SDValue & Base,SDValue & Disp,SDValue & Index) const669*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::selectBDVAddr12Only(SDValue Addr, SDValue Elem,
670*9880d681SAndroid Build Coastguard Worker SDValue &Base,
671*9880d681SAndroid Build Coastguard Worker SDValue &Disp,
672*9880d681SAndroid Build Coastguard Worker SDValue &Index) const {
673*9880d681SAndroid Build Coastguard Worker SDValue Regs[2];
674*9880d681SAndroid Build Coastguard Worker if (selectBDXAddr12Only(Addr, Regs[0], Disp, Regs[1]) &&
675*9880d681SAndroid Build Coastguard Worker Regs[0].getNode() && Regs[1].getNode()) {
676*9880d681SAndroid Build Coastguard Worker for (unsigned int I = 0; I < 2; ++I) {
677*9880d681SAndroid Build Coastguard Worker Base = Regs[I];
678*9880d681SAndroid Build Coastguard Worker Index = Regs[1 - I];
679*9880d681SAndroid Build Coastguard Worker // We can't tell here whether the index vector has the right type
680*9880d681SAndroid Build Coastguard Worker // for the access; the caller needs to do that instead.
681*9880d681SAndroid Build Coastguard Worker if (Index.getOpcode() == ISD::ZERO_EXTEND)
682*9880d681SAndroid Build Coastguard Worker Index = Index.getOperand(0);
683*9880d681SAndroid Build Coastguard Worker if (Index.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
684*9880d681SAndroid Build Coastguard Worker Index.getOperand(1) == Elem) {
685*9880d681SAndroid Build Coastguard Worker Index = Index.getOperand(0);
686*9880d681SAndroid Build Coastguard Worker return true;
687*9880d681SAndroid Build Coastguard Worker }
688*9880d681SAndroid Build Coastguard Worker }
689*9880d681SAndroid Build Coastguard Worker }
690*9880d681SAndroid Build Coastguard Worker return false;
691*9880d681SAndroid Build Coastguard Worker }
692*9880d681SAndroid Build Coastguard Worker
detectOrAndInsertion(SDValue & Op,uint64_t InsertMask) const693*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op,
694*9880d681SAndroid Build Coastguard Worker uint64_t InsertMask) const {
695*9880d681SAndroid Build Coastguard Worker // We're only interested in cases where the insertion is into some operand
696*9880d681SAndroid Build Coastguard Worker // of Op, rather than into Op itself. The only useful case is an AND.
697*9880d681SAndroid Build Coastguard Worker if (Op.getOpcode() != ISD::AND)
698*9880d681SAndroid Build Coastguard Worker return false;
699*9880d681SAndroid Build Coastguard Worker
700*9880d681SAndroid Build Coastguard Worker // We need a constant mask.
701*9880d681SAndroid Build Coastguard Worker auto *MaskNode = dyn_cast<ConstantSDNode>(Op.getOperand(1).getNode());
702*9880d681SAndroid Build Coastguard Worker if (!MaskNode)
703*9880d681SAndroid Build Coastguard Worker return false;
704*9880d681SAndroid Build Coastguard Worker
705*9880d681SAndroid Build Coastguard Worker // It's not an insertion of Op.getOperand(0) if the two masks overlap.
706*9880d681SAndroid Build Coastguard Worker uint64_t AndMask = MaskNode->getZExtValue();
707*9880d681SAndroid Build Coastguard Worker if (InsertMask & AndMask)
708*9880d681SAndroid Build Coastguard Worker return false;
709*9880d681SAndroid Build Coastguard Worker
710*9880d681SAndroid Build Coastguard Worker // It's only an insertion if all bits are covered or are known to be zero.
711*9880d681SAndroid Build Coastguard Worker // The inner check covers all cases but is more expensive.
712*9880d681SAndroid Build Coastguard Worker uint64_t Used = allOnes(Op.getValueType().getSizeInBits());
713*9880d681SAndroid Build Coastguard Worker if (Used != (AndMask | InsertMask)) {
714*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
715*9880d681SAndroid Build Coastguard Worker CurDAG->computeKnownBits(Op.getOperand(0), KnownZero, KnownOne);
716*9880d681SAndroid Build Coastguard Worker if (Used != (AndMask | InsertMask | KnownZero.getZExtValue()))
717*9880d681SAndroid Build Coastguard Worker return false;
718*9880d681SAndroid Build Coastguard Worker }
719*9880d681SAndroid Build Coastguard Worker
720*9880d681SAndroid Build Coastguard Worker Op = Op.getOperand(0);
721*9880d681SAndroid Build Coastguard Worker return true;
722*9880d681SAndroid Build Coastguard Worker }
723*9880d681SAndroid Build Coastguard Worker
refineRxSBGMask(RxSBGOperands & RxSBG,uint64_t Mask) const724*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
725*9880d681SAndroid Build Coastguard Worker uint64_t Mask) const {
726*9880d681SAndroid Build Coastguard Worker const SystemZInstrInfo *TII = getInstrInfo();
727*9880d681SAndroid Build Coastguard Worker if (RxSBG.Rotate != 0)
728*9880d681SAndroid Build Coastguard Worker Mask = (Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
729*9880d681SAndroid Build Coastguard Worker Mask &= RxSBG.Mask;
730*9880d681SAndroid Build Coastguard Worker if (TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
731*9880d681SAndroid Build Coastguard Worker RxSBG.Mask = Mask;
732*9880d681SAndroid Build Coastguard Worker return true;
733*9880d681SAndroid Build Coastguard Worker }
734*9880d681SAndroid Build Coastguard Worker return false;
735*9880d681SAndroid Build Coastguard Worker }
736*9880d681SAndroid Build Coastguard Worker
737*9880d681SAndroid Build Coastguard Worker // Return true if any bits of (RxSBG.Input & Mask) are significant.
maskMatters(RxSBGOperands & RxSBG,uint64_t Mask)738*9880d681SAndroid Build Coastguard Worker static bool maskMatters(RxSBGOperands &RxSBG, uint64_t Mask) {
739*9880d681SAndroid Build Coastguard Worker // Rotate the mask in the same way as RxSBG.Input is rotated.
740*9880d681SAndroid Build Coastguard Worker if (RxSBG.Rotate != 0)
741*9880d681SAndroid Build Coastguard Worker Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
742*9880d681SAndroid Build Coastguard Worker return (Mask & RxSBG.Mask) != 0;
743*9880d681SAndroid Build Coastguard Worker }
744*9880d681SAndroid Build Coastguard Worker
expandRxSBG(RxSBGOperands & RxSBG) const745*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const {
746*9880d681SAndroid Build Coastguard Worker SDValue N = RxSBG.Input;
747*9880d681SAndroid Build Coastguard Worker unsigned Opcode = N.getOpcode();
748*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
749*9880d681SAndroid Build Coastguard Worker case ISD::TRUNCATE: {
750*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode == SystemZ::RNSBG)
751*9880d681SAndroid Build Coastguard Worker return false;
752*9880d681SAndroid Build Coastguard Worker uint64_t BitSize = N.getValueType().getSizeInBits();
753*9880d681SAndroid Build Coastguard Worker uint64_t Mask = allOnes(BitSize);
754*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, Mask))
755*9880d681SAndroid Build Coastguard Worker return false;
756*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
757*9880d681SAndroid Build Coastguard Worker return true;
758*9880d681SAndroid Build Coastguard Worker }
759*9880d681SAndroid Build Coastguard Worker case ISD::AND: {
760*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode == SystemZ::RNSBG)
761*9880d681SAndroid Build Coastguard Worker return false;
762*9880d681SAndroid Build Coastguard Worker
763*9880d681SAndroid Build Coastguard Worker auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
764*9880d681SAndroid Build Coastguard Worker if (!MaskNode)
765*9880d681SAndroid Build Coastguard Worker return false;
766*9880d681SAndroid Build Coastguard Worker
767*9880d681SAndroid Build Coastguard Worker SDValue Input = N.getOperand(0);
768*9880d681SAndroid Build Coastguard Worker uint64_t Mask = MaskNode->getZExtValue();
769*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, Mask)) {
770*9880d681SAndroid Build Coastguard Worker // If some bits of Input are already known zeros, those bits will have
771*9880d681SAndroid Build Coastguard Worker // been removed from the mask. See if adding them back in makes the
772*9880d681SAndroid Build Coastguard Worker // mask suitable.
773*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
774*9880d681SAndroid Build Coastguard Worker CurDAG->computeKnownBits(Input, KnownZero, KnownOne);
775*9880d681SAndroid Build Coastguard Worker Mask |= KnownZero.getZExtValue();
776*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, Mask))
777*9880d681SAndroid Build Coastguard Worker return false;
778*9880d681SAndroid Build Coastguard Worker }
779*9880d681SAndroid Build Coastguard Worker RxSBG.Input = Input;
780*9880d681SAndroid Build Coastguard Worker return true;
781*9880d681SAndroid Build Coastguard Worker }
782*9880d681SAndroid Build Coastguard Worker
783*9880d681SAndroid Build Coastguard Worker case ISD::OR: {
784*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode != SystemZ::RNSBG)
785*9880d681SAndroid Build Coastguard Worker return false;
786*9880d681SAndroid Build Coastguard Worker
787*9880d681SAndroid Build Coastguard Worker auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
788*9880d681SAndroid Build Coastguard Worker if (!MaskNode)
789*9880d681SAndroid Build Coastguard Worker return false;
790*9880d681SAndroid Build Coastguard Worker
791*9880d681SAndroid Build Coastguard Worker SDValue Input = N.getOperand(0);
792*9880d681SAndroid Build Coastguard Worker uint64_t Mask = ~MaskNode->getZExtValue();
793*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, Mask)) {
794*9880d681SAndroid Build Coastguard Worker // If some bits of Input are already known ones, those bits will have
795*9880d681SAndroid Build Coastguard Worker // been removed from the mask. See if adding them back in makes the
796*9880d681SAndroid Build Coastguard Worker // mask suitable.
797*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
798*9880d681SAndroid Build Coastguard Worker CurDAG->computeKnownBits(Input, KnownZero, KnownOne);
799*9880d681SAndroid Build Coastguard Worker Mask &= ~KnownOne.getZExtValue();
800*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, Mask))
801*9880d681SAndroid Build Coastguard Worker return false;
802*9880d681SAndroid Build Coastguard Worker }
803*9880d681SAndroid Build Coastguard Worker RxSBG.Input = Input;
804*9880d681SAndroid Build Coastguard Worker return true;
805*9880d681SAndroid Build Coastguard Worker }
806*9880d681SAndroid Build Coastguard Worker
807*9880d681SAndroid Build Coastguard Worker case ISD::ROTL: {
808*9880d681SAndroid Build Coastguard Worker // Any 64-bit rotate left can be merged into the RxSBG.
809*9880d681SAndroid Build Coastguard Worker if (RxSBG.BitSize != 64 || N.getValueType() != MVT::i64)
810*9880d681SAndroid Build Coastguard Worker return false;
811*9880d681SAndroid Build Coastguard Worker auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
812*9880d681SAndroid Build Coastguard Worker if (!CountNode)
813*9880d681SAndroid Build Coastguard Worker return false;
814*9880d681SAndroid Build Coastguard Worker
815*9880d681SAndroid Build Coastguard Worker RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
816*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
817*9880d681SAndroid Build Coastguard Worker return true;
818*9880d681SAndroid Build Coastguard Worker }
819*9880d681SAndroid Build Coastguard Worker
820*9880d681SAndroid Build Coastguard Worker case ISD::ANY_EXTEND:
821*9880d681SAndroid Build Coastguard Worker // Bits above the extended operand are don't-care.
822*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
823*9880d681SAndroid Build Coastguard Worker return true;
824*9880d681SAndroid Build Coastguard Worker
825*9880d681SAndroid Build Coastguard Worker case ISD::ZERO_EXTEND:
826*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode != SystemZ::RNSBG) {
827*9880d681SAndroid Build Coastguard Worker // Restrict the mask to the extended operand.
828*9880d681SAndroid Build Coastguard Worker unsigned InnerBitSize = N.getOperand(0).getValueType().getSizeInBits();
829*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, allOnes(InnerBitSize)))
830*9880d681SAndroid Build Coastguard Worker return false;
831*9880d681SAndroid Build Coastguard Worker
832*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
833*9880d681SAndroid Build Coastguard Worker return true;
834*9880d681SAndroid Build Coastguard Worker }
835*9880d681SAndroid Build Coastguard Worker // Fall through.
836*9880d681SAndroid Build Coastguard Worker
837*9880d681SAndroid Build Coastguard Worker case ISD::SIGN_EXTEND: {
838*9880d681SAndroid Build Coastguard Worker // Check that the extension bits are don't-care (i.e. are masked out
839*9880d681SAndroid Build Coastguard Worker // by the final mask).
840*9880d681SAndroid Build Coastguard Worker unsigned InnerBitSize = N.getOperand(0).getValueType().getSizeInBits();
841*9880d681SAndroid Build Coastguard Worker if (maskMatters(RxSBG, allOnes(RxSBG.BitSize) - allOnes(InnerBitSize)))
842*9880d681SAndroid Build Coastguard Worker return false;
843*9880d681SAndroid Build Coastguard Worker
844*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
845*9880d681SAndroid Build Coastguard Worker return true;
846*9880d681SAndroid Build Coastguard Worker }
847*9880d681SAndroid Build Coastguard Worker
848*9880d681SAndroid Build Coastguard Worker case ISD::SHL: {
849*9880d681SAndroid Build Coastguard Worker auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
850*9880d681SAndroid Build Coastguard Worker if (!CountNode)
851*9880d681SAndroid Build Coastguard Worker return false;
852*9880d681SAndroid Build Coastguard Worker
853*9880d681SAndroid Build Coastguard Worker uint64_t Count = CountNode->getZExtValue();
854*9880d681SAndroid Build Coastguard Worker unsigned BitSize = N.getValueType().getSizeInBits();
855*9880d681SAndroid Build Coastguard Worker if (Count < 1 || Count >= BitSize)
856*9880d681SAndroid Build Coastguard Worker return false;
857*9880d681SAndroid Build Coastguard Worker
858*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode == SystemZ::RNSBG) {
859*9880d681SAndroid Build Coastguard Worker // Treat (shl X, count) as (rotl X, size-count) as long as the bottom
860*9880d681SAndroid Build Coastguard Worker // count bits from RxSBG.Input are ignored.
861*9880d681SAndroid Build Coastguard Worker if (maskMatters(RxSBG, allOnes(Count)))
862*9880d681SAndroid Build Coastguard Worker return false;
863*9880d681SAndroid Build Coastguard Worker } else {
864*9880d681SAndroid Build Coastguard Worker // Treat (shl X, count) as (and (rotl X, count), ~0<<count).
865*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, allOnes(BitSize - Count) << Count))
866*9880d681SAndroid Build Coastguard Worker return false;
867*9880d681SAndroid Build Coastguard Worker }
868*9880d681SAndroid Build Coastguard Worker
869*9880d681SAndroid Build Coastguard Worker RxSBG.Rotate = (RxSBG.Rotate + Count) & 63;
870*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
871*9880d681SAndroid Build Coastguard Worker return true;
872*9880d681SAndroid Build Coastguard Worker }
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker case ISD::SRL:
875*9880d681SAndroid Build Coastguard Worker case ISD::SRA: {
876*9880d681SAndroid Build Coastguard Worker auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
877*9880d681SAndroid Build Coastguard Worker if (!CountNode)
878*9880d681SAndroid Build Coastguard Worker return false;
879*9880d681SAndroid Build Coastguard Worker
880*9880d681SAndroid Build Coastguard Worker uint64_t Count = CountNode->getZExtValue();
881*9880d681SAndroid Build Coastguard Worker unsigned BitSize = N.getValueType().getSizeInBits();
882*9880d681SAndroid Build Coastguard Worker if (Count < 1 || Count >= BitSize)
883*9880d681SAndroid Build Coastguard Worker return false;
884*9880d681SAndroid Build Coastguard Worker
885*9880d681SAndroid Build Coastguard Worker if (RxSBG.Opcode == SystemZ::RNSBG || Opcode == ISD::SRA) {
886*9880d681SAndroid Build Coastguard Worker // Treat (srl|sra X, count) as (rotl X, size-count) as long as the top
887*9880d681SAndroid Build Coastguard Worker // count bits from RxSBG.Input are ignored.
888*9880d681SAndroid Build Coastguard Worker if (maskMatters(RxSBG, allOnes(Count) << (BitSize - Count)))
889*9880d681SAndroid Build Coastguard Worker return false;
890*9880d681SAndroid Build Coastguard Worker } else {
891*9880d681SAndroid Build Coastguard Worker // Treat (srl X, count), mask) as (and (rotl X, size-count), ~0>>count),
892*9880d681SAndroid Build Coastguard Worker // which is similar to SLL above.
893*9880d681SAndroid Build Coastguard Worker if (!refineRxSBGMask(RxSBG, allOnes(BitSize - Count)))
894*9880d681SAndroid Build Coastguard Worker return false;
895*9880d681SAndroid Build Coastguard Worker }
896*9880d681SAndroid Build Coastguard Worker
897*9880d681SAndroid Build Coastguard Worker RxSBG.Rotate = (RxSBG.Rotate - Count) & 63;
898*9880d681SAndroid Build Coastguard Worker RxSBG.Input = N.getOperand(0);
899*9880d681SAndroid Build Coastguard Worker return true;
900*9880d681SAndroid Build Coastguard Worker }
901*9880d681SAndroid Build Coastguard Worker default:
902*9880d681SAndroid Build Coastguard Worker return false;
903*9880d681SAndroid Build Coastguard Worker }
904*9880d681SAndroid Build Coastguard Worker }
905*9880d681SAndroid Build Coastguard Worker
getUNDEF(const SDLoc & DL,EVT VT) const906*9880d681SAndroid Build Coastguard Worker SDValue SystemZDAGToDAGISel::getUNDEF(const SDLoc &DL, EVT VT) const {
907*9880d681SAndroid Build Coastguard Worker SDNode *N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
908*9880d681SAndroid Build Coastguard Worker return SDValue(N, 0);
909*9880d681SAndroid Build Coastguard Worker }
910*9880d681SAndroid Build Coastguard Worker
convertTo(const SDLoc & DL,EVT VT,SDValue N) const911*9880d681SAndroid Build Coastguard Worker SDValue SystemZDAGToDAGISel::convertTo(const SDLoc &DL, EVT VT,
912*9880d681SAndroid Build Coastguard Worker SDValue N) const {
913*9880d681SAndroid Build Coastguard Worker if (N.getValueType() == MVT::i32 && VT == MVT::i64)
914*9880d681SAndroid Build Coastguard Worker return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
915*9880d681SAndroid Build Coastguard Worker DL, VT, getUNDEF(DL, MVT::i64), N);
916*9880d681SAndroid Build Coastguard Worker if (N.getValueType() == MVT::i64 && VT == MVT::i32)
917*9880d681SAndroid Build Coastguard Worker return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32, DL, VT, N);
918*9880d681SAndroid Build Coastguard Worker assert(N.getValueType() == VT && "Unexpected value types");
919*9880d681SAndroid Build Coastguard Worker return N;
920*9880d681SAndroid Build Coastguard Worker }
921*9880d681SAndroid Build Coastguard Worker
tryRISBGZero(SDNode * N)922*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) {
923*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
924*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
925*9880d681SAndroid Build Coastguard Worker if (!VT.isInteger() || VT.getSizeInBits() > 64)
926*9880d681SAndroid Build Coastguard Worker return false;
927*9880d681SAndroid Build Coastguard Worker RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0));
928*9880d681SAndroid Build Coastguard Worker unsigned Count = 0;
929*9880d681SAndroid Build Coastguard Worker while (expandRxSBG(RISBG))
930*9880d681SAndroid Build Coastguard Worker // The widening or narrowing is expected to be free.
931*9880d681SAndroid Build Coastguard Worker // Counting widening or narrowing as a saved operation will result in
932*9880d681SAndroid Build Coastguard Worker // preferring an R*SBG over a simple shift/logical instruction.
933*9880d681SAndroid Build Coastguard Worker if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND &&
934*9880d681SAndroid Build Coastguard Worker RISBG.Input.getOpcode() != ISD::TRUNCATE)
935*9880d681SAndroid Build Coastguard Worker Count += 1;
936*9880d681SAndroid Build Coastguard Worker if (Count == 0)
937*9880d681SAndroid Build Coastguard Worker return false;
938*9880d681SAndroid Build Coastguard Worker if (Count == 1) {
939*9880d681SAndroid Build Coastguard Worker // Prefer to use normal shift instructions over RISBG, since they can handle
940*9880d681SAndroid Build Coastguard Worker // all cases and are sometimes shorter.
941*9880d681SAndroid Build Coastguard Worker if (N->getOpcode() != ISD::AND)
942*9880d681SAndroid Build Coastguard Worker return false;
943*9880d681SAndroid Build Coastguard Worker
944*9880d681SAndroid Build Coastguard Worker // Prefer register extensions like LLC over RISBG. Also prefer to start
945*9880d681SAndroid Build Coastguard Worker // out with normal ANDs if one instruction would be enough. We can convert
946*9880d681SAndroid Build Coastguard Worker // these ANDs into an RISBG later if a three-address instruction is useful.
947*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32 ||
948*9880d681SAndroid Build Coastguard Worker RISBG.Mask == 0xff ||
949*9880d681SAndroid Build Coastguard Worker RISBG.Mask == 0xffff ||
950*9880d681SAndroid Build Coastguard Worker SystemZ::isImmLF(~RISBG.Mask) ||
951*9880d681SAndroid Build Coastguard Worker SystemZ::isImmHF(~RISBG.Mask)) {
952*9880d681SAndroid Build Coastguard Worker // Force the new mask into the DAG, since it may include known-one bits.
953*9880d681SAndroid Build Coastguard Worker auto *MaskN = cast<ConstantSDNode>(N->getOperand(1).getNode());
954*9880d681SAndroid Build Coastguard Worker if (MaskN->getZExtValue() != RISBG.Mask) {
955*9880d681SAndroid Build Coastguard Worker SDValue NewMask = CurDAG->getConstant(RISBG.Mask, DL, VT);
956*9880d681SAndroid Build Coastguard Worker N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewMask);
957*9880d681SAndroid Build Coastguard Worker SelectCode(N);
958*9880d681SAndroid Build Coastguard Worker return true;
959*9880d681SAndroid Build Coastguard Worker }
960*9880d681SAndroid Build Coastguard Worker return false;
961*9880d681SAndroid Build Coastguard Worker }
962*9880d681SAndroid Build Coastguard Worker }
963*9880d681SAndroid Build Coastguard Worker
964*9880d681SAndroid Build Coastguard Worker // If the RISBG operands require no rotation and just masks the bottom
965*9880d681SAndroid Build Coastguard Worker // 8/16 bits, attempt to convert this to a LLC zero extension.
966*9880d681SAndroid Build Coastguard Worker if (RISBG.Rotate == 0 && (RISBG.Mask == 0xff || RISBG.Mask == 0xffff)) {
967*9880d681SAndroid Build Coastguard Worker unsigned OpCode = (RISBG.Mask == 0xff ? SystemZ::LLGCR : SystemZ::LLGHR);
968*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32) {
969*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasHighWord())
970*9880d681SAndroid Build Coastguard Worker OpCode = (RISBG.Mask == 0xff ? SystemZ::LLCRMux : SystemZ::LLHRMux);
971*9880d681SAndroid Build Coastguard Worker else
972*9880d681SAndroid Build Coastguard Worker OpCode = (RISBG.Mask == 0xff ? SystemZ::LLCR : SystemZ::LLHR);
973*9880d681SAndroid Build Coastguard Worker }
974*9880d681SAndroid Build Coastguard Worker
975*9880d681SAndroid Build Coastguard Worker SDValue In = convertTo(DL, VT, RISBG.Input);
976*9880d681SAndroid Build Coastguard Worker SDValue New = convertTo(
977*9880d681SAndroid Build Coastguard Worker DL, VT, SDValue(CurDAG->getMachineNode(OpCode, DL, VT, In), 0));
978*9880d681SAndroid Build Coastguard Worker ReplaceUses(N, New.getNode());
979*9880d681SAndroid Build Coastguard Worker CurDAG->RemoveDeadNode(N);
980*9880d681SAndroid Build Coastguard Worker return true;
981*9880d681SAndroid Build Coastguard Worker }
982*9880d681SAndroid Build Coastguard Worker
983*9880d681SAndroid Build Coastguard Worker unsigned Opcode = SystemZ::RISBG;
984*9880d681SAndroid Build Coastguard Worker // Prefer RISBGN if available, since it does not clobber CC.
985*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasMiscellaneousExtensions())
986*9880d681SAndroid Build Coastguard Worker Opcode = SystemZ::RISBGN;
987*9880d681SAndroid Build Coastguard Worker EVT OpcodeVT = MVT::i64;
988*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32 && Subtarget->hasHighWord()) {
989*9880d681SAndroid Build Coastguard Worker Opcode = SystemZ::RISBMux;
990*9880d681SAndroid Build Coastguard Worker OpcodeVT = MVT::i32;
991*9880d681SAndroid Build Coastguard Worker RISBG.Start &= 31;
992*9880d681SAndroid Build Coastguard Worker RISBG.End &= 31;
993*9880d681SAndroid Build Coastguard Worker }
994*9880d681SAndroid Build Coastguard Worker SDValue Ops[5] = {
995*9880d681SAndroid Build Coastguard Worker getUNDEF(DL, OpcodeVT),
996*9880d681SAndroid Build Coastguard Worker convertTo(DL, OpcodeVT, RISBG.Input),
997*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RISBG.Start, DL, MVT::i32),
998*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RISBG.End | 128, DL, MVT::i32),
999*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RISBG.Rotate, DL, MVT::i32)
1000*9880d681SAndroid Build Coastguard Worker };
1001*9880d681SAndroid Build Coastguard Worker SDValue New = convertTo(
1002*9880d681SAndroid Build Coastguard Worker DL, VT, SDValue(CurDAG->getMachineNode(Opcode, DL, OpcodeVT, Ops), 0));
1003*9880d681SAndroid Build Coastguard Worker ReplaceUses(N, New.getNode());
1004*9880d681SAndroid Build Coastguard Worker CurDAG->RemoveDeadNode(N);
1005*9880d681SAndroid Build Coastguard Worker return true;
1006*9880d681SAndroid Build Coastguard Worker }
1007*9880d681SAndroid Build Coastguard Worker
tryRxSBG(SDNode * N,unsigned Opcode)1008*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) {
1009*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
1010*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
1011*9880d681SAndroid Build Coastguard Worker if (!VT.isInteger() || VT.getSizeInBits() > 64)
1012*9880d681SAndroid Build Coastguard Worker return false;
1013*9880d681SAndroid Build Coastguard Worker // Try treating each operand of N as the second operand of the RxSBG
1014*9880d681SAndroid Build Coastguard Worker // and see which goes deepest.
1015*9880d681SAndroid Build Coastguard Worker RxSBGOperands RxSBG[] = {
1016*9880d681SAndroid Build Coastguard Worker RxSBGOperands(Opcode, N->getOperand(0)),
1017*9880d681SAndroid Build Coastguard Worker RxSBGOperands(Opcode, N->getOperand(1))
1018*9880d681SAndroid Build Coastguard Worker };
1019*9880d681SAndroid Build Coastguard Worker unsigned Count[] = { 0, 0 };
1020*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0; I < 2; ++I)
1021*9880d681SAndroid Build Coastguard Worker while (expandRxSBG(RxSBG[I]))
1022*9880d681SAndroid Build Coastguard Worker // The widening or narrowing is expected to be free.
1023*9880d681SAndroid Build Coastguard Worker // Counting widening or narrowing as a saved operation will result in
1024*9880d681SAndroid Build Coastguard Worker // preferring an R*SBG over a simple shift/logical instruction.
1025*9880d681SAndroid Build Coastguard Worker if (RxSBG[I].Input.getOpcode() != ISD::ANY_EXTEND &&
1026*9880d681SAndroid Build Coastguard Worker RxSBG[I].Input.getOpcode() != ISD::TRUNCATE)
1027*9880d681SAndroid Build Coastguard Worker Count[I] += 1;
1028*9880d681SAndroid Build Coastguard Worker
1029*9880d681SAndroid Build Coastguard Worker // Do nothing if neither operand is suitable.
1030*9880d681SAndroid Build Coastguard Worker if (Count[0] == 0 && Count[1] == 0)
1031*9880d681SAndroid Build Coastguard Worker return false;
1032*9880d681SAndroid Build Coastguard Worker
1033*9880d681SAndroid Build Coastguard Worker // Pick the deepest second operand.
1034*9880d681SAndroid Build Coastguard Worker unsigned I = Count[0] > Count[1] ? 0 : 1;
1035*9880d681SAndroid Build Coastguard Worker SDValue Op0 = N->getOperand(I ^ 1);
1036*9880d681SAndroid Build Coastguard Worker
1037*9880d681SAndroid Build Coastguard Worker // Prefer IC for character insertions from memory.
1038*9880d681SAndroid Build Coastguard Worker if (Opcode == SystemZ::ROSBG && (RxSBG[I].Mask & 0xff) == 0)
1039*9880d681SAndroid Build Coastguard Worker if (auto *Load = dyn_cast<LoadSDNode>(Op0.getNode()))
1040*9880d681SAndroid Build Coastguard Worker if (Load->getMemoryVT() == MVT::i8)
1041*9880d681SAndroid Build Coastguard Worker return false;
1042*9880d681SAndroid Build Coastguard Worker
1043*9880d681SAndroid Build Coastguard Worker // See whether we can avoid an AND in the first operand by converting
1044*9880d681SAndroid Build Coastguard Worker // ROSBG to RISBG.
1045*9880d681SAndroid Build Coastguard Worker if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask)) {
1046*9880d681SAndroid Build Coastguard Worker Opcode = SystemZ::RISBG;
1047*9880d681SAndroid Build Coastguard Worker // Prefer RISBGN if available, since it does not clobber CC.
1048*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasMiscellaneousExtensions())
1049*9880d681SAndroid Build Coastguard Worker Opcode = SystemZ::RISBGN;
1050*9880d681SAndroid Build Coastguard Worker }
1051*9880d681SAndroid Build Coastguard Worker
1052*9880d681SAndroid Build Coastguard Worker SDValue Ops[5] = {
1053*9880d681SAndroid Build Coastguard Worker convertTo(DL, MVT::i64, Op0),
1054*9880d681SAndroid Build Coastguard Worker convertTo(DL, MVT::i64, RxSBG[I].Input),
1055*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RxSBG[I].Start, DL, MVT::i32),
1056*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RxSBG[I].End, DL, MVT::i32),
1057*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(RxSBG[I].Rotate, DL, MVT::i32)
1058*9880d681SAndroid Build Coastguard Worker };
1059*9880d681SAndroid Build Coastguard Worker SDValue New = convertTo(
1060*9880d681SAndroid Build Coastguard Worker DL, VT, SDValue(CurDAG->getMachineNode(Opcode, DL, MVT::i64, Ops), 0));
1061*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, New.getNode());
1062*9880d681SAndroid Build Coastguard Worker return true;
1063*9880d681SAndroid Build Coastguard Worker }
1064*9880d681SAndroid Build Coastguard Worker
splitLargeImmediate(unsigned Opcode,SDNode * Node,SDValue Op0,uint64_t UpperVal,uint64_t LowerVal)1065*9880d681SAndroid Build Coastguard Worker void SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node,
1066*9880d681SAndroid Build Coastguard Worker SDValue Op0, uint64_t UpperVal,
1067*9880d681SAndroid Build Coastguard Worker uint64_t LowerVal) {
1068*9880d681SAndroid Build Coastguard Worker EVT VT = Node->getValueType(0);
1069*9880d681SAndroid Build Coastguard Worker SDLoc DL(Node);
1070*9880d681SAndroid Build Coastguard Worker SDValue Upper = CurDAG->getConstant(UpperVal, DL, VT);
1071*9880d681SAndroid Build Coastguard Worker if (Op0.getNode())
1072*9880d681SAndroid Build Coastguard Worker Upper = CurDAG->getNode(Opcode, DL, VT, Op0, Upper);
1073*9880d681SAndroid Build Coastguard Worker
1074*9880d681SAndroid Build Coastguard Worker {
1075*9880d681SAndroid Build Coastguard Worker // When we haven't passed in Op0, Upper will be a constant. In order to
1076*9880d681SAndroid Build Coastguard Worker // prevent folding back to the large immediate in `Or = getNode(...)` we run
1077*9880d681SAndroid Build Coastguard Worker // SelectCode first and end up with an opaque machine node. This means that
1078*9880d681SAndroid Build Coastguard Worker // we need to use a handle to keep track of Upper in case it gets CSE'd by
1079*9880d681SAndroid Build Coastguard Worker // SelectCode.
1080*9880d681SAndroid Build Coastguard Worker //
1081*9880d681SAndroid Build Coastguard Worker // Note that in the case where Op0 is passed in we could just call
1082*9880d681SAndroid Build Coastguard Worker // SelectCode(Upper) later, along with the SelectCode(Or), and avoid needing
1083*9880d681SAndroid Build Coastguard Worker // the handle at all, but it's fine to do it here.
1084*9880d681SAndroid Build Coastguard Worker //
1085*9880d681SAndroid Build Coastguard Worker // TODO: This is a pretty hacky way to do this. Can we do something that
1086*9880d681SAndroid Build Coastguard Worker // doesn't require a two paragraph explanation?
1087*9880d681SAndroid Build Coastguard Worker HandleSDNode Handle(Upper);
1088*9880d681SAndroid Build Coastguard Worker SelectCode(Upper.getNode());
1089*9880d681SAndroid Build Coastguard Worker Upper = Handle.getValue();
1090*9880d681SAndroid Build Coastguard Worker }
1091*9880d681SAndroid Build Coastguard Worker
1092*9880d681SAndroid Build Coastguard Worker SDValue Lower = CurDAG->getConstant(LowerVal, DL, VT);
1093*9880d681SAndroid Build Coastguard Worker SDValue Or = CurDAG->getNode(Opcode, DL, VT, Upper, Lower);
1094*9880d681SAndroid Build Coastguard Worker
1095*9880d681SAndroid Build Coastguard Worker ReplaceUses(Node, Or.getNode());
1096*9880d681SAndroid Build Coastguard Worker CurDAG->RemoveDeadNode(Node);
1097*9880d681SAndroid Build Coastguard Worker
1098*9880d681SAndroid Build Coastguard Worker SelectCode(Or.getNode());
1099*9880d681SAndroid Build Coastguard Worker }
1100*9880d681SAndroid Build Coastguard Worker
tryGather(SDNode * N,unsigned Opcode)1101*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::tryGather(SDNode *N, unsigned Opcode) {
1102*9880d681SAndroid Build Coastguard Worker SDValue ElemV = N->getOperand(2);
1103*9880d681SAndroid Build Coastguard Worker auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1104*9880d681SAndroid Build Coastguard Worker if (!ElemN)
1105*9880d681SAndroid Build Coastguard Worker return false;
1106*9880d681SAndroid Build Coastguard Worker
1107*9880d681SAndroid Build Coastguard Worker unsigned Elem = ElemN->getZExtValue();
1108*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
1109*9880d681SAndroid Build Coastguard Worker if (Elem >= VT.getVectorNumElements())
1110*9880d681SAndroid Build Coastguard Worker return false;
1111*9880d681SAndroid Build Coastguard Worker
1112*9880d681SAndroid Build Coastguard Worker auto *Load = dyn_cast<LoadSDNode>(N->getOperand(1));
1113*9880d681SAndroid Build Coastguard Worker if (!Load || !Load->hasOneUse())
1114*9880d681SAndroid Build Coastguard Worker return false;
1115*9880d681SAndroid Build Coastguard Worker if (Load->getMemoryVT().getSizeInBits() !=
1116*9880d681SAndroid Build Coastguard Worker Load->getValueType(0).getSizeInBits())
1117*9880d681SAndroid Build Coastguard Worker return false;
1118*9880d681SAndroid Build Coastguard Worker
1119*9880d681SAndroid Build Coastguard Worker SDValue Base, Disp, Index;
1120*9880d681SAndroid Build Coastguard Worker if (!selectBDVAddr12Only(Load->getBasePtr(), ElemV, Base, Disp, Index) ||
1121*9880d681SAndroid Build Coastguard Worker Index.getValueType() != VT.changeVectorElementTypeToInteger())
1122*9880d681SAndroid Build Coastguard Worker return false;
1123*9880d681SAndroid Build Coastguard Worker
1124*9880d681SAndroid Build Coastguard Worker SDLoc DL(Load);
1125*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1126*9880d681SAndroid Build Coastguard Worker N->getOperand(0), Base, Disp, Index,
1127*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(Elem, DL, MVT::i32), Load->getChain()
1128*9880d681SAndroid Build Coastguard Worker };
1129*9880d681SAndroid Build Coastguard Worker SDNode *Res = CurDAG->getMachineNode(Opcode, DL, VT, MVT::Other, Ops);
1130*9880d681SAndroid Build Coastguard Worker ReplaceUses(SDValue(Load, 1), SDValue(Res, 1));
1131*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, Res);
1132*9880d681SAndroid Build Coastguard Worker return true;
1133*9880d681SAndroid Build Coastguard Worker }
1134*9880d681SAndroid Build Coastguard Worker
tryScatter(StoreSDNode * Store,unsigned Opcode)1135*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::tryScatter(StoreSDNode *Store, unsigned Opcode) {
1136*9880d681SAndroid Build Coastguard Worker SDValue Value = Store->getValue();
1137*9880d681SAndroid Build Coastguard Worker if (Value.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
1138*9880d681SAndroid Build Coastguard Worker return false;
1139*9880d681SAndroid Build Coastguard Worker if (Store->getMemoryVT().getSizeInBits() !=
1140*9880d681SAndroid Build Coastguard Worker Value.getValueType().getSizeInBits())
1141*9880d681SAndroid Build Coastguard Worker return false;
1142*9880d681SAndroid Build Coastguard Worker
1143*9880d681SAndroid Build Coastguard Worker SDValue ElemV = Value.getOperand(1);
1144*9880d681SAndroid Build Coastguard Worker auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1145*9880d681SAndroid Build Coastguard Worker if (!ElemN)
1146*9880d681SAndroid Build Coastguard Worker return false;
1147*9880d681SAndroid Build Coastguard Worker
1148*9880d681SAndroid Build Coastguard Worker SDValue Vec = Value.getOperand(0);
1149*9880d681SAndroid Build Coastguard Worker EVT VT = Vec.getValueType();
1150*9880d681SAndroid Build Coastguard Worker unsigned Elem = ElemN->getZExtValue();
1151*9880d681SAndroid Build Coastguard Worker if (Elem >= VT.getVectorNumElements())
1152*9880d681SAndroid Build Coastguard Worker return false;
1153*9880d681SAndroid Build Coastguard Worker
1154*9880d681SAndroid Build Coastguard Worker SDValue Base, Disp, Index;
1155*9880d681SAndroid Build Coastguard Worker if (!selectBDVAddr12Only(Store->getBasePtr(), ElemV, Base, Disp, Index) ||
1156*9880d681SAndroid Build Coastguard Worker Index.getValueType() != VT.changeVectorElementTypeToInteger())
1157*9880d681SAndroid Build Coastguard Worker return false;
1158*9880d681SAndroid Build Coastguard Worker
1159*9880d681SAndroid Build Coastguard Worker SDLoc DL(Store);
1160*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1161*9880d681SAndroid Build Coastguard Worker Vec, Base, Disp, Index, CurDAG->getTargetConstant(Elem, DL, MVT::i32),
1162*9880d681SAndroid Build Coastguard Worker Store->getChain()
1163*9880d681SAndroid Build Coastguard Worker };
1164*9880d681SAndroid Build Coastguard Worker ReplaceNode(Store, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
1165*9880d681SAndroid Build Coastguard Worker return true;
1166*9880d681SAndroid Build Coastguard Worker }
1167*9880d681SAndroid Build Coastguard Worker
canUseBlockOperation(StoreSDNode * Store,LoadSDNode * Load) const1168*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store,
1169*9880d681SAndroid Build Coastguard Worker LoadSDNode *Load) const {
1170*9880d681SAndroid Build Coastguard Worker // Check that the two memory operands have the same size.
1171*9880d681SAndroid Build Coastguard Worker if (Load->getMemoryVT() != Store->getMemoryVT())
1172*9880d681SAndroid Build Coastguard Worker return false;
1173*9880d681SAndroid Build Coastguard Worker
1174*9880d681SAndroid Build Coastguard Worker // Volatility stops an access from being decomposed.
1175*9880d681SAndroid Build Coastguard Worker if (Load->isVolatile() || Store->isVolatile())
1176*9880d681SAndroid Build Coastguard Worker return false;
1177*9880d681SAndroid Build Coastguard Worker
1178*9880d681SAndroid Build Coastguard Worker // There's no chance of overlap if the load is invariant.
1179*9880d681SAndroid Build Coastguard Worker if (Load->isInvariant())
1180*9880d681SAndroid Build Coastguard Worker return true;
1181*9880d681SAndroid Build Coastguard Worker
1182*9880d681SAndroid Build Coastguard Worker // Otherwise we need to check whether there's an alias.
1183*9880d681SAndroid Build Coastguard Worker const Value *V1 = Load->getMemOperand()->getValue();
1184*9880d681SAndroid Build Coastguard Worker const Value *V2 = Store->getMemOperand()->getValue();
1185*9880d681SAndroid Build Coastguard Worker if (!V1 || !V2)
1186*9880d681SAndroid Build Coastguard Worker return false;
1187*9880d681SAndroid Build Coastguard Worker
1188*9880d681SAndroid Build Coastguard Worker // Reject equality.
1189*9880d681SAndroid Build Coastguard Worker uint64_t Size = Load->getMemoryVT().getStoreSize();
1190*9880d681SAndroid Build Coastguard Worker int64_t End1 = Load->getSrcValueOffset() + Size;
1191*9880d681SAndroid Build Coastguard Worker int64_t End2 = Store->getSrcValueOffset() + Size;
1192*9880d681SAndroid Build Coastguard Worker if (V1 == V2 && End1 == End2)
1193*9880d681SAndroid Build Coastguard Worker return false;
1194*9880d681SAndroid Build Coastguard Worker
1195*9880d681SAndroid Build Coastguard Worker return !AA->alias(MemoryLocation(V1, End1, Load->getAAInfo()),
1196*9880d681SAndroid Build Coastguard Worker MemoryLocation(V2, End2, Store->getAAInfo()));
1197*9880d681SAndroid Build Coastguard Worker }
1198*9880d681SAndroid Build Coastguard Worker
storeLoadCanUseMVC(SDNode * N) const1199*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
1200*9880d681SAndroid Build Coastguard Worker auto *Store = cast<StoreSDNode>(N);
1201*9880d681SAndroid Build Coastguard Worker auto *Load = cast<LoadSDNode>(Store->getValue());
1202*9880d681SAndroid Build Coastguard Worker
1203*9880d681SAndroid Build Coastguard Worker // Prefer not to use MVC if either address can use ... RELATIVE LONG
1204*9880d681SAndroid Build Coastguard Worker // instructions.
1205*9880d681SAndroid Build Coastguard Worker uint64_t Size = Load->getMemoryVT().getStoreSize();
1206*9880d681SAndroid Build Coastguard Worker if (Size > 1 && Size <= 8) {
1207*9880d681SAndroid Build Coastguard Worker // Prefer LHRL, LRL and LGRL.
1208*9880d681SAndroid Build Coastguard Worker if (SystemZISD::isPCREL(Load->getBasePtr().getOpcode()))
1209*9880d681SAndroid Build Coastguard Worker return false;
1210*9880d681SAndroid Build Coastguard Worker // Prefer STHRL, STRL and STGRL.
1211*9880d681SAndroid Build Coastguard Worker if (SystemZISD::isPCREL(Store->getBasePtr().getOpcode()))
1212*9880d681SAndroid Build Coastguard Worker return false;
1213*9880d681SAndroid Build Coastguard Worker }
1214*9880d681SAndroid Build Coastguard Worker
1215*9880d681SAndroid Build Coastguard Worker return canUseBlockOperation(Store, Load);
1216*9880d681SAndroid Build Coastguard Worker }
1217*9880d681SAndroid Build Coastguard Worker
storeLoadCanUseBlockBinary(SDNode * N,unsigned I) const1218*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N,
1219*9880d681SAndroid Build Coastguard Worker unsigned I) const {
1220*9880d681SAndroid Build Coastguard Worker auto *StoreA = cast<StoreSDNode>(N);
1221*9880d681SAndroid Build Coastguard Worker auto *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 - I));
1222*9880d681SAndroid Build Coastguard Worker auto *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(I));
1223*9880d681SAndroid Build Coastguard Worker return !LoadA->isVolatile() && canUseBlockOperation(StoreA, LoadB);
1224*9880d681SAndroid Build Coastguard Worker }
1225*9880d681SAndroid Build Coastguard Worker
Select(SDNode * Node)1226*9880d681SAndroid Build Coastguard Worker void SystemZDAGToDAGISel::Select(SDNode *Node) {
1227*9880d681SAndroid Build Coastguard Worker // Dump information about the Node being selected
1228*9880d681SAndroid Build Coastguard Worker DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
1229*9880d681SAndroid Build Coastguard Worker
1230*9880d681SAndroid Build Coastguard Worker // If we have a custom node, we already have selected!
1231*9880d681SAndroid Build Coastguard Worker if (Node->isMachineOpcode()) {
1232*9880d681SAndroid Build Coastguard Worker DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
1233*9880d681SAndroid Build Coastguard Worker Node->setNodeId(-1);
1234*9880d681SAndroid Build Coastguard Worker return;
1235*9880d681SAndroid Build Coastguard Worker }
1236*9880d681SAndroid Build Coastguard Worker
1237*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Node->getOpcode();
1238*9880d681SAndroid Build Coastguard Worker switch (Opcode) {
1239*9880d681SAndroid Build Coastguard Worker case ISD::OR:
1240*9880d681SAndroid Build Coastguard Worker if (Node->getOperand(1).getOpcode() != ISD::Constant)
1241*9880d681SAndroid Build Coastguard Worker if (tryRxSBG(Node, SystemZ::ROSBG))
1242*9880d681SAndroid Build Coastguard Worker return;
1243*9880d681SAndroid Build Coastguard Worker goto or_xor;
1244*9880d681SAndroid Build Coastguard Worker
1245*9880d681SAndroid Build Coastguard Worker case ISD::XOR:
1246*9880d681SAndroid Build Coastguard Worker if (Node->getOperand(1).getOpcode() != ISD::Constant)
1247*9880d681SAndroid Build Coastguard Worker if (tryRxSBG(Node, SystemZ::RXSBG))
1248*9880d681SAndroid Build Coastguard Worker return;
1249*9880d681SAndroid Build Coastguard Worker // Fall through.
1250*9880d681SAndroid Build Coastguard Worker or_xor:
1251*9880d681SAndroid Build Coastguard Worker // If this is a 64-bit operation in which both 32-bit halves are nonzero,
1252*9880d681SAndroid Build Coastguard Worker // split the operation into two.
1253*9880d681SAndroid Build Coastguard Worker if (Node->getValueType(0) == MVT::i64)
1254*9880d681SAndroid Build Coastguard Worker if (auto *Op1 = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
1255*9880d681SAndroid Build Coastguard Worker uint64_t Val = Op1->getZExtValue();
1256*9880d681SAndroid Build Coastguard Worker if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val)) {
1257*9880d681SAndroid Build Coastguard Worker splitLargeImmediate(Opcode, Node, Node->getOperand(0),
1258*9880d681SAndroid Build Coastguard Worker Val - uint32_t(Val), uint32_t(Val));
1259*9880d681SAndroid Build Coastguard Worker return;
1260*9880d681SAndroid Build Coastguard Worker }
1261*9880d681SAndroid Build Coastguard Worker }
1262*9880d681SAndroid Build Coastguard Worker break;
1263*9880d681SAndroid Build Coastguard Worker
1264*9880d681SAndroid Build Coastguard Worker case ISD::AND:
1265*9880d681SAndroid Build Coastguard Worker if (Node->getOperand(1).getOpcode() != ISD::Constant)
1266*9880d681SAndroid Build Coastguard Worker if (tryRxSBG(Node, SystemZ::RNSBG))
1267*9880d681SAndroid Build Coastguard Worker return;
1268*9880d681SAndroid Build Coastguard Worker // Fall through.
1269*9880d681SAndroid Build Coastguard Worker case ISD::ROTL:
1270*9880d681SAndroid Build Coastguard Worker case ISD::SHL:
1271*9880d681SAndroid Build Coastguard Worker case ISD::SRL:
1272*9880d681SAndroid Build Coastguard Worker case ISD::ZERO_EXTEND:
1273*9880d681SAndroid Build Coastguard Worker if (tryRISBGZero(Node))
1274*9880d681SAndroid Build Coastguard Worker return;
1275*9880d681SAndroid Build Coastguard Worker break;
1276*9880d681SAndroid Build Coastguard Worker
1277*9880d681SAndroid Build Coastguard Worker case ISD::Constant:
1278*9880d681SAndroid Build Coastguard Worker // If this is a 64-bit constant that is out of the range of LLILF,
1279*9880d681SAndroid Build Coastguard Worker // LLIHF and LGFI, split it into two 32-bit pieces.
1280*9880d681SAndroid Build Coastguard Worker if (Node->getValueType(0) == MVT::i64) {
1281*9880d681SAndroid Build Coastguard Worker uint64_t Val = cast<ConstantSDNode>(Node)->getZExtValue();
1282*9880d681SAndroid Build Coastguard Worker if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val) && !isInt<32>(Val)) {
1283*9880d681SAndroid Build Coastguard Worker splitLargeImmediate(ISD::OR, Node, SDValue(), Val - uint32_t(Val),
1284*9880d681SAndroid Build Coastguard Worker uint32_t(Val));
1285*9880d681SAndroid Build Coastguard Worker return;
1286*9880d681SAndroid Build Coastguard Worker }
1287*9880d681SAndroid Build Coastguard Worker }
1288*9880d681SAndroid Build Coastguard Worker break;
1289*9880d681SAndroid Build Coastguard Worker
1290*9880d681SAndroid Build Coastguard Worker case SystemZISD::SELECT_CCMASK: {
1291*9880d681SAndroid Build Coastguard Worker SDValue Op0 = Node->getOperand(0);
1292*9880d681SAndroid Build Coastguard Worker SDValue Op1 = Node->getOperand(1);
1293*9880d681SAndroid Build Coastguard Worker // Prefer to put any load first, so that it can be matched as a
1294*9880d681SAndroid Build Coastguard Worker // conditional load.
1295*9880d681SAndroid Build Coastguard Worker if (Op1.getOpcode() == ISD::LOAD && Op0.getOpcode() != ISD::LOAD) {
1296*9880d681SAndroid Build Coastguard Worker SDValue CCValid = Node->getOperand(2);
1297*9880d681SAndroid Build Coastguard Worker SDValue CCMask = Node->getOperand(3);
1298*9880d681SAndroid Build Coastguard Worker uint64_t ConstCCValid =
1299*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(CCValid.getNode())->getZExtValue();
1300*9880d681SAndroid Build Coastguard Worker uint64_t ConstCCMask =
1301*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(CCMask.getNode())->getZExtValue();
1302*9880d681SAndroid Build Coastguard Worker // Invert the condition.
1303*9880d681SAndroid Build Coastguard Worker CCMask = CurDAG->getConstant(ConstCCValid ^ ConstCCMask, SDLoc(Node),
1304*9880d681SAndroid Build Coastguard Worker CCMask.getValueType());
1305*9880d681SAndroid Build Coastguard Worker SDValue Op4 = Node->getOperand(4);
1306*9880d681SAndroid Build Coastguard Worker Node = CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1307*9880d681SAndroid Build Coastguard Worker }
1308*9880d681SAndroid Build Coastguard Worker break;
1309*9880d681SAndroid Build Coastguard Worker }
1310*9880d681SAndroid Build Coastguard Worker
1311*9880d681SAndroid Build Coastguard Worker case ISD::INSERT_VECTOR_ELT: {
1312*9880d681SAndroid Build Coastguard Worker EVT VT = Node->getValueType(0);
1313*9880d681SAndroid Build Coastguard Worker unsigned ElemBitSize = VT.getVectorElementType().getSizeInBits();
1314*9880d681SAndroid Build Coastguard Worker if (ElemBitSize == 32) {
1315*9880d681SAndroid Build Coastguard Worker if (tryGather(Node, SystemZ::VGEF))
1316*9880d681SAndroid Build Coastguard Worker return;
1317*9880d681SAndroid Build Coastguard Worker } else if (ElemBitSize == 64) {
1318*9880d681SAndroid Build Coastguard Worker if (tryGather(Node, SystemZ::VGEG))
1319*9880d681SAndroid Build Coastguard Worker return;
1320*9880d681SAndroid Build Coastguard Worker }
1321*9880d681SAndroid Build Coastguard Worker break;
1322*9880d681SAndroid Build Coastguard Worker }
1323*9880d681SAndroid Build Coastguard Worker
1324*9880d681SAndroid Build Coastguard Worker case ISD::STORE: {
1325*9880d681SAndroid Build Coastguard Worker auto *Store = cast<StoreSDNode>(Node);
1326*9880d681SAndroid Build Coastguard Worker unsigned ElemBitSize = Store->getValue().getValueType().getSizeInBits();
1327*9880d681SAndroid Build Coastguard Worker if (ElemBitSize == 32) {
1328*9880d681SAndroid Build Coastguard Worker if (tryScatter(Store, SystemZ::VSCEF))
1329*9880d681SAndroid Build Coastguard Worker return;
1330*9880d681SAndroid Build Coastguard Worker } else if (ElemBitSize == 64) {
1331*9880d681SAndroid Build Coastguard Worker if (tryScatter(Store, SystemZ::VSCEG))
1332*9880d681SAndroid Build Coastguard Worker return;
1333*9880d681SAndroid Build Coastguard Worker }
1334*9880d681SAndroid Build Coastguard Worker break;
1335*9880d681SAndroid Build Coastguard Worker }
1336*9880d681SAndroid Build Coastguard Worker }
1337*9880d681SAndroid Build Coastguard Worker
1338*9880d681SAndroid Build Coastguard Worker SelectCode(Node);
1339*9880d681SAndroid Build Coastguard Worker }
1340*9880d681SAndroid Build Coastguard Worker
1341*9880d681SAndroid Build Coastguard Worker bool SystemZDAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue & Op,unsigned ConstraintID,std::vector<SDValue> & OutOps)1342*9880d681SAndroid Build Coastguard Worker SelectInlineAsmMemoryOperand(const SDValue &Op,
1343*9880d681SAndroid Build Coastguard Worker unsigned ConstraintID,
1344*9880d681SAndroid Build Coastguard Worker std::vector<SDValue> &OutOps) {
1345*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::AddrForm Form;
1346*9880d681SAndroid Build Coastguard Worker SystemZAddressingMode::DispRange DispRange;
1347*9880d681SAndroid Build Coastguard Worker SDValue Base, Disp, Index;
1348*9880d681SAndroid Build Coastguard Worker
1349*9880d681SAndroid Build Coastguard Worker switch(ConstraintID) {
1350*9880d681SAndroid Build Coastguard Worker default:
1351*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected asm memory constraint");
1352*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_i:
1353*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_Q:
1354*9880d681SAndroid Build Coastguard Worker // Accept an address with a short displacement, but no index.
1355*9880d681SAndroid Build Coastguard Worker Form = SystemZAddressingMode::FormBD;
1356*9880d681SAndroid Build Coastguard Worker DispRange = SystemZAddressingMode::Disp12Only;
1357*9880d681SAndroid Build Coastguard Worker break;
1358*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_R:
1359*9880d681SAndroid Build Coastguard Worker // Accept an address with a short displacement and an index.
1360*9880d681SAndroid Build Coastguard Worker Form = SystemZAddressingMode::FormBDXNormal;
1361*9880d681SAndroid Build Coastguard Worker DispRange = SystemZAddressingMode::Disp12Only;
1362*9880d681SAndroid Build Coastguard Worker break;
1363*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_S:
1364*9880d681SAndroid Build Coastguard Worker // Accept an address with a long displacement, but no index.
1365*9880d681SAndroid Build Coastguard Worker Form = SystemZAddressingMode::FormBD;
1366*9880d681SAndroid Build Coastguard Worker DispRange = SystemZAddressingMode::Disp20Only;
1367*9880d681SAndroid Build Coastguard Worker break;
1368*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_T:
1369*9880d681SAndroid Build Coastguard Worker case InlineAsm::Constraint_m:
1370*9880d681SAndroid Build Coastguard Worker // Accept an address with a long displacement and an index.
1371*9880d681SAndroid Build Coastguard Worker // m works the same as T, as this is the most general case.
1372*9880d681SAndroid Build Coastguard Worker Form = SystemZAddressingMode::FormBDXNormal;
1373*9880d681SAndroid Build Coastguard Worker DispRange = SystemZAddressingMode::Disp20Only;
1374*9880d681SAndroid Build Coastguard Worker break;
1375*9880d681SAndroid Build Coastguard Worker }
1376*9880d681SAndroid Build Coastguard Worker
1377*9880d681SAndroid Build Coastguard Worker if (selectBDXAddr(Form, DispRange, Op, Base, Disp, Index)) {
1378*9880d681SAndroid Build Coastguard Worker OutOps.push_back(Base);
1379*9880d681SAndroid Build Coastguard Worker OutOps.push_back(Disp);
1380*9880d681SAndroid Build Coastguard Worker OutOps.push_back(Index);
1381*9880d681SAndroid Build Coastguard Worker return false;
1382*9880d681SAndroid Build Coastguard Worker }
1383*9880d681SAndroid Build Coastguard Worker
1384*9880d681SAndroid Build Coastguard Worker return true;
1385*9880d681SAndroid Build Coastguard Worker }
1386