1284c1978SDimitry Andric //===-- SystemZInstrInfo.cpp - SystemZ instruction information ------------===//
2284c1978SDimitry Andric //
3284c1978SDimitry Andric //                     The LLVM Compiler Infrastructure
4284c1978SDimitry Andric //
5284c1978SDimitry Andric // This file is distributed under the University of Illinois Open Source
6284c1978SDimitry Andric // License. See LICENSE.TXT for details.
7284c1978SDimitry Andric //
8284c1978SDimitry Andric //===----------------------------------------------------------------------===//
9284c1978SDimitry Andric //
10284c1978SDimitry Andric // This file contains the SystemZ implementation of the TargetInstrInfo class.
11284c1978SDimitry Andric //
12284c1978SDimitry Andric //===----------------------------------------------------------------------===//
13284c1978SDimitry Andric 
14db17bf38SDimitry Andric #include "SystemZInstrInfo.h"
157a7e6055SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
167a7e6055SDimitry Andric #include "SystemZ.h"
17284c1978SDimitry Andric #include "SystemZInstrBuilder.h"
187a7e6055SDimitry Andric #include "SystemZSubtarget.h"
192cab237bSDimitry Andric #include "llvm/ADT/Statistic.h"
207a7e6055SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
212cab237bSDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
227a7e6055SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
237a7e6055SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
247a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
257a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
267a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
277a7e6055SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
287a7e6055SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
29f785676fSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
307a7e6055SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
312cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
322cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
337a7e6055SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
347a7e6055SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
357a7e6055SDimitry Andric #include "llvm/Support/BranchProbability.h"
367a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
377a7e6055SDimitry Andric #include "llvm/Support/MathExtras.h"
387a7e6055SDimitry Andric #include "llvm/Target/TargetMachine.h"
397a7e6055SDimitry Andric #include <cassert>
407a7e6055SDimitry Andric #include <cstdint>
417a7e6055SDimitry Andric #include <iterator>
42284c1978SDimitry Andric 
4391bc56edSDimitry Andric using namespace llvm;
4491bc56edSDimitry Andric 
45f785676fSDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
46284c1978SDimitry Andric #define GET_INSTRMAP_INFO
47284c1978SDimitry Andric #include "SystemZGenInstrInfo.inc"
48284c1978SDimitry Andric 
492cab237bSDimitry Andric #define DEBUG_TYPE "systemz-II"
502cab237bSDimitry Andric STATISTIC(LOCRMuxJumps, "Number of LOCRMux jump-sequences (lower is better)");
512cab237bSDimitry Andric 
52f785676fSDimitry Andric // Return a mask with Count low bits set.
allOnes(unsigned int Count)53f785676fSDimitry Andric static uint64_t allOnes(unsigned int Count) {
54f785676fSDimitry Andric   return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;
55f785676fSDimitry Andric }
56f785676fSDimitry Andric 
57f785676fSDimitry Andric // Reg should be a 32-bit GPR.  Return true if it is a high register rather
58f785676fSDimitry Andric // than a low register.
isHighReg(unsigned int Reg)59f785676fSDimitry Andric static bool isHighReg(unsigned int Reg) {
60f785676fSDimitry Andric   if (SystemZ::GRH32BitRegClass.contains(Reg))
61f785676fSDimitry Andric     return true;
62f785676fSDimitry Andric   assert(SystemZ::GR32BitRegClass.contains(Reg) && "Invalid GRX32");
63f785676fSDimitry Andric   return false;
64f785676fSDimitry Andric }
65f785676fSDimitry Andric 
66f785676fSDimitry Andric // Pin the vtable to this file.
anchor()67f785676fSDimitry Andric void SystemZInstrInfo::anchor() {}
68f785676fSDimitry Andric 
SystemZInstrInfo(SystemZSubtarget & sti)6991bc56edSDimitry Andric SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti)
70284c1978SDimitry Andric   : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP),
7191bc56edSDimitry Andric     RI(), STI(sti) {
72284c1978SDimitry Andric }
73284c1978SDimitry Andric 
74284c1978SDimitry Andric // MI is a 128-bit load or store.  Split it into two 64-bit loads or stores,
75284c1978SDimitry Andric // each having the opcode given by NewOpcode.
splitMove(MachineBasicBlock::iterator MI,unsigned NewOpcode) const76284c1978SDimitry Andric void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,
77284c1978SDimitry Andric                                  unsigned NewOpcode) const {
78284c1978SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
79284c1978SDimitry Andric   MachineFunction &MF = *MBB->getParent();
80284c1978SDimitry Andric 
81284c1978SDimitry Andric   // Get two load or store instructions.  Use the original instruction for one
8291bc56edSDimitry Andric   // of them (arbitrarily the second here) and create a clone for the other.
833ca95b02SDimitry Andric   MachineInstr *EarlierMI = MF.CloneMachineInstr(&*MI);
84284c1978SDimitry Andric   MBB->insert(MI, EarlierMI);
85284c1978SDimitry Andric 
867a7e6055SDimitry Andric   // Set up the two 64-bit registers and remember super reg and its flags.
87284c1978SDimitry Andric   MachineOperand &HighRegOp = EarlierMI->getOperand(0);
88284c1978SDimitry Andric   MachineOperand &LowRegOp = MI->getOperand(0);
897a7e6055SDimitry Andric   unsigned Reg128 = LowRegOp.getReg();
907a7e6055SDimitry Andric   unsigned Reg128Killed = getKillRegState(LowRegOp.isKill());
917a7e6055SDimitry Andric   unsigned Reg128Undef  = getUndefRegState(LowRegOp.isUndef());
92f785676fSDimitry Andric   HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64));
93f785676fSDimitry Andric   LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64));
94284c1978SDimitry Andric 
957a7e6055SDimitry Andric   if (MI->mayStore()) {
967a7e6055SDimitry Andric     // Add implicit uses of the super register in case one of the subregs is
977a7e6055SDimitry Andric     // undefined. We could track liveness and skip storing an undefined
987a7e6055SDimitry Andric     // subreg, but this is hopefully rare (discovered with llvm-stress).
997a7e6055SDimitry Andric     // If Reg128 was killed, set kill flag on MI.
1007a7e6055SDimitry Andric     unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);
1017a7e6055SDimitry Andric     MachineInstrBuilder(MF, EarlierMI).addReg(Reg128, Reg128UndefImpl);
1027a7e6055SDimitry Andric     MachineInstrBuilder(MF, MI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));
1037a7e6055SDimitry Andric   }
1047a7e6055SDimitry Andric 
105284c1978SDimitry Andric   // The address in the first (high) instruction is already correct.
106284c1978SDimitry Andric   // Adjust the offset in the second (low) instruction.
107284c1978SDimitry Andric   MachineOperand &HighOffsetOp = EarlierMI->getOperand(2);
108284c1978SDimitry Andric   MachineOperand &LowOffsetOp = MI->getOperand(2);
109284c1978SDimitry Andric   LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);
110284c1978SDimitry Andric 
11151690af2SDimitry Andric   // Clear the kill flags on the registers in the first instruction.
11251690af2SDimitry Andric   if (EarlierMI->getOperand(0).isReg() && EarlierMI->getOperand(0).isUse())
11351690af2SDimitry Andric     EarlierMI->getOperand(0).setIsKill(false);
1147d523365SDimitry Andric   EarlierMI->getOperand(1).setIsKill(false);
1157d523365SDimitry Andric   EarlierMI->getOperand(3).setIsKill(false);
1167d523365SDimitry Andric 
117284c1978SDimitry Andric   // Set the opcodes.
118284c1978SDimitry Andric   unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());
119284c1978SDimitry Andric   unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());
120284c1978SDimitry Andric   assert(HighOpcode && LowOpcode && "Both offsets should be in range");
121284c1978SDimitry Andric 
122284c1978SDimitry Andric   EarlierMI->setDesc(get(HighOpcode));
123284c1978SDimitry Andric   MI->setDesc(get(LowOpcode));
124284c1978SDimitry Andric }
125284c1978SDimitry Andric 
126284c1978SDimitry Andric // Split ADJDYNALLOC instruction MI.
splitAdjDynAlloc(MachineBasicBlock::iterator MI) const127284c1978SDimitry Andric void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {
128284c1978SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
129284c1978SDimitry Andric   MachineFunction &MF = *MBB->getParent();
130d88c1a5aSDimitry Andric   MachineFrameInfo &MFFrame = MF.getFrameInfo();
131284c1978SDimitry Andric   MachineOperand &OffsetMO = MI->getOperand(2);
132284c1978SDimitry Andric 
133d88c1a5aSDimitry Andric   uint64_t Offset = (MFFrame.getMaxCallFrameSize() +
134284c1978SDimitry Andric                      SystemZMC::CallFrameSize +
135284c1978SDimitry Andric                      OffsetMO.getImm());
136284c1978SDimitry Andric   unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);
137284c1978SDimitry Andric   assert(NewOpcode && "No support for huge argument lists yet");
138284c1978SDimitry Andric   MI->setDesc(get(NewOpcode));
139284c1978SDimitry Andric   OffsetMO.setImm(Offset);
140284c1978SDimitry Andric }
141284c1978SDimitry Andric 
142f785676fSDimitry Andric // MI is an RI-style pseudo instruction.  Replace it with LowOpcode
143f785676fSDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
144f785676fSDimitry Andric // is a high GR32.  ConvertHigh is true if LowOpcode takes a signed operand
145f785676fSDimitry Andric // and HighOpcode takes an unsigned 32-bit operand.  In those cases,
146f785676fSDimitry Andric // MI has the same kind of operand as LowOpcode, so needs to be converted
147f785676fSDimitry Andric // if HighOpcode is used.
expandRIPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode,bool ConvertHigh) const1483ca95b02SDimitry Andric void SystemZInstrInfo::expandRIPseudo(MachineInstr &MI, unsigned LowOpcode,
149f785676fSDimitry Andric                                       unsigned HighOpcode,
150f785676fSDimitry Andric                                       bool ConvertHigh) const {
1513ca95b02SDimitry Andric   unsigned Reg = MI.getOperand(0).getReg();
152f785676fSDimitry Andric   bool IsHigh = isHighReg(Reg);
1533ca95b02SDimitry Andric   MI.setDesc(get(IsHigh ? HighOpcode : LowOpcode));
154f785676fSDimitry Andric   if (IsHigh && ConvertHigh)
1553ca95b02SDimitry Andric     MI.getOperand(1).setImm(uint32_t(MI.getOperand(1).getImm()));
156f785676fSDimitry Andric }
157f785676fSDimitry Andric 
158f785676fSDimitry Andric // MI is a three-operand RIE-style pseudo instruction.  Replace it with
1597d523365SDimitry Andric // LowOpcodeK if the registers are both low GR32s, otherwise use a move
160f785676fSDimitry Andric // followed by HighOpcode or LowOpcode, depending on whether the target
161f785676fSDimitry Andric // is a high or low GR32.
expandRIEPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned LowOpcodeK,unsigned HighOpcode) const1623ca95b02SDimitry Andric void SystemZInstrInfo::expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,
163f785676fSDimitry Andric                                        unsigned LowOpcodeK,
164f785676fSDimitry Andric                                        unsigned HighOpcode) const {
1653ca95b02SDimitry Andric   unsigned DestReg = MI.getOperand(0).getReg();
1663ca95b02SDimitry Andric   unsigned SrcReg = MI.getOperand(1).getReg();
167f785676fSDimitry Andric   bool DestIsHigh = isHighReg(DestReg);
168f785676fSDimitry Andric   bool SrcIsHigh = isHighReg(SrcReg);
169f785676fSDimitry Andric   if (!DestIsHigh && !SrcIsHigh)
1703ca95b02SDimitry Andric     MI.setDesc(get(LowOpcodeK));
171f785676fSDimitry Andric   else {
1723ca95b02SDimitry Andric     emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), DestReg, SrcReg,
1737a7e6055SDimitry Andric                   SystemZ::LR, 32, MI.getOperand(1).isKill(),
1747a7e6055SDimitry Andric                   MI.getOperand(1).isUndef());
1753ca95b02SDimitry Andric     MI.setDesc(get(DestIsHigh ? HighOpcode : LowOpcode));
1763ca95b02SDimitry Andric     MI.getOperand(1).setReg(DestReg);
1773ca95b02SDimitry Andric     MI.tieOperands(0, 1);
178f785676fSDimitry Andric   }
179f785676fSDimitry Andric }
180f785676fSDimitry Andric 
181f785676fSDimitry Andric // MI is an RXY-style pseudo instruction.  Replace it with LowOpcode
182f785676fSDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
183f785676fSDimitry Andric // is a high GR32.
expandRXYPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode) const1843ca95b02SDimitry Andric void SystemZInstrInfo::expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,
185f785676fSDimitry Andric                                        unsigned HighOpcode) const {
1863ca95b02SDimitry Andric   unsigned Reg = MI.getOperand(0).getReg();
187f785676fSDimitry Andric   unsigned Opcode = getOpcodeForOffset(isHighReg(Reg) ? HighOpcode : LowOpcode,
1883ca95b02SDimitry Andric                                        MI.getOperand(2).getImm());
1893ca95b02SDimitry Andric   MI.setDesc(get(Opcode));
190f785676fSDimitry Andric }
191f785676fSDimitry Andric 
192d88c1a5aSDimitry Andric // MI is a load-on-condition pseudo instruction with a single register
193d88c1a5aSDimitry Andric // (source or destination) operand.  Replace it with LowOpcode if the
194d88c1a5aSDimitry Andric // register is a low GR32 and HighOpcode if the register is a high GR32.
expandLOCPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode) const195d88c1a5aSDimitry Andric void SystemZInstrInfo::expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,
196d88c1a5aSDimitry Andric                                        unsigned HighOpcode) const {
197d88c1a5aSDimitry Andric   unsigned Reg = MI.getOperand(0).getReg();
198d88c1a5aSDimitry Andric   unsigned Opcode = isHighReg(Reg) ? HighOpcode : LowOpcode;
199d88c1a5aSDimitry Andric   MI.setDesc(get(Opcode));
200d88c1a5aSDimitry Andric }
201d88c1a5aSDimitry Andric 
202d88c1a5aSDimitry Andric // MI is a load-register-on-condition pseudo instruction.  Replace it with
203d88c1a5aSDimitry Andric // LowOpcode if source and destination are both low GR32s and HighOpcode if
204d88c1a5aSDimitry Andric // source and destination are both high GR32s.
expandLOCRPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode) const205d88c1a5aSDimitry Andric void SystemZInstrInfo::expandLOCRPseudo(MachineInstr &MI, unsigned LowOpcode,
206d88c1a5aSDimitry Andric                                         unsigned HighOpcode) const {
207d88c1a5aSDimitry Andric   unsigned DestReg = MI.getOperand(0).getReg();
208d88c1a5aSDimitry Andric   unsigned SrcReg = MI.getOperand(2).getReg();
209d88c1a5aSDimitry Andric   bool DestIsHigh = isHighReg(DestReg);
210d88c1a5aSDimitry Andric   bool SrcIsHigh = isHighReg(SrcReg);
211d88c1a5aSDimitry Andric 
212d88c1a5aSDimitry Andric   if (!DestIsHigh && !SrcIsHigh)
213d88c1a5aSDimitry Andric     MI.setDesc(get(LowOpcode));
214d88c1a5aSDimitry Andric   else if (DestIsHigh && SrcIsHigh)
215d88c1a5aSDimitry Andric     MI.setDesc(get(HighOpcode));
2162cab237bSDimitry Andric   else
2172cab237bSDimitry Andric     LOCRMuxJumps++;
218d88c1a5aSDimitry Andric 
219d88c1a5aSDimitry Andric   // If we were unable to implement the pseudo with a single instruction, we
220d88c1a5aSDimitry Andric   // need to convert it back into a branch sequence.  This cannot be done here
221d88c1a5aSDimitry Andric   // since the caller of expandPostRAPseudo does not handle changes to the CFG
222d88c1a5aSDimitry Andric   // correctly.  This change is defered to the SystemZExpandPseudo pass.
223d88c1a5aSDimitry Andric }
224d88c1a5aSDimitry Andric 
225f785676fSDimitry Andric // MI is an RR-style pseudo instruction that zero-extends the low Size bits
226f785676fSDimitry Andric // of one GRX32 into another.  Replace it with LowOpcode if both operands
227f785676fSDimitry Andric // are low registers, otherwise use RISB[LH]G.
expandZExtPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned Size) const2283ca95b02SDimitry Andric void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,
229f785676fSDimitry Andric                                         unsigned Size) const {
2307a7e6055SDimitry Andric   MachineInstrBuilder MIB =
2313ca95b02SDimitry Andric     emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(),
2323ca95b02SDimitry Andric                MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), LowOpcode,
2337a7e6055SDimitry Andric                Size, MI.getOperand(1).isKill(), MI.getOperand(1).isUndef());
2347a7e6055SDimitry Andric 
2357a7e6055SDimitry Andric   // Keep the remaining operands as-is.
2367a7e6055SDimitry Andric   for (unsigned I = 2; I < MI.getNumOperands(); ++I)
2377a7e6055SDimitry Andric     MIB.add(MI.getOperand(I));
2387a7e6055SDimitry Andric 
2393ca95b02SDimitry Andric   MI.eraseFromParent();
2403ca95b02SDimitry Andric }
2413ca95b02SDimitry Andric 
expandLoadStackGuard(MachineInstr * MI) const2423ca95b02SDimitry Andric void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const {
2433ca95b02SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
2443ca95b02SDimitry Andric   MachineFunction &MF = *MBB->getParent();
245302affcbSDimitry Andric   const unsigned Reg64 = MI->getOperand(0).getReg();
246302affcbSDimitry Andric   const unsigned Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32);
2473ca95b02SDimitry Andric 
248302affcbSDimitry Andric   // EAR can only load the low subregister so us a shift for %a0 to produce
249302affcbSDimitry Andric   // the GR containing %a0 and %a1.
2503ca95b02SDimitry Andric 
2513ca95b02SDimitry Andric   // ear <reg>, %a0
252302affcbSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
253302affcbSDimitry Andric     .addReg(SystemZ::A0)
254302affcbSDimitry Andric     .addReg(Reg64, RegState::ImplicitDefine);
2553ca95b02SDimitry Andric 
2563ca95b02SDimitry Andric   // sllg <reg>, <reg>, 32
257302affcbSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64)
258302affcbSDimitry Andric     .addReg(Reg64)
259302affcbSDimitry Andric     .addReg(0)
260302affcbSDimitry Andric     .addImm(32);
2613ca95b02SDimitry Andric 
2623ca95b02SDimitry Andric   // ear <reg>, %a1
263302affcbSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
264302affcbSDimitry Andric     .addReg(SystemZ::A1);
2653ca95b02SDimitry Andric 
2663ca95b02SDimitry Andric   // lg <reg>, 40(<reg>)
2673ca95b02SDimitry Andric   MI->setDesc(get(SystemZ::LG));
268302affcbSDimitry Andric   MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0);
269f785676fSDimitry Andric }
270f785676fSDimitry Andric 
271f785676fSDimitry Andric // Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR
272f785676fSDimitry Andric // DestReg before MBBI in MBB.  Use LowLowOpcode when both DestReg and SrcReg
273f785676fSDimitry Andric // are low registers, otherwise use RISB[LH]G.  Size is the number of bits
274f785676fSDimitry Andric // taken from the low end of SrcReg (8 for LLCR, 16 for LLHR and 32 for LR).
275f785676fSDimitry Andric // KillSrc is true if this move is the last use of SrcReg.
2767a7e6055SDimitry Andric MachineInstrBuilder
emitGRX32Move(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,unsigned LowLowOpcode,unsigned Size,bool KillSrc,bool UndefSrc) const2777a7e6055SDimitry Andric SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB,
278f785676fSDimitry Andric                                 MachineBasicBlock::iterator MBBI,
2793ca95b02SDimitry Andric                                 const DebugLoc &DL, unsigned DestReg,
280f785676fSDimitry Andric                                 unsigned SrcReg, unsigned LowLowOpcode,
2817a7e6055SDimitry Andric                                 unsigned Size, bool KillSrc,
2827a7e6055SDimitry Andric                                 bool UndefSrc) const {
283f785676fSDimitry Andric   unsigned Opcode;
284f785676fSDimitry Andric   bool DestIsHigh = isHighReg(DestReg);
285f785676fSDimitry Andric   bool SrcIsHigh = isHighReg(SrcReg);
286f785676fSDimitry Andric   if (DestIsHigh && SrcIsHigh)
287f785676fSDimitry Andric     Opcode = SystemZ::RISBHH;
288f785676fSDimitry Andric   else if (DestIsHigh && !SrcIsHigh)
289f785676fSDimitry Andric     Opcode = SystemZ::RISBHL;
290f785676fSDimitry Andric   else if (!DestIsHigh && SrcIsHigh)
291f785676fSDimitry Andric     Opcode = SystemZ::RISBLH;
292f785676fSDimitry Andric   else {
2937a7e6055SDimitry Andric     return BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg)
2947a7e6055SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc));
295f785676fSDimitry Andric   }
296f785676fSDimitry Andric   unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0);
2977a7e6055SDimitry Andric   return BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
298f785676fSDimitry Andric     .addReg(DestReg, RegState::Undef)
2997a7e6055SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc))
300f785676fSDimitry Andric     .addImm(32 - Size).addImm(128 + 31).addImm(Rotate);
301f785676fSDimitry Andric }
302f785676fSDimitry Andric 
commuteInstructionImpl(MachineInstr & MI,bool NewMI,unsigned OpIdx1,unsigned OpIdx2) const303d88c1a5aSDimitry Andric MachineInstr *SystemZInstrInfo::commuteInstructionImpl(MachineInstr &MI,
304d88c1a5aSDimitry Andric                                                        bool NewMI,
305d88c1a5aSDimitry Andric                                                        unsigned OpIdx1,
306d88c1a5aSDimitry Andric                                                        unsigned OpIdx2) const {
307d88c1a5aSDimitry Andric   auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {
308d88c1a5aSDimitry Andric     if (NewMI)
309d88c1a5aSDimitry Andric       return *MI.getParent()->getParent()->CloneMachineInstr(&MI);
310d88c1a5aSDimitry Andric     return MI;
311d88c1a5aSDimitry Andric   };
312d88c1a5aSDimitry Andric 
313d88c1a5aSDimitry Andric   switch (MI.getOpcode()) {
314d88c1a5aSDimitry Andric   case SystemZ::LOCRMux:
315d88c1a5aSDimitry Andric   case SystemZ::LOCFHR:
316d88c1a5aSDimitry Andric   case SystemZ::LOCR:
317d88c1a5aSDimitry Andric   case SystemZ::LOCGR: {
318d88c1a5aSDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
319d88c1a5aSDimitry Andric     // Invert condition.
320d88c1a5aSDimitry Andric     unsigned CCValid = WorkingMI.getOperand(3).getImm();
321d88c1a5aSDimitry Andric     unsigned CCMask = WorkingMI.getOperand(4).getImm();
322d88c1a5aSDimitry Andric     WorkingMI.getOperand(4).setImm(CCMask ^ CCValid);
323d88c1a5aSDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
324d88c1a5aSDimitry Andric                                                    OpIdx1, OpIdx2);
325d88c1a5aSDimitry Andric   }
326d88c1a5aSDimitry Andric   default:
327d88c1a5aSDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
328d88c1a5aSDimitry Andric   }
329d88c1a5aSDimitry Andric }
330d88c1a5aSDimitry Andric 
331284c1978SDimitry Andric // If MI is a simple load or store for a frame object, return the register
332284c1978SDimitry Andric // it loads or stores and set FrameIndex to the index of the frame object.
333284c1978SDimitry Andric // Return 0 otherwise.
334284c1978SDimitry Andric //
335284c1978SDimitry Andric // Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
isSimpleMove(const MachineInstr & MI,int & FrameIndex,unsigned Flag)3363ca95b02SDimitry Andric static int isSimpleMove(const MachineInstr &MI, int &FrameIndex,
337f785676fSDimitry Andric                         unsigned Flag) {
3383ca95b02SDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
3393ca95b02SDimitry Andric   if ((MCID.TSFlags & Flag) && MI.getOperand(1).isFI() &&
3403ca95b02SDimitry Andric       MI.getOperand(2).getImm() == 0 && MI.getOperand(3).getReg() == 0) {
3413ca95b02SDimitry Andric     FrameIndex = MI.getOperand(1).getIndex();
3423ca95b02SDimitry Andric     return MI.getOperand(0).getReg();
343284c1978SDimitry Andric   }
344284c1978SDimitry Andric   return 0;
345284c1978SDimitry Andric }
346284c1978SDimitry Andric 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const3473ca95b02SDimitry Andric unsigned SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
348284c1978SDimitry Andric                                                int &FrameIndex) const {
349284c1978SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXLoad);
350284c1978SDimitry Andric }
351284c1978SDimitry Andric 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const3523ca95b02SDimitry Andric unsigned SystemZInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
353284c1978SDimitry Andric                                               int &FrameIndex) const {
354284c1978SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXStore);
355284c1978SDimitry Andric }
356284c1978SDimitry Andric 
isStackSlotCopy(const MachineInstr & MI,int & DestFrameIndex,int & SrcFrameIndex) const3573ca95b02SDimitry Andric bool SystemZInstrInfo::isStackSlotCopy(const MachineInstr &MI,
358f785676fSDimitry Andric                                        int &DestFrameIndex,
359f785676fSDimitry Andric                                        int &SrcFrameIndex) const {
360f785676fSDimitry Andric   // Check for MVC 0(Length,FI1),0(FI2)
361d88c1a5aSDimitry Andric   const MachineFrameInfo &MFI = MI.getParent()->getParent()->getFrameInfo();
3623ca95b02SDimitry Andric   if (MI.getOpcode() != SystemZ::MVC || !MI.getOperand(0).isFI() ||
3633ca95b02SDimitry Andric       MI.getOperand(1).getImm() != 0 || !MI.getOperand(3).isFI() ||
3643ca95b02SDimitry Andric       MI.getOperand(4).getImm() != 0)
365f785676fSDimitry Andric     return false;
366f785676fSDimitry Andric 
367f785676fSDimitry Andric   // Check that Length covers the full slots.
3683ca95b02SDimitry Andric   int64_t Length = MI.getOperand(2).getImm();
3693ca95b02SDimitry Andric   unsigned FI1 = MI.getOperand(0).getIndex();
3703ca95b02SDimitry Andric   unsigned FI2 = MI.getOperand(3).getIndex();
371d88c1a5aSDimitry Andric   if (MFI.getObjectSize(FI1) != Length ||
372d88c1a5aSDimitry Andric       MFI.getObjectSize(FI2) != Length)
373f785676fSDimitry Andric     return false;
374f785676fSDimitry Andric 
375f785676fSDimitry Andric   DestFrameIndex = FI1;
376f785676fSDimitry Andric   SrcFrameIndex = FI2;
377f785676fSDimitry Andric   return true;
378f785676fSDimitry Andric }
379f785676fSDimitry Andric 
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const3803ca95b02SDimitry Andric bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
381284c1978SDimitry Andric                                      MachineBasicBlock *&TBB,
382284c1978SDimitry Andric                                      MachineBasicBlock *&FBB,
383284c1978SDimitry Andric                                      SmallVectorImpl<MachineOperand> &Cond,
384284c1978SDimitry Andric                                      bool AllowModify) const {
385284c1978SDimitry Andric   // Most of the code and comments here are boilerplate.
386284c1978SDimitry Andric 
387284c1978SDimitry Andric   // Start from the bottom of the block and work up, examining the
388284c1978SDimitry Andric   // terminator instructions.
389284c1978SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
390284c1978SDimitry Andric   while (I != MBB.begin()) {
391284c1978SDimitry Andric     --I;
3924ba319b5SDimitry Andric     if (I->isDebugInstr())
393284c1978SDimitry Andric       continue;
394284c1978SDimitry Andric 
395284c1978SDimitry Andric     // Working from the bottom, when we see a non-terminator instruction, we're
396284c1978SDimitry Andric     // done.
3973ca95b02SDimitry Andric     if (!isUnpredicatedTerminator(*I))
398284c1978SDimitry Andric       break;
399284c1978SDimitry Andric 
400284c1978SDimitry Andric     // A terminator that isn't a branch can't easily be handled by this
401284c1978SDimitry Andric     // analysis.
402f785676fSDimitry Andric     if (!I->isBranch())
403284c1978SDimitry Andric       return true;
404284c1978SDimitry Andric 
405284c1978SDimitry Andric     // Can't handle indirect branches.
4063ca95b02SDimitry Andric     SystemZII::Branch Branch(getBranchInfo(*I));
407f785676fSDimitry Andric     if (!Branch.Target->isMBB())
408284c1978SDimitry Andric       return true;
409284c1978SDimitry Andric 
410f785676fSDimitry Andric     // Punt on compound branches.
411f785676fSDimitry Andric     if (Branch.Type != SystemZII::BranchNormal)
412f785676fSDimitry Andric       return true;
413f785676fSDimitry Andric 
414f785676fSDimitry Andric     if (Branch.CCMask == SystemZ::CCMASK_ANY) {
415284c1978SDimitry Andric       // Handle unconditional branches.
416284c1978SDimitry Andric       if (!AllowModify) {
417f785676fSDimitry Andric         TBB = Branch.Target->getMBB();
418284c1978SDimitry Andric         continue;
419284c1978SDimitry Andric       }
420284c1978SDimitry Andric 
421284c1978SDimitry Andric       // If the block has any instructions after a JMP, delete them.
42291bc56edSDimitry Andric       while (std::next(I) != MBB.end())
42391bc56edSDimitry Andric         std::next(I)->eraseFromParent();
424284c1978SDimitry Andric 
425284c1978SDimitry Andric       Cond.clear();
42691bc56edSDimitry Andric       FBB = nullptr;
427284c1978SDimitry Andric 
428284c1978SDimitry Andric       // Delete the JMP if it's equivalent to a fall-through.
429f785676fSDimitry Andric       if (MBB.isLayoutSuccessor(Branch.Target->getMBB())) {
43091bc56edSDimitry Andric         TBB = nullptr;
431284c1978SDimitry Andric         I->eraseFromParent();
432284c1978SDimitry Andric         I = MBB.end();
433284c1978SDimitry Andric         continue;
434284c1978SDimitry Andric       }
435284c1978SDimitry Andric 
436284c1978SDimitry Andric       // TBB is used to indicate the unconditinal destination.
437f785676fSDimitry Andric       TBB = Branch.Target->getMBB();
438284c1978SDimitry Andric       continue;
439284c1978SDimitry Andric     }
440284c1978SDimitry Andric 
441284c1978SDimitry Andric     // Working from the bottom, handle the first conditional branch.
442284c1978SDimitry Andric     if (Cond.empty()) {
443284c1978SDimitry Andric       // FIXME: add X86-style branch swap
444284c1978SDimitry Andric       FBB = TBB;
445f785676fSDimitry Andric       TBB = Branch.Target->getMBB();
446f785676fSDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCValid));
447f785676fSDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
448284c1978SDimitry Andric       continue;
449284c1978SDimitry Andric     }
450284c1978SDimitry Andric 
451284c1978SDimitry Andric     // Handle subsequent conditional branches.
452f785676fSDimitry Andric     assert(Cond.size() == 2 && TBB && "Should have seen a conditional branch");
453284c1978SDimitry Andric 
454284c1978SDimitry Andric     // Only handle the case where all conditional branches branch to the same
455284c1978SDimitry Andric     // destination.
456f785676fSDimitry Andric     if (TBB != Branch.Target->getMBB())
457284c1978SDimitry Andric       return true;
458284c1978SDimitry Andric 
459284c1978SDimitry Andric     // If the conditions are the same, we can leave them alone.
460f785676fSDimitry Andric     unsigned OldCCValid = Cond[0].getImm();
461f785676fSDimitry Andric     unsigned OldCCMask = Cond[1].getImm();
462f785676fSDimitry Andric     if (OldCCValid == Branch.CCValid && OldCCMask == Branch.CCMask)
463284c1978SDimitry Andric       continue;
464284c1978SDimitry Andric 
465284c1978SDimitry Andric     // FIXME: Try combining conditions like X86 does.  Should be easy on Z!
466f785676fSDimitry Andric     return false;
467284c1978SDimitry Andric   }
468284c1978SDimitry Andric 
469284c1978SDimitry Andric   return false;
470284c1978SDimitry Andric }
471284c1978SDimitry Andric 
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const472d88c1a5aSDimitry Andric unsigned SystemZInstrInfo::removeBranch(MachineBasicBlock &MBB,
473d88c1a5aSDimitry Andric                                         int *BytesRemoved) const {
474d88c1a5aSDimitry Andric   assert(!BytesRemoved && "code size not handled");
475d88c1a5aSDimitry Andric 
476284c1978SDimitry Andric   // Most of the code and comments here are boilerplate.
477284c1978SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
478284c1978SDimitry Andric   unsigned Count = 0;
479284c1978SDimitry Andric 
480284c1978SDimitry Andric   while (I != MBB.begin()) {
481284c1978SDimitry Andric     --I;
4824ba319b5SDimitry Andric     if (I->isDebugInstr())
483284c1978SDimitry Andric       continue;
484f785676fSDimitry Andric     if (!I->isBranch())
485284c1978SDimitry Andric       break;
4863ca95b02SDimitry Andric     if (!getBranchInfo(*I).Target->isMBB())
487284c1978SDimitry Andric       break;
488284c1978SDimitry Andric     // Remove the branch.
489284c1978SDimitry Andric     I->eraseFromParent();
490284c1978SDimitry Andric     I = MBB.end();
491284c1978SDimitry Andric     ++Count;
492284c1978SDimitry Andric   }
493284c1978SDimitry Andric 
494284c1978SDimitry Andric   return Count;
495284c1978SDimitry Andric }
496284c1978SDimitry Andric 
497f785676fSDimitry Andric bool SystemZInstrInfo::
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const498d88c1a5aSDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
499f785676fSDimitry Andric   assert(Cond.size() == 2 && "Invalid condition");
500f785676fSDimitry Andric   Cond[1].setImm(Cond[1].getImm() ^ Cond[0].getImm());
501f785676fSDimitry Andric   return false;
502f785676fSDimitry Andric }
503f785676fSDimitry Andric 
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const504d88c1a5aSDimitry Andric unsigned SystemZInstrInfo::insertBranch(MachineBasicBlock &MBB,
5053ca95b02SDimitry Andric                                         MachineBasicBlock *TBB,
506284c1978SDimitry Andric                                         MachineBasicBlock *FBB,
5078f0fd8f6SDimitry Andric                                         ArrayRef<MachineOperand> Cond,
508d88c1a5aSDimitry Andric                                         const DebugLoc &DL,
509d88c1a5aSDimitry Andric                                         int *BytesAdded) const {
510284c1978SDimitry Andric   // In this function we output 32-bit branches, which should always
511284c1978SDimitry Andric   // have enough range.  They can be shortened and relaxed by later code
512284c1978SDimitry Andric   // in the pipeline, if desired.
513284c1978SDimitry Andric 
514284c1978SDimitry Andric   // Shouldn't be a fall through.
515d88c1a5aSDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
516f785676fSDimitry Andric   assert((Cond.size() == 2 || Cond.size() == 0) &&
517284c1978SDimitry Andric          "SystemZ branch conditions have one component!");
518d88c1a5aSDimitry Andric   assert(!BytesAdded && "code size not handled");
519284c1978SDimitry Andric 
520284c1978SDimitry Andric   if (Cond.empty()) {
521284c1978SDimitry Andric     // Unconditional branch?
522284c1978SDimitry Andric     assert(!FBB && "Unconditional branch with multiple successors!");
523f785676fSDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(TBB);
524284c1978SDimitry Andric     return 1;
525284c1978SDimitry Andric   }
526284c1978SDimitry Andric 
527284c1978SDimitry Andric   // Conditional branch.
528284c1978SDimitry Andric   unsigned Count = 0;
529f785676fSDimitry Andric   unsigned CCValid = Cond[0].getImm();
530f785676fSDimitry Andric   unsigned CCMask = Cond[1].getImm();
531f785676fSDimitry Andric   BuildMI(&MBB, DL, get(SystemZ::BRC))
532f785676fSDimitry Andric     .addImm(CCValid).addImm(CCMask).addMBB(TBB);
533284c1978SDimitry Andric   ++Count;
534284c1978SDimitry Andric 
535284c1978SDimitry Andric   if (FBB) {
536284c1978SDimitry Andric     // Two-way Conditional branch. Insert the second branch.
537f785676fSDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(FBB);
538284c1978SDimitry Andric     ++Count;
539284c1978SDimitry Andric   }
540284c1978SDimitry Andric   return Count;
541284c1978SDimitry Andric }
542284c1978SDimitry Andric 
analyzeCompare(const MachineInstr & MI,unsigned & SrcReg,unsigned & SrcReg2,int & Mask,int & Value) const5433ca95b02SDimitry Andric bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg,
5443ca95b02SDimitry Andric                                       unsigned &SrcReg2, int &Mask,
5453ca95b02SDimitry Andric                                       int &Value) const {
5463ca95b02SDimitry Andric   assert(MI.isCompare() && "Caller should have checked for a comparison");
547f785676fSDimitry Andric 
5483ca95b02SDimitry Andric   if (MI.getNumExplicitOperands() == 2 && MI.getOperand(0).isReg() &&
5493ca95b02SDimitry Andric       MI.getOperand(1).isImm()) {
5503ca95b02SDimitry Andric     SrcReg = MI.getOperand(0).getReg();
551f785676fSDimitry Andric     SrcReg2 = 0;
5523ca95b02SDimitry Andric     Value = MI.getOperand(1).getImm();
553f785676fSDimitry Andric     Mask = ~0;
554f785676fSDimitry Andric     return true;
555f785676fSDimitry Andric   }
556f785676fSDimitry Andric 
557f785676fSDimitry Andric   return false;
558f785676fSDimitry Andric }
559f785676fSDimitry Andric 
canInsertSelect(const MachineBasicBlock & MBB,ArrayRef<MachineOperand> Pred,unsigned TrueReg,unsigned FalseReg,int & CondCycles,int & TrueCycles,int & FalseCycles) const560d88c1a5aSDimitry Andric bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
561d88c1a5aSDimitry Andric                                        ArrayRef<MachineOperand> Pred,
562d88c1a5aSDimitry Andric                                        unsigned TrueReg, unsigned FalseReg,
563d88c1a5aSDimitry Andric                                        int &CondCycles, int &TrueCycles,
564d88c1a5aSDimitry Andric                                        int &FalseCycles) const {
565d88c1a5aSDimitry Andric   // Not all subtargets have LOCR instructions.
566d88c1a5aSDimitry Andric   if (!STI.hasLoadStoreOnCond())
567d88c1a5aSDimitry Andric     return false;
568d88c1a5aSDimitry Andric   if (Pred.size() != 2)
569d88c1a5aSDimitry Andric     return false;
570d88c1a5aSDimitry Andric 
571d88c1a5aSDimitry Andric   // Check register classes.
572d88c1a5aSDimitry Andric   const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
573d88c1a5aSDimitry Andric   const TargetRegisterClass *RC =
574d88c1a5aSDimitry Andric     RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
575d88c1a5aSDimitry Andric   if (!RC)
576d88c1a5aSDimitry Andric     return false;
577d88c1a5aSDimitry Andric 
578d88c1a5aSDimitry Andric   // We have LOCR instructions for 32 and 64 bit general purpose registers.
579d88c1a5aSDimitry Andric   if ((STI.hasLoadStoreOnCond2() &&
580d88c1a5aSDimitry Andric        SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) ||
581d88c1a5aSDimitry Andric       SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
582d88c1a5aSDimitry Andric       SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {
583d88c1a5aSDimitry Andric     CondCycles = 2;
584d88c1a5aSDimitry Andric     TrueCycles = 2;
585d88c1a5aSDimitry Andric     FalseCycles = 2;
586d88c1a5aSDimitry Andric     return true;
587f785676fSDimitry Andric   }
588f785676fSDimitry Andric 
589d88c1a5aSDimitry Andric   // Can't do anything else.
590d88c1a5aSDimitry Andric   return false;
5913ca95b02SDimitry Andric }
592d88c1a5aSDimitry Andric 
insertSelect(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,unsigned DstReg,ArrayRef<MachineOperand> Pred,unsigned TrueReg,unsigned FalseReg) const593d88c1a5aSDimitry Andric void SystemZInstrInfo::insertSelect(MachineBasicBlock &MBB,
594d88c1a5aSDimitry Andric                                     MachineBasicBlock::iterator I,
595d88c1a5aSDimitry Andric                                     const DebugLoc &DL, unsigned DstReg,
596d88c1a5aSDimitry Andric                                     ArrayRef<MachineOperand> Pred,
597d88c1a5aSDimitry Andric                                     unsigned TrueReg,
598d88c1a5aSDimitry Andric                                     unsigned FalseReg) const {
599d88c1a5aSDimitry Andric   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
600d88c1a5aSDimitry Andric   const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
601d88c1a5aSDimitry Andric 
602d88c1a5aSDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
603d88c1a5aSDimitry Andric   unsigned CCValid = Pred[0].getImm();
604d88c1a5aSDimitry Andric   unsigned CCMask = Pred[1].getImm();
605d88c1a5aSDimitry Andric 
606d88c1a5aSDimitry Andric   unsigned Opc;
607d88c1a5aSDimitry Andric   if (SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) {
608d88c1a5aSDimitry Andric     if (STI.hasLoadStoreOnCond2())
609d88c1a5aSDimitry Andric       Opc = SystemZ::LOCRMux;
610d88c1a5aSDimitry Andric     else {
611d88c1a5aSDimitry Andric       Opc = SystemZ::LOCR;
612d88c1a5aSDimitry Andric       MRI.constrainRegClass(DstReg, &SystemZ::GR32BitRegClass);
6137a7e6055SDimitry Andric       unsigned TReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
6147a7e6055SDimitry Andric       unsigned FReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
6157a7e6055SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), TReg).addReg(TrueReg);
6167a7e6055SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), FReg).addReg(FalseReg);
6177a7e6055SDimitry Andric       TrueReg = TReg;
6187a7e6055SDimitry Andric       FalseReg = FReg;
619d88c1a5aSDimitry Andric     }
620d88c1a5aSDimitry Andric   } else if (SystemZ::GR64BitRegClass.hasSubClassEq(RC))
621d88c1a5aSDimitry Andric     Opc = SystemZ::LOCGR;
622d88c1a5aSDimitry Andric   else
623d88c1a5aSDimitry Andric     llvm_unreachable("Invalid register class");
624d88c1a5aSDimitry Andric 
625d88c1a5aSDimitry Andric   BuildMI(MBB, I, DL, get(Opc), DstReg)
626d88c1a5aSDimitry Andric     .addReg(FalseReg).addReg(TrueReg)
627d88c1a5aSDimitry Andric     .addImm(CCValid).addImm(CCMask);
628d88c1a5aSDimitry Andric }
629d88c1a5aSDimitry Andric 
FoldImmediate(MachineInstr & UseMI,MachineInstr & DefMI,unsigned Reg,MachineRegisterInfo * MRI) const630d88c1a5aSDimitry Andric bool SystemZInstrInfo::FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
631d88c1a5aSDimitry Andric                                      unsigned Reg,
632d88c1a5aSDimitry Andric                                      MachineRegisterInfo *MRI) const {
633d88c1a5aSDimitry Andric   unsigned DefOpc = DefMI.getOpcode();
634d88c1a5aSDimitry Andric   if (DefOpc != SystemZ::LHIMux && DefOpc != SystemZ::LHI &&
635d88c1a5aSDimitry Andric       DefOpc != SystemZ::LGHI)
636d88c1a5aSDimitry Andric     return false;
637d88c1a5aSDimitry Andric   if (DefMI.getOperand(0).getReg() != Reg)
638d88c1a5aSDimitry Andric     return false;
639d88c1a5aSDimitry Andric   int32_t ImmVal = (int32_t)DefMI.getOperand(1).getImm();
640d88c1a5aSDimitry Andric 
641d88c1a5aSDimitry Andric   unsigned UseOpc = UseMI.getOpcode();
642d88c1a5aSDimitry Andric   unsigned NewUseOpc;
643d88c1a5aSDimitry Andric   unsigned UseIdx;
644d88c1a5aSDimitry Andric   int CommuteIdx = -1;
645d88c1a5aSDimitry Andric   switch (UseOpc) {
646d88c1a5aSDimitry Andric   case SystemZ::LOCRMux:
647d88c1a5aSDimitry Andric     if (!STI.hasLoadStoreOnCond2())
648d88c1a5aSDimitry Andric       return false;
649d88c1a5aSDimitry Andric     NewUseOpc = SystemZ::LOCHIMux;
650d88c1a5aSDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
651d88c1a5aSDimitry Andric       UseIdx = 2;
652d88c1a5aSDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
653d88c1a5aSDimitry Andric       UseIdx = 2, CommuteIdx = 1;
654d88c1a5aSDimitry Andric     else
655d88c1a5aSDimitry Andric       return false;
656d88c1a5aSDimitry Andric     break;
657d88c1a5aSDimitry Andric   case SystemZ::LOCGR:
658d88c1a5aSDimitry Andric     if (!STI.hasLoadStoreOnCond2())
659d88c1a5aSDimitry Andric       return false;
660d88c1a5aSDimitry Andric     NewUseOpc = SystemZ::LOCGHI;
661d88c1a5aSDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
662d88c1a5aSDimitry Andric       UseIdx = 2;
663d88c1a5aSDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
664d88c1a5aSDimitry Andric       UseIdx = 2, CommuteIdx = 1;
665d88c1a5aSDimitry Andric     else
666d88c1a5aSDimitry Andric       return false;
667d88c1a5aSDimitry Andric     break;
668d88c1a5aSDimitry Andric   default:
669d88c1a5aSDimitry Andric     return false;
670d88c1a5aSDimitry Andric   }
671d88c1a5aSDimitry Andric 
672d88c1a5aSDimitry Andric   if (CommuteIdx != -1)
673d88c1a5aSDimitry Andric     if (!commuteInstruction(UseMI, false, CommuteIdx, UseIdx))
674d88c1a5aSDimitry Andric       return false;
675d88c1a5aSDimitry Andric 
676d88c1a5aSDimitry Andric   bool DeleteDef = MRI->hasOneNonDBGUse(Reg);
677d88c1a5aSDimitry Andric   UseMI.setDesc(get(NewUseOpc));
678d88c1a5aSDimitry Andric   UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);
679d88c1a5aSDimitry Andric   if (DeleteDef)
680d88c1a5aSDimitry Andric     DefMI.eraseFromParent();
681d88c1a5aSDimitry Andric 
682d88c1a5aSDimitry Andric   return true;
6833ca95b02SDimitry Andric }
6843ca95b02SDimitry Andric 
isPredicable(const MachineInstr & MI) const6857a7e6055SDimitry Andric bool SystemZInstrInfo::isPredicable(const MachineInstr &MI) const {
6863ca95b02SDimitry Andric   unsigned Opcode = MI.getOpcode();
6873ca95b02SDimitry Andric   if (Opcode == SystemZ::Return ||
6883ca95b02SDimitry Andric       Opcode == SystemZ::Trap ||
6893ca95b02SDimitry Andric       Opcode == SystemZ::CallJG ||
6903ca95b02SDimitry Andric       Opcode == SystemZ::CallBR)
6913ca95b02SDimitry Andric     return true;
6923ca95b02SDimitry Andric   return false;
693f785676fSDimitry Andric }
694f785676fSDimitry Andric 
695f785676fSDimitry Andric bool SystemZInstrInfo::
isProfitableToIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,unsigned ExtraPredCycles,BranchProbability Probability) const696f785676fSDimitry Andric isProfitableToIfCvt(MachineBasicBlock &MBB,
697f785676fSDimitry Andric                     unsigned NumCycles, unsigned ExtraPredCycles,
6987d523365SDimitry Andric                     BranchProbability Probability) const {
6993ca95b02SDimitry Andric   // Avoid using conditional returns at the end of a loop (since then
7003ca95b02SDimitry Andric   // we'd need to emit an unconditional branch to the beginning anyway,
7013ca95b02SDimitry Andric   // making the loop body longer).  This doesn't apply for low-probability
7023ca95b02SDimitry Andric   // loops (eg. compare-and-swap retry), so just decide based on branch
7033ca95b02SDimitry Andric   // probability instead of looping structure.
7043ca95b02SDimitry Andric   // However, since Compare and Trap instructions cost the same as a regular
7053ca95b02SDimitry Andric   // Compare instruction, we should allow the if conversion to convert this
7063ca95b02SDimitry Andric   // into a Conditional Compare regardless of the branch probability.
7073ca95b02SDimitry Andric   if (MBB.getLastNonDebugInstr()->getOpcode() != SystemZ::Trap &&
7083ca95b02SDimitry Andric       MBB.succ_empty() && Probability < BranchProbability(1, 8))
7093ca95b02SDimitry Andric     return false;
710f785676fSDimitry Andric   // For now only convert single instructions.
711f785676fSDimitry Andric   return NumCycles == 1;
712f785676fSDimitry Andric }
713f785676fSDimitry Andric 
714f785676fSDimitry Andric bool SystemZInstrInfo::
isProfitableToIfCvt(MachineBasicBlock & TMBB,unsigned NumCyclesT,unsigned ExtraPredCyclesT,MachineBasicBlock & FMBB,unsigned NumCyclesF,unsigned ExtraPredCyclesF,BranchProbability Probability) const715f785676fSDimitry Andric isProfitableToIfCvt(MachineBasicBlock &TMBB,
716f785676fSDimitry Andric                     unsigned NumCyclesT, unsigned ExtraPredCyclesT,
717f785676fSDimitry Andric                     MachineBasicBlock &FMBB,
718f785676fSDimitry Andric                     unsigned NumCyclesF, unsigned ExtraPredCyclesF,
7197d523365SDimitry Andric                     BranchProbability Probability) const {
720f785676fSDimitry Andric   // For now avoid converting mutually-exclusive cases.
721f785676fSDimitry Andric   return false;
722f785676fSDimitry Andric }
723f785676fSDimitry Andric 
724f785676fSDimitry Andric bool SystemZInstrInfo::
isProfitableToDupForIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,BranchProbability Probability) const7253ca95b02SDimitry Andric isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
7263ca95b02SDimitry Andric                           BranchProbability Probability) const {
7273ca95b02SDimitry Andric   // For now only duplicate single instructions.
7283ca95b02SDimitry Andric   return NumCycles == 1;
7293ca95b02SDimitry Andric }
7303ca95b02SDimitry Andric 
PredicateInstruction(MachineInstr & MI,ArrayRef<MachineOperand> Pred) const7313ca95b02SDimitry Andric bool SystemZInstrInfo::PredicateInstruction(
7323ca95b02SDimitry Andric     MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {
733f785676fSDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
734f785676fSDimitry Andric   unsigned CCValid = Pred[0].getImm();
735f785676fSDimitry Andric   unsigned CCMask = Pred[1].getImm();
736f785676fSDimitry Andric   assert(CCMask > 0 && CCMask < 15 && "Invalid predicate");
7373ca95b02SDimitry Andric   unsigned Opcode = MI.getOpcode();
7383ca95b02SDimitry Andric   if (Opcode == SystemZ::Trap) {
7393ca95b02SDimitry Andric     MI.setDesc(get(SystemZ::CondTrap));
7403ca95b02SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
741f785676fSDimitry Andric       .addImm(CCValid).addImm(CCMask)
74291bc56edSDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
743f785676fSDimitry Andric     return true;
744f785676fSDimitry Andric   }
7453ca95b02SDimitry Andric   if (Opcode == SystemZ::Return) {
7463ca95b02SDimitry Andric     MI.setDesc(get(SystemZ::CondReturn));
7473ca95b02SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
7483ca95b02SDimitry Andric       .addImm(CCValid).addImm(CCMask)
7493ca95b02SDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
7503ca95b02SDimitry Andric     return true;
7513ca95b02SDimitry Andric   }
7523ca95b02SDimitry Andric   if (Opcode == SystemZ::CallJG) {
7533ca95b02SDimitry Andric     MachineOperand FirstOp = MI.getOperand(0);
7543ca95b02SDimitry Andric     const uint32_t *RegMask = MI.getOperand(1).getRegMask();
7553ca95b02SDimitry Andric     MI.RemoveOperand(1);
7563ca95b02SDimitry Andric     MI.RemoveOperand(0);
7573ca95b02SDimitry Andric     MI.setDesc(get(SystemZ::CallBRCL));
7583ca95b02SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
7597a7e6055SDimitry Andric         .addImm(CCValid)
7607a7e6055SDimitry Andric         .addImm(CCMask)
7617a7e6055SDimitry Andric         .add(FirstOp)
7623ca95b02SDimitry Andric         .addRegMask(RegMask)
7633ca95b02SDimitry Andric         .addReg(SystemZ::CC, RegState::Implicit);
7643ca95b02SDimitry Andric     return true;
7653ca95b02SDimitry Andric   }
7663ca95b02SDimitry Andric   if (Opcode == SystemZ::CallBR) {
7673ca95b02SDimitry Andric     const uint32_t *RegMask = MI.getOperand(0).getRegMask();
7683ca95b02SDimitry Andric     MI.RemoveOperand(0);
7693ca95b02SDimitry Andric     MI.setDesc(get(SystemZ::CallBCR));
7703ca95b02SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
7713ca95b02SDimitry Andric       .addImm(CCValid).addImm(CCMask)
7723ca95b02SDimitry Andric       .addRegMask(RegMask)
7733ca95b02SDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
7743ca95b02SDimitry Andric     return true;
775f785676fSDimitry Andric   }
776f785676fSDimitry Andric   return false;
777f785676fSDimitry Andric }
778f785676fSDimitry Andric 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const7797d523365SDimitry Andric void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
7807d523365SDimitry Andric                                    MachineBasicBlock::iterator MBBI,
7813ca95b02SDimitry Andric                                    const DebugLoc &DL, unsigned DestReg,
7827d523365SDimitry Andric                                    unsigned SrcReg, bool KillSrc) const {
7830f5676f4SDimitry Andric   // Split 128-bit GPR moves into two 64-bit moves. Add implicit uses of the
7840f5676f4SDimitry Andric   // super register in case one of the subregs is undefined.
7850f5676f4SDimitry Andric   // This handles ADDR128 too.
786284c1978SDimitry Andric   if (SystemZ::GR128BitRegClass.contains(DestReg, SrcReg)) {
787f785676fSDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_h64),
788f785676fSDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_h64), KillSrc);
7890f5676f4SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
7900f5676f4SDimitry Andric       .addReg(SrcReg, RegState::Implicit);
791f785676fSDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_l64),
792f785676fSDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_l64), KillSrc);
7930f5676f4SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
7940f5676f4SDimitry Andric       .addReg(SrcReg, (getKillRegState(KillSrc) | RegState::Implicit));
795f785676fSDimitry Andric     return;
796f785676fSDimitry Andric   }
797f785676fSDimitry Andric 
798f785676fSDimitry Andric   if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) {
7997a7e6055SDimitry Andric     emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc,
8007a7e6055SDimitry Andric                   false);
801284c1978SDimitry Andric     return;
802284c1978SDimitry Andric   }
803284c1978SDimitry Andric 
804b40b48b8SDimitry Andric   // Move 128-bit floating-point values between VR128 and FP128.
805b40b48b8SDimitry Andric   if (SystemZ::VR128BitRegClass.contains(DestReg) &&
806b40b48b8SDimitry Andric       SystemZ::FP128BitRegClass.contains(SrcReg)) {
807b40b48b8SDimitry Andric     unsigned SrcRegHi =
808b40b48b8SDimitry Andric       RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64),
809*b5893f02SDimitry Andric                              SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
810b40b48b8SDimitry Andric     unsigned SrcRegLo =
811b40b48b8SDimitry Andric       RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64),
812*b5893f02SDimitry Andric                              SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
813b40b48b8SDimitry Andric 
814b40b48b8SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VMRHG), DestReg)
815b40b48b8SDimitry Andric       .addReg(SrcRegHi, getKillRegState(KillSrc))
816b40b48b8SDimitry Andric       .addReg(SrcRegLo, getKillRegState(KillSrc));
817b40b48b8SDimitry Andric     return;
818b40b48b8SDimitry Andric   }
819b40b48b8SDimitry Andric   if (SystemZ::FP128BitRegClass.contains(DestReg) &&
820b40b48b8SDimitry Andric       SystemZ::VR128BitRegClass.contains(SrcReg)) {
821b40b48b8SDimitry Andric     unsigned DestRegHi =
822b40b48b8SDimitry Andric       RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_h64),
823*b5893f02SDimitry Andric                              SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
824b40b48b8SDimitry Andric     unsigned DestRegLo =
825b40b48b8SDimitry Andric       RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_l64),
826*b5893f02SDimitry Andric                              SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
827b40b48b8SDimitry Andric 
828b40b48b8SDimitry Andric     if (DestRegHi != SrcReg)
829b40b48b8SDimitry Andric       copyPhysReg(MBB, MBBI, DL, DestRegHi, SrcReg, false);
830b40b48b8SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VREPG), DestRegLo)
831b40b48b8SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1);
832b40b48b8SDimitry Andric     return;
833b40b48b8SDimitry Andric   }
834b40b48b8SDimitry Andric 
8354ba319b5SDimitry Andric   // Move CC value from/to a GR32.
8364ba319b5SDimitry Andric   if (SrcReg == SystemZ::CC) {
8374ba319b5SDimitry Andric     auto MIB = BuildMI(MBB, MBBI, DL, get(SystemZ::IPM), DestReg);
8384ba319b5SDimitry Andric     if (KillSrc) {
8394ba319b5SDimitry Andric       const MachineFunction *MF = MBB.getParent();
8404ba319b5SDimitry Andric       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
8414ba319b5SDimitry Andric       MIB->addRegisterKilled(SrcReg, TRI);
8424ba319b5SDimitry Andric     }
8434ba319b5SDimitry Andric     return;
8444ba319b5SDimitry Andric   }
8454ba319b5SDimitry Andric   if (DestReg == SystemZ::CC) {
8464ba319b5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::TMLH))
8474ba319b5SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc))
8484ba319b5SDimitry Andric       .addImm(3 << (SystemZ::IPM_CC - 16));
8494ba319b5SDimitry Andric     return;
8504ba319b5SDimitry Andric   }
8514ba319b5SDimitry Andric 
852284c1978SDimitry Andric   // Everything else needs only one instruction.
853284c1978SDimitry Andric   unsigned Opcode;
854f785676fSDimitry Andric   if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg))
855284c1978SDimitry Andric     Opcode = SystemZ::LGR;
856284c1978SDimitry Andric   else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg))
8573ca95b02SDimitry Andric     // For z13 we prefer LDR over LER to avoid partial register dependencies.
8583ca95b02SDimitry Andric     Opcode = STI.hasVector() ? SystemZ::LDR32 : SystemZ::LER;
859284c1978SDimitry Andric   else if (SystemZ::FP64BitRegClass.contains(DestReg, SrcReg))
860284c1978SDimitry Andric     Opcode = SystemZ::LDR;
861284c1978SDimitry Andric   else if (SystemZ::FP128BitRegClass.contains(DestReg, SrcReg))
862284c1978SDimitry Andric     Opcode = SystemZ::LXR;
863ff0cc061SDimitry Andric   else if (SystemZ::VR32BitRegClass.contains(DestReg, SrcReg))
864ff0cc061SDimitry Andric     Opcode = SystemZ::VLR32;
865ff0cc061SDimitry Andric   else if (SystemZ::VR64BitRegClass.contains(DestReg, SrcReg))
866ff0cc061SDimitry Andric     Opcode = SystemZ::VLR64;
867ff0cc061SDimitry Andric   else if (SystemZ::VR128BitRegClass.contains(DestReg, SrcReg))
868ff0cc061SDimitry Andric     Opcode = SystemZ::VLR;
869d88c1a5aSDimitry Andric   else if (SystemZ::AR32BitRegClass.contains(DestReg, SrcReg))
870d88c1a5aSDimitry Andric     Opcode = SystemZ::CPYA;
871d88c1a5aSDimitry Andric   else if (SystemZ::AR32BitRegClass.contains(DestReg) &&
872d88c1a5aSDimitry Andric            SystemZ::GR32BitRegClass.contains(SrcReg))
873d88c1a5aSDimitry Andric     Opcode = SystemZ::SAR;
874d88c1a5aSDimitry Andric   else if (SystemZ::GR32BitRegClass.contains(DestReg) &&
875d88c1a5aSDimitry Andric            SystemZ::AR32BitRegClass.contains(SrcReg))
876d88c1a5aSDimitry Andric     Opcode = SystemZ::EAR;
877284c1978SDimitry Andric   else
878284c1978SDimitry Andric     llvm_unreachable("Impossible reg-to-reg copy");
879284c1978SDimitry Andric 
880284c1978SDimitry Andric   BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
881284c1978SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc));
882284c1978SDimitry Andric }
883284c1978SDimitry Andric 
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned SrcReg,bool isKill,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const8847d523365SDimitry Andric void SystemZInstrInfo::storeRegToStackSlot(
8857d523365SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg,
8867d523365SDimitry Andric     bool isKill, int FrameIdx, const TargetRegisterClass *RC,
887284c1978SDimitry Andric     const TargetRegisterInfo *TRI) const {
888284c1978SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
889284c1978SDimitry Andric 
890284c1978SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
891284c1978SDimitry Andric   // together for now and lower them after register allocation.
892284c1978SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
893284c1978SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
894284c1978SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))
8957d523365SDimitry Andric                         .addReg(SrcReg, getKillRegState(isKill)),
8967d523365SDimitry Andric                     FrameIdx);
897284c1978SDimitry Andric }
898284c1978SDimitry Andric 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned DestReg,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const8997d523365SDimitry Andric void SystemZInstrInfo::loadRegFromStackSlot(
9007d523365SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg,
9017d523365SDimitry Andric     int FrameIdx, const TargetRegisterClass *RC,
902284c1978SDimitry Andric     const TargetRegisterInfo *TRI) const {
903284c1978SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
904284c1978SDimitry Andric 
905284c1978SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
906284c1978SDimitry Andric   // together for now and lower them after register allocation.
907284c1978SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
908284c1978SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
909284c1978SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg),
910284c1978SDimitry Andric                     FrameIdx);
911284c1978SDimitry Andric }
912284c1978SDimitry Andric 
913f785676fSDimitry Andric // Return true if MI is a simple load or store with a 12-bit displacement
914f785676fSDimitry Andric // and no index.  Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
isSimpleBD12Move(const MachineInstr * MI,unsigned Flag)915f785676fSDimitry Andric static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) {
916f785676fSDimitry Andric   const MCInstrDesc &MCID = MI->getDesc();
917f785676fSDimitry Andric   return ((MCID.TSFlags & Flag) &&
918f785676fSDimitry Andric           isUInt<12>(MI->getOperand(2).getImm()) &&
919f785676fSDimitry Andric           MI->getOperand(3).getReg() == 0);
920f785676fSDimitry Andric }
921f785676fSDimitry Andric 
922f785676fSDimitry Andric namespace {
9237a7e6055SDimitry Andric 
924f785676fSDimitry Andric struct LogicOp {
9257a7e6055SDimitry Andric   LogicOp() = default;
LogicOp__anon5b4df3140211::LogicOp926f785676fSDimitry Andric   LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize)
927f785676fSDimitry Andric     : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {}
928f785676fSDimitry Andric 
operator bool__anon5b4df3140211::LogicOp929ff0cc061SDimitry Andric   explicit operator bool() const { return RegSize; }
930f785676fSDimitry Andric 
9317a7e6055SDimitry Andric   unsigned RegSize = 0;
9327a7e6055SDimitry Andric   unsigned ImmLSB = 0;
9337a7e6055SDimitry Andric   unsigned ImmSize = 0;
934f785676fSDimitry Andric };
9357a7e6055SDimitry Andric 
93691bc56edSDimitry Andric } // end anonymous namespace
937f785676fSDimitry Andric 
interpretAndImmediate(unsigned Opcode)938f785676fSDimitry Andric static LogicOp interpretAndImmediate(unsigned Opcode) {
939f785676fSDimitry Andric   switch (Opcode) {
940f785676fSDimitry Andric   case SystemZ::NILMux: return LogicOp(32,  0, 16);
941f785676fSDimitry Andric   case SystemZ::NIHMux: return LogicOp(32, 16, 16);
942f785676fSDimitry Andric   case SystemZ::NILL64: return LogicOp(64,  0, 16);
943f785676fSDimitry Andric   case SystemZ::NILH64: return LogicOp(64, 16, 16);
944f785676fSDimitry Andric   case SystemZ::NIHL64: return LogicOp(64, 32, 16);
945f785676fSDimitry Andric   case SystemZ::NIHH64: return LogicOp(64, 48, 16);
946f785676fSDimitry Andric   case SystemZ::NIFMux: return LogicOp(32,  0, 32);
947f785676fSDimitry Andric   case SystemZ::NILF64: return LogicOp(64,  0, 32);
948f785676fSDimitry Andric   case SystemZ::NIHF64: return LogicOp(64, 32, 32);
949f785676fSDimitry Andric   default:              return LogicOp();
950f785676fSDimitry Andric   }
951f785676fSDimitry Andric }
952f785676fSDimitry Andric 
transferDeadCC(MachineInstr * OldMI,MachineInstr * NewMI)9533ca95b02SDimitry Andric static void transferDeadCC(MachineInstr *OldMI, MachineInstr *NewMI) {
9543ca95b02SDimitry Andric   if (OldMI->registerDefIsDead(SystemZ::CC)) {
9553ca95b02SDimitry Andric     MachineOperand *CCDef = NewMI->findRegisterDefOperand(SystemZ::CC);
9563ca95b02SDimitry Andric     if (CCDef != nullptr)
9573ca95b02SDimitry Andric       CCDef->setIsDead(true);
9583ca95b02SDimitry Andric   }
9593ca95b02SDimitry Andric }
9603ca95b02SDimitry Andric 
961f785676fSDimitry Andric // Used to return from convertToThreeAddress after replacing two-address
962f785676fSDimitry Andric // instruction OldMI with three-address instruction NewMI.
finishConvertToThreeAddress(MachineInstr * OldMI,MachineInstr * NewMI,LiveVariables * LV)963f785676fSDimitry Andric static MachineInstr *finishConvertToThreeAddress(MachineInstr *OldMI,
964f785676fSDimitry Andric                                                  MachineInstr *NewMI,
965f785676fSDimitry Andric                                                  LiveVariables *LV) {
966f785676fSDimitry Andric   if (LV) {
967f785676fSDimitry Andric     unsigned NumOps = OldMI->getNumOperands();
968f785676fSDimitry Andric     for (unsigned I = 1; I < NumOps; ++I) {
969f785676fSDimitry Andric       MachineOperand &Op = OldMI->getOperand(I);
970f785676fSDimitry Andric       if (Op.isReg() && Op.isKill())
9713ca95b02SDimitry Andric         LV->replaceKillInstruction(Op.getReg(), *OldMI, *NewMI);
972f785676fSDimitry Andric     }
973f785676fSDimitry Andric   }
9743ca95b02SDimitry Andric   transferDeadCC(OldMI, NewMI);
975f785676fSDimitry Andric   return NewMI;
976f785676fSDimitry Andric }
977f785676fSDimitry Andric 
convertToThreeAddress(MachineFunction::iterator & MFI,MachineInstr & MI,LiveVariables * LV) const9783ca95b02SDimitry Andric MachineInstr *SystemZInstrInfo::convertToThreeAddress(
9793ca95b02SDimitry Andric     MachineFunction::iterator &MFI, MachineInstr &MI, LiveVariables *LV) const {
9803ca95b02SDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
9817d523365SDimitry Andric   MachineFunction *MF = MBB->getParent();
9827d523365SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
983f785676fSDimitry Andric 
9843ca95b02SDimitry Andric   unsigned Opcode = MI.getOpcode();
9853ca95b02SDimitry Andric   unsigned NumOps = MI.getNumOperands();
986f785676fSDimitry Andric 
987f785676fSDimitry Andric   // Try to convert something like SLL into SLLK, if supported.
988f785676fSDimitry Andric   // We prefer to keep the two-operand form where possible both
989f785676fSDimitry Andric   // because it tends to be shorter and because some instructions
990f785676fSDimitry Andric   // have memory forms that can be used during spilling.
99191bc56edSDimitry Andric   if (STI.hasDistinctOps()) {
9923ca95b02SDimitry Andric     MachineOperand &Dest = MI.getOperand(0);
9933ca95b02SDimitry Andric     MachineOperand &Src = MI.getOperand(1);
994f785676fSDimitry Andric     unsigned DestReg = Dest.getReg();
995f785676fSDimitry Andric     unsigned SrcReg = Src.getReg();
996f785676fSDimitry Andric     // AHIMux is only really a three-operand instruction when both operands
997f785676fSDimitry Andric     // are low registers.  Try to constrain both operands to be low if
998f785676fSDimitry Andric     // possible.
999f785676fSDimitry Andric     if (Opcode == SystemZ::AHIMux &&
1000f785676fSDimitry Andric         TargetRegisterInfo::isVirtualRegister(DestReg) &&
1001f785676fSDimitry Andric         TargetRegisterInfo::isVirtualRegister(SrcReg) &&
1002f785676fSDimitry Andric         MRI.getRegClass(DestReg)->contains(SystemZ::R1L) &&
1003f785676fSDimitry Andric         MRI.getRegClass(SrcReg)->contains(SystemZ::R1L)) {
1004f785676fSDimitry Andric       MRI.constrainRegClass(DestReg, &SystemZ::GR32BitRegClass);
1005f785676fSDimitry Andric       MRI.constrainRegClass(SrcReg, &SystemZ::GR32BitRegClass);
1006f785676fSDimitry Andric     }
1007f785676fSDimitry Andric     int ThreeOperandOpcode = SystemZ::getThreeOperandOpcode(Opcode);
1008f785676fSDimitry Andric     if (ThreeOperandOpcode >= 0) {
10097d523365SDimitry Andric       // Create three address instruction without adding the implicit
10107d523365SDimitry Andric       // operands. Those will instead be copied over from the original
10117d523365SDimitry Andric       // instruction by the loop below.
10123ca95b02SDimitry Andric       MachineInstrBuilder MIB(
10133ca95b02SDimitry Andric           *MF, MF->CreateMachineInstr(get(ThreeOperandOpcode), MI.getDebugLoc(),
10143ca95b02SDimitry Andric                                       /*NoImplicit=*/true));
10157a7e6055SDimitry Andric       MIB.add(Dest);
1016f785676fSDimitry Andric       // Keep the kill state, but drop the tied flag.
1017f785676fSDimitry Andric       MIB.addReg(Src.getReg(), getKillRegState(Src.isKill()), Src.getSubReg());
1018f785676fSDimitry Andric       // Keep the remaining operands as-is.
1019f785676fSDimitry Andric       for (unsigned I = 2; I < NumOps; ++I)
10207a7e6055SDimitry Andric         MIB.add(MI.getOperand(I));
10217d523365SDimitry Andric       MBB->insert(MI, MIB);
10223ca95b02SDimitry Andric       return finishConvertToThreeAddress(&MI, MIB, LV);
1023f785676fSDimitry Andric     }
1024f785676fSDimitry Andric   }
1025f785676fSDimitry Andric 
1026f785676fSDimitry Andric   // Try to convert an AND into an RISBG-type instruction.
1027f785676fSDimitry Andric   if (LogicOp And = interpretAndImmediate(Opcode)) {
10283ca95b02SDimitry Andric     uint64_t Imm = MI.getOperand(2).getImm() << And.ImmLSB;
1029f785676fSDimitry Andric     // AND IMMEDIATE leaves the other bits of the register unchanged.
1030f785676fSDimitry Andric     Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB);
1031f785676fSDimitry Andric     unsigned Start, End;
1032f785676fSDimitry Andric     if (isRxSBGMask(Imm, And.RegSize, Start, End)) {
1033f785676fSDimitry Andric       unsigned NewOpcode;
1034ff0cc061SDimitry Andric       if (And.RegSize == 64) {
1035f785676fSDimitry Andric         NewOpcode = SystemZ::RISBG;
1036ff0cc061SDimitry Andric         // Prefer RISBGN if available, since it does not clobber CC.
1037ff0cc061SDimitry Andric         if (STI.hasMiscellaneousExtensions())
1038ff0cc061SDimitry Andric           NewOpcode = SystemZ::RISBGN;
1039ff0cc061SDimitry Andric       } else {
1040f785676fSDimitry Andric         NewOpcode = SystemZ::RISBMux;
1041f785676fSDimitry Andric         Start &= 31;
1042f785676fSDimitry Andric         End &= 31;
1043f785676fSDimitry Andric       }
10443ca95b02SDimitry Andric       MachineOperand &Dest = MI.getOperand(0);
10453ca95b02SDimitry Andric       MachineOperand &Src = MI.getOperand(1);
1046f785676fSDimitry Andric       MachineInstrBuilder MIB =
10473ca95b02SDimitry Andric           BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpcode))
10487a7e6055SDimitry Andric               .add(Dest)
10493ca95b02SDimitry Andric               .addReg(0)
10503ca95b02SDimitry Andric               .addReg(Src.getReg(), getKillRegState(Src.isKill()),
10513ca95b02SDimitry Andric                       Src.getSubReg())
10523ca95b02SDimitry Andric               .addImm(Start)
10533ca95b02SDimitry Andric               .addImm(End + 128)
10543ca95b02SDimitry Andric               .addImm(0);
10553ca95b02SDimitry Andric       return finishConvertToThreeAddress(&MI, MIB, LV);
1056f785676fSDimitry Andric     }
1057f785676fSDimitry Andric   }
105891bc56edSDimitry Andric   return nullptr;
1059f785676fSDimitry Andric }
1060f785676fSDimitry Andric 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,int FrameIndex,LiveIntervals * LIS) const106197bc6c73SDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
10623ca95b02SDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
10633ca95b02SDimitry Andric     MachineBasicBlock::iterator InsertPt, int FrameIndex,
10643ca95b02SDimitry Andric     LiveIntervals *LIS) const {
10653ca95b02SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1066d88c1a5aSDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1067d88c1a5aSDimitry Andric   unsigned Size = MFI.getObjectSize(FrameIndex);
10683ca95b02SDimitry Andric   unsigned Opcode = MI.getOpcode();
1069f785676fSDimitry Andric 
1070f785676fSDimitry Andric   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
10713ca95b02SDimitry Andric     if (LIS != nullptr && (Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&
10723ca95b02SDimitry Andric         isInt<8>(MI.getOperand(2).getImm()) && !MI.getOperand(3).getReg()) {
10733ca95b02SDimitry Andric 
10743ca95b02SDimitry Andric       // Check CC liveness, since new instruction introduces a dead
10753ca95b02SDimitry Andric       // def of CC.
10763ca95b02SDimitry Andric       MCRegUnitIterator CCUnit(SystemZ::CC, TRI);
10773ca95b02SDimitry Andric       LiveRange &CCLiveRange = LIS->getRegUnit(*CCUnit);
10783ca95b02SDimitry Andric       ++CCUnit;
10793ca95b02SDimitry Andric       assert(!CCUnit.isValid() && "CC only has one reg unit.");
10803ca95b02SDimitry Andric       SlotIndex MISlot =
10813ca95b02SDimitry Andric           LIS->getSlotIndexes()->getInstructionIndex(MI).getRegSlot();
10823ca95b02SDimitry Andric       if (!CCLiveRange.liveAt(MISlot)) {
1083f785676fSDimitry Andric         // LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST
10843ca95b02SDimitry Andric         MachineInstr *BuiltMI = BuildMI(*InsertPt->getParent(), InsertPt,
10853ca95b02SDimitry Andric                                         MI.getDebugLoc(), get(SystemZ::AGSI))
108697bc6c73SDimitry Andric                                     .addFrameIndex(FrameIndex)
108797bc6c73SDimitry Andric                                     .addImm(0)
10883ca95b02SDimitry Andric                                     .addImm(MI.getOperand(2).getImm());
10893ca95b02SDimitry Andric         BuiltMI->findRegisterDefOperand(SystemZ::CC)->setIsDead(true);
10903ca95b02SDimitry Andric         CCLiveRange.createDeadDef(MISlot, LIS->getVNInfoAllocator());
10913ca95b02SDimitry Andric         return BuiltMI;
10923ca95b02SDimitry Andric       }
1093f785676fSDimitry Andric     }
109491bc56edSDimitry Andric     return nullptr;
1095f785676fSDimitry Andric   }
1096f785676fSDimitry Andric 
1097f785676fSDimitry Andric   // All other cases require a single operand.
1098f785676fSDimitry Andric   if (Ops.size() != 1)
109991bc56edSDimitry Andric     return nullptr;
1100f785676fSDimitry Andric 
1101f785676fSDimitry Andric   unsigned OpNum = Ops[0];
110251690af2SDimitry Andric   assert(Size * 8 ==
110351690af2SDimitry Andric            TRI->getRegSizeInBits(*MF.getRegInfo()
110451690af2SDimitry Andric                                .getRegClass(MI.getOperand(OpNum).getReg())) &&
1105f785676fSDimitry Andric          "Invalid size combination");
1106f785676fSDimitry Andric 
11073ca95b02SDimitry Andric   if ((Opcode == SystemZ::AHI || Opcode == SystemZ::AGHI) && OpNum == 0 &&
11083ca95b02SDimitry Andric       isInt<8>(MI.getOperand(2).getImm())) {
1109f785676fSDimitry Andric     // A(G)HI %reg, CONST -> A(G)SI %mem, CONST
1110f785676fSDimitry Andric     Opcode = (Opcode == SystemZ::AHI ? SystemZ::ASI : SystemZ::AGSI);
11113ca95b02SDimitry Andric     MachineInstr *BuiltMI =
11123ca95b02SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
111397bc6c73SDimitry Andric             .addFrameIndex(FrameIndex)
111497bc6c73SDimitry Andric             .addImm(0)
11153ca95b02SDimitry Andric             .addImm(MI.getOperand(2).getImm());
11163ca95b02SDimitry Andric     transferDeadCC(&MI, BuiltMI);
11173ca95b02SDimitry Andric     return BuiltMI;
1118f785676fSDimitry Andric   }
1119f785676fSDimitry Andric 
11204ba319b5SDimitry Andric   if ((Opcode == SystemZ::ALFI && OpNum == 0 &&
11214ba319b5SDimitry Andric        isInt<8>((int32_t)MI.getOperand(2).getImm())) ||
11224ba319b5SDimitry Andric       (Opcode == SystemZ::ALGFI && OpNum == 0 &&
11234ba319b5SDimitry Andric        isInt<8>((int64_t)MI.getOperand(2).getImm()))) {
11244ba319b5SDimitry Andric     // AL(G)FI %reg, CONST -> AL(G)SI %mem, CONST
11254ba319b5SDimitry Andric     Opcode = (Opcode == SystemZ::ALFI ? SystemZ::ALSI : SystemZ::ALGSI);
11264ba319b5SDimitry Andric     MachineInstr *BuiltMI =
11274ba319b5SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
11284ba319b5SDimitry Andric             .addFrameIndex(FrameIndex)
11294ba319b5SDimitry Andric             .addImm(0)
11304ba319b5SDimitry Andric             .addImm((int8_t)MI.getOperand(2).getImm());
11314ba319b5SDimitry Andric     transferDeadCC(&MI, BuiltMI);
11324ba319b5SDimitry Andric     return BuiltMI;
11334ba319b5SDimitry Andric   }
11344ba319b5SDimitry Andric 
11354ba319b5SDimitry Andric   if ((Opcode == SystemZ::SLFI && OpNum == 0 &&
11364ba319b5SDimitry Andric        isInt<8>((int32_t)-MI.getOperand(2).getImm())) ||
11374ba319b5SDimitry Andric       (Opcode == SystemZ::SLGFI && OpNum == 0 &&
11384ba319b5SDimitry Andric        isInt<8>((int64_t)-MI.getOperand(2).getImm()))) {
11394ba319b5SDimitry Andric     // SL(G)FI %reg, CONST -> AL(G)SI %mem, -CONST
11404ba319b5SDimitry Andric     Opcode = (Opcode == SystemZ::SLFI ? SystemZ::ALSI : SystemZ::ALGSI);
11414ba319b5SDimitry Andric     MachineInstr *BuiltMI =
11424ba319b5SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
11434ba319b5SDimitry Andric             .addFrameIndex(FrameIndex)
11444ba319b5SDimitry Andric             .addImm(0)
11454ba319b5SDimitry Andric             .addImm((int8_t)-MI.getOperand(2).getImm());
11464ba319b5SDimitry Andric     transferDeadCC(&MI, BuiltMI);
11474ba319b5SDimitry Andric     return BuiltMI;
11484ba319b5SDimitry Andric   }
11494ba319b5SDimitry Andric 
1150f785676fSDimitry Andric   if (Opcode == SystemZ::LGDR || Opcode == SystemZ::LDGR) {
1151f785676fSDimitry Andric     bool Op0IsGPR = (Opcode == SystemZ::LGDR);
1152f785676fSDimitry Andric     bool Op1IsGPR = (Opcode == SystemZ::LDGR);
1153f785676fSDimitry Andric     // If we're spilling the destination of an LDGR or LGDR, store the
1154f785676fSDimitry Andric     // source register instead.
1155f785676fSDimitry Andric     if (OpNum == 0) {
1156f785676fSDimitry Andric       unsigned StoreOpcode = Op1IsGPR ? SystemZ::STG : SystemZ::STD;
11573ca95b02SDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
115897bc6c73SDimitry Andric                      get(StoreOpcode))
11597a7e6055SDimitry Andric           .add(MI.getOperand(1))
116097bc6c73SDimitry Andric           .addFrameIndex(FrameIndex)
116197bc6c73SDimitry Andric           .addImm(0)
116297bc6c73SDimitry Andric           .addReg(0);
1163f785676fSDimitry Andric     }
1164f785676fSDimitry Andric     // If we're spilling the source of an LDGR or LGDR, load the
1165f785676fSDimitry Andric     // destination register instead.
1166f785676fSDimitry Andric     if (OpNum == 1) {
1167f785676fSDimitry Andric       unsigned LoadOpcode = Op0IsGPR ? SystemZ::LG : SystemZ::LD;
11683ca95b02SDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
11697a7e6055SDimitry Andric                      get(LoadOpcode))
11707a7e6055SDimitry Andric         .add(MI.getOperand(0))
117197bc6c73SDimitry Andric         .addFrameIndex(FrameIndex)
117297bc6c73SDimitry Andric         .addImm(0)
117397bc6c73SDimitry Andric         .addReg(0);
1174f785676fSDimitry Andric     }
1175f785676fSDimitry Andric   }
1176f785676fSDimitry Andric 
1177f785676fSDimitry Andric   // Look for cases where the source of a simple store or the destination
1178f785676fSDimitry Andric   // of a simple load is being spilled.  Try to use MVC instead.
1179f785676fSDimitry Andric   //
1180f785676fSDimitry Andric   // Although MVC is in practice a fast choice in these cases, it is still
1181f785676fSDimitry Andric   // logically a bytewise copy.  This means that we cannot use it if the
1182f785676fSDimitry Andric   // load or store is volatile.  We also wouldn't be able to use MVC if
1183f785676fSDimitry Andric   // the two memories partially overlap, but that case cannot occur here,
1184f785676fSDimitry Andric   // because we know that one of the memories is a full frame index.
1185f785676fSDimitry Andric   //
1186f785676fSDimitry Andric   // For performance reasons, we also want to avoid using MVC if the addresses
1187f785676fSDimitry Andric   // might be equal.  We don't worry about that case here, because spill slot
1188f785676fSDimitry Andric   // coloring happens later, and because we have special code to remove
1189f785676fSDimitry Andric   // MVCs that turn out to be redundant.
11903ca95b02SDimitry Andric   if (OpNum == 0 && MI.hasOneMemOperand()) {
11913ca95b02SDimitry Andric     MachineMemOperand *MMO = *MI.memoperands_begin();
1192f785676fSDimitry Andric     if (MMO->getSize() == Size && !MMO->isVolatile()) {
1193f785676fSDimitry Andric       // Handle conversion of loads.
11943ca95b02SDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXLoad)) {
11953ca95b02SDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
119697bc6c73SDimitry Andric                        get(SystemZ::MVC))
119797bc6c73SDimitry Andric             .addFrameIndex(FrameIndex)
119897bc6c73SDimitry Andric             .addImm(0)
119997bc6c73SDimitry Andric             .addImm(Size)
12007a7e6055SDimitry Andric             .add(MI.getOperand(1))
12013ca95b02SDimitry Andric             .addImm(MI.getOperand(2).getImm())
1202f785676fSDimitry Andric             .addMemOperand(MMO);
1203f785676fSDimitry Andric       }
1204f785676fSDimitry Andric       // Handle conversion of stores.
12053ca95b02SDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXStore)) {
12063ca95b02SDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
120797bc6c73SDimitry Andric                        get(SystemZ::MVC))
12087a7e6055SDimitry Andric             .add(MI.getOperand(1))
12093ca95b02SDimitry Andric             .addImm(MI.getOperand(2).getImm())
121097bc6c73SDimitry Andric             .addImm(Size)
121197bc6c73SDimitry Andric             .addFrameIndex(FrameIndex)
121297bc6c73SDimitry Andric             .addImm(0)
1213f785676fSDimitry Andric             .addMemOperand(MMO);
1214f785676fSDimitry Andric       }
1215f785676fSDimitry Andric     }
1216f785676fSDimitry Andric   }
1217f785676fSDimitry Andric 
1218f785676fSDimitry Andric   // If the spilled operand is the final one, try to change <INSN>R
1219f785676fSDimitry Andric   // into <INSN>.
1220f785676fSDimitry Andric   int MemOpcode = SystemZ::getMemOpcode(Opcode);
1221f785676fSDimitry Andric   if (MemOpcode >= 0) {
12223ca95b02SDimitry Andric     unsigned NumOps = MI.getNumExplicitOperands();
1223f785676fSDimitry Andric     if (OpNum == NumOps - 1) {
1224f785676fSDimitry Andric       const MCInstrDesc &MemDesc = get(MemOpcode);
1225f785676fSDimitry Andric       uint64_t AccessBytes = SystemZII::getAccessSize(MemDesc.TSFlags);
1226f785676fSDimitry Andric       assert(AccessBytes != 0 && "Size of access should be known");
1227f785676fSDimitry Andric       assert(AccessBytes <= Size && "Access outside the frame index");
1228f785676fSDimitry Andric       uint64_t Offset = Size - AccessBytes;
122997bc6c73SDimitry Andric       MachineInstrBuilder MIB = BuildMI(*InsertPt->getParent(), InsertPt,
12303ca95b02SDimitry Andric                                         MI.getDebugLoc(), get(MemOpcode));
1231f785676fSDimitry Andric       for (unsigned I = 0; I < OpNum; ++I)
12327a7e6055SDimitry Andric         MIB.add(MI.getOperand(I));
1233f785676fSDimitry Andric       MIB.addFrameIndex(FrameIndex).addImm(Offset);
1234f785676fSDimitry Andric       if (MemDesc.TSFlags & SystemZII::HasIndex)
1235f785676fSDimitry Andric         MIB.addReg(0);
12363ca95b02SDimitry Andric       transferDeadCC(&MI, MIB);
1237f785676fSDimitry Andric       return MIB;
1238f785676fSDimitry Andric     }
1239f785676fSDimitry Andric   }
1240f785676fSDimitry Andric 
124191bc56edSDimitry Andric   return nullptr;
1242f785676fSDimitry Andric }
1243f785676fSDimitry Andric 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,MachineInstr & LoadMI,LiveIntervals * LIS) const124497bc6c73SDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
12453ca95b02SDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
12463ca95b02SDimitry Andric     MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
12473ca95b02SDimitry Andric     LiveIntervals *LIS) const {
124891bc56edSDimitry Andric   return nullptr;
1249f785676fSDimitry Andric }
1250f785676fSDimitry Andric 
expandPostRAPseudo(MachineInstr & MI) const12513ca95b02SDimitry Andric bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
12523ca95b02SDimitry Andric   switch (MI.getOpcode()) {
1253284c1978SDimitry Andric   case SystemZ::L128:
1254284c1978SDimitry Andric     splitMove(MI, SystemZ::LG);
1255284c1978SDimitry Andric     return true;
1256284c1978SDimitry Andric 
1257284c1978SDimitry Andric   case SystemZ::ST128:
1258284c1978SDimitry Andric     splitMove(MI, SystemZ::STG);
1259284c1978SDimitry Andric     return true;
1260284c1978SDimitry Andric 
1261284c1978SDimitry Andric   case SystemZ::LX:
1262284c1978SDimitry Andric     splitMove(MI, SystemZ::LD);
1263284c1978SDimitry Andric     return true;
1264284c1978SDimitry Andric 
1265284c1978SDimitry Andric   case SystemZ::STX:
1266284c1978SDimitry Andric     splitMove(MI, SystemZ::STD);
1267284c1978SDimitry Andric     return true;
1268284c1978SDimitry Andric 
1269f785676fSDimitry Andric   case SystemZ::LBMux:
1270f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::LB, SystemZ::LBH);
1271f785676fSDimitry Andric     return true;
1272f785676fSDimitry Andric 
1273f785676fSDimitry Andric   case SystemZ::LHMux:
1274f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::LH, SystemZ::LHH);
1275f785676fSDimitry Andric     return true;
1276f785676fSDimitry Andric 
1277f785676fSDimitry Andric   case SystemZ::LLCRMux:
1278f785676fSDimitry Andric     expandZExtPseudo(MI, SystemZ::LLCR, 8);
1279f785676fSDimitry Andric     return true;
1280f785676fSDimitry Andric 
1281f785676fSDimitry Andric   case SystemZ::LLHRMux:
1282f785676fSDimitry Andric     expandZExtPseudo(MI, SystemZ::LLHR, 16);
1283f785676fSDimitry Andric     return true;
1284f785676fSDimitry Andric 
1285f785676fSDimitry Andric   case SystemZ::LLCMux:
1286f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::LLC, SystemZ::LLCH);
1287f785676fSDimitry Andric     return true;
1288f785676fSDimitry Andric 
1289f785676fSDimitry Andric   case SystemZ::LLHMux:
1290f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::LLH, SystemZ::LLHH);
1291f785676fSDimitry Andric     return true;
1292f785676fSDimitry Andric 
1293f785676fSDimitry Andric   case SystemZ::LMux:
1294f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::L, SystemZ::LFH);
1295f785676fSDimitry Andric     return true;
1296f785676fSDimitry Andric 
1297d88c1a5aSDimitry Andric   case SystemZ::LOCMux:
1298d88c1a5aSDimitry Andric     expandLOCPseudo(MI, SystemZ::LOC, SystemZ::LOCFH);
1299d88c1a5aSDimitry Andric     return true;
1300d88c1a5aSDimitry Andric 
1301d88c1a5aSDimitry Andric   case SystemZ::LOCHIMux:
1302d88c1a5aSDimitry Andric     expandLOCPseudo(MI, SystemZ::LOCHI, SystemZ::LOCHHI);
1303d88c1a5aSDimitry Andric     return true;
1304d88c1a5aSDimitry Andric 
1305d88c1a5aSDimitry Andric   case SystemZ::LOCRMux:
1306d88c1a5aSDimitry Andric     expandLOCRPseudo(MI, SystemZ::LOCR, SystemZ::LOCFHR);
1307d88c1a5aSDimitry Andric     return true;
1308d88c1a5aSDimitry Andric 
1309f785676fSDimitry Andric   case SystemZ::STCMux:
1310f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::STC, SystemZ::STCH);
1311f785676fSDimitry Andric     return true;
1312f785676fSDimitry Andric 
1313f785676fSDimitry Andric   case SystemZ::STHMux:
1314f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::STH, SystemZ::STHH);
1315f785676fSDimitry Andric     return true;
1316f785676fSDimitry Andric 
1317f785676fSDimitry Andric   case SystemZ::STMux:
1318f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH);
1319f785676fSDimitry Andric     return true;
1320f785676fSDimitry Andric 
1321d88c1a5aSDimitry Andric   case SystemZ::STOCMux:
1322d88c1a5aSDimitry Andric     expandLOCPseudo(MI, SystemZ::STOC, SystemZ::STOCFH);
1323d88c1a5aSDimitry Andric     return true;
1324d88c1a5aSDimitry Andric 
1325f785676fSDimitry Andric   case SystemZ::LHIMux:
1326f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::LHI, SystemZ::IIHF, true);
1327f785676fSDimitry Andric     return true;
1328f785676fSDimitry Andric 
1329f785676fSDimitry Andric   case SystemZ::IIFMux:
1330f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false);
1331f785676fSDimitry Andric     return true;
1332f785676fSDimitry Andric 
1333f785676fSDimitry Andric   case SystemZ::IILMux:
1334f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::IILL, SystemZ::IIHL, false);
1335f785676fSDimitry Andric     return true;
1336f785676fSDimitry Andric 
1337f785676fSDimitry Andric   case SystemZ::IIHMux:
1338f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false);
1339f785676fSDimitry Andric     return true;
1340f785676fSDimitry Andric 
1341f785676fSDimitry Andric   case SystemZ::NIFMux:
1342f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::NILF, SystemZ::NIHF, false);
1343f785676fSDimitry Andric     return true;
1344f785676fSDimitry Andric 
1345f785676fSDimitry Andric   case SystemZ::NILMux:
1346f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::NILL, SystemZ::NIHL, false);
1347f785676fSDimitry Andric     return true;
1348f785676fSDimitry Andric 
1349f785676fSDimitry Andric   case SystemZ::NIHMux:
1350f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::NILH, SystemZ::NIHH, false);
1351f785676fSDimitry Andric     return true;
1352f785676fSDimitry Andric 
1353f785676fSDimitry Andric   case SystemZ::OIFMux:
1354f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::OILF, SystemZ::OIHF, false);
1355f785676fSDimitry Andric     return true;
1356f785676fSDimitry Andric 
1357f785676fSDimitry Andric   case SystemZ::OILMux:
1358f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::OILL, SystemZ::OIHL, false);
1359f785676fSDimitry Andric     return true;
1360f785676fSDimitry Andric 
1361f785676fSDimitry Andric   case SystemZ::OIHMux:
1362f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::OILH, SystemZ::OIHH, false);
1363f785676fSDimitry Andric     return true;
1364f785676fSDimitry Andric 
1365f785676fSDimitry Andric   case SystemZ::XIFMux:
1366f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::XILF, SystemZ::XIHF, false);
1367f785676fSDimitry Andric     return true;
1368f785676fSDimitry Andric 
1369f785676fSDimitry Andric   case SystemZ::TMLMux:
1370f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::TMLL, SystemZ::TMHL, false);
1371f785676fSDimitry Andric     return true;
1372f785676fSDimitry Andric 
1373f785676fSDimitry Andric   case SystemZ::TMHMux:
1374f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::TMLH, SystemZ::TMHH, false);
1375f785676fSDimitry Andric     return true;
1376f785676fSDimitry Andric 
1377f785676fSDimitry Andric   case SystemZ::AHIMux:
1378f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::AHI, SystemZ::AIH, false);
1379f785676fSDimitry Andric     return true;
1380f785676fSDimitry Andric 
1381f785676fSDimitry Andric   case SystemZ::AHIMuxK:
1382f785676fSDimitry Andric     expandRIEPseudo(MI, SystemZ::AHI, SystemZ::AHIK, SystemZ::AIH);
1383f785676fSDimitry Andric     return true;
1384f785676fSDimitry Andric 
1385f785676fSDimitry Andric   case SystemZ::AFIMux:
1386f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false);
1387f785676fSDimitry Andric     return true;
1388f785676fSDimitry Andric 
1389d88c1a5aSDimitry Andric   case SystemZ::CHIMux:
1390d88c1a5aSDimitry Andric     expandRIPseudo(MI, SystemZ::CHI, SystemZ::CIH, false);
1391d88c1a5aSDimitry Andric     return true;
1392d88c1a5aSDimitry Andric 
1393f785676fSDimitry Andric   case SystemZ::CFIMux:
1394f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false);
1395f785676fSDimitry Andric     return true;
1396f785676fSDimitry Andric 
1397f785676fSDimitry Andric   case SystemZ::CLFIMux:
1398f785676fSDimitry Andric     expandRIPseudo(MI, SystemZ::CLFI, SystemZ::CLIH, false);
1399f785676fSDimitry Andric     return true;
1400f785676fSDimitry Andric 
1401f785676fSDimitry Andric   case SystemZ::CMux:
1402f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::C, SystemZ::CHF);
1403f785676fSDimitry Andric     return true;
1404f785676fSDimitry Andric 
1405f785676fSDimitry Andric   case SystemZ::CLMux:
1406f785676fSDimitry Andric     expandRXYPseudo(MI, SystemZ::CL, SystemZ::CLHF);
1407f785676fSDimitry Andric     return true;
1408f785676fSDimitry Andric 
1409f785676fSDimitry Andric   case SystemZ::RISBMux: {
14103ca95b02SDimitry Andric     bool DestIsHigh = isHighReg(MI.getOperand(0).getReg());
14113ca95b02SDimitry Andric     bool SrcIsHigh = isHighReg(MI.getOperand(2).getReg());
1412f785676fSDimitry Andric     if (SrcIsHigh == DestIsHigh)
14133ca95b02SDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHH : SystemZ::RISBLL));
1414f785676fSDimitry Andric     else {
14153ca95b02SDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHL : SystemZ::RISBLH));
14163ca95b02SDimitry Andric       MI.getOperand(5).setImm(MI.getOperand(5).getImm() ^ 32);
1417f785676fSDimitry Andric     }
1418f785676fSDimitry Andric     return true;
1419f785676fSDimitry Andric   }
1420f785676fSDimitry Andric 
1421284c1978SDimitry Andric   case SystemZ::ADJDYNALLOC:
1422284c1978SDimitry Andric     splitAdjDynAlloc(MI);
1423284c1978SDimitry Andric     return true;
1424284c1978SDimitry Andric 
14253ca95b02SDimitry Andric   case TargetOpcode::LOAD_STACK_GUARD:
14263ca95b02SDimitry Andric     expandLoadStackGuard(&MI);
14273ca95b02SDimitry Andric     return true;
14283ca95b02SDimitry Andric 
1429284c1978SDimitry Andric   default:
1430284c1978SDimitry Andric     return false;
1431284c1978SDimitry Andric   }
1432284c1978SDimitry Andric }
1433284c1978SDimitry Andric 
getInstSizeInBytes(const MachineInstr & MI) const1434d88c1a5aSDimitry Andric unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
14353ca95b02SDimitry Andric   if (MI.getOpcode() == TargetOpcode::INLINEASM) {
14363ca95b02SDimitry Andric     const MachineFunction *MF = MI.getParent()->getParent();
14373ca95b02SDimitry Andric     const char *AsmStr = MI.getOperand(0).getSymbolName();
1438f785676fSDimitry Andric     return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
1439f785676fSDimitry Andric   }
14403ca95b02SDimitry Andric   return MI.getDesc().getSize();
1441284c1978SDimitry Andric }
1442284c1978SDimitry Andric 
1443f785676fSDimitry Andric SystemZII::Branch
getBranchInfo(const MachineInstr & MI) const14443ca95b02SDimitry Andric SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {
14453ca95b02SDimitry Andric   switch (MI.getOpcode()) {
1446284c1978SDimitry Andric   case SystemZ::BR:
1447b40b48b8SDimitry Andric   case SystemZ::BI:
1448284c1978SDimitry Andric   case SystemZ::J:
1449284c1978SDimitry Andric   case SystemZ::JG:
1450f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
14513ca95b02SDimitry Andric                              SystemZ::CCMASK_ANY, &MI.getOperand(0));
1452284c1978SDimitry Andric 
1453284c1978SDimitry Andric   case SystemZ::BRC:
1454284c1978SDimitry Andric   case SystemZ::BRCL:
14553ca95b02SDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, MI.getOperand(0).getImm(),
14563ca95b02SDimitry Andric                              MI.getOperand(1).getImm(), &MI.getOperand(2));
1457f785676fSDimitry Andric 
1458f785676fSDimitry Andric   case SystemZ::BRCT:
1459d88c1a5aSDimitry Andric   case SystemZ::BRCTH:
1460f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchCT, SystemZ::CCMASK_ICMP,
14613ca95b02SDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
1462f785676fSDimitry Andric 
1463f785676fSDimitry Andric   case SystemZ::BRCTG:
1464f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchCTG, SystemZ::CCMASK_ICMP,
14653ca95b02SDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
1466f785676fSDimitry Andric 
1467f785676fSDimitry Andric   case SystemZ::CIJ:
1468f785676fSDimitry Andric   case SystemZ::CRJ:
1469f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchC, SystemZ::CCMASK_ICMP,
14703ca95b02SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1471f785676fSDimitry Andric 
1472f785676fSDimitry Andric   case SystemZ::CLIJ:
1473f785676fSDimitry Andric   case SystemZ::CLRJ:
1474f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchCL, SystemZ::CCMASK_ICMP,
14753ca95b02SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1476f785676fSDimitry Andric 
1477f785676fSDimitry Andric   case SystemZ::CGIJ:
1478f785676fSDimitry Andric   case SystemZ::CGRJ:
1479f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchCG, SystemZ::CCMASK_ICMP,
14803ca95b02SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1481f785676fSDimitry Andric 
1482f785676fSDimitry Andric   case SystemZ::CLGIJ:
1483f785676fSDimitry Andric   case SystemZ::CLGRJ:
1484f785676fSDimitry Andric     return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP,
14853ca95b02SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1486284c1978SDimitry Andric 
1487284c1978SDimitry Andric   default:
1488f785676fSDimitry Andric     llvm_unreachable("Unrecognized branch opcode");
1489284c1978SDimitry Andric   }
1490284c1978SDimitry Andric }
1491284c1978SDimitry Andric 
getLoadStoreOpcodes(const TargetRegisterClass * RC,unsigned & LoadOpcode,unsigned & StoreOpcode) const1492284c1978SDimitry Andric void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
1493284c1978SDimitry Andric                                            unsigned &LoadOpcode,
1494284c1978SDimitry Andric                                            unsigned &StoreOpcode) const {
1495284c1978SDimitry Andric   if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {
1496284c1978SDimitry Andric     LoadOpcode = SystemZ::L;
1497f785676fSDimitry Andric     StoreOpcode = SystemZ::ST;
1498f785676fSDimitry Andric   } else if (RC == &SystemZ::GRH32BitRegClass) {
1499f785676fSDimitry Andric     LoadOpcode = SystemZ::LFH;
1500f785676fSDimitry Andric     StoreOpcode = SystemZ::STFH;
1501f785676fSDimitry Andric   } else if (RC == &SystemZ::GRX32BitRegClass) {
1502f785676fSDimitry Andric     LoadOpcode = SystemZ::LMux;
1503f785676fSDimitry Andric     StoreOpcode = SystemZ::STMux;
1504284c1978SDimitry Andric   } else if (RC == &SystemZ::GR64BitRegClass ||
1505284c1978SDimitry Andric              RC == &SystemZ::ADDR64BitRegClass) {
1506284c1978SDimitry Andric     LoadOpcode = SystemZ::LG;
1507284c1978SDimitry Andric     StoreOpcode = SystemZ::STG;
1508284c1978SDimitry Andric   } else if (RC == &SystemZ::GR128BitRegClass ||
1509284c1978SDimitry Andric              RC == &SystemZ::ADDR128BitRegClass) {
1510284c1978SDimitry Andric     LoadOpcode = SystemZ::L128;
1511284c1978SDimitry Andric     StoreOpcode = SystemZ::ST128;
1512284c1978SDimitry Andric   } else if (RC == &SystemZ::FP32BitRegClass) {
1513284c1978SDimitry Andric     LoadOpcode = SystemZ::LE;
1514284c1978SDimitry Andric     StoreOpcode = SystemZ::STE;
1515284c1978SDimitry Andric   } else if (RC == &SystemZ::FP64BitRegClass) {
1516284c1978SDimitry Andric     LoadOpcode = SystemZ::LD;
1517284c1978SDimitry Andric     StoreOpcode = SystemZ::STD;
1518284c1978SDimitry Andric   } else if (RC == &SystemZ::FP128BitRegClass) {
1519284c1978SDimitry Andric     LoadOpcode = SystemZ::LX;
1520284c1978SDimitry Andric     StoreOpcode = SystemZ::STX;
1521ff0cc061SDimitry Andric   } else if (RC == &SystemZ::VR32BitRegClass) {
1522ff0cc061SDimitry Andric     LoadOpcode = SystemZ::VL32;
1523ff0cc061SDimitry Andric     StoreOpcode = SystemZ::VST32;
1524ff0cc061SDimitry Andric   } else if (RC == &SystemZ::VR64BitRegClass) {
1525ff0cc061SDimitry Andric     LoadOpcode = SystemZ::VL64;
1526ff0cc061SDimitry Andric     StoreOpcode = SystemZ::VST64;
1527ff0cc061SDimitry Andric   } else if (RC == &SystemZ::VF128BitRegClass ||
1528ff0cc061SDimitry Andric              RC == &SystemZ::VR128BitRegClass) {
1529ff0cc061SDimitry Andric     LoadOpcode = SystemZ::VL;
1530ff0cc061SDimitry Andric     StoreOpcode = SystemZ::VST;
1531284c1978SDimitry Andric   } else
1532284c1978SDimitry Andric     llvm_unreachable("Unsupported regclass to load or store");
1533284c1978SDimitry Andric }
1534284c1978SDimitry Andric 
getOpcodeForOffset(unsigned Opcode,int64_t Offset) const1535284c1978SDimitry Andric unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
1536284c1978SDimitry Andric                                               int64_t Offset) const {
1537284c1978SDimitry Andric   const MCInstrDesc &MCID = get(Opcode);
1538284c1978SDimitry Andric   int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);
1539284c1978SDimitry Andric   if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {
1540284c1978SDimitry Andric     // Get the instruction to use for unsigned 12-bit displacements.
1541284c1978SDimitry Andric     int Disp12Opcode = SystemZ::getDisp12Opcode(Opcode);
1542284c1978SDimitry Andric     if (Disp12Opcode >= 0)
1543284c1978SDimitry Andric       return Disp12Opcode;
1544284c1978SDimitry Andric 
1545284c1978SDimitry Andric     // All address-related instructions can use unsigned 12-bit
1546284c1978SDimitry Andric     // displacements.
1547284c1978SDimitry Andric     return Opcode;
1548284c1978SDimitry Andric   }
1549284c1978SDimitry Andric   if (isInt<20>(Offset) && isInt<20>(Offset2)) {
1550284c1978SDimitry Andric     // Get the instruction to use for signed 20-bit displacements.
1551284c1978SDimitry Andric     int Disp20Opcode = SystemZ::getDisp20Opcode(Opcode);
1552284c1978SDimitry Andric     if (Disp20Opcode >= 0)
1553284c1978SDimitry Andric       return Disp20Opcode;
1554284c1978SDimitry Andric 
1555284c1978SDimitry Andric     // Check whether Opcode allows signed 20-bit displacements.
1556284c1978SDimitry Andric     if (MCID.TSFlags & SystemZII::Has20BitOffset)
1557284c1978SDimitry Andric       return Opcode;
1558284c1978SDimitry Andric   }
1559284c1978SDimitry Andric   return 0;
1560284c1978SDimitry Andric }
1561284c1978SDimitry Andric 
getLoadAndTest(unsigned Opcode) const1562f785676fSDimitry Andric unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
1563f785676fSDimitry Andric   switch (Opcode) {
1564f785676fSDimitry Andric   case SystemZ::L:      return SystemZ::LT;
1565f785676fSDimitry Andric   case SystemZ::LY:     return SystemZ::LT;
1566f785676fSDimitry Andric   case SystemZ::LG:     return SystemZ::LTG;
1567f785676fSDimitry Andric   case SystemZ::LGF:    return SystemZ::LTGF;
1568f785676fSDimitry Andric   case SystemZ::LR:     return SystemZ::LTR;
1569f785676fSDimitry Andric   case SystemZ::LGFR:   return SystemZ::LTGFR;
1570f785676fSDimitry Andric   case SystemZ::LGR:    return SystemZ::LTGR;
1571f785676fSDimitry Andric   case SystemZ::LER:    return SystemZ::LTEBR;
1572f785676fSDimitry Andric   case SystemZ::LDR:    return SystemZ::LTDBR;
1573f785676fSDimitry Andric   case SystemZ::LXR:    return SystemZ::LTXBR;
15747d523365SDimitry Andric   case SystemZ::LCDFR:  return SystemZ::LCDBR;
15757d523365SDimitry Andric   case SystemZ::LPDFR:  return SystemZ::LPDBR;
15767d523365SDimitry Andric   case SystemZ::LNDFR:  return SystemZ::LNDBR;
15777d523365SDimitry Andric   case SystemZ::LCDFR_32:  return SystemZ::LCEBR;
15787d523365SDimitry Andric   case SystemZ::LPDFR_32:  return SystemZ::LPEBR;
15797d523365SDimitry Andric   case SystemZ::LNDFR_32:  return SystemZ::LNEBR;
1580ff0cc061SDimitry Andric   // On zEC12 we prefer to use RISBGN.  But if there is a chance to
1581ff0cc061SDimitry Andric   // actually use the condition code, we may turn it back into RISGB.
1582ff0cc061SDimitry Andric   // Note that RISBG is not really a "load-and-test" instruction,
1583ff0cc061SDimitry Andric   // but sets the same condition code values, so is OK to use here.
1584ff0cc061SDimitry Andric   case SystemZ::RISBGN: return SystemZ::RISBG;
1585f785676fSDimitry Andric   default:              return 0;
1586f785676fSDimitry Andric   }
1587f785676fSDimitry Andric }
1588f785676fSDimitry Andric 
1589f785676fSDimitry Andric // Return true if Mask matches the regexp 0*1+0*, given that zero masks
1590f785676fSDimitry Andric // have already been filtered out.  Store the first set bit in LSB and
1591f785676fSDimitry Andric // the number of set bits in Length if so.
isStringOfOnes(uint64_t Mask,unsigned & LSB,unsigned & Length)1592f785676fSDimitry Andric static bool isStringOfOnes(uint64_t Mask, unsigned &LSB, unsigned &Length) {
1593f785676fSDimitry Andric   unsigned First = findFirstSet(Mask);
1594f785676fSDimitry Andric   uint64_t Top = (Mask >> First) + 1;
1595f785676fSDimitry Andric   if ((Top & -Top) == Top) {
1596f785676fSDimitry Andric     LSB = First;
1597f785676fSDimitry Andric     Length = findFirstSet(Top);
1598f785676fSDimitry Andric     return true;
1599f785676fSDimitry Andric   }
1600f785676fSDimitry Andric   return false;
1601f785676fSDimitry Andric }
1602f785676fSDimitry Andric 
isRxSBGMask(uint64_t Mask,unsigned BitSize,unsigned & Start,unsigned & End) const1603f785676fSDimitry Andric bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
1604f785676fSDimitry Andric                                    unsigned &Start, unsigned &End) const {
1605f785676fSDimitry Andric   // Reject trivial all-zero masks.
1606ff0cc061SDimitry Andric   Mask &= allOnes(BitSize);
1607f785676fSDimitry Andric   if (Mask == 0)
1608f785676fSDimitry Andric     return false;
1609f785676fSDimitry Andric 
1610f785676fSDimitry Andric   // Handle the 1+0+ or 0+1+0* cases.  Start then specifies the index of
1611f785676fSDimitry Andric   // the msb and End specifies the index of the lsb.
1612f785676fSDimitry Andric   unsigned LSB, Length;
1613f785676fSDimitry Andric   if (isStringOfOnes(Mask, LSB, Length)) {
1614f785676fSDimitry Andric     Start = 63 - (LSB + Length - 1);
1615f785676fSDimitry Andric     End = 63 - LSB;
1616f785676fSDimitry Andric     return true;
1617f785676fSDimitry Andric   }
1618f785676fSDimitry Andric 
1619f785676fSDimitry Andric   // Handle the wrap-around 1+0+1+ cases.  Start then specifies the msb
1620f785676fSDimitry Andric   // of the low 1s and End specifies the lsb of the high 1s.
1621f785676fSDimitry Andric   if (isStringOfOnes(Mask ^ allOnes(BitSize), LSB, Length)) {
1622f785676fSDimitry Andric     assert(LSB > 0 && "Bottom bit must be set");
1623f785676fSDimitry Andric     assert(LSB + Length < BitSize && "Top bit must be set");
1624f785676fSDimitry Andric     Start = 63 - (LSB - 1);
1625f785676fSDimitry Andric     End = 63 - (LSB + Length);
1626f785676fSDimitry Andric     return true;
1627f785676fSDimitry Andric   }
1628f785676fSDimitry Andric 
1629f785676fSDimitry Andric   return false;
1630f785676fSDimitry Andric }
1631f785676fSDimitry Andric 
getFusedCompare(unsigned Opcode,SystemZII::FusedCompareType Type,const MachineInstr * MI) const16323ca95b02SDimitry Andric unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
16333ca95b02SDimitry Andric                                            SystemZII::FusedCompareType Type,
1634f785676fSDimitry Andric                                            const MachineInstr *MI) const {
1635f785676fSDimitry Andric   switch (Opcode) {
16363ca95b02SDimitry Andric   case SystemZ::CHI:
16373ca95b02SDimitry Andric   case SystemZ::CGHI:
16383ca95b02SDimitry Andric     if (!(MI && isInt<8>(MI->getOperand(1).getImm())))
16393ca95b02SDimitry Andric       return 0;
16403ca95b02SDimitry Andric     break;
16413ca95b02SDimitry Andric   case SystemZ::CLFI:
16423ca95b02SDimitry Andric   case SystemZ::CLGFI:
16433ca95b02SDimitry Andric     if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
16443ca95b02SDimitry Andric       return 0;
1645d88c1a5aSDimitry Andric     break;
1646d88c1a5aSDimitry Andric   case SystemZ::CL:
1647d88c1a5aSDimitry Andric   case SystemZ::CLG:
1648d88c1a5aSDimitry Andric     if (!STI.hasMiscellaneousExtensions())
1649d88c1a5aSDimitry Andric       return 0;
1650d88c1a5aSDimitry Andric     if (!(MI && MI->getOperand(3).getReg() == 0))
1651d88c1a5aSDimitry Andric       return 0;
1652d88c1a5aSDimitry Andric     break;
16533ca95b02SDimitry Andric   }
16543ca95b02SDimitry Andric   switch (Type) {
16553ca95b02SDimitry Andric   case SystemZII::CompareAndBranch:
16563ca95b02SDimitry Andric     switch (Opcode) {
1657f785676fSDimitry Andric     case SystemZ::CR:
1658f785676fSDimitry Andric       return SystemZ::CRJ;
1659f785676fSDimitry Andric     case SystemZ::CGR:
1660f785676fSDimitry Andric       return SystemZ::CGRJ;
1661f785676fSDimitry Andric     case SystemZ::CHI:
16623ca95b02SDimitry Andric       return SystemZ::CIJ;
1663f785676fSDimitry Andric     case SystemZ::CGHI:
16643ca95b02SDimitry Andric       return SystemZ::CGIJ;
1665f785676fSDimitry Andric     case SystemZ::CLR:
1666f785676fSDimitry Andric       return SystemZ::CLRJ;
1667f785676fSDimitry Andric     case SystemZ::CLGR:
1668f785676fSDimitry Andric       return SystemZ::CLGRJ;
1669f785676fSDimitry Andric     case SystemZ::CLFI:
16703ca95b02SDimitry Andric       return SystemZ::CLIJ;
1671f785676fSDimitry Andric     case SystemZ::CLGFI:
16723ca95b02SDimitry Andric       return SystemZ::CLGIJ;
1673f785676fSDimitry Andric     default:
1674f785676fSDimitry Andric       return 0;
1675f785676fSDimitry Andric     }
16763ca95b02SDimitry Andric   case SystemZII::CompareAndReturn:
16773ca95b02SDimitry Andric     switch (Opcode) {
16783ca95b02SDimitry Andric     case SystemZ::CR:
16793ca95b02SDimitry Andric       return SystemZ::CRBReturn;
16803ca95b02SDimitry Andric     case SystemZ::CGR:
16813ca95b02SDimitry Andric       return SystemZ::CGRBReturn;
16823ca95b02SDimitry Andric     case SystemZ::CHI:
16833ca95b02SDimitry Andric       return SystemZ::CIBReturn;
16843ca95b02SDimitry Andric     case SystemZ::CGHI:
16853ca95b02SDimitry Andric       return SystemZ::CGIBReturn;
16863ca95b02SDimitry Andric     case SystemZ::CLR:
16873ca95b02SDimitry Andric       return SystemZ::CLRBReturn;
16883ca95b02SDimitry Andric     case SystemZ::CLGR:
16893ca95b02SDimitry Andric       return SystemZ::CLGRBReturn;
16903ca95b02SDimitry Andric     case SystemZ::CLFI:
16913ca95b02SDimitry Andric       return SystemZ::CLIBReturn;
16923ca95b02SDimitry Andric     case SystemZ::CLGFI:
16933ca95b02SDimitry Andric       return SystemZ::CLGIBReturn;
16943ca95b02SDimitry Andric     default:
16953ca95b02SDimitry Andric       return 0;
16963ca95b02SDimitry Andric     }
16973ca95b02SDimitry Andric   case SystemZII::CompareAndSibcall:
16983ca95b02SDimitry Andric     switch (Opcode) {
16993ca95b02SDimitry Andric     case SystemZ::CR:
17003ca95b02SDimitry Andric       return SystemZ::CRBCall;
17013ca95b02SDimitry Andric     case SystemZ::CGR:
17023ca95b02SDimitry Andric       return SystemZ::CGRBCall;
17033ca95b02SDimitry Andric     case SystemZ::CHI:
17043ca95b02SDimitry Andric       return SystemZ::CIBCall;
17053ca95b02SDimitry Andric     case SystemZ::CGHI:
17063ca95b02SDimitry Andric       return SystemZ::CGIBCall;
17073ca95b02SDimitry Andric     case SystemZ::CLR:
17083ca95b02SDimitry Andric       return SystemZ::CLRBCall;
17093ca95b02SDimitry Andric     case SystemZ::CLGR:
17103ca95b02SDimitry Andric       return SystemZ::CLGRBCall;
17113ca95b02SDimitry Andric     case SystemZ::CLFI:
17123ca95b02SDimitry Andric       return SystemZ::CLIBCall;
17133ca95b02SDimitry Andric     case SystemZ::CLGFI:
17143ca95b02SDimitry Andric       return SystemZ::CLGIBCall;
17153ca95b02SDimitry Andric     default:
17163ca95b02SDimitry Andric       return 0;
17173ca95b02SDimitry Andric     }
17183ca95b02SDimitry Andric   case SystemZII::CompareAndTrap:
17193ca95b02SDimitry Andric     switch (Opcode) {
17203ca95b02SDimitry Andric     case SystemZ::CR:
17213ca95b02SDimitry Andric       return SystemZ::CRT;
17223ca95b02SDimitry Andric     case SystemZ::CGR:
17233ca95b02SDimitry Andric       return SystemZ::CGRT;
17243ca95b02SDimitry Andric     case SystemZ::CHI:
17253ca95b02SDimitry Andric       return SystemZ::CIT;
17263ca95b02SDimitry Andric     case SystemZ::CGHI:
17273ca95b02SDimitry Andric       return SystemZ::CGIT;
17283ca95b02SDimitry Andric     case SystemZ::CLR:
17293ca95b02SDimitry Andric       return SystemZ::CLRT;
17303ca95b02SDimitry Andric     case SystemZ::CLGR:
17313ca95b02SDimitry Andric       return SystemZ::CLGRT;
17323ca95b02SDimitry Andric     case SystemZ::CLFI:
17333ca95b02SDimitry Andric       return SystemZ::CLFIT;
17343ca95b02SDimitry Andric     case SystemZ::CLGFI:
17353ca95b02SDimitry Andric       return SystemZ::CLGIT;
1736d88c1a5aSDimitry Andric     case SystemZ::CL:
1737d88c1a5aSDimitry Andric       return SystemZ::CLT;
1738d88c1a5aSDimitry Andric     case SystemZ::CLG:
1739d88c1a5aSDimitry Andric       return SystemZ::CLGT;
17403ca95b02SDimitry Andric     default:
17413ca95b02SDimitry Andric       return 0;
17423ca95b02SDimitry Andric     }
17433ca95b02SDimitry Andric   }
17443ca95b02SDimitry Andric   return 0;
1745f785676fSDimitry Andric }
1746f785676fSDimitry Andric 
getLoadAndTrap(unsigned Opcode) const1747d88c1a5aSDimitry Andric unsigned SystemZInstrInfo::getLoadAndTrap(unsigned Opcode) const {
1748d88c1a5aSDimitry Andric   if (!STI.hasLoadAndTrap())
1749d88c1a5aSDimitry Andric     return 0;
1750d88c1a5aSDimitry Andric   switch (Opcode) {
1751d88c1a5aSDimitry Andric   case SystemZ::L:
1752d88c1a5aSDimitry Andric   case SystemZ::LY:
1753d88c1a5aSDimitry Andric     return SystemZ::LAT;
1754d88c1a5aSDimitry Andric   case SystemZ::LG:
1755d88c1a5aSDimitry Andric     return SystemZ::LGAT;
1756d88c1a5aSDimitry Andric   case SystemZ::LFH:
1757d88c1a5aSDimitry Andric     return SystemZ::LFHAT;
1758d88c1a5aSDimitry Andric   case SystemZ::LLGF:
1759d88c1a5aSDimitry Andric     return SystemZ::LLGFAT;
1760d88c1a5aSDimitry Andric   case SystemZ::LLGT:
1761d88c1a5aSDimitry Andric     return SystemZ::LLGTAT;
1762d88c1a5aSDimitry Andric   }
1763d88c1a5aSDimitry Andric   return 0;
1764d88c1a5aSDimitry Andric }
1765d88c1a5aSDimitry Andric 
loadImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Reg,uint64_t Value) const1766284c1978SDimitry Andric void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
1767284c1978SDimitry Andric                                      MachineBasicBlock::iterator MBBI,
1768284c1978SDimitry Andric                                      unsigned Reg, uint64_t Value) const {
1769284c1978SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
1770284c1978SDimitry Andric   unsigned Opcode;
1771284c1978SDimitry Andric   if (isInt<16>(Value))
1772284c1978SDimitry Andric     Opcode = SystemZ::LGHI;
1773284c1978SDimitry Andric   else if (SystemZ::isImmLL(Value))
1774284c1978SDimitry Andric     Opcode = SystemZ::LLILL;
1775284c1978SDimitry Andric   else if (SystemZ::isImmLH(Value)) {
1776284c1978SDimitry Andric     Opcode = SystemZ::LLILH;
1777284c1978SDimitry Andric     Value >>= 16;
1778284c1978SDimitry Andric   } else {
1779284c1978SDimitry Andric     assert(isInt<32>(Value) && "Huge values not handled yet");
1780284c1978SDimitry Andric     Opcode = SystemZ::LGFI;
1781284c1978SDimitry Andric   }
1782284c1978SDimitry Andric   BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);
1783284c1978SDimitry Andric }
1784d88c1a5aSDimitry Andric 
1785d88c1a5aSDimitry Andric bool SystemZInstrInfo::
areMemAccessesTriviallyDisjoint(MachineInstr & MIa,MachineInstr & MIb,AliasAnalysis * AA) const1786d88c1a5aSDimitry Andric areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
1787d88c1a5aSDimitry Andric                                 AliasAnalysis *AA) const {
1788d88c1a5aSDimitry Andric 
1789d88c1a5aSDimitry Andric   if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand())
1790d88c1a5aSDimitry Andric     return false;
1791d88c1a5aSDimitry Andric 
1792d88c1a5aSDimitry Andric   // If mem-operands show that the same address Value is used by both
1793d88c1a5aSDimitry Andric   // instructions, check for non-overlapping offsets and widths. Not
1794d88c1a5aSDimitry Andric   // sure if a register based analysis would be an improvement...
1795d88c1a5aSDimitry Andric 
1796d88c1a5aSDimitry Andric   MachineMemOperand *MMOa = *MIa.memoperands_begin();
1797d88c1a5aSDimitry Andric   MachineMemOperand *MMOb = *MIb.memoperands_begin();
1798d88c1a5aSDimitry Andric   const Value *VALa = MMOa->getValue();
1799d88c1a5aSDimitry Andric   const Value *VALb = MMOb->getValue();
1800d88c1a5aSDimitry Andric   bool SameVal = (VALa && VALb && (VALa == VALb));
1801d88c1a5aSDimitry Andric   if (!SameVal) {
1802d88c1a5aSDimitry Andric     const PseudoSourceValue *PSVa = MMOa->getPseudoValue();
1803d88c1a5aSDimitry Andric     const PseudoSourceValue *PSVb = MMOb->getPseudoValue();
1804d88c1a5aSDimitry Andric     if (PSVa && PSVb && (PSVa == PSVb))
1805d88c1a5aSDimitry Andric       SameVal = true;
1806d88c1a5aSDimitry Andric   }
1807d88c1a5aSDimitry Andric   if (SameVal) {
1808d88c1a5aSDimitry Andric     int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset();
1809d88c1a5aSDimitry Andric     int WidthA = MMOa->getSize(), WidthB = MMOb->getSize();
1810d88c1a5aSDimitry Andric     int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1811d88c1a5aSDimitry Andric     int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1812d88c1a5aSDimitry Andric     int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1813d88c1a5aSDimitry Andric     if (LowOffset + LowWidth <= HighOffset)
1814d88c1a5aSDimitry Andric       return true;
1815d88c1a5aSDimitry Andric   }
1816d88c1a5aSDimitry Andric 
1817d88c1a5aSDimitry Andric   return false;
1818d88c1a5aSDimitry Andric }
1819