15f613dfdSUlrich Weigand //===-- SystemZISelDAGToDAG.cpp - A dag to dag inst selector for SystemZ --===//
25f613dfdSUlrich Weigand //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f613dfdSUlrich Weigand //
75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
85f613dfdSUlrich Weigand //
95f613dfdSUlrich Weigand // This file defines an instruction selector for the SystemZ target.
105f613dfdSUlrich Weigand //
115f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
125f613dfdSUlrich Weigand 
135f613dfdSUlrich Weigand #include "SystemZTargetMachine.h"
148cda83a5SJonas Paulsson #include "SystemZISelLowering.h"
1597846491SRichard Sandiford #include "llvm/Analysis/AliasAnalysis.h"
165f613dfdSUlrich Weigand #include "llvm/CodeGen/SelectionDAGISel.h"
175f613dfdSUlrich Weigand #include "llvm/Support/Debug.h"
18d0af7e8aSCraig Topper #include "llvm/Support/KnownBits.h"
195f613dfdSUlrich Weigand #include "llvm/Support/raw_ostream.h"
205f613dfdSUlrich Weigand 
215f613dfdSUlrich Weigand using namespace llvm;
225f613dfdSUlrich Weigand 
23e96dd897SChandler Carruth #define DEBUG_TYPE "systemz-isel"
24e96dd897SChandler Carruth 
255f613dfdSUlrich Weigand namespace {
265f613dfdSUlrich Weigand // Used to build addressing modes.
275f613dfdSUlrich Weigand struct SystemZAddressingMode {
285f613dfdSUlrich Weigand   // The shape of the address.
295f613dfdSUlrich Weigand   enum AddrForm {
305f613dfdSUlrich Weigand     // base+displacement
315f613dfdSUlrich Weigand     FormBD,
325f613dfdSUlrich Weigand 
335f613dfdSUlrich Weigand     // base+displacement+index for load and store operands
345f613dfdSUlrich Weigand     FormBDXNormal,
355f613dfdSUlrich Weigand 
365f613dfdSUlrich Weigand     // base+displacement+index for load address operands
375f613dfdSUlrich Weigand     FormBDXLA,
385f613dfdSUlrich Weigand 
395f613dfdSUlrich Weigand     // base+displacement+index+ADJDYNALLOC
405f613dfdSUlrich Weigand     FormBDXDynAlloc
415f613dfdSUlrich Weigand   };
425f613dfdSUlrich Weigand   AddrForm Form;
435f613dfdSUlrich Weigand 
445f613dfdSUlrich Weigand   // The type of displacement.  The enum names here correspond directly
455f613dfdSUlrich Weigand   // to the definitions in SystemZOperand.td.  We could split them into
465f613dfdSUlrich Weigand   // flags -- single/pair, 128-bit, etc. -- but it hardly seems worth it.
475f613dfdSUlrich Weigand   enum DispRange {
485f613dfdSUlrich Weigand     Disp12Only,
495f613dfdSUlrich Weigand     Disp12Pair,
505f613dfdSUlrich Weigand     Disp20Only,
515f613dfdSUlrich Weigand     Disp20Only128,
525f613dfdSUlrich Weigand     Disp20Pair
535f613dfdSUlrich Weigand   };
545f613dfdSUlrich Weigand   DispRange DR;
555f613dfdSUlrich Weigand 
565f613dfdSUlrich Weigand   // The parts of the address.  The address is equivalent to:
575f613dfdSUlrich Weigand   //
585f613dfdSUlrich Weigand   //     Base + Disp + Index + (IncludesDynAlloc ? ADJDYNALLOC : 0)
595f613dfdSUlrich Weigand   SDValue Base;
605f613dfdSUlrich Weigand   int64_t Disp;
615f613dfdSUlrich Weigand   SDValue Index;
625f613dfdSUlrich Weigand   bool IncludesDynAlloc;
635f613dfdSUlrich Weigand 
SystemZAddressingMode__anon6e09402b0111::SystemZAddressingMode645f613dfdSUlrich Weigand   SystemZAddressingMode(AddrForm form, DispRange dr)
65f3a344d2SKazu Hirata       : Form(form), DR(dr), Disp(0), IncludesDynAlloc(false) {}
665f613dfdSUlrich Weigand 
675f613dfdSUlrich Weigand   // True if the address can have an index register.
hasIndexField__anon6e09402b0111::SystemZAddressingMode685f613dfdSUlrich Weigand   bool hasIndexField() { return Form != FormBD; }
695f613dfdSUlrich Weigand 
705f613dfdSUlrich Weigand   // True if the address can (and must) include ADJDYNALLOC.
isDynAlloc__anon6e09402b0111::SystemZAddressingMode715f613dfdSUlrich Weigand   bool isDynAlloc() { return Form == FormBDXDynAlloc; }
725f613dfdSUlrich Weigand 
dump__anon6e09402b0111::SystemZAddressingMode73e2c5cbc1SJonas Paulsson   void dump(const llvm::SelectionDAG *DAG) {
745f613dfdSUlrich Weigand     errs() << "SystemZAddressingMode " << this << '\n';
755f613dfdSUlrich Weigand 
765f613dfdSUlrich Weigand     errs() << " Base ";
77062a2baeSCraig Topper     if (Base.getNode())
78e2c5cbc1SJonas Paulsson       Base.getNode()->dump(DAG);
795f613dfdSUlrich Weigand     else
805f613dfdSUlrich Weigand       errs() << "null\n";
815f613dfdSUlrich Weigand 
825f613dfdSUlrich Weigand     if (hasIndexField()) {
835f613dfdSUlrich Weigand       errs() << " Index ";
84062a2baeSCraig Topper       if (Index.getNode())
85e2c5cbc1SJonas Paulsson         Index.getNode()->dump(DAG);
865f613dfdSUlrich Weigand       else
875f613dfdSUlrich Weigand         errs() << "null\n";
885f613dfdSUlrich Weigand     }
895f613dfdSUlrich Weigand 
905f613dfdSUlrich Weigand     errs() << " Disp " << Disp;
915f613dfdSUlrich Weigand     if (IncludesDynAlloc)
925f613dfdSUlrich Weigand       errs() << " + ADJDYNALLOC";
935f613dfdSUlrich Weigand     errs() << '\n';
945f613dfdSUlrich Weigand   }
955f613dfdSUlrich Weigand };
965f613dfdSUlrich Weigand 
9782ec87dbSRichard Sandiford // Return a mask with Count low bits set.
allOnes(unsigned int Count)9882ec87dbSRichard Sandiford static uint64_t allOnes(unsigned int Count) {
9977884bcbSUlrich Weigand   assert(Count <= 64);
100c97c48aaSJustin Bogner   if (Count > 63)
101c97c48aaSJustin Bogner     return UINT64_MAX;
102c97c48aaSJustin Bogner   return (uint64_t(1) << Count) - 1;
10382ec87dbSRichard Sandiford }
10482ec87dbSRichard Sandiford 
10551093210SRichard Sandiford // Represents operands 2 to 5 of the ROTATE AND ... SELECTED BITS operation
10651093210SRichard Sandiford // given by Opcode.  The operands are: Input (R2), Start (I3), End (I4) and
10751093210SRichard Sandiford // Rotate (I5).  The combined operand value is effectively:
10851093210SRichard Sandiford //
10951093210SRichard Sandiford //   (or (rotl Input, Rotate), ~Mask)
11051093210SRichard Sandiford //
11151093210SRichard Sandiford // for RNSBG and:
11251093210SRichard Sandiford //
11351093210SRichard Sandiford //   (and (rotl Input, Rotate), Mask)
11451093210SRichard Sandiford //
1153e382972SRichard Sandiford // otherwise.  The output value has BitSize bits, although Input may be
1160df35058SZhan Jun Liau // narrower (in which case the upper bits are don't care), or wider (in which
1170df35058SZhan Jun Liau // case the result will be truncated as part of the operation).
1185cbac967SRichard Sandiford struct RxSBGOperands {
RxSBGOperands__anon6e09402b0111::RxSBGOperands11951093210SRichard Sandiford   RxSBGOperands(unsigned Op, SDValue N)
120b1f0a0f4SSanjay Patel     : Opcode(Op), BitSize(N.getValueSizeInBits()),
12151093210SRichard Sandiford       Mask(allOnes(BitSize)), Input(N), Start(64 - BitSize), End(63),
12251093210SRichard Sandiford       Rotate(0) {}
12382ec87dbSRichard Sandiford 
12451093210SRichard Sandiford   unsigned Opcode;
12582ec87dbSRichard Sandiford   unsigned BitSize;
12682ec87dbSRichard Sandiford   uint64_t Mask;
12782ec87dbSRichard Sandiford   SDValue Input;
12882ec87dbSRichard Sandiford   unsigned Start;
12982ec87dbSRichard Sandiford   unsigned End;
13082ec87dbSRichard Sandiford   unsigned Rotate;
13182ec87dbSRichard Sandiford };
13282ec87dbSRichard Sandiford 
1335f613dfdSUlrich Weigand class SystemZDAGToDAGISel : public SelectionDAGISel {
134a6734178SEric Christopher   const SystemZSubtarget *Subtarget;
1355f613dfdSUlrich Weigand 
1365f613dfdSUlrich Weigand   // Used by SystemZOperands.td to create integer constants.
getImm(const SDNode * Node,uint64_t Imm) const13754b36916SRichard Sandiford   inline SDValue getImm(const SDNode *Node, uint64_t Imm) const {
138842a51baSSergey Dmitrouk     return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0));
1395f613dfdSUlrich Weigand   }
1405f613dfdSUlrich Weigand 
getTargetMachine() const1416a06ba36SRichard Sandiford   const SystemZTargetMachine &getTargetMachine() const {
1426a06ba36SRichard Sandiford     return static_cast<const SystemZTargetMachine &>(TM);
1436a06ba36SRichard Sandiford   }
1446a06ba36SRichard Sandiford 
getInstrInfo() const1456a06ba36SRichard Sandiford   const SystemZInstrInfo *getInstrInfo() const {
146a6734178SEric Christopher     return Subtarget->getInstrInfo();
1476a06ba36SRichard Sandiford   }
1486a06ba36SRichard Sandiford 
1495f613dfdSUlrich Weigand   // Try to fold more of the base or index of AM into AM, where IsBase
1505f613dfdSUlrich Weigand   // selects between the base and index.
15154b36916SRichard Sandiford   bool expandAddress(SystemZAddressingMode &AM, bool IsBase) const;
1525f613dfdSUlrich Weigand 
1535f613dfdSUlrich Weigand   // Try to describe N in AM, returning true on success.
15454b36916SRichard Sandiford   bool selectAddress(SDValue N, SystemZAddressingMode &AM) const;
1555f613dfdSUlrich Weigand 
1565f613dfdSUlrich Weigand   // Extract individual target operands from matched address AM.
1575f613dfdSUlrich Weigand   void getAddressOperands(const SystemZAddressingMode &AM, EVT VT,
15854b36916SRichard Sandiford                           SDValue &Base, SDValue &Disp) const;
1595f613dfdSUlrich Weigand   void getAddressOperands(const SystemZAddressingMode &AM, EVT VT,
16054b36916SRichard Sandiford                           SDValue &Base, SDValue &Disp, SDValue &Index) const;
1615f613dfdSUlrich Weigand 
1625f613dfdSUlrich Weigand   // Try to match Addr as a FormBD address with displacement type DR.
1635f613dfdSUlrich Weigand   // Return true on success, storing the base and displacement in
1645f613dfdSUlrich Weigand   // Base and Disp respectively.
1655f613dfdSUlrich Weigand   bool selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
16654b36916SRichard Sandiford                     SDValue &Base, SDValue &Disp) const;
1675f613dfdSUlrich Weigand 
168a481f585SRichard Sandiford   // Try to match Addr as a FormBDX address with displacement type DR.
169a481f585SRichard Sandiford   // Return true on success and if the result had no index.  Store the
170a481f585SRichard Sandiford   // base and displacement in Base and Disp respectively.
171a481f585SRichard Sandiford   bool selectMVIAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
17254b36916SRichard Sandiford                      SDValue &Base, SDValue &Disp) const;
173a481f585SRichard Sandiford 
1745f613dfdSUlrich Weigand   // Try to match Addr as a FormBDX* address of form Form with
1755f613dfdSUlrich Weigand   // displacement type DR.  Return true on success, storing the base,
1765f613dfdSUlrich Weigand   // displacement and index in Base, Disp and Index respectively.
1775f613dfdSUlrich Weigand   bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
1785f613dfdSUlrich Weigand                      SystemZAddressingMode::DispRange DR, SDValue Addr,
17954b36916SRichard Sandiford                      SDValue &Base, SDValue &Disp, SDValue &Index) const;
1805f613dfdSUlrich Weigand 
1815f613dfdSUlrich Weigand   // PC-relative address matching routines used by SystemZOperands.td.
selectPCRelAddress(SDValue Addr,SDValue & Target) const18254b36916SRichard Sandiford   bool selectPCRelAddress(SDValue Addr, SDValue &Target) const {
18354b36916SRichard Sandiford     if (SystemZISD::isPCREL(Addr.getOpcode())) {
1845f613dfdSUlrich Weigand       Target = Addr.getOperand(0);
1855f613dfdSUlrich Weigand       return true;
1865f613dfdSUlrich Weigand     }
1875f613dfdSUlrich Weigand     return false;
1885f613dfdSUlrich Weigand   }
1895f613dfdSUlrich Weigand 
1905f613dfdSUlrich Weigand   // BD matching routines used by SystemZOperands.td.
selectBDAddr12Only(SDValue Addr,SDValue & Base,SDValue & Disp) const19154b36916SRichard Sandiford   bool selectBDAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp) const {
1925f613dfdSUlrich Weigand     return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr, Base, Disp);
1935f613dfdSUlrich Weigand   }
selectBDAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const19454b36916SRichard Sandiford   bool selectBDAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
1955f613dfdSUlrich Weigand     return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp);
1965f613dfdSUlrich Weigand   }
selectBDAddr20Only(SDValue Addr,SDValue & Base,SDValue & Disp) const19754b36916SRichard Sandiford   bool selectBDAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp) const {
1985f613dfdSUlrich Weigand     return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr, Base, Disp);
1995f613dfdSUlrich Weigand   }
selectBDAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const20054b36916SRichard Sandiford   bool selectBDAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
2015f613dfdSUlrich Weigand     return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
2025f613dfdSUlrich Weigand   }
2035f613dfdSUlrich Weigand 
204a481f585SRichard Sandiford   // MVI matching routines used by SystemZOperands.td.
selectMVIAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const20554b36916SRichard Sandiford   bool selectMVIAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
206a481f585SRichard Sandiford     return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp);
207a481f585SRichard Sandiford   }
selectMVIAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp) const20854b36916SRichard Sandiford   bool selectMVIAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) const {
209a481f585SRichard Sandiford     return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
210a481f585SRichard Sandiford   }
211a481f585SRichard Sandiford 
2125f613dfdSUlrich Weigand   // BDX matching routines used by SystemZOperands.td.
selectBDXAddr12Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2135f613dfdSUlrich Weigand   bool selectBDXAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp,
21454b36916SRichard Sandiford                            SDValue &Index) const {
2155f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
2165f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp12Only,
2175f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2185f613dfdSUlrich Weigand   }
selectBDXAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2195f613dfdSUlrich Weigand   bool selectBDXAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
22054b36916SRichard Sandiford                            SDValue &Index) const {
2215f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
2225f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp12Pair,
2235f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2245f613dfdSUlrich Weigand   }
selectDynAlloc12Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2255f613dfdSUlrich Weigand   bool selectDynAlloc12Only(SDValue Addr, SDValue &Base, SDValue &Disp,
22654b36916SRichard Sandiford                             SDValue &Index) const {
2275f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
2285f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp12Only,
2295f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2305f613dfdSUlrich Weigand   }
selectBDXAddr20Only(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2315f613dfdSUlrich Weigand   bool selectBDXAddr20Only(SDValue Addr, SDValue &Base, SDValue &Disp,
23254b36916SRichard Sandiford                            SDValue &Index) const {
2335f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
2345f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp20Only,
2355f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2365f613dfdSUlrich Weigand   }
selectBDXAddr20Only128(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2375f613dfdSUlrich Weigand   bool selectBDXAddr20Only128(SDValue Addr, SDValue &Base, SDValue &Disp,
23854b36916SRichard Sandiford                               SDValue &Index) const {
2395f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
2405f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp20Only128,
2415f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2425f613dfdSUlrich Weigand   }
selectBDXAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2435f613dfdSUlrich Weigand   bool selectBDXAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
24454b36916SRichard Sandiford                            SDValue &Index) const {
2455f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
2465f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp20Pair,
2475f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2485f613dfdSUlrich Weigand   }
selectLAAddr12Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2495f613dfdSUlrich Weigand   bool selectLAAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
25054b36916SRichard Sandiford                           SDValue &Index) const {
2515f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
2525f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp12Pair,
2535f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2545f613dfdSUlrich Weigand   }
selectLAAddr20Pair(SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const2555f613dfdSUlrich Weigand   bool selectLAAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp,
25654b36916SRichard Sandiford                           SDValue &Index) const {
2575f613dfdSUlrich Weigand     return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
2585f613dfdSUlrich Weigand                          SystemZAddressingMode::Disp20Pair,
2595f613dfdSUlrich Weigand                          Addr, Base, Disp, Index);
2605f613dfdSUlrich Weigand   }
2615f613dfdSUlrich Weigand 
262ce4c1095SUlrich Weigand   // Try to match Addr as an address with a base, 12-bit displacement
263ce4c1095SUlrich Weigand   // and index, where the index is element Elem of a vector.
264ce4c1095SUlrich Weigand   // Return true on success, storing the base, displacement and vector
265ce4c1095SUlrich Weigand   // in Base, Disp and Index respectively.
266ce4c1095SUlrich Weigand   bool selectBDVAddr12Only(SDValue Addr, SDValue Elem, SDValue &Base,
267ce4c1095SUlrich Weigand                            SDValue &Disp, SDValue &Index) const;
268ce4c1095SUlrich Weigand 
269885140c9SRichard Sandiford   // Check whether (or Op (and X InsertMask)) is effectively an insertion
270885140c9SRichard Sandiford   // of X into bits InsertMask of some Y != Op.  Return true if so and
271885140c9SRichard Sandiford   // set Op to that Y.
27254b36916SRichard Sandiford   bool detectOrAndInsertion(SDValue &Op, uint64_t InsertMask) const;
273885140c9SRichard Sandiford 
2746a06ba36SRichard Sandiford   // Try to update RxSBG so that only the bits of RxSBG.Input in Mask are used.
2756a06ba36SRichard Sandiford   // Return true on success.
27654b36916SRichard Sandiford   bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) const;
2776a06ba36SRichard Sandiford 
2785cbac967SRichard Sandiford   // Try to fold some of RxSBG.Input into other fields of RxSBG.
2795cbac967SRichard Sandiford   // Return true on success.
28054b36916SRichard Sandiford   bool expandRxSBG(RxSBGOperands &RxSBG) const;
28182ec87dbSRichard Sandiford 
2823ad5a15bSRichard Sandiford   // Return an undefined value of type VT.
283bdc4956bSBenjamin Kramer   SDValue getUNDEF(const SDLoc &DL, EVT VT) const;
28484f54a3bSRichard Sandiford 
28584f54a3bSRichard Sandiford   // Convert N to VT, if it isn't already.
286bdc4956bSBenjamin Kramer   SDValue convertTo(const SDLoc &DL, EVT VT, SDValue N) const;
28784f54a3bSRichard Sandiford 
28882ec87dbSRichard Sandiford   // Try to implement AND or shift node N using RISBG with the zero flag set.
28982ec87dbSRichard Sandiford   // Return the selected node on success, otherwise return null.
290bbcd2233SJustin Bogner   bool tryRISBGZero(SDNode *N);
29184f54a3bSRichard Sandiford 
2927878b852SRichard Sandiford   // Try to use RISBG or Opcode to implement OR or XOR node N.
2937878b852SRichard Sandiford   // Return the selected node on success, otherwise return null.
2949b34e8a7SJustin Bogner   bool tryRxSBG(SDNode *N, unsigned Opcode);
295885140c9SRichard Sandiford 
2965f613dfdSUlrich Weigand   // If Op0 is null, then Node is a constant that can be loaded using:
2975f613dfdSUlrich Weigand   //
2985f613dfdSUlrich Weigand   //   (Opcode UpperVal LowerVal)
2995f613dfdSUlrich Weigand   //
3005f613dfdSUlrich Weigand   // If Op0 is nonnull, then Node can be implemented using:
3015f613dfdSUlrich Weigand   //
3025f613dfdSUlrich Weigand   //   (Opcode (Opcode Op0 UpperVal) LowerVal)
303ffb273d2SJustin Bogner   void splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0,
3045f613dfdSUlrich Weigand                            uint64_t UpperVal, uint64_t LowerVal);
3055f613dfdSUlrich Weigand 
306c110b5b6SJonas Paulsson   void loadVectorConstant(const SystemZVectorConstantInfo &VCI,
307c110b5b6SJonas Paulsson                           SDNode *Node);
308c110b5b6SJonas Paulsson 
309ce4c1095SUlrich Weigand   // Try to use gather instruction Opcode to implement vector insertion N.
3109b34e8a7SJustin Bogner   bool tryGather(SDNode *N, unsigned Opcode);
311ce4c1095SUlrich Weigand 
312ce4c1095SUlrich Weigand   // Try to use scatter instruction Opcode to implement store Store.
3139b34e8a7SJustin Bogner   bool tryScatter(StoreSDNode *Store, unsigned Opcode);
314ce4c1095SUlrich Weigand 
315c3ec80feSUlrich Weigand   // Change a chain of {load; op; store} of the same value into a simple op
316c3ec80feSUlrich Weigand   // through memory of that value, if the uses of the modified value and its
317c3ec80feSUlrich Weigand   // address are suitable.
318c3ec80feSUlrich Weigand   bool tryFoldLoadStoreIntoMemOperand(SDNode *Node);
319c3ec80feSUlrich Weigand 
320067817eeSRichard Sandiford   // Return true if Load and Store are loads and stores of the same size
321067817eeSRichard Sandiford   // and are guaranteed not to overlap.  Such operations can be implemented
322067817eeSRichard Sandiford   // using block (SS-format) instructions.
323067817eeSRichard Sandiford   //
324067817eeSRichard Sandiford   // Partial overlap would lead to incorrect code, since the block operations
325067817eeSRichard Sandiford   // are logically bytewise, even though they have a fast path for the
326067817eeSRichard Sandiford   // non-overlapping case.  We also need to avoid full overlap (i.e. two
327067817eeSRichard Sandiford   // addresses that might be equal at run time) because although that case
328067817eeSRichard Sandiford   // would be handled correctly, it might be implemented by millicode.
329067817eeSRichard Sandiford   bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load) const;
330067817eeSRichard Sandiford 
331178273a1SRichard Sandiford   // N is a (store (load Y), X) pattern.  Return true if it can use an MVC
332178273a1SRichard Sandiford   // from Y to X.
33397846491SRichard Sandiford   bool storeLoadCanUseMVC(SDNode *N) const;
33497846491SRichard Sandiford 
335178273a1SRichard Sandiford   // N is a (store (op (load A[0]), (load A[1])), X) pattern.  Return true
336178273a1SRichard Sandiford   // if A[1 - I] == X and if N can use a block operation like NC from A[I]
337178273a1SRichard Sandiford   // to X.
338178273a1SRichard Sandiford   bool storeLoadCanUseBlockBinary(SDNode *N, unsigned I) const;
339178273a1SRichard Sandiford 
34075a5febeSJonas Paulsson   // Return true if N (a load or a store) fullfills the alignment
34175a5febeSJonas Paulsson   // requirements for a PC-relative access.
34275a5febeSJonas Paulsson   bool storeLoadIsAligned(SDNode *N) const;
34375a5febeSJonas Paulsson 
344849a59fdSUlrich Weigand   // Try to expand a boolean SELECT_CCMASK using an IPM sequence.
345849a59fdSUlrich Weigand   SDValue expandSelectBoolean(SDNode *Node);
346849a59fdSUlrich Weigand 
3475f613dfdSUlrich Weigand public:
SystemZDAGToDAGISel(SystemZTargetMachine & TM,CodeGenOpt::Level OptLevel)3485f613dfdSUlrich Weigand   SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
349a6734178SEric Christopher       : SelectionDAGISel(TM, OptLevel) {}
350a6734178SEric Christopher 
runOnMachineFunction(MachineFunction & MF)351a6734178SEric Christopher   bool runOnMachineFunction(MachineFunction &MF) override {
3526e504d77SJonas Paulsson     const Function &F = MF.getFunction();
3536be15788SJonas Paulsson     if (F.getFnAttribute("fentry-call").getValueAsString() != "true") {
3546be15788SJonas Paulsson       if (F.hasFnAttribute("mnop-mcount"))
3556e504d77SJonas Paulsson         report_fatal_error("mnop-mcount only supported with fentry-call");
3566be15788SJonas Paulsson       if (F.hasFnAttribute("mrecord-mcount"))
3576be15788SJonas Paulsson         report_fatal_error("mrecord-mcount only supported with fentry-call");
3586be15788SJonas Paulsson     }
3596e504d77SJonas Paulsson 
360a6734178SEric Christopher     Subtarget = &MF.getSubtarget<SystemZSubtarget>();
361a6734178SEric Christopher     return SelectionDAGISel::runOnMachineFunction(MF);
362a6734178SEric Christopher   }
3635f613dfdSUlrich Weigand 
3645f613dfdSUlrich Weigand   // Override MachineFunctionPass.
getPassName() const365117296c0SMehdi Amini   StringRef getPassName() const override {
3665f613dfdSUlrich Weigand     return "SystemZ DAG->DAG Pattern Instruction Selection";
3675f613dfdSUlrich Weigand   }
3685f613dfdSUlrich Weigand 
3695f613dfdSUlrich Weigand   // Override SelectionDAGISel.
3709b34e8a7SJustin Bogner   void Select(SDNode *Node) override;
37160f1db05SDaniel Sanders   bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
37273156025SCraig Topper                                     std::vector<SDValue> &OutOps) override;
373b32f3656SUlrich Weigand   bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const override;
374849a59fdSUlrich Weigand   void PreprocessISelDAG() override;
3755f613dfdSUlrich Weigand 
3765f613dfdSUlrich Weigand   // Include the pieces autogenerated from the target description.
3775f613dfdSUlrich Weigand   #include "SystemZGenDAGISel.inc"
3785f613dfdSUlrich Weigand };
3795f613dfdSUlrich Weigand } // end anonymous namespace
3805f613dfdSUlrich Weigand 
createSystemZISelDag(SystemZTargetMachine & TM,CodeGenOpt::Level OptLevel)3815f613dfdSUlrich Weigand FunctionPass *llvm::createSystemZISelDag(SystemZTargetMachine &TM,
3825f613dfdSUlrich Weigand                                          CodeGenOpt::Level OptLevel) {
3835f613dfdSUlrich Weigand   return new SystemZDAGToDAGISel(TM, OptLevel);
3845f613dfdSUlrich Weigand }
3855f613dfdSUlrich Weigand 
3865f613dfdSUlrich Weigand // Return true if Val should be selected as a displacement for an address
3875f613dfdSUlrich Weigand // with range DR.  Here we're interested in the range of both the instruction
3885f613dfdSUlrich Weigand // described by DR and of any pairing instruction.
selectDisp(SystemZAddressingMode::DispRange DR,int64_t Val)3895f613dfdSUlrich Weigand static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
3905f613dfdSUlrich Weigand   switch (DR) {
3915f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp12Only:
3925f613dfdSUlrich Weigand     return isUInt<12>(Val);
3935f613dfdSUlrich Weigand 
3945f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp12Pair:
3955f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Only:
3965f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Pair:
3975f613dfdSUlrich Weigand     return isInt<20>(Val);
3985f613dfdSUlrich Weigand 
3995f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Only128:
4005f613dfdSUlrich Weigand     return isInt<20>(Val) && isInt<20>(Val + 8);
4015f613dfdSUlrich Weigand   }
4025f613dfdSUlrich Weigand   llvm_unreachable("Unhandled displacement range");
4035f613dfdSUlrich Weigand }
4045f613dfdSUlrich Weigand 
4055f613dfdSUlrich Weigand // Change the base or index in AM to Value, where IsBase selects
4065f613dfdSUlrich Weigand // between the base and index.
changeComponent(SystemZAddressingMode & AM,bool IsBase,SDValue Value)4075f613dfdSUlrich Weigand static void changeComponent(SystemZAddressingMode &AM, bool IsBase,
4085f613dfdSUlrich Weigand                             SDValue Value) {
4095f613dfdSUlrich Weigand   if (IsBase)
4105f613dfdSUlrich Weigand     AM.Base = Value;
4115f613dfdSUlrich Weigand   else
4125f613dfdSUlrich Weigand     AM.Index = Value;
4135f613dfdSUlrich Weigand }
4145f613dfdSUlrich Weigand 
4155f613dfdSUlrich Weigand // The base or index of AM is equivalent to Value + ADJDYNALLOC,
4165f613dfdSUlrich Weigand // where IsBase selects between the base and index.  Try to fold the
4175f613dfdSUlrich Weigand // ADJDYNALLOC into AM.
expandAdjDynAlloc(SystemZAddressingMode & AM,bool IsBase,SDValue Value)4185f613dfdSUlrich Weigand static bool expandAdjDynAlloc(SystemZAddressingMode &AM, bool IsBase,
4195f613dfdSUlrich Weigand                               SDValue Value) {
4205f613dfdSUlrich Weigand   if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
4215f613dfdSUlrich Weigand     changeComponent(AM, IsBase, Value);
4225f613dfdSUlrich Weigand     AM.IncludesDynAlloc = true;
4235f613dfdSUlrich Weigand     return true;
4245f613dfdSUlrich Weigand   }
4255f613dfdSUlrich Weigand   return false;
4265f613dfdSUlrich Weigand }
4275f613dfdSUlrich Weigand 
4285f613dfdSUlrich Weigand // The base of AM is equivalent to Base + Index.  Try to use Index as
4295f613dfdSUlrich Weigand // the index register.
expandIndex(SystemZAddressingMode & AM,SDValue Base,SDValue Index)4305f613dfdSUlrich Weigand static bool expandIndex(SystemZAddressingMode &AM, SDValue Base,
4315f613dfdSUlrich Weigand                         SDValue Index) {
4325f613dfdSUlrich Weigand   if (AM.hasIndexField() && !AM.Index.getNode()) {
4335f613dfdSUlrich Weigand     AM.Base = Base;
4345f613dfdSUlrich Weigand     AM.Index = Index;
4355f613dfdSUlrich Weigand     return true;
4365f613dfdSUlrich Weigand   }
4375f613dfdSUlrich Weigand   return false;
4385f613dfdSUlrich Weigand }
4395f613dfdSUlrich Weigand 
4405f613dfdSUlrich Weigand // The base or index of AM is equivalent to Op0 + Op1, where IsBase selects
4415f613dfdSUlrich Weigand // between the base and index.  Try to fold Op1 into AM's displacement.
expandDisp(SystemZAddressingMode & AM,bool IsBase,SDValue Op0,uint64_t Op1)4425f613dfdSUlrich Weigand static bool expandDisp(SystemZAddressingMode &AM, bool IsBase,
44354b36916SRichard Sandiford                        SDValue Op0, uint64_t Op1) {
4445f613dfdSUlrich Weigand   // First try adjusting the displacement.
44554b36916SRichard Sandiford   int64_t TestDisp = AM.Disp + Op1;
4465f613dfdSUlrich Weigand   if (selectDisp(AM.DR, TestDisp)) {
4475f613dfdSUlrich Weigand     changeComponent(AM, IsBase, Op0);
4485f613dfdSUlrich Weigand     AM.Disp = TestDisp;
4495f613dfdSUlrich Weigand     return true;
4505f613dfdSUlrich Weigand   }
4515f613dfdSUlrich Weigand 
4525f613dfdSUlrich Weigand   // We could consider forcing the displacement into a register and
4535f613dfdSUlrich Weigand   // using it as an index, but it would need to be carefully tuned.
4545f613dfdSUlrich Weigand   return false;
4555f613dfdSUlrich Weigand }
4565f613dfdSUlrich Weigand 
expandAddress(SystemZAddressingMode & AM,bool IsBase) const4575f613dfdSUlrich Weigand bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
45854b36916SRichard Sandiford                                         bool IsBase) const {
4595f613dfdSUlrich Weigand   SDValue N = IsBase ? AM.Base : AM.Index;
4605f613dfdSUlrich Weigand   unsigned Opcode = N.getOpcode();
4615f613dfdSUlrich Weigand   if (Opcode == ISD::TRUNCATE) {
4625f613dfdSUlrich Weigand     N = N.getOperand(0);
4635f613dfdSUlrich Weigand     Opcode = N.getOpcode();
4645f613dfdSUlrich Weigand   }
4655f613dfdSUlrich Weigand   if (Opcode == ISD::ADD || CurDAG->isBaseWithConstantOffset(N)) {
4665f613dfdSUlrich Weigand     SDValue Op0 = N.getOperand(0);
4675f613dfdSUlrich Weigand     SDValue Op1 = N.getOperand(1);
4685f613dfdSUlrich Weigand 
4695f613dfdSUlrich Weigand     unsigned Op0Code = Op0->getOpcode();
4705f613dfdSUlrich Weigand     unsigned Op1Code = Op1->getOpcode();
4715f613dfdSUlrich Weigand 
4725f613dfdSUlrich Weigand     if (Op0Code == SystemZISD::ADJDYNALLOC)
4735f613dfdSUlrich Weigand       return expandAdjDynAlloc(AM, IsBase, Op1);
4745f613dfdSUlrich Weigand     if (Op1Code == SystemZISD::ADJDYNALLOC)
4755f613dfdSUlrich Weigand       return expandAdjDynAlloc(AM, IsBase, Op0);
4765f613dfdSUlrich Weigand 
4775f613dfdSUlrich Weigand     if (Op0Code == ISD::Constant)
47854b36916SRichard Sandiford       return expandDisp(AM, IsBase, Op1,
47954b36916SRichard Sandiford                         cast<ConstantSDNode>(Op0)->getSExtValue());
4805f613dfdSUlrich Weigand     if (Op1Code == ISD::Constant)
48154b36916SRichard Sandiford       return expandDisp(AM, IsBase, Op0,
48254b36916SRichard Sandiford                         cast<ConstantSDNode>(Op1)->getSExtValue());
4835f613dfdSUlrich Weigand 
4845f613dfdSUlrich Weigand     if (IsBase && expandIndex(AM, Op0, Op1))
4855f613dfdSUlrich Weigand       return true;
4865f613dfdSUlrich Weigand   }
48754b36916SRichard Sandiford   if (Opcode == SystemZISD::PCREL_OFFSET) {
48854b36916SRichard Sandiford     SDValue Full = N.getOperand(0);
48954b36916SRichard Sandiford     SDValue Base = N.getOperand(1);
49054b36916SRichard Sandiford     SDValue Anchor = Base.getOperand(0);
49154b36916SRichard Sandiford     uint64_t Offset = (cast<GlobalAddressSDNode>(Full)->getOffset() -
49254b36916SRichard Sandiford                        cast<GlobalAddressSDNode>(Anchor)->getOffset());
49354b36916SRichard Sandiford     return expandDisp(AM, IsBase, Base, Offset);
49454b36916SRichard Sandiford   }
4955f613dfdSUlrich Weigand   return false;
4965f613dfdSUlrich Weigand }
4975f613dfdSUlrich Weigand 
4985f613dfdSUlrich Weigand // Return true if an instruction with displacement range DR should be
4995f613dfdSUlrich Weigand // used for displacement value Val.  selectDisp(DR, Val) must already hold.
isValidDisp(SystemZAddressingMode::DispRange DR,int64_t Val)5005f613dfdSUlrich Weigand static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
5015f613dfdSUlrich Weigand   assert(selectDisp(DR, Val) && "Invalid displacement");
5025f613dfdSUlrich Weigand   switch (DR) {
5035f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp12Only:
5045f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Only:
5055f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Only128:
5065f613dfdSUlrich Weigand     return true;
5075f613dfdSUlrich Weigand 
5085f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp12Pair:
5095f613dfdSUlrich Weigand     // Use the other instruction if the displacement is too large.
5105f613dfdSUlrich Weigand     return isUInt<12>(Val);
5115f613dfdSUlrich Weigand 
5125f613dfdSUlrich Weigand   case SystemZAddressingMode::Disp20Pair:
5135f613dfdSUlrich Weigand     // Use the other instruction if the displacement is small enough.
5145f613dfdSUlrich Weigand     return !isUInt<12>(Val);
5155f613dfdSUlrich Weigand   }
5165f613dfdSUlrich Weigand   llvm_unreachable("Unhandled displacement range");
5175f613dfdSUlrich Weigand }
5185f613dfdSUlrich Weigand 
5195f613dfdSUlrich Weigand // Return true if Base + Disp + Index should be performed by LA(Y).
shouldUseLA(SDNode * Base,int64_t Disp,SDNode * Index)5205f613dfdSUlrich Weigand static bool shouldUseLA(SDNode *Base, int64_t Disp, SDNode *Index) {
5215f613dfdSUlrich Weigand   // Don't use LA(Y) for constants.
5225f613dfdSUlrich Weigand   if (!Base)
5235f613dfdSUlrich Weigand     return false;
5245f613dfdSUlrich Weigand 
5255f613dfdSUlrich Weigand   // Always use LA(Y) for frame addresses, since we know that the destination
5265f613dfdSUlrich Weigand   // register is almost always (perhaps always) going to be different from
5275f613dfdSUlrich Weigand   // the frame register.
5285f613dfdSUlrich Weigand   if (Base->getOpcode() == ISD::FrameIndex)
5295f613dfdSUlrich Weigand     return true;
5305f613dfdSUlrich Weigand 
5315f613dfdSUlrich Weigand   if (Disp) {
5325f613dfdSUlrich Weigand     // Always use LA(Y) if there is a base, displacement and index.
5335f613dfdSUlrich Weigand     if (Index)
5345f613dfdSUlrich Weigand       return true;
5355f613dfdSUlrich Weigand 
5365f613dfdSUlrich Weigand     // Always use LA if the displacement is small enough.  It should always
5375f613dfdSUlrich Weigand     // be no worse than AGHI (and better if it avoids a move).
5385f613dfdSUlrich Weigand     if (isUInt<12>(Disp))
5395f613dfdSUlrich Weigand       return true;
5405f613dfdSUlrich Weigand 
5415f613dfdSUlrich Weigand     // For similar reasons, always use LAY if the constant is too big for AGHI.
5425f613dfdSUlrich Weigand     // LAY should be no worse than AGFI.
5435f613dfdSUlrich Weigand     if (!isInt<16>(Disp))
5445f613dfdSUlrich Weigand       return true;
5455f613dfdSUlrich Weigand   } else {
5465f613dfdSUlrich Weigand     // Don't use LA for plain registers.
5475f613dfdSUlrich Weigand     if (!Index)
5485f613dfdSUlrich Weigand       return false;
5495f613dfdSUlrich Weigand 
5505f613dfdSUlrich Weigand     // Don't use LA for plain addition if the index operand is only used
5515f613dfdSUlrich Weigand     // once.  It should be a natural two-operand addition in that case.
5525f613dfdSUlrich Weigand     if (Index->hasOneUse())
5535f613dfdSUlrich Weigand       return false;
5545f613dfdSUlrich Weigand 
5555f613dfdSUlrich Weigand     // Prefer addition if the second operation is sign-extended, in the
5565f613dfdSUlrich Weigand     // hope of using AGF.
5575f613dfdSUlrich Weigand     unsigned IndexOpcode = Index->getOpcode();
5585f613dfdSUlrich Weigand     if (IndexOpcode == ISD::SIGN_EXTEND ||
5595f613dfdSUlrich Weigand         IndexOpcode == ISD::SIGN_EXTEND_INREG)
5605f613dfdSUlrich Weigand       return false;
5615f613dfdSUlrich Weigand   }
5625f613dfdSUlrich Weigand 
5635f613dfdSUlrich Weigand   // Don't use LA for two-operand addition if either operand is only
5645f613dfdSUlrich Weigand   // used once.  The addition instructions are better in that case.
5655f613dfdSUlrich Weigand   if (Base->hasOneUse())
5665f613dfdSUlrich Weigand     return false;
5675f613dfdSUlrich Weigand 
5685f613dfdSUlrich Weigand   return true;
5695f613dfdSUlrich Weigand }
5705f613dfdSUlrich Weigand 
5715f613dfdSUlrich Weigand // Return true if Addr is suitable for AM, updating AM if so.
selectAddress(SDValue Addr,SystemZAddressingMode & AM) const5725f613dfdSUlrich Weigand bool SystemZDAGToDAGISel::selectAddress(SDValue Addr,
57354b36916SRichard Sandiford                                         SystemZAddressingMode &AM) const {
5745f613dfdSUlrich Weigand   // Start out assuming that the address will need to be loaded separately,
5755f613dfdSUlrich Weigand   // then try to extend it as much as we can.
5765f613dfdSUlrich Weigand   AM.Base = Addr;
5775f613dfdSUlrich Weigand 
5785f613dfdSUlrich Weigand   // First try treating the address as a constant.
5795f613dfdSUlrich Weigand   if (Addr.getOpcode() == ISD::Constant &&
58054b36916SRichard Sandiford       expandDisp(AM, true, SDValue(),
58154b36916SRichard Sandiford                  cast<ConstantSDNode>(Addr)->getSExtValue()))
5825f613dfdSUlrich Weigand     ;
5839de88d9bSMarcin Koscielnicki   // Also see if it's a bare ADJDYNALLOC.
5849de88d9bSMarcin Koscielnicki   else if (Addr.getOpcode() == SystemZISD::ADJDYNALLOC &&
5859de88d9bSMarcin Koscielnicki            expandAdjDynAlloc(AM, true, SDValue()))
5869de88d9bSMarcin Koscielnicki     ;
5875f613dfdSUlrich Weigand   else
5885f613dfdSUlrich Weigand     // Otherwise try expanding each component.
5895f613dfdSUlrich Weigand     while (expandAddress(AM, true) ||
5905f613dfdSUlrich Weigand            (AM.Index.getNode() && expandAddress(AM, false)))
5915f613dfdSUlrich Weigand       continue;
5925f613dfdSUlrich Weigand 
5935f613dfdSUlrich Weigand   // Reject cases where it isn't profitable to use LA(Y).
5945f613dfdSUlrich Weigand   if (AM.Form == SystemZAddressingMode::FormBDXLA &&
5955f613dfdSUlrich Weigand       !shouldUseLA(AM.Base.getNode(), AM.Disp, AM.Index.getNode()))
5965f613dfdSUlrich Weigand     return false;
5975f613dfdSUlrich Weigand 
5985f613dfdSUlrich Weigand   // Reject cases where the other instruction in a pair should be used.
5995f613dfdSUlrich Weigand   if (!isValidDisp(AM.DR, AM.Disp))
6005f613dfdSUlrich Weigand     return false;
6015f613dfdSUlrich Weigand 
6025f613dfdSUlrich Weigand   // Make sure that ADJDYNALLOC is included where necessary.
6035f613dfdSUlrich Weigand   if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
6045f613dfdSUlrich Weigand     return false;
6055f613dfdSUlrich Weigand 
606e2c5cbc1SJonas Paulsson   LLVM_DEBUG(AM.dump(CurDAG));
6075f613dfdSUlrich Weigand   return true;
6085f613dfdSUlrich Weigand }
6095f613dfdSUlrich Weigand 
6105f613dfdSUlrich Weigand // Insert a node into the DAG at least before Pos.  This will reposition
6115f613dfdSUlrich Weigand // the node as needed, and will assign it a node ID that is <= Pos's ID.
6125f613dfdSUlrich Weigand // Note that this does *not* preserve the uniqueness of node IDs!
6135f613dfdSUlrich Weigand // The selection DAG must no longer depend on their uniqueness when this
6145f613dfdSUlrich Weigand // function is used.
insertDAGNode(SelectionDAG * DAG,SDNode * Pos,SDValue N)6155f613dfdSUlrich Weigand static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N) {
6168c5f47acSNirav Dave   if (N->getNodeId() == -1 ||
6178c5f47acSNirav Dave       (SelectionDAGISel::getUninvalidatedNodeId(N.getNode()) >
6188c5f47acSNirav Dave        SelectionDAGISel::getUninvalidatedNodeId(Pos))) {
619a2c90e47SDuncan P. N. Exon Smith     DAG->RepositionNode(Pos->getIterator(), N.getNode());
6203264c1bdSNirav Dave     // Mark Node as invalid for pruning as after this it may be a successor to a
6213264c1bdSNirav Dave     // selected node but otherwise be in the same position of Pos.
6223264c1bdSNirav Dave     // Conservatively mark it with the same -abs(Id) to assure node id
6233264c1bdSNirav Dave     // invariant is preserved.
6248c5f47acSNirav Dave     N->setNodeId(Pos->getNodeId());
6258c5f47acSNirav Dave     SelectionDAGISel::InvalidateNodeId(N.getNode());
6265f613dfdSUlrich Weigand   }
6275f613dfdSUlrich Weigand }
6285f613dfdSUlrich Weigand 
getAddressOperands(const SystemZAddressingMode & AM,EVT VT,SDValue & Base,SDValue & Disp) const6295f613dfdSUlrich Weigand void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM,
6305f613dfdSUlrich Weigand                                              EVT VT, SDValue &Base,
63154b36916SRichard Sandiford                                              SDValue &Disp) const {
6325f613dfdSUlrich Weigand   Base = AM.Base;
6335f613dfdSUlrich Weigand   if (!Base.getNode())
6345f613dfdSUlrich Weigand     // Register 0 means "no base".  This is mostly useful for shifts.
6355f613dfdSUlrich Weigand     Base = CurDAG->getRegister(0, VT);
6365f613dfdSUlrich Weigand   else if (Base.getOpcode() == ISD::FrameIndex) {
6375f613dfdSUlrich Weigand     // Lower a FrameIndex to a TargetFrameIndex.
6385f613dfdSUlrich Weigand     int64_t FrameIndex = cast<FrameIndexSDNode>(Base)->getIndex();
6395f613dfdSUlrich Weigand     Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
6405f613dfdSUlrich Weigand   } else if (Base.getValueType() != VT) {
6415f613dfdSUlrich Weigand     // Truncate values from i64 to i32, for shifts.
6425f613dfdSUlrich Weigand     assert(VT == MVT::i32 && Base.getValueType() == MVT::i64 &&
6435f613dfdSUlrich Weigand            "Unexpected truncation");
644ef9de2a7SAndrew Trick     SDLoc DL(Base);
6455f613dfdSUlrich Weigand     SDValue Trunc = CurDAG->getNode(ISD::TRUNCATE, DL, VT, Base);
6465f613dfdSUlrich Weigand     insertDAGNode(CurDAG, Base.getNode(), Trunc);
6475f613dfdSUlrich Weigand     Base = Trunc;
6485f613dfdSUlrich Weigand   }
6495f613dfdSUlrich Weigand 
6505f613dfdSUlrich Weigand   // Lower the displacement to a TargetConstant.
651842a51baSSergey Dmitrouk   Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(Base), VT);
6525f613dfdSUlrich Weigand }
6535f613dfdSUlrich Weigand 
getAddressOperands(const SystemZAddressingMode & AM,EVT VT,SDValue & Base,SDValue & Disp,SDValue & Index) const6545f613dfdSUlrich Weigand void SystemZDAGToDAGISel::getAddressOperands(const SystemZAddressingMode &AM,
6555f613dfdSUlrich Weigand                                              EVT VT, SDValue &Base,
65654b36916SRichard Sandiford                                              SDValue &Disp,
65754b36916SRichard Sandiford                                              SDValue &Index) const {
6585f613dfdSUlrich Weigand   getAddressOperands(AM, VT, Base, Disp);
6595f613dfdSUlrich Weigand 
6605f613dfdSUlrich Weigand   Index = AM.Index;
6615f613dfdSUlrich Weigand   if (!Index.getNode())
6625f613dfdSUlrich Weigand     // Register 0 means "no index".
6635f613dfdSUlrich Weigand     Index = CurDAG->getRegister(0, VT);
6645f613dfdSUlrich Weigand }
6655f613dfdSUlrich Weigand 
selectBDAddr(SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp) const6665f613dfdSUlrich Weigand bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
6675f613dfdSUlrich Weigand                                        SDValue Addr, SDValue &Base,
66854b36916SRichard Sandiford                                        SDValue &Disp) const {
6695f613dfdSUlrich Weigand   SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
6705f613dfdSUlrich Weigand   if (!selectAddress(Addr, AM))
6715f613dfdSUlrich Weigand     return false;
6725f613dfdSUlrich Weigand 
6735f613dfdSUlrich Weigand   getAddressOperands(AM, Addr.getValueType(), Base, Disp);
6745f613dfdSUlrich Weigand   return true;
6755f613dfdSUlrich Weigand }
6765f613dfdSUlrich Weigand 
selectMVIAddr(SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp) const677a481f585SRichard Sandiford bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
678a481f585SRichard Sandiford                                         SDValue Addr, SDValue &Base,
67954b36916SRichard Sandiford                                         SDValue &Disp) const {
680a481f585SRichard Sandiford   SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
681a481f585SRichard Sandiford   if (!selectAddress(Addr, AM) || AM.Index.getNode())
682a481f585SRichard Sandiford     return false;
683a481f585SRichard Sandiford 
684a481f585SRichard Sandiford   getAddressOperands(AM, Addr.getValueType(), Base, Disp);
685a481f585SRichard Sandiford   return true;
686a481f585SRichard Sandiford }
687a481f585SRichard Sandiford 
selectBDXAddr(SystemZAddressingMode::AddrForm Form,SystemZAddressingMode::DispRange DR,SDValue Addr,SDValue & Base,SDValue & Disp,SDValue & Index) const6885f613dfdSUlrich Weigand bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
6895f613dfdSUlrich Weigand                                         SystemZAddressingMode::DispRange DR,
6905f613dfdSUlrich Weigand                                         SDValue Addr, SDValue &Base,
69154b36916SRichard Sandiford                                         SDValue &Disp, SDValue &Index) const {
6925f613dfdSUlrich Weigand   SystemZAddressingMode AM(Form, DR);
6935f613dfdSUlrich Weigand   if (!selectAddress(Addr, AM))
6945f613dfdSUlrich Weigand     return false;
6955f613dfdSUlrich Weigand 
6965f613dfdSUlrich Weigand   getAddressOperands(AM, Addr.getValueType(), Base, Disp, Index);
6975f613dfdSUlrich Weigand   return true;
6985f613dfdSUlrich Weigand }
6995f613dfdSUlrich Weigand 
selectBDVAddr12Only(SDValue Addr,SDValue Elem,SDValue & Base,SDValue & Disp,SDValue & Index) const700ce4c1095SUlrich Weigand bool SystemZDAGToDAGISel::selectBDVAddr12Only(SDValue Addr, SDValue Elem,
701ce4c1095SUlrich Weigand                                               SDValue &Base,
702ce4c1095SUlrich Weigand                                               SDValue &Disp,
703ce4c1095SUlrich Weigand                                               SDValue &Index) const {
704ce4c1095SUlrich Weigand   SDValue Regs[2];
705ce4c1095SUlrich Weigand   if (selectBDXAddr12Only(Addr, Regs[0], Disp, Regs[1]) &&
706ce4c1095SUlrich Weigand       Regs[0].getNode() && Regs[1].getNode()) {
707ce4c1095SUlrich Weigand     for (unsigned int I = 0; I < 2; ++I) {
708ce4c1095SUlrich Weigand       Base = Regs[I];
709ce4c1095SUlrich Weigand       Index = Regs[1 - I];
710ce4c1095SUlrich Weigand       // We can't tell here whether the index vector has the right type
711ce4c1095SUlrich Weigand       // for the access; the caller needs to do that instead.
712ce4c1095SUlrich Weigand       if (Index.getOpcode() == ISD::ZERO_EXTEND)
713ce4c1095SUlrich Weigand         Index = Index.getOperand(0);
714ce4c1095SUlrich Weigand       if (Index.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
715ce4c1095SUlrich Weigand           Index.getOperand(1) == Elem) {
716ce4c1095SUlrich Weigand         Index = Index.getOperand(0);
717ce4c1095SUlrich Weigand         return true;
718ce4c1095SUlrich Weigand       }
719ce4c1095SUlrich Weigand     }
720ce4c1095SUlrich Weigand   }
721ce4c1095SUlrich Weigand   return false;
722ce4c1095SUlrich Weigand }
723ce4c1095SUlrich Weigand 
detectOrAndInsertion(SDValue & Op,uint64_t InsertMask) const724885140c9SRichard Sandiford bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op,
72554b36916SRichard Sandiford                                                uint64_t InsertMask) const {
726885140c9SRichard Sandiford   // We're only interested in cases where the insertion is into some operand
727885140c9SRichard Sandiford   // of Op, rather than into Op itself.  The only useful case is an AND.
728885140c9SRichard Sandiford   if (Op.getOpcode() != ISD::AND)
729885140c9SRichard Sandiford     return false;
730885140c9SRichard Sandiford 
731885140c9SRichard Sandiford   // We need a constant mask.
73221f5d68aSRichard Sandiford   auto *MaskNode = dyn_cast<ConstantSDNode>(Op.getOperand(1).getNode());
733885140c9SRichard Sandiford   if (!MaskNode)
734885140c9SRichard Sandiford     return false;
735885140c9SRichard Sandiford 
736885140c9SRichard Sandiford   // It's not an insertion of Op.getOperand(0) if the two masks overlap.
737885140c9SRichard Sandiford   uint64_t AndMask = MaskNode->getZExtValue();
738885140c9SRichard Sandiford   if (InsertMask & AndMask)
739885140c9SRichard Sandiford     return false;
740885140c9SRichard Sandiford 
741885140c9SRichard Sandiford   // It's only an insertion if all bits are covered or are known to be zero.
742885140c9SRichard Sandiford   // The inner check covers all cases but is more expensive.
743b1f0a0f4SSanjay Patel   uint64_t Used = allOnes(Op.getValueSizeInBits());
744885140c9SRichard Sandiford   if (Used != (AndMask | InsertMask)) {
7452482c51eSSimon Pilgrim     KnownBits Known = CurDAG->computeKnownBits(Op.getOperand(0));
746d0af7e8aSCraig Topper     if (Used != (AndMask | InsertMask | Known.Zero.getZExtValue()))
747885140c9SRichard Sandiford       return false;
748885140c9SRichard Sandiford   }
749885140c9SRichard Sandiford 
750885140c9SRichard Sandiford   Op = Op.getOperand(0);
751885140c9SRichard Sandiford   return true;
752885140c9SRichard Sandiford }
753885140c9SRichard Sandiford 
refineRxSBGMask(RxSBGOperands & RxSBG,uint64_t Mask) const75454b36916SRichard Sandiford bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
75554b36916SRichard Sandiford                                           uint64_t Mask) const {
7566a06ba36SRichard Sandiford   const SystemZInstrInfo *TII = getInstrInfo();
7575cbac967SRichard Sandiford   if (RxSBG.Rotate != 0)
7585cbac967SRichard Sandiford     Mask = (Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
7595cbac967SRichard Sandiford   Mask &= RxSBG.Mask;
7606a06ba36SRichard Sandiford   if (TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
7615cbac967SRichard Sandiford     RxSBG.Mask = Mask;
76284f54a3bSRichard Sandiford     return true;
76384f54a3bSRichard Sandiford   }
76484f54a3bSRichard Sandiford   return false;
76584f54a3bSRichard Sandiford }
76684f54a3bSRichard Sandiford 
767dd7dd930SRichard Sandiford // Return true if any bits of (RxSBG.Input & Mask) are significant.
maskMatters(RxSBGOperands & RxSBG,uint64_t Mask)768dd7dd930SRichard Sandiford static bool maskMatters(RxSBGOperands &RxSBG, uint64_t Mask) {
769dd7dd930SRichard Sandiford   // Rotate the mask in the same way as RxSBG.Input is rotated.
770297f7d27SRichard Sandiford   if (RxSBG.Rotate != 0)
771dd7dd930SRichard Sandiford     Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
772dd7dd930SRichard Sandiford   return (Mask & RxSBG.Mask) != 0;
773297f7d27SRichard Sandiford }
774297f7d27SRichard Sandiford 
expandRxSBG(RxSBGOperands & RxSBG) const77554b36916SRichard Sandiford bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const {
7765cbac967SRichard Sandiford   SDValue N = RxSBG.Input;
777297f7d27SRichard Sandiford   unsigned Opcode = N.getOpcode();
778297f7d27SRichard Sandiford   switch (Opcode) {
7790df35058SZhan Jun Liau   case ISD::TRUNCATE: {
7800df35058SZhan Jun Liau     if (RxSBG.Opcode == SystemZ::RNSBG)
7810df35058SZhan Jun Liau       return false;
782b1f0a0f4SSanjay Patel     uint64_t BitSize = N.getValueSizeInBits();
7830df35058SZhan Jun Liau     uint64_t Mask = allOnes(BitSize);
7840df35058SZhan Jun Liau     if (!refineRxSBGMask(RxSBG, Mask))
7850df35058SZhan Jun Liau       return false;
7860df35058SZhan Jun Liau     RxSBG.Input = N.getOperand(0);
7870df35058SZhan Jun Liau     return true;
7880df35058SZhan Jun Liau   }
78982ec87dbSRichard Sandiford   case ISD::AND: {
79051093210SRichard Sandiford     if (RxSBG.Opcode == SystemZ::RNSBG)
79151093210SRichard Sandiford       return false;
79251093210SRichard Sandiford 
79321f5d68aSRichard Sandiford     auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
79482ec87dbSRichard Sandiford     if (!MaskNode)
79582ec87dbSRichard Sandiford       return false;
79682ec87dbSRichard Sandiford 
79782ec87dbSRichard Sandiford     SDValue Input = N.getOperand(0);
79882ec87dbSRichard Sandiford     uint64_t Mask = MaskNode->getZExtValue();
7995cbac967SRichard Sandiford     if (!refineRxSBGMask(RxSBG, Mask)) {
80082ec87dbSRichard Sandiford       // If some bits of Input are already known zeros, those bits will have
80182ec87dbSRichard Sandiford       // been removed from the mask.  See if adding them back in makes the
80282ec87dbSRichard Sandiford       // mask suitable.
8032482c51eSSimon Pilgrim       KnownBits Known = CurDAG->computeKnownBits(Input);
804d0af7e8aSCraig Topper       Mask |= Known.Zero.getZExtValue();
8055cbac967SRichard Sandiford       if (!refineRxSBGMask(RxSBG, Mask))
80682ec87dbSRichard Sandiford         return false;
80782ec87dbSRichard Sandiford     }
8085cbac967SRichard Sandiford     RxSBG.Input = Input;
80982ec87dbSRichard Sandiford     return true;
81082ec87dbSRichard Sandiford   }
81182ec87dbSRichard Sandiford 
81251093210SRichard Sandiford   case ISD::OR: {
81351093210SRichard Sandiford     if (RxSBG.Opcode != SystemZ::RNSBG)
81451093210SRichard Sandiford       return false;
81551093210SRichard Sandiford 
81621f5d68aSRichard Sandiford     auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
81751093210SRichard Sandiford     if (!MaskNode)
81851093210SRichard Sandiford       return false;
81951093210SRichard Sandiford 
82051093210SRichard Sandiford     SDValue Input = N.getOperand(0);
82151093210SRichard Sandiford     uint64_t Mask = ~MaskNode->getZExtValue();
82251093210SRichard Sandiford     if (!refineRxSBGMask(RxSBG, Mask)) {
82351093210SRichard Sandiford       // If some bits of Input are already known ones, those bits will have
82451093210SRichard Sandiford       // been removed from the mask.  See if adding them back in makes the
82551093210SRichard Sandiford       // mask suitable.
8262482c51eSSimon Pilgrim       KnownBits Known = CurDAG->computeKnownBits(Input);
827d0af7e8aSCraig Topper       Mask &= ~Known.One.getZExtValue();
82851093210SRichard Sandiford       if (!refineRxSBGMask(RxSBG, Mask))
82951093210SRichard Sandiford         return false;
83051093210SRichard Sandiford     }
83151093210SRichard Sandiford     RxSBG.Input = Input;
83251093210SRichard Sandiford     return true;
83351093210SRichard Sandiford   }
83451093210SRichard Sandiford 
83582ec87dbSRichard Sandiford   case ISD::ROTL: {
8365cbac967SRichard Sandiford     // Any 64-bit rotate left can be merged into the RxSBG.
8373e382972SRichard Sandiford     if (RxSBG.BitSize != 64 || N.getValueType() != MVT::i64)
83882ec87dbSRichard Sandiford       return false;
83921f5d68aSRichard Sandiford     auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
84082ec87dbSRichard Sandiford     if (!CountNode)
84182ec87dbSRichard Sandiford       return false;
84282ec87dbSRichard Sandiford 
8435cbac967SRichard Sandiford     RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
8445cbac967SRichard Sandiford     RxSBG.Input = N.getOperand(0);
84582ec87dbSRichard Sandiford     return true;
84682ec87dbSRichard Sandiford   }
84782ec87dbSRichard Sandiford 
848220ee49bSRichard Sandiford   case ISD::ANY_EXTEND:
849220ee49bSRichard Sandiford     // Bits above the extended operand are don't-care.
850220ee49bSRichard Sandiford     RxSBG.Input = N.getOperand(0);
851220ee49bSRichard Sandiford     return true;
852220ee49bSRichard Sandiford 
8533875cb60SRichard Sandiford   case ISD::ZERO_EXTEND:
8543875cb60SRichard Sandiford     if (RxSBG.Opcode != SystemZ::RNSBG) {
855220ee49bSRichard Sandiford       // Restrict the mask to the extended operand.
856b1f0a0f4SSanjay Patel       unsigned InnerBitSize = N.getOperand(0).getValueSizeInBits();
857220ee49bSRichard Sandiford       if (!refineRxSBGMask(RxSBG, allOnes(InnerBitSize)))
858220ee49bSRichard Sandiford         return false;
859220ee49bSRichard Sandiford 
860220ee49bSRichard Sandiford       RxSBG.Input = N.getOperand(0);
861220ee49bSRichard Sandiford       return true;
862220ee49bSRichard Sandiford     }
863cd1d5aafSJustin Bogner     LLVM_FALLTHROUGH;
864220ee49bSRichard Sandiford 
865220ee49bSRichard Sandiford   case ISD::SIGN_EXTEND: {
8663e382972SRichard Sandiford     // Check that the extension bits are don't-care (i.e. are masked out
8673e382972SRichard Sandiford     // by the final mask).
86819380baeSJonas Paulsson     unsigned BitSize = N.getValueSizeInBits();
869b1f0a0f4SSanjay Patel     unsigned InnerBitSize = N.getOperand(0).getValueSizeInBits();
87019380baeSJonas Paulsson     if (maskMatters(RxSBG, allOnes(BitSize) - allOnes(InnerBitSize))) {
87119380baeSJonas Paulsson       // In the case where only the sign bit is active, increase Rotate with
87219380baeSJonas Paulsson       // the extension width.
87319380baeSJonas Paulsson       if (RxSBG.Mask == 1 && RxSBG.Rotate == 1)
87419380baeSJonas Paulsson         RxSBG.Rotate += (BitSize - InnerBitSize);
87519380baeSJonas Paulsson       else
8763e382972SRichard Sandiford         return false;
87719380baeSJonas Paulsson     }
8783e382972SRichard Sandiford 
8793e382972SRichard Sandiford     RxSBG.Input = N.getOperand(0);
8803e382972SRichard Sandiford     return true;
8813e382972SRichard Sandiford   }
8823e382972SRichard Sandiford 
88382ec87dbSRichard Sandiford   case ISD::SHL: {
88421f5d68aSRichard Sandiford     auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
88582ec87dbSRichard Sandiford     if (!CountNode)
88682ec87dbSRichard Sandiford       return false;
88782ec87dbSRichard Sandiford 
88882ec87dbSRichard Sandiford     uint64_t Count = CountNode->getZExtValue();
889b1f0a0f4SSanjay Patel     unsigned BitSize = N.getValueSizeInBits();
8903e382972SRichard Sandiford     if (Count < 1 || Count >= BitSize)
89182ec87dbSRichard Sandiford       return false;
89282ec87dbSRichard Sandiford 
89351093210SRichard Sandiford     if (RxSBG.Opcode == SystemZ::RNSBG) {
89451093210SRichard Sandiford       // Treat (shl X, count) as (rotl X, size-count) as long as the bottom
89551093210SRichard Sandiford       // count bits from RxSBG.Input are ignored.
896dd7dd930SRichard Sandiford       if (maskMatters(RxSBG, allOnes(Count)))
89751093210SRichard Sandiford         return false;
89851093210SRichard Sandiford     } else {
89951093210SRichard Sandiford       // Treat (shl X, count) as (and (rotl X, count), ~0<<count).
9003e382972SRichard Sandiford       if (!refineRxSBGMask(RxSBG, allOnes(BitSize - Count) << Count))
90151093210SRichard Sandiford         return false;
90251093210SRichard Sandiford     }
90351093210SRichard Sandiford 
9045cbac967SRichard Sandiford     RxSBG.Rotate = (RxSBG.Rotate + Count) & 63;
9055cbac967SRichard Sandiford     RxSBG.Input = N.getOperand(0);
90682ec87dbSRichard Sandiford     return true;
90782ec87dbSRichard Sandiford   }
90882ec87dbSRichard Sandiford 
909297f7d27SRichard Sandiford   case ISD::SRL:
910297f7d27SRichard Sandiford   case ISD::SRA: {
91121f5d68aSRichard Sandiford     auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode());
912297f7d27SRichard Sandiford     if (!CountNode)
913297f7d27SRichard Sandiford       return false;
914297f7d27SRichard Sandiford 
915297f7d27SRichard Sandiford     uint64_t Count = CountNode->getZExtValue();
916b1f0a0f4SSanjay Patel     unsigned BitSize = N.getValueSizeInBits();
9173e382972SRichard Sandiford     if (Count < 1 || Count >= BitSize)
918297f7d27SRichard Sandiford       return false;
919297f7d27SRichard Sandiford 
92051093210SRichard Sandiford     if (RxSBG.Opcode == SystemZ::RNSBG || Opcode == ISD::SRA) {
92151093210SRichard Sandiford       // Treat (srl|sra X, count) as (rotl X, size-count) as long as the top
92251093210SRichard Sandiford       // count bits from RxSBG.Input are ignored.
923dd7dd930SRichard Sandiford       if (maskMatters(RxSBG, allOnes(Count) << (BitSize - Count)))
924297f7d27SRichard Sandiford         return false;
925297f7d27SRichard Sandiford     } else {
92682ec87dbSRichard Sandiford       // Treat (srl X, count), mask) as (and (rotl X, size-count), ~0>>count),
92782ec87dbSRichard Sandiford       // which is similar to SLL above.
9283e382972SRichard Sandiford       if (!refineRxSBGMask(RxSBG, allOnes(BitSize - Count)))
92982ec87dbSRichard Sandiford         return false;
93082ec87dbSRichard Sandiford     }
93182ec87dbSRichard Sandiford 
932297f7d27SRichard Sandiford     RxSBG.Rotate = (RxSBG.Rotate - Count) & 63;
9335cbac967SRichard Sandiford     RxSBG.Input = N.getOperand(0);
93482ec87dbSRichard Sandiford     return true;
93582ec87dbSRichard Sandiford   }
93682ec87dbSRichard Sandiford   default:
93782ec87dbSRichard Sandiford     return false;
93882ec87dbSRichard Sandiford   }
93982ec87dbSRichard Sandiford }
94082ec87dbSRichard Sandiford 
getUNDEF(const SDLoc & DL,EVT VT) const941bdc4956bSBenjamin Kramer SDValue SystemZDAGToDAGISel::getUNDEF(const SDLoc &DL, EVT VT) const {
9423ad5a15bSRichard Sandiford   SDNode *N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, VT);
94384f54a3bSRichard Sandiford   return SDValue(N, 0);
94484f54a3bSRichard Sandiford }
94584f54a3bSRichard Sandiford 
convertTo(const SDLoc & DL,EVT VT,SDValue N) const946bdc4956bSBenjamin Kramer SDValue SystemZDAGToDAGISel::convertTo(const SDLoc &DL, EVT VT,
947bdc4956bSBenjamin Kramer                                        SDValue N) const {
948d8163208SRichard Sandiford   if (N.getValueType() == MVT::i32 && VT == MVT::i64)
94987a44364SRichard Sandiford     return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
9503ad5a15bSRichard Sandiford                                          DL, VT, getUNDEF(DL, MVT::i64), N);
951d8163208SRichard Sandiford   if (N.getValueType() == MVT::i64 && VT == MVT::i32)
95287a44364SRichard Sandiford     return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32, DL, VT, N);
95384f54a3bSRichard Sandiford   assert(N.getValueType() == VT && "Unexpected value types");
95484f54a3bSRichard Sandiford   return N;
95584f54a3bSRichard Sandiford }
95684f54a3bSRichard Sandiford 
tryRISBGZero(SDNode * N)957bbcd2233SJustin Bogner bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) {
958842a51baSSergey Dmitrouk   SDLoc DL(N);
9596a06ba36SRichard Sandiford   EVT VT = N->getValueType(0);
96077884bcbSUlrich Weigand   if (!VT.isInteger() || VT.getSizeInBits() > 64)
961bbcd2233SJustin Bogner     return false;
96251093210SRichard Sandiford   RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0));
96382ec87dbSRichard Sandiford   unsigned Count = 0;
9645cbac967SRichard Sandiford   while (expandRxSBG(RISBG))
9650df35058SZhan Jun Liau     // The widening or narrowing is expected to be free.
9660df35058SZhan Jun Liau     // Counting widening or narrowing as a saved operation will result in
9670df35058SZhan Jun Liau     // preferring an R*SBG over a simple shift/logical instruction.
9680df35058SZhan Jun Liau     if (RISBG.Input.getOpcode() != ISD::ANY_EXTEND &&
9690df35058SZhan Jun Liau         RISBG.Input.getOpcode() != ISD::TRUNCATE)
97082ec87dbSRichard Sandiford       Count += 1;
971fbaec116SJonas Paulsson   if (Count == 0 || isa<ConstantSDNode>(RISBG.Input))
972bbcd2233SJustin Bogner     return false;
9735dc7b67cSUlrich Weigand 
97482ec87dbSRichard Sandiford   // Prefer to use normal shift instructions over RISBG, since they can handle
9756a06ba36SRichard Sandiford   // all cases and are sometimes shorter.
9765dc7b67cSUlrich Weigand   if (Count == 1 && N->getOpcode() != ISD::AND)
977bbcd2233SJustin Bogner     return false;
97882ec87dbSRichard Sandiford 
9796a06ba36SRichard Sandiford   // Prefer register extensions like LLC over RISBG.  Also prefer to start
9806a06ba36SRichard Sandiford   // out with normal ANDs if one instruction would be enough.  We can convert
9816a06ba36SRichard Sandiford   // these ANDs into an RISBG later if a three-address instruction is useful.
9825dc7b67cSUlrich Weigand   if (RISBG.Rotate == 0) {
9835dc7b67cSUlrich Weigand     bool PreferAnd = false;
9845dc7b67cSUlrich Weigand     // Prefer AND for any 32-bit and-immediate operation.
9855dc7b67cSUlrich Weigand     if (VT == MVT::i32)
9865dc7b67cSUlrich Weigand       PreferAnd = true;
9875dc7b67cSUlrich Weigand     // As well as for any 64-bit operation that can be implemented via LLC(R),
9885dc7b67cSUlrich Weigand     // LLH(R), LLGT(R), or one of the and-immediate instructions.
9895dc7b67cSUlrich Weigand     else if (RISBG.Mask == 0xff ||
9906a06ba36SRichard Sandiford              RISBG.Mask == 0xffff ||
9915dc7b67cSUlrich Weigand              RISBG.Mask == 0x7fffffff ||
9926a06ba36SRichard Sandiford              SystemZ::isImmLF(~RISBG.Mask) ||
9935dc7b67cSUlrich Weigand              SystemZ::isImmHF(~RISBG.Mask))
9945dc7b67cSUlrich Weigand      PreferAnd = true;
99592c2c672SUlrich Weigand     // And likewise for the LLZRGF instruction, which doesn't have a register
99692c2c672SUlrich Weigand     // to register version.
99792c2c672SUlrich Weigand     else if (auto *Load = dyn_cast<LoadSDNode>(RISBG.Input)) {
99892c2c672SUlrich Weigand       if (Load->getMemoryVT() == MVT::i32 &&
99992c2c672SUlrich Weigand           (Load->getExtensionType() == ISD::EXTLOAD ||
100092c2c672SUlrich Weigand            Load->getExtensionType() == ISD::ZEXTLOAD) &&
100192c2c672SUlrich Weigand           RISBG.Mask == 0xffffff00 &&
100292c2c672SUlrich Weigand           Subtarget->hasLoadAndZeroRightmostByte())
100392c2c672SUlrich Weigand       PreferAnd = true;
100492c2c672SUlrich Weigand     }
10055dc7b67cSUlrich Weigand     if (PreferAnd) {
10065dc7b67cSUlrich Weigand       // Replace the current node with an AND.  Note that the current node
10075dc7b67cSUlrich Weigand       // might already be that same AND, in which case it is already CSE'd
10085dc7b67cSUlrich Weigand       // with it, and we must not call ReplaceNode.
10095dc7b67cSUlrich Weigand       SDValue In = convertTo(DL, VT, RISBG.Input);
10105dc7b67cSUlrich Weigand       SDValue Mask = CurDAG->getConstant(RISBG.Mask, DL, VT);
10115dc7b67cSUlrich Weigand       SDValue New = CurDAG->getNode(ISD::AND, DL, VT, In, Mask);
10125dc7b67cSUlrich Weigand       if (N != New.getNode()) {
10135dc7b67cSUlrich Weigand         insertDAGNode(CurDAG, N, Mask);
10145dc7b67cSUlrich Weigand         insertDAGNode(CurDAG, N, New);
10155dc7b67cSUlrich Weigand         ReplaceNode(N, New.getNode());
10165dc7b67cSUlrich Weigand         N = New.getNode();
10175dc7b67cSUlrich Weigand       }
10185dc7b67cSUlrich Weigand       // Now, select the machine opcode to implement this operation.
1019f268cd0aSJonas Paulsson       if (!N->isMachineOpcode())
1020bbcd2233SJustin Bogner         SelectCode(N);
1021bbcd2233SJustin Bogner       return true;
10226a06ba36SRichard Sandiford     }
10230750c846SSimon Pilgrim   }
102482ec87dbSRichard Sandiford 
10253ad5a15bSRichard Sandiford   unsigned Opcode = SystemZ::RISBG;
1026371d10a4SUlrich Weigand   // Prefer RISBGN if available, since it does not clobber CC.
1027371d10a4SUlrich Weigand   if (Subtarget->hasMiscellaneousExtensions())
1028371d10a4SUlrich Weigand     Opcode = SystemZ::RISBGN;
10293ad5a15bSRichard Sandiford   EVT OpcodeVT = MVT::i64;
103055b8590eSUlrich Weigand   if (VT == MVT::i32 && Subtarget->hasHighWord() &&
103155b8590eSUlrich Weigand       // We can only use the 32-bit instructions if all source bits are
103255b8590eSUlrich Weigand       // in the low 32 bits without wrapping, both after rotation (because
103355b8590eSUlrich Weigand       // of the smaller range for Start and End) and before rotation
103455b8590eSUlrich Weigand       // (because the input value is truncated).
103555b8590eSUlrich Weigand       RISBG.Start >= 32 && RISBG.End >= RISBG.Start &&
103655b8590eSUlrich Weigand       ((RISBG.Start + RISBG.Rotate) & 63) >= 32 &&
103755b8590eSUlrich Weigand       ((RISBG.End + RISBG.Rotate) & 63) >=
103855b8590eSUlrich Weigand       ((RISBG.Start + RISBG.Rotate) & 63)) {
10393ad5a15bSRichard Sandiford     Opcode = SystemZ::RISBMux;
10403ad5a15bSRichard Sandiford     OpcodeVT = MVT::i32;
10413ad5a15bSRichard Sandiford     RISBG.Start &= 31;
10423ad5a15bSRichard Sandiford     RISBG.End &= 31;
10433ad5a15bSRichard Sandiford   }
104484f54a3bSRichard Sandiford   SDValue Ops[5] = {
1045842a51baSSergey Dmitrouk     getUNDEF(DL, OpcodeVT),
1046842a51baSSergey Dmitrouk     convertTo(DL, OpcodeVT, RISBG.Input),
1047842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RISBG.Start, DL, MVT::i32),
1048842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RISBG.End | 128, DL, MVT::i32),
1049842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RISBG.Rotate, DL, MVT::i32)
105084f54a3bSRichard Sandiford   };
1051bbcd2233SJustin Bogner   SDValue New = convertTo(
1052bbcd2233SJustin Bogner       DL, VT, SDValue(CurDAG->getMachineNode(Opcode, DL, OpcodeVT, Ops), 0));
10533264c1bdSNirav Dave   ReplaceNode(N, New.getNode());
1054bbcd2233SJustin Bogner   return true;
105584f54a3bSRichard Sandiford }
105684f54a3bSRichard Sandiford 
tryRxSBG(SDNode * N,unsigned Opcode)10579b34e8a7SJustin Bogner bool SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) {
105877884bcbSUlrich Weigand   SDLoc DL(N);
105977884bcbSUlrich Weigand   EVT VT = N->getValueType(0);
106077884bcbSUlrich Weigand   if (!VT.isInteger() || VT.getSizeInBits() > 64)
10619b34e8a7SJustin Bogner     return false;
10627878b852SRichard Sandiford   // Try treating each operand of N as the second operand of the RxSBG
1063885140c9SRichard Sandiford   // and see which goes deepest.
106451093210SRichard Sandiford   RxSBGOperands RxSBG[] = {
106551093210SRichard Sandiford     RxSBGOperands(Opcode, N->getOperand(0)),
106651093210SRichard Sandiford     RxSBGOperands(Opcode, N->getOperand(1))
106751093210SRichard Sandiford   };
1068885140c9SRichard Sandiford   unsigned Count[] = { 0, 0 };
1069885140c9SRichard Sandiford   for (unsigned I = 0; I < 2; ++I)
10705cbac967SRichard Sandiford     while (expandRxSBG(RxSBG[I]))
10710df35058SZhan Jun Liau       // The widening or narrowing is expected to be free.
10720df35058SZhan Jun Liau       // Counting widening or narrowing as a saved operation will result in
10730df35058SZhan Jun Liau       // preferring an R*SBG over a simple shift/logical instruction.
10740df35058SZhan Jun Liau       if (RxSBG[I].Input.getOpcode() != ISD::ANY_EXTEND &&
10750df35058SZhan Jun Liau           RxSBG[I].Input.getOpcode() != ISD::TRUNCATE)
1076885140c9SRichard Sandiford         Count[I] += 1;
1077885140c9SRichard Sandiford 
1078885140c9SRichard Sandiford   // Do nothing if neither operand is suitable.
1079885140c9SRichard Sandiford   if (Count[0] == 0 && Count[1] == 0)
10809b34e8a7SJustin Bogner     return false;
1081885140c9SRichard Sandiford 
1082885140c9SRichard Sandiford   // Pick the deepest second operand.
1083885140c9SRichard Sandiford   unsigned I = Count[0] > Count[1] ? 0 : 1;
1084885140c9SRichard Sandiford   SDValue Op0 = N->getOperand(I ^ 1);
1085885140c9SRichard Sandiford 
1086885140c9SRichard Sandiford   // Prefer IC for character insertions from memory.
10877878b852SRichard Sandiford   if (Opcode == SystemZ::ROSBG && (RxSBG[I].Mask & 0xff) == 0)
108821f5d68aSRichard Sandiford     if (auto *Load = dyn_cast<LoadSDNode>(Op0.getNode()))
1089885140c9SRichard Sandiford       if (Load->getMemoryVT() == MVT::i8)
10909b34e8a7SJustin Bogner         return false;
1091885140c9SRichard Sandiford 
1092885140c9SRichard Sandiford   // See whether we can avoid an AND in the first operand by converting
1093885140c9SRichard Sandiford   // ROSBG to RISBG.
1094371d10a4SUlrich Weigand   if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[I].Mask)) {
1095885140c9SRichard Sandiford     Opcode = SystemZ::RISBG;
1096371d10a4SUlrich Weigand     // Prefer RISBGN if available, since it does not clobber CC.
1097371d10a4SUlrich Weigand     if (Subtarget->hasMiscellaneousExtensions())
1098371d10a4SUlrich Weigand       Opcode = SystemZ::RISBGN;
1099371d10a4SUlrich Weigand   }
1100885140c9SRichard Sandiford 
1101885140c9SRichard Sandiford   SDValue Ops[5] = {
1102842a51baSSergey Dmitrouk     convertTo(DL, MVT::i64, Op0),
1103842a51baSSergey Dmitrouk     convertTo(DL, MVT::i64, RxSBG[I].Input),
1104842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RxSBG[I].Start, DL, MVT::i32),
1105842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RxSBG[I].End, DL, MVT::i32),
1106842a51baSSergey Dmitrouk     CurDAG->getTargetConstant(RxSBG[I].Rotate, DL, MVT::i32)
1107885140c9SRichard Sandiford   };
11089b34e8a7SJustin Bogner   SDValue New = convertTo(
11099b34e8a7SJustin Bogner       DL, VT, SDValue(CurDAG->getMachineNode(Opcode, DL, MVT::i64, Ops), 0));
11109b34e8a7SJustin Bogner   ReplaceNode(N, New.getNode());
11119b34e8a7SJustin Bogner   return true;
1112885140c9SRichard Sandiford }
1113885140c9SRichard Sandiford 
splitLargeImmediate(unsigned Opcode,SDNode * Node,SDValue Op0,uint64_t UpperVal,uint64_t LowerVal)1114ffb273d2SJustin Bogner void SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node,
11155f613dfdSUlrich Weigand                                               SDValue Op0, uint64_t UpperVal,
11165f613dfdSUlrich Weigand                                               uint64_t LowerVal) {
11175f613dfdSUlrich Weigand   EVT VT = Node->getValueType(0);
1118ef9de2a7SAndrew Trick   SDLoc DL(Node);
1119842a51baSSergey Dmitrouk   SDValue Upper = CurDAG->getConstant(UpperVal, DL, VT);
11205f613dfdSUlrich Weigand   if (Op0.getNode())
11215f613dfdSUlrich Weigand     Upper = CurDAG->getNode(Opcode, DL, VT, Op0, Upper);
1122ffb273d2SJustin Bogner 
1123ffb273d2SJustin Bogner   {
1124ffb273d2SJustin Bogner     // When we haven't passed in Op0, Upper will be a constant. In order to
1125ffb273d2SJustin Bogner     // prevent folding back to the large immediate in `Or = getNode(...)` we run
1126ffb273d2SJustin Bogner     // SelectCode first and end up with an opaque machine node. This means that
1127ffb273d2SJustin Bogner     // we need to use a handle to keep track of Upper in case it gets CSE'd by
1128ffb273d2SJustin Bogner     // SelectCode.
1129ffb273d2SJustin Bogner     //
1130ffb273d2SJustin Bogner     // Note that in the case where Op0 is passed in we could just call
1131ffb273d2SJustin Bogner     // SelectCode(Upper) later, along with the SelectCode(Or), and avoid needing
1132ffb273d2SJustin Bogner     // the handle at all, but it's fine to do it here.
1133ffb273d2SJustin Bogner     //
1134ffb273d2SJustin Bogner     // TODO: This is a pretty hacky way to do this. Can we do something that
1135ffb273d2SJustin Bogner     // doesn't require a two paragraph explanation?
1136ffb273d2SJustin Bogner     HandleSDNode Handle(Upper);
1137ffb273d2SJustin Bogner     SelectCode(Upper.getNode());
1138ffb273d2SJustin Bogner     Upper = Handle.getValue();
1139ffb273d2SJustin Bogner   }
11405f613dfdSUlrich Weigand 
1141842a51baSSergey Dmitrouk   SDValue Lower = CurDAG->getConstant(LowerVal, DL, VT);
11425f613dfdSUlrich Weigand   SDValue Or = CurDAG->getNode(Opcode, DL, VT, Upper, Lower);
1143ffb273d2SJustin Bogner 
11443264c1bdSNirav Dave   ReplaceNode(Node, Or.getNode());
1145ffb273d2SJustin Bogner 
1146ffb273d2SJustin Bogner   SelectCode(Or.getNode());
11475f613dfdSUlrich Weigand }
11485f613dfdSUlrich Weigand 
loadVectorConstant(const SystemZVectorConstantInfo & VCI,SDNode * Node)1149c110b5b6SJonas Paulsson void SystemZDAGToDAGISel::loadVectorConstant(
1150c110b5b6SJonas Paulsson     const SystemZVectorConstantInfo &VCI, SDNode *Node) {
1151c110b5b6SJonas Paulsson   assert((VCI.Opcode == SystemZISD::BYTE_MASK ||
1152c110b5b6SJonas Paulsson           VCI.Opcode == SystemZISD::REPLICATE ||
1153c110b5b6SJonas Paulsson           VCI.Opcode == SystemZISD::ROTATE_MASK) &&
1154c110b5b6SJonas Paulsson          "Bad opcode!");
1155c110b5b6SJonas Paulsson   assert(VCI.VecVT.getSizeInBits() == 128 && "Expected a vector type");
1156c110b5b6SJonas Paulsson   EVT VT = Node->getValueType(0);
1157c110b5b6SJonas Paulsson   SDLoc DL(Node);
1158c110b5b6SJonas Paulsson   SmallVector<SDValue, 2> Ops;
1159c110b5b6SJonas Paulsson   for (unsigned OpVal : VCI.OpVals)
11603ecab8e4SMatt Arsenault     Ops.push_back(CurDAG->getTargetConstant(OpVal, DL, MVT::i32));
1161c110b5b6SJonas Paulsson   SDValue Op = CurDAG->getNode(VCI.Opcode, DL, VCI.VecVT, Ops);
1162c110b5b6SJonas Paulsson 
1163c110b5b6SJonas Paulsson   if (VCI.VecVT == VT.getSimpleVT())
1164c110b5b6SJonas Paulsson     ReplaceNode(Node, Op.getNode());
1165c110b5b6SJonas Paulsson   else if (VT.getSizeInBits() == 128) {
1166c110b5b6SJonas Paulsson     SDValue BitCast = CurDAG->getNode(ISD::BITCAST, DL, VT, Op);
1167c110b5b6SJonas Paulsson     ReplaceNode(Node, BitCast.getNode());
1168c110b5b6SJonas Paulsson     SelectCode(BitCast.getNode());
1169c110b5b6SJonas Paulsson   } else { // float or double
1170c110b5b6SJonas Paulsson     unsigned SubRegIdx =
1171c110b5b6SJonas Paulsson         (VT.getSizeInBits() == 32 ? SystemZ::subreg_h32 : SystemZ::subreg_h64);
1172c110b5b6SJonas Paulsson     ReplaceNode(
1173c110b5b6SJonas Paulsson         Node, CurDAG->getTargetExtractSubreg(SubRegIdx, DL, VT, Op).getNode());
1174c110b5b6SJonas Paulsson   }
1175c110b5b6SJonas Paulsson   SelectCode(Op.getNode());
1176c110b5b6SJonas Paulsson }
1177c110b5b6SJonas Paulsson 
tryGather(SDNode * N,unsigned Opcode)11789b34e8a7SJustin Bogner bool SystemZDAGToDAGISel::tryGather(SDNode *N, unsigned Opcode) {
1179ce4c1095SUlrich Weigand   SDValue ElemV = N->getOperand(2);
1180ce4c1095SUlrich Weigand   auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1181ce4c1095SUlrich Weigand   if (!ElemN)
11829b34e8a7SJustin Bogner     return false;
1183ce4c1095SUlrich Weigand 
1184ce4c1095SUlrich Weigand   unsigned Elem = ElemN->getZExtValue();
1185ce4c1095SUlrich Weigand   EVT VT = N->getValueType(0);
1186ce4c1095SUlrich Weigand   if (Elem >= VT.getVectorNumElements())
11879b34e8a7SJustin Bogner     return false;
1188ce4c1095SUlrich Weigand 
1189ce4c1095SUlrich Weigand   auto *Load = dyn_cast<LoadSDNode>(N->getOperand(1));
11908bb46b0fSUlrich Weigand   if (!Load || !Load->hasNUsesOfValue(1, 0))
11919b34e8a7SJustin Bogner     return false;
1192ce4c1095SUlrich Weigand   if (Load->getMemoryVT().getSizeInBits() !=
1193ce4c1095SUlrich Weigand       Load->getValueType(0).getSizeInBits())
11949b34e8a7SJustin Bogner     return false;
1195ce4c1095SUlrich Weigand 
1196ce4c1095SUlrich Weigand   SDValue Base, Disp, Index;
1197ce4c1095SUlrich Weigand   if (!selectBDVAddr12Only(Load->getBasePtr(), ElemV, Base, Disp, Index) ||
1198ce4c1095SUlrich Weigand       Index.getValueType() != VT.changeVectorElementTypeToInteger())
11999b34e8a7SJustin Bogner     return false;
1200ce4c1095SUlrich Weigand 
1201ce4c1095SUlrich Weigand   SDLoc DL(Load);
1202ce4c1095SUlrich Weigand   SDValue Ops[] = {
1203ce4c1095SUlrich Weigand     N->getOperand(0), Base, Disp, Index,
1204ce4c1095SUlrich Weigand     CurDAG->getTargetConstant(Elem, DL, MVT::i32), Load->getChain()
1205ce4c1095SUlrich Weigand   };
1206ce4c1095SUlrich Weigand   SDNode *Res = CurDAG->getMachineNode(Opcode, DL, VT, MVT::Other, Ops);
1207ce4c1095SUlrich Weigand   ReplaceUses(SDValue(Load, 1), SDValue(Res, 1));
12089b34e8a7SJustin Bogner   ReplaceNode(N, Res);
12099b34e8a7SJustin Bogner   return true;
1210ce4c1095SUlrich Weigand }
1211ce4c1095SUlrich Weigand 
tryScatter(StoreSDNode * Store,unsigned Opcode)12129b34e8a7SJustin Bogner bool SystemZDAGToDAGISel::tryScatter(StoreSDNode *Store, unsigned Opcode) {
1213ce4c1095SUlrich Weigand   SDValue Value = Store->getValue();
1214ce4c1095SUlrich Weigand   if (Value.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
12159b34e8a7SJustin Bogner     return false;
1216b1f0a0f4SSanjay Patel   if (Store->getMemoryVT().getSizeInBits() != Value.getValueSizeInBits())
12179b34e8a7SJustin Bogner     return false;
1218ce4c1095SUlrich Weigand 
1219ce4c1095SUlrich Weigand   SDValue ElemV = Value.getOperand(1);
1220ce4c1095SUlrich Weigand   auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1221ce4c1095SUlrich Weigand   if (!ElemN)
12229b34e8a7SJustin Bogner     return false;
1223ce4c1095SUlrich Weigand 
1224ce4c1095SUlrich Weigand   SDValue Vec = Value.getOperand(0);
1225ce4c1095SUlrich Weigand   EVT VT = Vec.getValueType();
1226ce4c1095SUlrich Weigand   unsigned Elem = ElemN->getZExtValue();
1227ce4c1095SUlrich Weigand   if (Elem >= VT.getVectorNumElements())
12289b34e8a7SJustin Bogner     return false;
1229ce4c1095SUlrich Weigand 
1230ce4c1095SUlrich Weigand   SDValue Base, Disp, Index;
1231ce4c1095SUlrich Weigand   if (!selectBDVAddr12Only(Store->getBasePtr(), ElemV, Base, Disp, Index) ||
1232ce4c1095SUlrich Weigand       Index.getValueType() != VT.changeVectorElementTypeToInteger())
12339b34e8a7SJustin Bogner     return false;
1234ce4c1095SUlrich Weigand 
1235ce4c1095SUlrich Weigand   SDLoc DL(Store);
1236ce4c1095SUlrich Weigand   SDValue Ops[] = {
1237ce4c1095SUlrich Weigand     Vec, Base, Disp, Index, CurDAG->getTargetConstant(Elem, DL, MVT::i32),
1238ce4c1095SUlrich Weigand     Store->getChain()
1239ce4c1095SUlrich Weigand   };
12409b34e8a7SJustin Bogner   ReplaceNode(Store, CurDAG->getMachineNode(Opcode, DL, MVT::Other, Ops));
12419b34e8a7SJustin Bogner   return true;
1242ce4c1095SUlrich Weigand }
1243ce4c1095SUlrich Weigand 
1244c3ec80feSUlrich Weigand // Check whether or not the chain ending in StoreNode is suitable for doing
1245c3ec80feSUlrich Weigand // the {load; op; store} to modify transformation.
isFusableLoadOpStorePattern(StoreSDNode * StoreNode,SDValue StoredVal,SelectionDAG * CurDAG,LoadSDNode * & LoadNode,SDValue & InputChain)1246c3ec80feSUlrich Weigand static bool isFusableLoadOpStorePattern(StoreSDNode *StoreNode,
1247c3ec80feSUlrich Weigand                                         SDValue StoredVal, SelectionDAG *CurDAG,
1248c3ec80feSUlrich Weigand                                         LoadSDNode *&LoadNode,
1249c3ec80feSUlrich Weigand                                         SDValue &InputChain) {
1250c3ec80feSUlrich Weigand   // Is the stored value result 0 of the operation?
1251c3ec80feSUlrich Weigand   if (StoredVal.getResNo() != 0)
1252c3ec80feSUlrich Weigand     return false;
1253c3ec80feSUlrich Weigand 
1254c3ec80feSUlrich Weigand   // Are there other uses of the loaded value than the operation?
1255c3ec80feSUlrich Weigand   if (!StoredVal.getNode()->hasNUsesOfValue(1, 0))
1256c3ec80feSUlrich Weigand     return false;
1257c3ec80feSUlrich Weigand 
1258c3ec80feSUlrich Weigand   // Is the store non-extending and non-indexed?
1259c3ec80feSUlrich Weigand   if (!ISD::isNormalStore(StoreNode) || StoreNode->isNonTemporal())
1260c3ec80feSUlrich Weigand     return false;
1261c3ec80feSUlrich Weigand 
1262c3ec80feSUlrich Weigand   SDValue Load = StoredVal->getOperand(0);
1263c3ec80feSUlrich Weigand   // Is the stored value a non-extending and non-indexed load?
1264c3ec80feSUlrich Weigand   if (!ISD::isNormalLoad(Load.getNode()))
1265c3ec80feSUlrich Weigand     return false;
1266c3ec80feSUlrich Weigand 
1267c3ec80feSUlrich Weigand   // Return LoadNode by reference.
1268c3ec80feSUlrich Weigand   LoadNode = cast<LoadSDNode>(Load);
1269c3ec80feSUlrich Weigand 
1270c3ec80feSUlrich Weigand   // Is store the only read of the loaded value?
1271c3ec80feSUlrich Weigand   if (!Load.hasOneUse())
1272c3ec80feSUlrich Weigand     return false;
1273c3ec80feSUlrich Weigand 
1274c3ec80feSUlrich Weigand   // Is the address of the store the same as the load?
1275c3ec80feSUlrich Weigand   if (LoadNode->getBasePtr() != StoreNode->getBasePtr() ||
1276c3ec80feSUlrich Weigand       LoadNode->getOffset() != StoreNode->getOffset())
1277c3ec80feSUlrich Weigand     return false;
1278c3ec80feSUlrich Weigand 
1279c3ec80feSUlrich Weigand   // Check if the chain is produced by the load or is a TokenFactor with
1280c3ec80feSUlrich Weigand   // the load output chain as an operand. Return InputChain by reference.
1281c3ec80feSUlrich Weigand   SDValue Chain = StoreNode->getChain();
1282c3ec80feSUlrich Weigand 
1283c3ec80feSUlrich Weigand   bool ChainCheck = false;
1284c3ec80feSUlrich Weigand   if (Chain == Load.getValue(1)) {
1285c3ec80feSUlrich Weigand     ChainCheck = true;
1286c3ec80feSUlrich Weigand     InputChain = LoadNode->getChain();
1287c3ec80feSUlrich Weigand   } else if (Chain.getOpcode() == ISD::TokenFactor) {
1288c3ec80feSUlrich Weigand     SmallVector<SDValue, 4> ChainOps;
1289c56ffed3SJonas Paulsson     SmallVector<const SDNode *, 4> LoopWorklist;
1290c56ffed3SJonas Paulsson     SmallPtrSet<const SDNode *, 16> Visited;
1291c56ffed3SJonas Paulsson     const unsigned int Max = 1024;
1292c3ec80feSUlrich Weigand     for (unsigned i = 0, e = Chain.getNumOperands(); i != e; ++i) {
1293c3ec80feSUlrich Weigand       SDValue Op = Chain.getOperand(i);
1294c3ec80feSUlrich Weigand       if (Op == Load.getValue(1)) {
1295c3ec80feSUlrich Weigand         ChainCheck = true;
1296c3ec80feSUlrich Weigand         // Drop Load, but keep its chain. No cycle check necessary.
1297c3ec80feSUlrich Weigand         ChainOps.push_back(Load.getOperand(0));
1298c3ec80feSUlrich Weigand         continue;
1299c3ec80feSUlrich Weigand       }
1300c56ffed3SJonas Paulsson       LoopWorklist.push_back(Op.getNode());
1301c3ec80feSUlrich Weigand       ChainOps.push_back(Op);
1302c3ec80feSUlrich Weigand     }
1303c3ec80feSUlrich Weigand 
1304c56ffed3SJonas Paulsson     if (ChainCheck) {
1305c56ffed3SJonas Paulsson       // Add the other operand of StoredVal to worklist.
1306c56ffed3SJonas Paulsson       for (SDValue Op : StoredVal->ops())
1307c56ffed3SJonas Paulsson         if (Op.getNode() != LoadNode)
1308c56ffed3SJonas Paulsson           LoopWorklist.push_back(Op.getNode());
1309c56ffed3SJonas Paulsson 
1310c56ffed3SJonas Paulsson       // Check if Load is reachable from any of the nodes in the worklist.
1311c56ffed3SJonas Paulsson       if (SDNode::hasPredecessorHelper(Load.getNode(), Visited, LoopWorklist, Max,
1312c56ffed3SJonas Paulsson                                        true))
1313c56ffed3SJonas Paulsson         return false;
1314c56ffed3SJonas Paulsson 
1315c3ec80feSUlrich Weigand       // Make a new TokenFactor with all the other input chains except
1316c3ec80feSUlrich Weigand       // for the load.
1317c3ec80feSUlrich Weigand       InputChain = CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain),
1318c3ec80feSUlrich Weigand                                    MVT::Other, ChainOps);
1319c3ec80feSUlrich Weigand     }
1320c56ffed3SJonas Paulsson   }
1321c3ec80feSUlrich Weigand   if (!ChainCheck)
1322c3ec80feSUlrich Weigand     return false;
1323c3ec80feSUlrich Weigand 
1324c3ec80feSUlrich Weigand   return true;
1325c3ec80feSUlrich Weigand }
1326c3ec80feSUlrich Weigand 
1327c3ec80feSUlrich Weigand // Change a chain of {load; op; store} of the same value into a simple op
1328c3ec80feSUlrich Weigand // through memory of that value, if the uses of the modified value and its
1329c3ec80feSUlrich Weigand // address are suitable.
1330c3ec80feSUlrich Weigand //
1331c3ec80feSUlrich Weigand // The tablegen pattern memory operand pattern is currently not able to match
1332c3ec80feSUlrich Weigand // the case where the CC on the original operation are used.
1333c3ec80feSUlrich Weigand //
1334c3ec80feSUlrich Weigand // See the equivalent routine in X86ISelDAGToDAG for further comments.
tryFoldLoadStoreIntoMemOperand(SDNode * Node)1335c3ec80feSUlrich Weigand bool SystemZDAGToDAGISel::tryFoldLoadStoreIntoMemOperand(SDNode *Node) {
1336c3ec80feSUlrich Weigand   StoreSDNode *StoreNode = cast<StoreSDNode>(Node);
1337c3ec80feSUlrich Weigand   SDValue StoredVal = StoreNode->getOperand(1);
1338c3ec80feSUlrich Weigand   unsigned Opc = StoredVal->getOpcode();
1339c3ec80feSUlrich Weigand   SDLoc DL(StoreNode);
1340c3ec80feSUlrich Weigand 
1341c3ec80feSUlrich Weigand   // Before we try to select anything, make sure this is memory operand size
1342c3ec80feSUlrich Weigand   // and opcode we can handle. Note that this must match the code below that
1343c3ec80feSUlrich Weigand   // actually lowers the opcodes.
1344c3ec80feSUlrich Weigand   EVT MemVT = StoreNode->getMemoryVT();
1345c3ec80feSUlrich Weigand   unsigned NewOpc = 0;
1346c3ec80feSUlrich Weigand   bool NegateOperand = false;
1347c3ec80feSUlrich Weigand   switch (Opc) {
1348c3ec80feSUlrich Weigand   default:
1349c3ec80feSUlrich Weigand     return false;
1350c3ec80feSUlrich Weigand   case SystemZISD::SSUBO:
1351c3ec80feSUlrich Weigand     NegateOperand = true;
13524dc0b1acSReid Kleckner     LLVM_FALLTHROUGH;
1353c3ec80feSUlrich Weigand   case SystemZISD::SADDO:
1354c3ec80feSUlrich Weigand     if (MemVT == MVT::i32)
1355c3ec80feSUlrich Weigand       NewOpc = SystemZ::ASI;
1356c3ec80feSUlrich Weigand     else if (MemVT == MVT::i64)
1357c3ec80feSUlrich Weigand       NewOpc = SystemZ::AGSI;
1358c3ec80feSUlrich Weigand     else
1359c3ec80feSUlrich Weigand       return false;
1360c3ec80feSUlrich Weigand     break;
1361c3ec80feSUlrich Weigand   case SystemZISD::USUBO:
1362c3ec80feSUlrich Weigand     NegateOperand = true;
13634dc0b1acSReid Kleckner     LLVM_FALLTHROUGH;
1364c3ec80feSUlrich Weigand   case SystemZISD::UADDO:
1365c3ec80feSUlrich Weigand     if (MemVT == MVT::i32)
1366c3ec80feSUlrich Weigand       NewOpc = SystemZ::ALSI;
1367c3ec80feSUlrich Weigand     else if (MemVT == MVT::i64)
1368c3ec80feSUlrich Weigand       NewOpc = SystemZ::ALGSI;
1369c3ec80feSUlrich Weigand     else
1370c3ec80feSUlrich Weigand       return false;
1371c3ec80feSUlrich Weigand     break;
1372c3ec80feSUlrich Weigand   }
1373c3ec80feSUlrich Weigand 
1374c3ec80feSUlrich Weigand   LoadSDNode *LoadNode = nullptr;
1375c3ec80feSUlrich Weigand   SDValue InputChain;
1376c3ec80feSUlrich Weigand   if (!isFusableLoadOpStorePattern(StoreNode, StoredVal, CurDAG, LoadNode,
1377c3ec80feSUlrich Weigand                                    InputChain))
1378c3ec80feSUlrich Weigand     return false;
1379c3ec80feSUlrich Weigand 
1380c3ec80feSUlrich Weigand   SDValue Operand = StoredVal.getOperand(1);
1381c3ec80feSUlrich Weigand   auto *OperandC = dyn_cast<ConstantSDNode>(Operand);
1382c3ec80feSUlrich Weigand   if (!OperandC)
1383c3ec80feSUlrich Weigand     return false;
1384c3ec80feSUlrich Weigand   auto OperandV = OperandC->getAPIntValue();
1385c3ec80feSUlrich Weigand   if (NegateOperand)
1386c3ec80feSUlrich Weigand     OperandV = -OperandV;
1387c3ec80feSUlrich Weigand   if (OperandV.getMinSignedBits() > 8)
1388c3ec80feSUlrich Weigand     return false;
1389c3ec80feSUlrich Weigand   Operand = CurDAG->getTargetConstant(OperandV, DL, MemVT);
1390c3ec80feSUlrich Weigand 
1391c3ec80feSUlrich Weigand   SDValue Base, Disp;
1392c3ec80feSUlrich Weigand   if (!selectBDAddr20Only(StoreNode->getBasePtr(), Base, Disp))
1393c3ec80feSUlrich Weigand     return false;
1394c3ec80feSUlrich Weigand 
1395c3ec80feSUlrich Weigand   SDValue Ops[] = { Base, Disp, Operand, InputChain };
1396c3ec80feSUlrich Weigand   MachineSDNode *Result =
1397c3ec80feSUlrich Weigand     CurDAG->getMachineNode(NewOpc, DL, MVT::i32, MVT::Other, Ops);
139866654b72SChandler Carruth   CurDAG->setNodeMemRefs(
139966654b72SChandler Carruth       Result, {StoreNode->getMemOperand(), LoadNode->getMemOperand()});
1400c3ec80feSUlrich Weigand 
1401c3ec80feSUlrich Weigand   ReplaceUses(SDValue(StoreNode, 0), SDValue(Result, 1));
1402c3ec80feSUlrich Weigand   ReplaceUses(SDValue(StoredVal.getNode(), 1), SDValue(Result, 0));
1403c3ec80feSUlrich Weigand   CurDAG->RemoveDeadNode(Node);
1404c3ec80feSUlrich Weigand   return true;
1405c3ec80feSUlrich Weigand }
1406c3ec80feSUlrich Weigand 
canUseBlockOperation(StoreSDNode * Store,LoadSDNode * Load) const1407067817eeSRichard Sandiford bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store,
1408067817eeSRichard Sandiford                                                LoadSDNode *Load) const {
1409178273a1SRichard Sandiford   // Check that the two memory operands have the same size.
1410178273a1SRichard Sandiford   if (Load->getMemoryVT() != Store->getMemoryVT())
1411178273a1SRichard Sandiford     return false;
141297846491SRichard Sandiford 
1413178273a1SRichard Sandiford   // Volatility stops an access from being decomposed.
141497846491SRichard Sandiford   if (Load->isVolatile() || Store->isVolatile())
141597846491SRichard Sandiford     return false;
141697846491SRichard Sandiford 
141797846491SRichard Sandiford   // There's no chance of overlap if the load is invariant.
1418adbf09e8SJustin Lebar   if (Load->isInvariant() && Load->isDereferenceable())
141997846491SRichard Sandiford     return true;
142097846491SRichard Sandiford 
142197846491SRichard Sandiford   // Otherwise we need to check whether there's an alias.
1422aad475b3SNick Lewycky   const Value *V1 = Load->getMemOperand()->getValue();
1423aad475b3SNick Lewycky   const Value *V2 = Store->getMemOperand()->getValue();
142497846491SRichard Sandiford   if (!V1 || !V2)
142597846491SRichard Sandiford     return false;
142697846491SRichard Sandiford 
1427067817eeSRichard Sandiford   // Reject equality.
1428067817eeSRichard Sandiford   uint64_t Size = Load->getMemoryVT().getStoreSize();
142997846491SRichard Sandiford   int64_t End1 = Load->getSrcValueOffset() + Size;
143097846491SRichard Sandiford   int64_t End2 = Store->getSrcValueOffset() + Size;
1431067817eeSRichard Sandiford   if (V1 == V2 && End1 == End2)
1432067817eeSRichard Sandiford     return false;
1433067817eeSRichard Sandiford 
1434d0660797Sdfukalov   return AA->isNoAlias(MemoryLocation(V1, End1, Load->getAAInfo()),
1435ac80dc75SChandler Carruth                        MemoryLocation(V2, End2, Store->getAAInfo()));
143697846491SRichard Sandiford }
143797846491SRichard Sandiford 
storeLoadCanUseMVC(SDNode * N) const1438178273a1SRichard Sandiford bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
143921f5d68aSRichard Sandiford   auto *Store = cast<StoreSDNode>(N);
144021f5d68aSRichard Sandiford   auto *Load = cast<LoadSDNode>(Store->getValue());
1441178273a1SRichard Sandiford 
1442178273a1SRichard Sandiford   // Prefer not to use MVC if either address can use ... RELATIVE LONG
1443178273a1SRichard Sandiford   // instructions.
1444178273a1SRichard Sandiford   uint64_t Size = Load->getMemoryVT().getStoreSize();
1445178273a1SRichard Sandiford   if (Size > 1 && Size <= 8) {
1446178273a1SRichard Sandiford     // Prefer LHRL, LRL and LGRL.
144754b36916SRichard Sandiford     if (SystemZISD::isPCREL(Load->getBasePtr().getOpcode()))
1448178273a1SRichard Sandiford       return false;
1449178273a1SRichard Sandiford     // Prefer STHRL, STRL and STGRL.
145054b36916SRichard Sandiford     if (SystemZISD::isPCREL(Store->getBasePtr().getOpcode()))
1451178273a1SRichard Sandiford       return false;
1452178273a1SRichard Sandiford   }
1453178273a1SRichard Sandiford 
1454067817eeSRichard Sandiford   return canUseBlockOperation(Store, Load);
1455178273a1SRichard Sandiford }
1456178273a1SRichard Sandiford 
storeLoadCanUseBlockBinary(SDNode * N,unsigned I) const1457178273a1SRichard Sandiford bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N,
1458178273a1SRichard Sandiford                                                      unsigned I) const {
145921f5d68aSRichard Sandiford   auto *StoreA = cast<StoreSDNode>(N);
146021f5d68aSRichard Sandiford   auto *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 - I));
146121f5d68aSRichard Sandiford   auto *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(I));
1462d3f7448eSJonas Paulsson   return !LoadA->isVolatile() && LoadA->getMemoryVT() == LoadB->getMemoryVT() &&
1463d3f7448eSJonas Paulsson          canUseBlockOperation(StoreA, LoadB);
1464178273a1SRichard Sandiford }
1465178273a1SRichard Sandiford 
storeLoadIsAligned(SDNode * N) const146675a5febeSJonas Paulsson bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const {
146775a5febeSJonas Paulsson 
146875a5febeSJonas Paulsson   auto *MemAccess = cast<LSBaseSDNode>(N);
146975a5febeSJonas Paulsson   TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize();
147075a5febeSJonas Paulsson   SDValue BasePtr = MemAccess->getBasePtr();
147175a5febeSJonas Paulsson   MachineMemOperand *MMO = MemAccess->getMemOperand();
147275a5febeSJonas Paulsson   assert(MMO && "Expected a memory operand.");
147375a5febeSJonas Paulsson 
147475a5febeSJonas Paulsson   // The memory access must have a proper alignment and no index register.
1475*07881861SGuillaume Chatelet   if (MemAccess->getAlign().value() < StoreSize ||
147675a5febeSJonas Paulsson       !MemAccess->getOffset().isUndef())
147775a5febeSJonas Paulsson     return false;
147875a5febeSJonas Paulsson 
147975a5febeSJonas Paulsson   // The MMO must not have an unaligned offset.
148075a5febeSJonas Paulsson   if (MMO->getOffset() % StoreSize != 0)
148175a5febeSJonas Paulsson     return false;
148275a5febeSJonas Paulsson 
148375a5febeSJonas Paulsson   // An access to GOT or the Constant Pool is aligned.
148475a5febeSJonas Paulsson   if (const PseudoSourceValue *PSV = MMO->getPseudoValue())
148575a5febeSJonas Paulsson     if ((PSV->isGOT() || PSV->isConstantPool()))
148675a5febeSJonas Paulsson       return true;
148775a5febeSJonas Paulsson 
148875a5febeSJonas Paulsson   // Check the alignment of a Global Address.
148975a5febeSJonas Paulsson   if (BasePtr.getNumOperands())
149075a5febeSJonas Paulsson     if (GlobalAddressSDNode *GA =
149175a5febeSJonas Paulsson         dyn_cast<GlobalAddressSDNode>(BasePtr.getOperand(0))) {
149275a5febeSJonas Paulsson       // The immediate offset must be aligned.
149375a5febeSJonas Paulsson       if (GA->getOffset() % StoreSize != 0)
149475a5febeSJonas Paulsson         return false;
149575a5febeSJonas Paulsson 
149675a5febeSJonas Paulsson       // The alignment of the symbol itself must be at least the store size.
149775a5febeSJonas Paulsson       const GlobalValue *GV = GA->getGlobal();
149875a5febeSJonas Paulsson       const DataLayout &DL = GV->getParent()->getDataLayout();
149975a5febeSJonas Paulsson       if (GV->getPointerAlignment(DL).value() < StoreSize)
150075a5febeSJonas Paulsson         return false;
150175a5febeSJonas Paulsson     }
150275a5febeSJonas Paulsson 
150375a5febeSJonas Paulsson   return true;
150475a5febeSJonas Paulsson }
150575a5febeSJonas Paulsson 
Select(SDNode * Node)15069b34e8a7SJustin Bogner void SystemZDAGToDAGISel::Select(SDNode *Node) {
15075f613dfdSUlrich Weigand   // If we have a custom node, we already have selected!
15085f613dfdSUlrich Weigand   if (Node->isMachineOpcode()) {
1509d34e60caSNicola Zaghen     LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
151031d093c7STim Northover     Node->setNodeId(-1);
15119b34e8a7SJustin Bogner     return;
15125f613dfdSUlrich Weigand   }
15135f613dfdSUlrich Weigand 
15145f613dfdSUlrich Weigand   unsigned Opcode = Node->getOpcode();
15155f613dfdSUlrich Weigand   switch (Opcode) {
15165f613dfdSUlrich Weigand   case ISD::OR:
1517885140c9SRichard Sandiford     if (Node->getOperand(1).getOpcode() != ISD::Constant)
15189b34e8a7SJustin Bogner       if (tryRxSBG(Node, SystemZ::ROSBG))
15199b34e8a7SJustin Bogner         return;
15207878b852SRichard Sandiford     goto or_xor;
15217878b852SRichard Sandiford 
15225f613dfdSUlrich Weigand   case ISD::XOR:
15237878b852SRichard Sandiford     if (Node->getOperand(1).getOpcode() != ISD::Constant)
15249b34e8a7SJustin Bogner       if (tryRxSBG(Node, SystemZ::RXSBG))
15259b34e8a7SJustin Bogner         return;
15267878b852SRichard Sandiford     // Fall through.
15277878b852SRichard Sandiford   or_xor:
15285f613dfdSUlrich Weigand     // If this is a 64-bit operation in which both 32-bit halves are nonzero,
15295f4373a2SUlrich Weigand     // split the operation into two.  If both operands here happen to be
15305f4373a2SUlrich Weigand     // constant, leave this to common code to optimize.
15315f4373a2SUlrich Weigand     if (Node->getValueType(0) == MVT::i64 &&
15325f4373a2SUlrich Weigand         Node->getOperand(0).getOpcode() != ISD::Constant)
153321f5d68aSRichard Sandiford       if (auto *Op1 = dyn_cast<ConstantSDNode>(Node->getOperand(1))) {
15345f613dfdSUlrich Weigand         uint64_t Val = Op1->getZExtValue();
15350f0a8b77SUlrich Weigand         // Don't split the operation if we can match one of the combined
15360f0a8b77SUlrich Weigand         // logical operations provided by miscellaneous-extensions-3.
15370f0a8b77SUlrich Weigand         if (Subtarget->hasMiscellaneousExtensions3()) {
15380f0a8b77SUlrich Weigand           unsigned ChildOpcode = Node->getOperand(0).getOpcode();
15390f0a8b77SUlrich Weigand           // Check whether this expression matches NAND/NOR/NXOR.
15400f0a8b77SUlrich Weigand           if (Val == (uint64_t)-1 && Opcode == ISD::XOR)
15410f0a8b77SUlrich Weigand             if (ChildOpcode == ISD::AND || ChildOpcode == ISD::OR ||
15420f0a8b77SUlrich Weigand                 ChildOpcode == ISD::XOR)
15430f0a8b77SUlrich Weigand               break;
1544b51fa867SUlrich Weigand           // Check whether this expression matches OR-with-complement
1545b51fa867SUlrich Weigand           // (or matches an alternate pattern for NXOR).
1546b51fa867SUlrich Weigand           if (ChildOpcode == ISD::XOR) {
15470f0a8b77SUlrich Weigand             auto Op0 = Node->getOperand(0);
15480f0a8b77SUlrich Weigand             if (auto *Op0Op1 = dyn_cast<ConstantSDNode>(Op0->getOperand(1)))
15490f0a8b77SUlrich Weigand               if (Op0Op1->getZExtValue() == (uint64_t)-1)
15500f0a8b77SUlrich Weigand                 break;
15510f0a8b77SUlrich Weigand           }
15520f0a8b77SUlrich Weigand         }
1553ffb273d2SJustin Bogner         if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val)) {
1554ffb273d2SJustin Bogner           splitLargeImmediate(Opcode, Node, Node->getOperand(0),
15555f613dfdSUlrich Weigand                               Val - uint32_t(Val), uint32_t(Val));
15569b34e8a7SJustin Bogner           return;
1557ffb273d2SJustin Bogner         }
15585f613dfdSUlrich Weigand       }
15595f613dfdSUlrich Weigand     break;
15605f613dfdSUlrich Weigand 
156184f54a3bSRichard Sandiford   case ISD::AND:
156251093210SRichard Sandiford     if (Node->getOperand(1).getOpcode() != ISD::Constant)
15639b34e8a7SJustin Bogner       if (tryRxSBG(Node, SystemZ::RNSBG))
15649b34e8a7SJustin Bogner         return;
1565cd1d5aafSJustin Bogner     LLVM_FALLTHROUGH;
156682ec87dbSRichard Sandiford   case ISD::ROTL:
156782ec87dbSRichard Sandiford   case ISD::SHL:
156882ec87dbSRichard Sandiford   case ISD::SRL:
1569220ee49bSRichard Sandiford   case ISD::ZERO_EXTEND:
1570bbcd2233SJustin Bogner     if (tryRISBGZero(Node))
15719b34e8a7SJustin Bogner       return;
157284f54a3bSRichard Sandiford     break;
157384f54a3bSRichard Sandiford 
15745f613dfdSUlrich Weigand   case ISD::Constant:
15755f613dfdSUlrich Weigand     // If this is a 64-bit constant that is out of the range of LLILF,
15765f613dfdSUlrich Weigand     // LLIHF and LGFI, split it into two 32-bit pieces.
15775f613dfdSUlrich Weigand     if (Node->getValueType(0) == MVT::i64) {
15785f613dfdSUlrich Weigand       uint64_t Val = cast<ConstantSDNode>(Node)->getZExtValue();
1579ffb273d2SJustin Bogner       if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val) && !isInt<32>(Val)) {
1580ffb273d2SJustin Bogner         splitLargeImmediate(ISD::OR, Node, SDValue(), Val - uint32_t(Val),
1581ffb273d2SJustin Bogner                             uint32_t(Val));
15829b34e8a7SJustin Bogner         return;
1583ffb273d2SJustin Bogner       }
15845f613dfdSUlrich Weigand     }
15855f613dfdSUlrich Weigand     break;
15865f613dfdSUlrich Weigand 
1587ee834382SRichard Sandiford   case SystemZISD::SELECT_CCMASK: {
1588ee834382SRichard Sandiford     SDValue Op0 = Node->getOperand(0);
1589ee834382SRichard Sandiford     SDValue Op1 = Node->getOperand(1);
1590ee834382SRichard Sandiford     // Prefer to put any load first, so that it can be matched as a
1591524f276cSUlrich Weigand     // conditional load.  Likewise for constants in range for LOCHI.
1592524f276cSUlrich Weigand     if ((Op1.getOpcode() == ISD::LOAD && Op0.getOpcode() != ISD::LOAD) ||
1593524f276cSUlrich Weigand         (Subtarget->hasLoadStoreOnCond2() &&
1594524f276cSUlrich Weigand          Node->getValueType(0).isInteger() &&
1595524f276cSUlrich Weigand          Op1.getOpcode() == ISD::Constant &&
1596524f276cSUlrich Weigand          isInt<16>(cast<ConstantSDNode>(Op1)->getSExtValue()) &&
1597524f276cSUlrich Weigand          !(Op0.getOpcode() == ISD::Constant &&
1598524f276cSUlrich Weigand            isInt<16>(cast<ConstantSDNode>(Op0)->getSExtValue())))) {
1599ee834382SRichard Sandiford       SDValue CCValid = Node->getOperand(2);
1600ee834382SRichard Sandiford       SDValue CCMask = Node->getOperand(3);
1601ee834382SRichard Sandiford       uint64_t ConstCCValid =
1602ee834382SRichard Sandiford         cast<ConstantSDNode>(CCValid.getNode())->getZExtValue();
1603ee834382SRichard Sandiford       uint64_t ConstCCMask =
1604ee834382SRichard Sandiford         cast<ConstantSDNode>(CCMask.getNode())->getZExtValue();
1605ee834382SRichard Sandiford       // Invert the condition.
16063ecab8e4SMatt Arsenault       CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
16073ecab8e4SMatt Arsenault                                          SDLoc(Node), CCMask.getValueType());
1608ee834382SRichard Sandiford       SDValue Op4 = Node->getOperand(4);
1609de54c058SJonas Paulsson       SDNode *UpdatedNode =
1610de54c058SJonas Paulsson         CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1611de54c058SJonas Paulsson       if (UpdatedNode != Node) {
1612b51ccaf4SJonas Paulsson         // In case this node already exists then replace Node with it.
1613de54c058SJonas Paulsson         ReplaceNode(Node, UpdatedNode);
1614de54c058SJonas Paulsson         Node = UpdatedNode;
1615de54c058SJonas Paulsson       }
1616ee834382SRichard Sandiford     }
1617ee834382SRichard Sandiford     break;
1618ee834382SRichard Sandiford   }
1619ce4c1095SUlrich Weigand 
1620ce4c1095SUlrich Weigand   case ISD::INSERT_VECTOR_ELT: {
1621ce4c1095SUlrich Weigand     EVT VT = Node->getValueType(0);
16221ed771f5SSanjay Patel     unsigned ElemBitSize = VT.getScalarSizeInBits();
16239b34e8a7SJustin Bogner     if (ElemBitSize == 32) {
16249b34e8a7SJustin Bogner       if (tryGather(Node, SystemZ::VGEF))
16259b34e8a7SJustin Bogner         return;
16269b34e8a7SJustin Bogner     } else if (ElemBitSize == 64) {
16279b34e8a7SJustin Bogner       if (tryGather(Node, SystemZ::VGEG))
16289b34e8a7SJustin Bogner         return;
16299b34e8a7SJustin Bogner     }
1630ce4c1095SUlrich Weigand     break;
1631ce4c1095SUlrich Weigand   }
1632ce4c1095SUlrich Weigand 
16338cda83a5SJonas Paulsson   case ISD::BUILD_VECTOR: {
16348cda83a5SJonas Paulsson     auto *BVN = cast<BuildVectorSDNode>(Node);
1635c110b5b6SJonas Paulsson     SystemZVectorConstantInfo VCI(BVN);
1636c110b5b6SJonas Paulsson     if (VCI.isVectorConstantLegal(*Subtarget)) {
1637c110b5b6SJonas Paulsson       loadVectorConstant(VCI, Node);
16388cda83a5SJonas Paulsson       return;
16398cda83a5SJonas Paulsson     }
16408cda83a5SJonas Paulsson     break;
16418cda83a5SJonas Paulsson   }
16428cda83a5SJonas Paulsson 
164334bead75SJonas Paulsson   case ISD::ConstantFP: {
164434bead75SJonas Paulsson     APFloat Imm = cast<ConstantFPSDNode>(Node)->getValueAPF();
164534bead75SJonas Paulsson     if (Imm.isZero() || Imm.isNegZero())
164634bead75SJonas Paulsson       break;
1647c110b5b6SJonas Paulsson     SystemZVectorConstantInfo VCI(Imm);
1648c110b5b6SJonas Paulsson     bool Success = VCI.isVectorConstantLegal(*Subtarget); (void)Success;
164934bead75SJonas Paulsson     assert(Success && "Expected legal FP immediate");
1650c110b5b6SJonas Paulsson     loadVectorConstant(VCI, Node);
165134bead75SJonas Paulsson     return;
165234bead75SJonas Paulsson   }
165334bead75SJonas Paulsson 
1654ce4c1095SUlrich Weigand   case ISD::STORE: {
1655c3ec80feSUlrich Weigand     if (tryFoldLoadStoreIntoMemOperand(Node))
1656c3ec80feSUlrich Weigand       return;
1657ce4c1095SUlrich Weigand     auto *Store = cast<StoreSDNode>(Node);
1658b1f0a0f4SSanjay Patel     unsigned ElemBitSize = Store->getValue().getValueSizeInBits();
16599b34e8a7SJustin Bogner     if (ElemBitSize == 32) {
16609b34e8a7SJustin Bogner       if (tryScatter(Store, SystemZ::VSCEF))
16619b34e8a7SJustin Bogner         return;
16629b34e8a7SJustin Bogner     } else if (ElemBitSize == 64) {
16639b34e8a7SJustin Bogner       if (tryScatter(Store, SystemZ::VSCEG))
16649b34e8a7SJustin Bogner         return;
16659b34e8a7SJustin Bogner     }
1666ce4c1095SUlrich Weigand     break;
1667ce4c1095SUlrich Weigand   }
16685f613dfdSUlrich Weigand   }
16695f613dfdSUlrich Weigand 
16709b34e8a7SJustin Bogner   SelectCode(Node);
16715f613dfdSUlrich Weigand }
16725f613dfdSUlrich Weigand 
16735f613dfdSUlrich Weigand bool SystemZDAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue & Op,unsigned ConstraintID,std::vector<SDValue> & OutOps)16745f613dfdSUlrich Weigand SelectInlineAsmMemoryOperand(const SDValue &Op,
167560f1db05SDaniel Sanders                              unsigned ConstraintID,
16765f613dfdSUlrich Weigand                              std::vector<SDValue> &OutOps) {
1677daae87aaSUlrich Weigand   SystemZAddressingMode::AddrForm Form;
1678daae87aaSUlrich Weigand   SystemZAddressingMode::DispRange DispRange;
167979564611SUlrich Weigand   SDValue Base, Disp, Index;
168079564611SUlrich Weigand 
16812eeace21SDaniel Sanders   switch(ConstraintID) {
16822eeace21SDaniel Sanders   default:
16832eeace21SDaniel Sanders     llvm_unreachable("Unexpected asm memory constraint");
16842eeace21SDaniel Sanders   case InlineAsm::Constraint_i:
16852eeace21SDaniel Sanders   case InlineAsm::Constraint_Q:
16864aa5dc15SJonas Paulsson   case InlineAsm::Constraint_ZQ:
1687daae87aaSUlrich Weigand     // Accept an address with a short displacement, but no index.
1688daae87aaSUlrich Weigand     Form = SystemZAddressingMode::FormBD;
1689daae87aaSUlrich Weigand     DispRange = SystemZAddressingMode::Disp12Only;
1690daae87aaSUlrich Weigand     break;
16912eeace21SDaniel Sanders   case InlineAsm::Constraint_R:
16924aa5dc15SJonas Paulsson   case InlineAsm::Constraint_ZR:
1693daae87aaSUlrich Weigand     // Accept an address with a short displacement and an index.
1694daae87aaSUlrich Weigand     Form = SystemZAddressingMode::FormBDXNormal;
1695daae87aaSUlrich Weigand     DispRange = SystemZAddressingMode::Disp12Only;
16962eeace21SDaniel Sanders     break;
169779564611SUlrich Weigand   case InlineAsm::Constraint_S:
16984aa5dc15SJonas Paulsson   case InlineAsm::Constraint_ZS:
1699daae87aaSUlrich Weigand     // Accept an address with a long displacement, but no index.
1700daae87aaSUlrich Weigand     Form = SystemZAddressingMode::FormBD;
1701daae87aaSUlrich Weigand     DispRange = SystemZAddressingMode::Disp20Only;
1702daae87aaSUlrich Weigand     break;
170379564611SUlrich Weigand   case InlineAsm::Constraint_T:
170479564611SUlrich Weigand   case InlineAsm::Constraint_m:
1705d39e9dcaSUlrich Weigand   case InlineAsm::Constraint_o:
170646f83caeSJonas Paulsson   case InlineAsm::Constraint_p:
17074aa5dc15SJonas Paulsson   case InlineAsm::Constraint_ZT:
1708daae87aaSUlrich Weigand     // Accept an address with a long displacement and an index.
1709daae87aaSUlrich Weigand     // m works the same as T, as this is the most general case.
1710d39e9dcaSUlrich Weigand     // We don't really have any special handling of "offsettable"
1711d39e9dcaSUlrich Weigand     // memory addresses, so just treat o the same as m.
1712daae87aaSUlrich Weigand     Form = SystemZAddressingMode::FormBDXNormal;
1713daae87aaSUlrich Weigand     DispRange = SystemZAddressingMode::Disp20Only;
1714daae87aaSUlrich Weigand     break;
1715daae87aaSUlrich Weigand   }
1716daae87aaSUlrich Weigand 
1717daae87aaSUlrich Weigand   if (selectBDXAddr(Form, DispRange, Op, Base, Disp, Index)) {
1718cf2f4b32SZhan Jun Liau     const TargetRegisterClass *TRC =
1719cf2f4b32SZhan Jun Liau       Subtarget->getRegisterInfo()->getPointerRegClass(*MF);
1720cf2f4b32SZhan Jun Liau     SDLoc DL(Base);
1721cf2f4b32SZhan Jun Liau     SDValue RC = CurDAG->getTargetConstant(TRC->getID(), DL, MVT::i32);
1722cf2f4b32SZhan Jun Liau 
1723cf2f4b32SZhan Jun Liau     // Make sure that the base address doesn't go into %r0.
1724cf2f4b32SZhan Jun Liau     // If it's a TargetFrameIndex or a fixed register, we shouldn't do anything.
1725cf2f4b32SZhan Jun Liau     if (Base.getOpcode() != ISD::TargetFrameIndex &&
1726cf2f4b32SZhan Jun Liau         Base.getOpcode() != ISD::Register) {
1727cf2f4b32SZhan Jun Liau       Base =
1728cf2f4b32SZhan Jun Liau         SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1729cf2f4b32SZhan Jun Liau                                        DL, Base.getValueType(),
1730cf2f4b32SZhan Jun Liau                                        Base, RC), 0);
1731cf2f4b32SZhan Jun Liau     }
1732cf2f4b32SZhan Jun Liau 
1733cf2f4b32SZhan Jun Liau     // Make sure that the index register isn't assigned to %r0 either.
1734cf2f4b32SZhan Jun Liau     if (Index.getOpcode() != ISD::Register) {
1735cf2f4b32SZhan Jun Liau       Index =
1736cf2f4b32SZhan Jun Liau         SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1737cf2f4b32SZhan Jun Liau                                        DL, Index.getValueType(),
1738cf2f4b32SZhan Jun Liau                                        Index, RC), 0);
1739cf2f4b32SZhan Jun Liau     }
1740cf2f4b32SZhan Jun Liau 
174179564611SUlrich Weigand     OutOps.push_back(Base);
174279564611SUlrich Weigand     OutOps.push_back(Disp);
174379564611SUlrich Weigand     OutOps.push_back(Index);
174479564611SUlrich Weigand     return false;
174579564611SUlrich Weigand   }
1746daae87aaSUlrich Weigand 
17472eeace21SDaniel Sanders   return true;
17482eeace21SDaniel Sanders }
1749849a59fdSUlrich Weigand 
1750b32f3656SUlrich Weigand // IsProfitableToFold - Returns true if is profitable to fold the specific
1751b32f3656SUlrich Weigand // operand node N of U during instruction selection that starts at Root.
1752b32f3656SUlrich Weigand bool
IsProfitableToFold(SDValue N,SDNode * U,SDNode * Root) const1753b32f3656SUlrich Weigand SystemZDAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U,
1754b32f3656SUlrich Weigand                                         SDNode *Root) const {
1755b32f3656SUlrich Weigand   // We want to avoid folding a LOAD into an ICMP node if as a result
1756b32f3656SUlrich Weigand   // we would be forced to spill the condition code into a GPR.
1757b32f3656SUlrich Weigand   if (N.getOpcode() == ISD::LOAD && U->getOpcode() == SystemZISD::ICMP) {
1758b32f3656SUlrich Weigand     if (!N.hasOneUse() || !U->hasOneUse())
1759b32f3656SUlrich Weigand       return false;
1760b32f3656SUlrich Weigand 
1761b32f3656SUlrich Weigand     // The user of the CC value will usually be a CopyToReg into the
1762b32f3656SUlrich Weigand     // physical CC register, which in turn is glued and chained to the
1763b32f3656SUlrich Weigand     // actual instruction that uses the CC value.  Bail out if we have
1764b32f3656SUlrich Weigand     // anything else than that.
1765b32f3656SUlrich Weigand     SDNode *CCUser = *U->use_begin();
1766b32f3656SUlrich Weigand     SDNode *CCRegUser = nullptr;
1767b32f3656SUlrich Weigand     if (CCUser->getOpcode() == ISD::CopyToReg ||
1768b32f3656SUlrich Weigand         cast<RegisterSDNode>(CCUser->getOperand(1))->getReg() == SystemZ::CC) {
1769b32f3656SUlrich Weigand       for (auto *U : CCUser->uses()) {
1770b32f3656SUlrich Weigand         if (CCRegUser == nullptr)
1771b32f3656SUlrich Weigand           CCRegUser = U;
1772b32f3656SUlrich Weigand         else if (CCRegUser != U)
1773b32f3656SUlrich Weigand           return false;
1774b32f3656SUlrich Weigand       }
1775b32f3656SUlrich Weigand     }
1776b32f3656SUlrich Weigand     if (CCRegUser == nullptr)
1777b32f3656SUlrich Weigand       return false;
1778b32f3656SUlrich Weigand 
1779b32f3656SUlrich Weigand     // If the actual instruction is a branch, the only thing that remains to be
1780b32f3656SUlrich Weigand     // checked is whether the CCUser chain is a predecessor of the load.
1781b32f3656SUlrich Weigand     if (CCRegUser->isMachineOpcode() &&
1782b32f3656SUlrich Weigand         CCRegUser->getMachineOpcode() == SystemZ::BRC)
1783b32f3656SUlrich Weigand       return !N->isPredecessorOf(CCUser->getOperand(0).getNode());
1784b32f3656SUlrich Weigand 
1785b32f3656SUlrich Weigand     // Otherwise, the instruction may have multiple operands, and we need to
1786b32f3656SUlrich Weigand     // verify that none of them are a predecessor of the load.  This is exactly
1787b32f3656SUlrich Weigand     // the same check that would be done by common code if the CC setter were
1788b32f3656SUlrich Weigand     // glued to the CC user, so simply invoke that check here.
1789b32f3656SUlrich Weigand     if (!IsLegalToFold(N, U, CCRegUser, OptLevel, false))
1790b32f3656SUlrich Weigand       return false;
1791b32f3656SUlrich Weigand   }
1792b32f3656SUlrich Weigand 
1793b32f3656SUlrich Weigand   return true;
1794b32f3656SUlrich Weigand }
1795b32f3656SUlrich Weigand 
1796849a59fdSUlrich Weigand namespace {
1797849a59fdSUlrich Weigand // Represents a sequence for extracting a 0/1 value from an IPM result:
1798849a59fdSUlrich Weigand // (((X ^ XORValue) + AddValue) >> Bit)
1799849a59fdSUlrich Weigand struct IPMConversion {
IPMConversion__anon6e09402b0211::IPMConversion1800849a59fdSUlrich Weigand   IPMConversion(unsigned xorValue, int64_t addValue, unsigned bit)
1801849a59fdSUlrich Weigand     : XORValue(xorValue), AddValue(addValue), Bit(bit) {}
1802849a59fdSUlrich Weigand 
1803849a59fdSUlrich Weigand   int64_t XORValue;
1804849a59fdSUlrich Weigand   int64_t AddValue;
1805849a59fdSUlrich Weigand   unsigned Bit;
1806849a59fdSUlrich Weigand };
1807849a59fdSUlrich Weigand } // end anonymous namespace
1808849a59fdSUlrich Weigand 
1809849a59fdSUlrich Weigand // Return a sequence for getting a 1 from an IPM result when CC has a
1810849a59fdSUlrich Weigand // value in CCMask and a 0 when CC has a value in CCValid & ~CCMask.
1811849a59fdSUlrich Weigand // The handling of CC values outside CCValid doesn't matter.
getIPMConversion(unsigned CCValid,unsigned CCMask)1812849a59fdSUlrich Weigand static IPMConversion getIPMConversion(unsigned CCValid, unsigned CCMask) {
1813849a59fdSUlrich Weigand   // Deal with cases where the result can be taken directly from a bit
1814849a59fdSUlrich Weigand   // of the IPM result.
1815849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_1 | SystemZ::CCMASK_3)))
1816849a59fdSUlrich Weigand     return IPMConversion(0, 0, SystemZ::IPM_CC);
1817849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_2 | SystemZ::CCMASK_3)))
1818849a59fdSUlrich Weigand     return IPMConversion(0, 0, SystemZ::IPM_CC + 1);
1819849a59fdSUlrich Weigand 
1820849a59fdSUlrich Weigand   // Deal with cases where we can add a value to force the sign bit
1821849a59fdSUlrich Weigand   // to contain the right value.  Putting the bit in 31 means we can
1822849a59fdSUlrich Weigand   // use SRL rather than RISBG(L), and also makes it easier to get a
1823849a59fdSUlrich Weigand   // 0/-1 value, so it has priority over the other tests below.
1824849a59fdSUlrich Weigand   //
1825849a59fdSUlrich Weigand   // These sequences rely on the fact that the upper two bits of the
1826849a59fdSUlrich Weigand   // IPM result are zero.
1827849a59fdSUlrich Weigand   uint64_t TopBit = uint64_t(1) << 31;
1828849a59fdSUlrich Weigand   if (CCMask == (CCValid & SystemZ::CCMASK_0))
1829849a59fdSUlrich Weigand     return IPMConversion(0, -(1 << SystemZ::IPM_CC), 31);
1830849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_1)))
1831849a59fdSUlrich Weigand     return IPMConversion(0, -(2 << SystemZ::IPM_CC), 31);
1832849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0
1833849a59fdSUlrich Weigand                             | SystemZ::CCMASK_1
1834849a59fdSUlrich Weigand                             | SystemZ::CCMASK_2)))
1835849a59fdSUlrich Weigand     return IPMConversion(0, -(3 << SystemZ::IPM_CC), 31);
1836849a59fdSUlrich Weigand   if (CCMask == (CCValid & SystemZ::CCMASK_3))
1837849a59fdSUlrich Weigand     return IPMConversion(0, TopBit - (3 << SystemZ::IPM_CC), 31);
1838849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_1
1839849a59fdSUlrich Weigand                             | SystemZ::CCMASK_2
1840849a59fdSUlrich Weigand                             | SystemZ::CCMASK_3)))
1841849a59fdSUlrich Weigand     return IPMConversion(0, TopBit - (1 << SystemZ::IPM_CC), 31);
1842849a59fdSUlrich Weigand 
1843849a59fdSUlrich Weigand   // Next try inverting the value and testing a bit.  0/1 could be
1844849a59fdSUlrich Weigand   // handled this way too, but we dealt with that case above.
1845849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_2)))
1846849a59fdSUlrich Weigand     return IPMConversion(-1, 0, SystemZ::IPM_CC);
1847849a59fdSUlrich Weigand 
1848849a59fdSUlrich Weigand   // Handle cases where adding a value forces a non-sign bit to contain
1849849a59fdSUlrich Weigand   // the right value.
1850849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_1 | SystemZ::CCMASK_2)))
1851849a59fdSUlrich Weigand     return IPMConversion(0, 1 << SystemZ::IPM_CC, SystemZ::IPM_CC + 1);
1852849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_3)))
1853849a59fdSUlrich Weigand     return IPMConversion(0, -(1 << SystemZ::IPM_CC), SystemZ::IPM_CC + 1);
1854849a59fdSUlrich Weigand 
1855849a59fdSUlrich Weigand   // The remaining cases are 1, 2, 0/1/3 and 0/2/3.  All these are
1856849a59fdSUlrich Weigand   // can be done by inverting the low CC bit and applying one of the
1857849a59fdSUlrich Weigand   // sign-based extractions above.
1858849a59fdSUlrich Weigand   if (CCMask == (CCValid & SystemZ::CCMASK_1))
1859849a59fdSUlrich Weigand     return IPMConversion(1 << SystemZ::IPM_CC, -(1 << SystemZ::IPM_CC), 31);
1860849a59fdSUlrich Weigand   if (CCMask == (CCValid & SystemZ::CCMASK_2))
1861849a59fdSUlrich Weigand     return IPMConversion(1 << SystemZ::IPM_CC,
1862849a59fdSUlrich Weigand                          TopBit - (3 << SystemZ::IPM_CC), 31);
1863849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0
1864849a59fdSUlrich Weigand                             | SystemZ::CCMASK_1
1865849a59fdSUlrich Weigand                             | SystemZ::CCMASK_3)))
1866849a59fdSUlrich Weigand     return IPMConversion(1 << SystemZ::IPM_CC, -(3 << SystemZ::IPM_CC), 31);
1867849a59fdSUlrich Weigand   if (CCMask == (CCValid & (SystemZ::CCMASK_0
1868849a59fdSUlrich Weigand                             | SystemZ::CCMASK_2
1869849a59fdSUlrich Weigand                             | SystemZ::CCMASK_3)))
1870849a59fdSUlrich Weigand     return IPMConversion(1 << SystemZ::IPM_CC,
1871849a59fdSUlrich Weigand                          TopBit - (1 << SystemZ::IPM_CC), 31);
1872849a59fdSUlrich Weigand 
1873849a59fdSUlrich Weigand   llvm_unreachable("Unexpected CC combination");
1874849a59fdSUlrich Weigand }
1875849a59fdSUlrich Weigand 
expandSelectBoolean(SDNode * Node)1876849a59fdSUlrich Weigand SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) {
1877849a59fdSUlrich Weigand   auto *TrueOp = dyn_cast<ConstantSDNode>(Node->getOperand(0));
1878849a59fdSUlrich Weigand   auto *FalseOp = dyn_cast<ConstantSDNode>(Node->getOperand(1));
1879849a59fdSUlrich Weigand   if (!TrueOp || !FalseOp)
1880849a59fdSUlrich Weigand     return SDValue();
1881849a59fdSUlrich Weigand   if (FalseOp->getZExtValue() != 0)
1882849a59fdSUlrich Weigand     return SDValue();
1883849a59fdSUlrich Weigand   if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
1884849a59fdSUlrich Weigand     return SDValue();
1885849a59fdSUlrich Weigand 
1886849a59fdSUlrich Weigand   auto *CCValidOp = dyn_cast<ConstantSDNode>(Node->getOperand(2));
1887849a59fdSUlrich Weigand   auto *CCMaskOp = dyn_cast<ConstantSDNode>(Node->getOperand(3));
1888849a59fdSUlrich Weigand   if (!CCValidOp || !CCMaskOp)
1889849a59fdSUlrich Weigand     return SDValue();
1890849a59fdSUlrich Weigand   int CCValid = CCValidOp->getZExtValue();
1891849a59fdSUlrich Weigand   int CCMask = CCMaskOp->getZExtValue();
1892849a59fdSUlrich Weigand 
1893849a59fdSUlrich Weigand   SDLoc DL(Node);
1894b32f3656SUlrich Weigand   SDValue CCReg = Node->getOperand(4);
1895849a59fdSUlrich Weigand   IPMConversion IPM = getIPMConversion(CCValid, CCMask);
1896b32f3656SUlrich Weigand   SDValue Result = CurDAG->getNode(SystemZISD::IPM, DL, MVT::i32, CCReg);
1897849a59fdSUlrich Weigand 
1898849a59fdSUlrich Weigand   if (IPM.XORValue)
1899849a59fdSUlrich Weigand     Result = CurDAG->getNode(ISD::XOR, DL, MVT::i32, Result,
1900849a59fdSUlrich Weigand                              CurDAG->getConstant(IPM.XORValue, DL, MVT::i32));
1901849a59fdSUlrich Weigand 
1902849a59fdSUlrich Weigand   if (IPM.AddValue)
1903849a59fdSUlrich Weigand     Result = CurDAG->getNode(ISD::ADD, DL, MVT::i32, Result,
1904849a59fdSUlrich Weigand                              CurDAG->getConstant(IPM.AddValue, DL, MVT::i32));
1905849a59fdSUlrich Weigand 
1906849a59fdSUlrich Weigand   EVT VT = Node->getValueType(0);
1907849a59fdSUlrich Weigand   if (VT == MVT::i32 && IPM.Bit == 31) {
1908849a59fdSUlrich Weigand     unsigned ShiftOp = TrueOp->getSExtValue() == 1 ? ISD::SRL : ISD::SRA;
1909849a59fdSUlrich Weigand     Result = CurDAG->getNode(ShiftOp, DL, MVT::i32, Result,
1910849a59fdSUlrich Weigand                              CurDAG->getConstant(IPM.Bit, DL, MVT::i32));
1911849a59fdSUlrich Weigand   } else {
1912849a59fdSUlrich Weigand     if (VT != MVT::i32)
1913849a59fdSUlrich Weigand       Result = CurDAG->getNode(ISD::ANY_EXTEND, DL, VT, Result);
1914849a59fdSUlrich Weigand 
1915849a59fdSUlrich Weigand     if (TrueOp->getSExtValue() == 1) {
1916849a59fdSUlrich Weigand       // The SHR/AND sequence should get optimized to an RISBG.
1917849a59fdSUlrich Weigand       Result = CurDAG->getNode(ISD::SRL, DL, VT, Result,
1918849a59fdSUlrich Weigand                                CurDAG->getConstant(IPM.Bit, DL, MVT::i32));
1919849a59fdSUlrich Weigand       Result = CurDAG->getNode(ISD::AND, DL, VT, Result,
1920849a59fdSUlrich Weigand                                CurDAG->getConstant(1, DL, VT));
1921849a59fdSUlrich Weigand     } else {
1922849a59fdSUlrich Weigand       // Sign-extend from IPM.Bit using a pair of shifts.
1923849a59fdSUlrich Weigand       int ShlAmt = VT.getSizeInBits() - 1 - IPM.Bit;
1924849a59fdSUlrich Weigand       int SraAmt = VT.getSizeInBits() - 1;
1925849a59fdSUlrich Weigand       Result = CurDAG->getNode(ISD::SHL, DL, VT, Result,
1926849a59fdSUlrich Weigand                                CurDAG->getConstant(ShlAmt, DL, MVT::i32));
1927849a59fdSUlrich Weigand       Result = CurDAG->getNode(ISD::SRA, DL, VT, Result,
1928849a59fdSUlrich Weigand                                CurDAG->getConstant(SraAmt, DL, MVT::i32));
1929849a59fdSUlrich Weigand     }
1930849a59fdSUlrich Weigand   }
1931849a59fdSUlrich Weigand 
1932849a59fdSUlrich Weigand   return Result;
1933849a59fdSUlrich Weigand }
1934849a59fdSUlrich Weigand 
PreprocessISelDAG()1935849a59fdSUlrich Weigand void SystemZDAGToDAGISel::PreprocessISelDAG() {
1936426f6befSUlrich Weigand   // If we have conditional immediate loads, we always prefer
1937426f6befSUlrich Weigand   // using those over an IPM sequence.
1938426f6befSUlrich Weigand   if (Subtarget->hasLoadStoreOnCond2())
1939426f6befSUlrich Weigand     return;
1940426f6befSUlrich Weigand 
1941849a59fdSUlrich Weigand   bool MadeChange = false;
1942849a59fdSUlrich Weigand 
1943849a59fdSUlrich Weigand   for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
1944849a59fdSUlrich Weigand                                        E = CurDAG->allnodes_end();
1945849a59fdSUlrich Weigand        I != E;) {
1946849a59fdSUlrich Weigand     SDNode *N = &*I++;
1947849a59fdSUlrich Weigand     if (N->use_empty())
1948849a59fdSUlrich Weigand       continue;
1949849a59fdSUlrich Weigand 
1950849a59fdSUlrich Weigand     SDValue Res;
1951849a59fdSUlrich Weigand     switch (N->getOpcode()) {
1952849a59fdSUlrich Weigand     default: break;
1953849a59fdSUlrich Weigand     case SystemZISD::SELECT_CCMASK:
1954849a59fdSUlrich Weigand       Res = expandSelectBoolean(N);
1955849a59fdSUlrich Weigand       break;
1956849a59fdSUlrich Weigand     }
1957849a59fdSUlrich Weigand 
1958849a59fdSUlrich Weigand     if (Res) {
1959d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "SystemZ DAG preprocessing replacing:\nOld:    ");
1960d34e60caSNicola Zaghen       LLVM_DEBUG(N->dump(CurDAG));
1961d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "\nNew: ");
1962d34e60caSNicola Zaghen       LLVM_DEBUG(Res.getNode()->dump(CurDAG));
1963d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "\n");
1964849a59fdSUlrich Weigand 
1965849a59fdSUlrich Weigand       CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Res);
1966849a59fdSUlrich Weigand       MadeChange = true;
1967849a59fdSUlrich Weigand     }
1968849a59fdSUlrich Weigand   }
1969849a59fdSUlrich Weigand 
1970849a59fdSUlrich Weigand   if (MadeChange)
1971849a59fdSUlrich Weigand     CurDAG->RemoveDeadNodes();
1972849a59fdSUlrich Weigand }
1973