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