xref: /src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
159d6cff9SDimitry Andric //===-- SystemZInstrInfo.cpp - SystemZ instruction information ------------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric //
959d6cff9SDimitry Andric // This file contains the SystemZ implementation of the TargetInstrInfo class.
1059d6cff9SDimitry Andric //
1159d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
1259d6cff9SDimitry Andric 
137ab83427SDimitry Andric #include "SystemZInstrInfo.h"
1471d5a254SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
1571d5a254SDimitry Andric #include "SystemZ.h"
1659d6cff9SDimitry Andric #include "SystemZInstrBuilder.h"
1771d5a254SDimitry Andric #include "SystemZSubtarget.h"
18044eb2f6SDimitry Andric #include "llvm/ADT/Statistic.h"
1971d5a254SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
20044eb2f6SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
21ac9a064cSDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
2271d5a254SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
2371d5a254SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
2471d5a254SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
2571d5a254SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
2671d5a254SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
2771d5a254SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
2871d5a254SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
29f8af5cf6SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
3071d5a254SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
31c0981da4SDimitry Andric #include "llvm/CodeGen/StackMaps.h"
32044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
33044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
34145449b1SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
3571d5a254SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
3671d5a254SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
3771d5a254SDimitry Andric #include "llvm/Support/BranchProbability.h"
3871d5a254SDimitry Andric #include "llvm/Support/ErrorHandling.h"
3971d5a254SDimitry Andric #include "llvm/Support/MathExtras.h"
4071d5a254SDimitry Andric #include "llvm/Target/TargetMachine.h"
4171d5a254SDimitry Andric #include <cassert>
4271d5a254SDimitry Andric #include <cstdint>
4371d5a254SDimitry Andric #include <iterator>
4459d6cff9SDimitry Andric 
455ca98fd9SDimitry Andric using namespace llvm;
465ca98fd9SDimitry Andric 
47f8af5cf6SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
4859d6cff9SDimitry Andric #define GET_INSTRMAP_INFO
4959d6cff9SDimitry Andric #include "SystemZGenInstrInfo.inc"
5059d6cff9SDimitry Andric 
51044eb2f6SDimitry Andric #define DEBUG_TYPE "systemz-II"
52044eb2f6SDimitry Andric 
53f8af5cf6SDimitry Andric // Return a mask with Count low bits set.
allOnes(unsigned int Count)54f8af5cf6SDimitry Andric static uint64_t allOnes(unsigned int Count) {
55f8af5cf6SDimitry Andric   return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;
56f8af5cf6SDimitry Andric }
57f8af5cf6SDimitry Andric 
58f8af5cf6SDimitry Andric // Pin the vtable to this file.
anchor()59f8af5cf6SDimitry Andric void SystemZInstrInfo::anchor() {}
60f8af5cf6SDimitry Andric 
SystemZInstrInfo(SystemZSubtarget & sti)615ca98fd9SDimitry Andric SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti)
62ac9a064cSDimitry Andric     : SystemZGenInstrInfo(-1, -1),
63344a3780SDimitry Andric       RI(sti.getSpecialRegisters()->getReturnFunctionAddressRegister()),
64344a3780SDimitry Andric       STI(sti) {}
6559d6cff9SDimitry Andric 
6659d6cff9SDimitry Andric // MI is a 128-bit load or store.  Split it into two 64-bit loads or stores,
6759d6cff9SDimitry Andric // each having the opcode given by NewOpcode.
splitMove(MachineBasicBlock::iterator MI,unsigned NewOpcode) const6859d6cff9SDimitry Andric void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,
6959d6cff9SDimitry Andric                                  unsigned NewOpcode) const {
7059d6cff9SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
7159d6cff9SDimitry Andric   MachineFunction &MF = *MBB->getParent();
7259d6cff9SDimitry Andric 
73ac9a064cSDimitry Andric   // Get two load or store instructions.  Use the original instruction for
74ac9a064cSDimitry Andric   // one of them and create a clone for the other.
75ac9a064cSDimitry Andric   MachineInstr *HighPartMI = MF.CloneMachineInstr(&*MI);
76ac9a064cSDimitry Andric   MachineInstr *LowPartMI = &*MI;
77ac9a064cSDimitry Andric   MBB->insert(LowPartMI, HighPartMI);
7859d6cff9SDimitry Andric 
7971d5a254SDimitry Andric   // Set up the two 64-bit registers and remember super reg and its flags.
80ac9a064cSDimitry Andric   MachineOperand &HighRegOp = HighPartMI->getOperand(0);
81ac9a064cSDimitry Andric   MachineOperand &LowRegOp = LowPartMI->getOperand(0);
821d5ae102SDimitry Andric   Register Reg128 = LowRegOp.getReg();
8371d5a254SDimitry Andric   unsigned Reg128Killed = getKillRegState(LowRegOp.isKill());
8471d5a254SDimitry Andric   unsigned Reg128Undef  = getUndefRegState(LowRegOp.isUndef());
85f8af5cf6SDimitry Andric   HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64));
86f8af5cf6SDimitry Andric   LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64));
8759d6cff9SDimitry Andric 
8859d6cff9SDimitry Andric   // The address in the first (high) instruction is already correct.
8959d6cff9SDimitry Andric   // Adjust the offset in the second (low) instruction.
90ac9a064cSDimitry Andric   MachineOperand &HighOffsetOp = HighPartMI->getOperand(2);
91ac9a064cSDimitry Andric   MachineOperand &LowOffsetOp = LowPartMI->getOperand(2);
9259d6cff9SDimitry Andric   LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);
9359d6cff9SDimitry Andric 
9459d6cff9SDimitry Andric   // Set the opcodes.
9559d6cff9SDimitry Andric   unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());
9659d6cff9SDimitry Andric   unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());
9759d6cff9SDimitry Andric   assert(HighOpcode && LowOpcode && "Both offsets should be in range");
98ac9a064cSDimitry Andric   HighPartMI->setDesc(get(HighOpcode));
99ac9a064cSDimitry Andric   LowPartMI->setDesc(get(LowOpcode));
10059d6cff9SDimitry Andric 
101ac9a064cSDimitry Andric   MachineInstr *FirstMI = HighPartMI;
102ac9a064cSDimitry Andric   if (MI->mayStore()) {
103ac9a064cSDimitry Andric     FirstMI->getOperand(0).setIsKill(false);
104ac9a064cSDimitry Andric     // Add implicit uses of the super register in case one of the subregs is
105ac9a064cSDimitry Andric     // undefined. We could track liveness and skip storing an undefined
106ac9a064cSDimitry Andric     // subreg, but this is hopefully rare (discovered with llvm-stress).
107ac9a064cSDimitry Andric     // If Reg128 was killed, set kill flag on MI.
108ac9a064cSDimitry Andric     unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);
109ac9a064cSDimitry Andric     MachineInstrBuilder(MF, HighPartMI).addReg(Reg128, Reg128UndefImpl);
110ac9a064cSDimitry Andric     MachineInstrBuilder(MF, LowPartMI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));
111ac9a064cSDimitry Andric   } else {
112ac9a064cSDimitry Andric     // If HighPartMI clobbers any of the address registers, it needs to come
113ac9a064cSDimitry Andric     // after LowPartMI.
114ac9a064cSDimitry Andric     auto overlapsAddressReg = [&](Register Reg) -> bool {
115ac9a064cSDimitry Andric       return RI.regsOverlap(Reg, MI->getOperand(1).getReg()) ||
116ac9a064cSDimitry Andric              RI.regsOverlap(Reg, MI->getOperand(3).getReg());
117ac9a064cSDimitry Andric     };
118ac9a064cSDimitry Andric     if (overlapsAddressReg(HighRegOp.getReg())) {
119ac9a064cSDimitry Andric       assert(!overlapsAddressReg(LowRegOp.getReg()) &&
120ac9a064cSDimitry Andric              "Both loads clobber address!");
121ac9a064cSDimitry Andric       MBB->splice(HighPartMI, MBB, LowPartMI);
122ac9a064cSDimitry Andric       FirstMI = LowPartMI;
123ac9a064cSDimitry Andric     }
124ac9a064cSDimitry Andric   }
125ac9a064cSDimitry Andric 
126ac9a064cSDimitry Andric   // Clear the kill flags on the address registers in the first instruction.
127ac9a064cSDimitry Andric   FirstMI->getOperand(1).setIsKill(false);
128ac9a064cSDimitry Andric   FirstMI->getOperand(3).setIsKill(false);
12959d6cff9SDimitry Andric }
13059d6cff9SDimitry Andric 
13159d6cff9SDimitry Andric // Split ADJDYNALLOC instruction MI.
splitAdjDynAlloc(MachineBasicBlock::iterator MI) const13259d6cff9SDimitry Andric void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {
13359d6cff9SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
13459d6cff9SDimitry Andric   MachineFunction &MF = *MBB->getParent();
135b915e9e0SDimitry Andric   MachineFrameInfo &MFFrame = MF.getFrameInfo();
13659d6cff9SDimitry Andric   MachineOperand &OffsetMO = MI->getOperand(2);
137145449b1SDimitry Andric   SystemZCallingConventionRegisters *Regs = STI.getSpecialRegisters();
13859d6cff9SDimitry Andric 
139b915e9e0SDimitry Andric   uint64_t Offset = (MFFrame.getMaxCallFrameSize() +
140145449b1SDimitry Andric                      Regs->getCallFrameSize() +
141145449b1SDimitry Andric                      Regs->getStackPointerBias() +
14259d6cff9SDimitry Andric                      OffsetMO.getImm());
14359d6cff9SDimitry Andric   unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);
14459d6cff9SDimitry Andric   assert(NewOpcode && "No support for huge argument lists yet");
14559d6cff9SDimitry Andric   MI->setDesc(get(NewOpcode));
14659d6cff9SDimitry Andric   OffsetMO.setImm(Offset);
14759d6cff9SDimitry Andric }
14859d6cff9SDimitry Andric 
149f8af5cf6SDimitry Andric // MI is an RI-style pseudo instruction.  Replace it with LowOpcode
150f8af5cf6SDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
151f8af5cf6SDimitry Andric // is a high GR32.  ConvertHigh is true if LowOpcode takes a signed operand
152f8af5cf6SDimitry Andric // and HighOpcode takes an unsigned 32-bit operand.  In those cases,
153f8af5cf6SDimitry Andric // MI has the same kind of operand as LowOpcode, so needs to be converted
154f8af5cf6SDimitry Andric // if HighOpcode is used.
expandRIPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode,bool ConvertHigh) const15501095a5dSDimitry Andric void SystemZInstrInfo::expandRIPseudo(MachineInstr &MI, unsigned LowOpcode,
156f8af5cf6SDimitry Andric                                       unsigned HighOpcode,
157f8af5cf6SDimitry Andric                                       bool ConvertHigh) const {
1581d5ae102SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
1591d5ae102SDimitry Andric   bool IsHigh = SystemZ::isHighReg(Reg);
16001095a5dSDimitry Andric   MI.setDesc(get(IsHigh ? HighOpcode : LowOpcode));
161f8af5cf6SDimitry Andric   if (IsHigh && ConvertHigh)
16201095a5dSDimitry Andric     MI.getOperand(1).setImm(uint32_t(MI.getOperand(1).getImm()));
163f8af5cf6SDimitry Andric }
164f8af5cf6SDimitry Andric 
165f8af5cf6SDimitry Andric // MI is a three-operand RIE-style pseudo instruction.  Replace it with
166dd58ef01SDimitry Andric // LowOpcodeK if the registers are both low GR32s, otherwise use a move
167f8af5cf6SDimitry Andric // followed by HighOpcode or LowOpcode, depending on whether the target
168f8af5cf6SDimitry Andric // is a high or low GR32.
expandRIEPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned LowOpcodeK,unsigned HighOpcode) const16901095a5dSDimitry Andric void SystemZInstrInfo::expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,
170f8af5cf6SDimitry Andric                                        unsigned LowOpcodeK,
171f8af5cf6SDimitry Andric                                        unsigned HighOpcode) const {
1721d5ae102SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
1731d5ae102SDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
1741d5ae102SDimitry Andric   bool DestIsHigh = SystemZ::isHighReg(DestReg);
1751d5ae102SDimitry Andric   bool SrcIsHigh = SystemZ::isHighReg(SrcReg);
176f8af5cf6SDimitry Andric   if (!DestIsHigh && !SrcIsHigh)
17701095a5dSDimitry Andric     MI.setDesc(get(LowOpcodeK));
178f8af5cf6SDimitry Andric   else {
179e6d15924SDimitry Andric     if (DestReg != SrcReg) {
18001095a5dSDimitry Andric       emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), DestReg, SrcReg,
18171d5a254SDimitry Andric                     SystemZ::LR, 32, MI.getOperand(1).isKill(),
18271d5a254SDimitry Andric                     MI.getOperand(1).isUndef());
18301095a5dSDimitry Andric       MI.getOperand(1).setReg(DestReg);
184e6d15924SDimitry Andric     }
185e6d15924SDimitry Andric     MI.setDesc(get(DestIsHigh ? HighOpcode : LowOpcode));
18601095a5dSDimitry Andric     MI.tieOperands(0, 1);
187f8af5cf6SDimitry Andric   }
188f8af5cf6SDimitry Andric }
189f8af5cf6SDimitry Andric 
190f8af5cf6SDimitry Andric // MI is an RXY-style pseudo instruction.  Replace it with LowOpcode
191f8af5cf6SDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
192f8af5cf6SDimitry Andric // is a high GR32.
expandRXYPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode) const19301095a5dSDimitry Andric void SystemZInstrInfo::expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,
194f8af5cf6SDimitry Andric                                        unsigned HighOpcode) const {
1951d5ae102SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
1961d5ae102SDimitry Andric   unsigned Opcode = getOpcodeForOffset(
1971d5ae102SDimitry Andric       SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode,
19801095a5dSDimitry Andric       MI.getOperand(2).getImm());
19901095a5dSDimitry Andric   MI.setDesc(get(Opcode));
200f8af5cf6SDimitry Andric }
201f8af5cf6SDimitry Andric 
202b915e9e0SDimitry Andric // MI is a load-on-condition pseudo instruction with a single register
203b915e9e0SDimitry Andric // (source or destination) operand.  Replace it with LowOpcode if the
204b915e9e0SDimitry Andric // register is a low GR32 and HighOpcode if the register is a high GR32.
expandLOCPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned HighOpcode) const205b915e9e0SDimitry Andric void SystemZInstrInfo::expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,
206b915e9e0SDimitry Andric                                        unsigned HighOpcode) const {
2071d5ae102SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
2081d5ae102SDimitry Andric   unsigned Opcode = SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode;
209b915e9e0SDimitry Andric   MI.setDesc(get(Opcode));
210b915e9e0SDimitry Andric }
211b915e9e0SDimitry Andric 
212f8af5cf6SDimitry Andric // MI is an RR-style pseudo instruction that zero-extends the low Size bits
213f8af5cf6SDimitry Andric // of one GRX32 into another.  Replace it with LowOpcode if both operands
214f8af5cf6SDimitry Andric // are low registers, otherwise use RISB[LH]G.
expandZExtPseudo(MachineInstr & MI,unsigned LowOpcode,unsigned Size) const21501095a5dSDimitry Andric void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,
216f8af5cf6SDimitry Andric                                         unsigned Size) const {
21771d5a254SDimitry Andric   MachineInstrBuilder MIB =
21801095a5dSDimitry Andric     emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(),
21901095a5dSDimitry Andric                MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), LowOpcode,
22071d5a254SDimitry Andric                Size, MI.getOperand(1).isKill(), MI.getOperand(1).isUndef());
22171d5a254SDimitry Andric 
22271d5a254SDimitry Andric   // Keep the remaining operands as-is.
223f65dcba8SDimitry Andric   for (const MachineOperand &MO : llvm::drop_begin(MI.operands(), 2))
224f65dcba8SDimitry Andric     MIB.add(MO);
22571d5a254SDimitry Andric 
22601095a5dSDimitry Andric   MI.eraseFromParent();
22701095a5dSDimitry Andric }
22801095a5dSDimitry Andric 
expandLoadStackGuard(MachineInstr * MI) const22901095a5dSDimitry Andric void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const {
23001095a5dSDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
23101095a5dSDimitry Andric   MachineFunction &MF = *MBB->getParent();
2321d5ae102SDimitry Andric   const Register Reg64 = MI->getOperand(0).getReg();
2331d5ae102SDimitry Andric   const Register Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32);
23401095a5dSDimitry Andric 
235ab44ce3dSDimitry Andric   // EAR can only load the low subregister so us a shift for %a0 to produce
236ab44ce3dSDimitry Andric   // the GR containing %a0 and %a1.
23701095a5dSDimitry Andric 
23801095a5dSDimitry Andric   // ear <reg>, %a0
239ab44ce3dSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
240ab44ce3dSDimitry Andric     .addReg(SystemZ::A0)
241ab44ce3dSDimitry Andric     .addReg(Reg64, RegState::ImplicitDefine);
24201095a5dSDimitry Andric 
24301095a5dSDimitry Andric   // sllg <reg>, <reg>, 32
244ab44ce3dSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64)
245ab44ce3dSDimitry Andric     .addReg(Reg64)
246ab44ce3dSDimitry Andric     .addReg(0)
247ab44ce3dSDimitry Andric     .addImm(32);
24801095a5dSDimitry Andric 
24901095a5dSDimitry Andric   // ear <reg>, %a1
250ab44ce3dSDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
251ab44ce3dSDimitry Andric     .addReg(SystemZ::A1);
25201095a5dSDimitry Andric 
25301095a5dSDimitry Andric   // lg <reg>, 40(<reg>)
25401095a5dSDimitry Andric   MI->setDesc(get(SystemZ::LG));
255ab44ce3dSDimitry Andric   MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0);
256f8af5cf6SDimitry Andric }
257f8af5cf6SDimitry Andric 
258f8af5cf6SDimitry Andric // Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR
259f8af5cf6SDimitry Andric // DestReg before MBBI in MBB.  Use LowLowOpcode when both DestReg and SrcReg
260f8af5cf6SDimitry Andric // are low registers, otherwise use RISB[LH]G.  Size is the number of bits
261f8af5cf6SDimitry Andric // taken from the low end of SrcReg (8 for LLCR, 16 for LLHR and 32 for LR).
262f8af5cf6SDimitry Andric // KillSrc is true if this move is the last use of SrcReg.
26371d5a254SDimitry Andric MachineInstrBuilder
emitGRX32Move(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,unsigned DestReg,unsigned SrcReg,unsigned LowLowOpcode,unsigned Size,bool KillSrc,bool UndefSrc) const26471d5a254SDimitry Andric SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB,
265f8af5cf6SDimitry Andric                                 MachineBasicBlock::iterator MBBI,
26601095a5dSDimitry Andric                                 const DebugLoc &DL, unsigned DestReg,
267f8af5cf6SDimitry Andric                                 unsigned SrcReg, unsigned LowLowOpcode,
26871d5a254SDimitry Andric                                 unsigned Size, bool KillSrc,
26971d5a254SDimitry Andric                                 bool UndefSrc) const {
270f8af5cf6SDimitry Andric   unsigned Opcode;
2711d5ae102SDimitry Andric   bool DestIsHigh = SystemZ::isHighReg(DestReg);
2721d5ae102SDimitry Andric   bool SrcIsHigh = SystemZ::isHighReg(SrcReg);
273f8af5cf6SDimitry Andric   if (DestIsHigh && SrcIsHigh)
274f8af5cf6SDimitry Andric     Opcode = SystemZ::RISBHH;
275f8af5cf6SDimitry Andric   else if (DestIsHigh && !SrcIsHigh)
276f8af5cf6SDimitry Andric     Opcode = SystemZ::RISBHL;
277f8af5cf6SDimitry Andric   else if (!DestIsHigh && SrcIsHigh)
278f8af5cf6SDimitry Andric     Opcode = SystemZ::RISBLH;
279f8af5cf6SDimitry Andric   else {
28071d5a254SDimitry Andric     return BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg)
28171d5a254SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc));
282f8af5cf6SDimitry Andric   }
283f8af5cf6SDimitry Andric   unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0);
28471d5a254SDimitry Andric   return BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
285f8af5cf6SDimitry Andric     .addReg(DestReg, RegState::Undef)
28671d5a254SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc))
287f8af5cf6SDimitry Andric     .addImm(32 - Size).addImm(128 + 31).addImm(Rotate);
288f8af5cf6SDimitry Andric }
289f8af5cf6SDimitry Andric 
commuteInstructionImpl(MachineInstr & MI,bool NewMI,unsigned OpIdx1,unsigned OpIdx2) const290b915e9e0SDimitry Andric MachineInstr *SystemZInstrInfo::commuteInstructionImpl(MachineInstr &MI,
291b915e9e0SDimitry Andric                                                        bool NewMI,
292b915e9e0SDimitry Andric                                                        unsigned OpIdx1,
293b915e9e0SDimitry Andric                                                        unsigned OpIdx2) const {
294b915e9e0SDimitry Andric   auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {
295b915e9e0SDimitry Andric     if (NewMI)
296b915e9e0SDimitry Andric       return *MI.getParent()->getParent()->CloneMachineInstr(&MI);
297b915e9e0SDimitry Andric     return MI;
298b915e9e0SDimitry Andric   };
299b915e9e0SDimitry Andric 
300b915e9e0SDimitry Andric   switch (MI.getOpcode()) {
301e6d15924SDimitry Andric   case SystemZ::SELRMux:
302e6d15924SDimitry Andric   case SystemZ::SELFHR:
303e6d15924SDimitry Andric   case SystemZ::SELR:
304e6d15924SDimitry Andric   case SystemZ::SELGR:
305b915e9e0SDimitry Andric   case SystemZ::LOCRMux:
306b915e9e0SDimitry Andric   case SystemZ::LOCFHR:
307b915e9e0SDimitry Andric   case SystemZ::LOCR:
308b915e9e0SDimitry Andric   case SystemZ::LOCGR: {
309b915e9e0SDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
310b915e9e0SDimitry Andric     // Invert condition.
311b915e9e0SDimitry Andric     unsigned CCValid = WorkingMI.getOperand(3).getImm();
312b915e9e0SDimitry Andric     unsigned CCMask = WorkingMI.getOperand(4).getImm();
313b915e9e0SDimitry Andric     WorkingMI.getOperand(4).setImm(CCMask ^ CCValid);
314b915e9e0SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
315b915e9e0SDimitry Andric                                                    OpIdx1, OpIdx2);
316b915e9e0SDimitry Andric   }
317b915e9e0SDimitry Andric   default:
318b915e9e0SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
319b915e9e0SDimitry Andric   }
320b915e9e0SDimitry Andric }
321b915e9e0SDimitry Andric 
32259d6cff9SDimitry Andric // If MI is a simple load or store for a frame object, return the register
32359d6cff9SDimitry Andric // it loads or stores and set FrameIndex to the index of the frame object.
32459d6cff9SDimitry Andric // Return 0 otherwise.
32559d6cff9SDimitry Andric //
32659d6cff9SDimitry Andric // Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
isSimpleMove(const MachineInstr & MI,int & FrameIndex,unsigned Flag)32701095a5dSDimitry Andric static int isSimpleMove(const MachineInstr &MI, int &FrameIndex,
328f8af5cf6SDimitry Andric                         unsigned Flag) {
32901095a5dSDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
33001095a5dSDimitry Andric   if ((MCID.TSFlags & Flag) && MI.getOperand(1).isFI() &&
33101095a5dSDimitry Andric       MI.getOperand(2).getImm() == 0 && MI.getOperand(3).getReg() == 0) {
33201095a5dSDimitry Andric     FrameIndex = MI.getOperand(1).getIndex();
33301095a5dSDimitry Andric     return MI.getOperand(0).getReg();
33459d6cff9SDimitry Andric   }
33559d6cff9SDimitry Andric   return 0;
33659d6cff9SDimitry Andric }
33759d6cff9SDimitry Andric 
isLoadFromStackSlot(const MachineInstr & MI,int & FrameIndex) const338ac9a064cSDimitry Andric Register SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
33959d6cff9SDimitry Andric                                                int &FrameIndex) const {
34059d6cff9SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXLoad);
34159d6cff9SDimitry Andric }
34259d6cff9SDimitry Andric 
isStoreToStackSlot(const MachineInstr & MI,int & FrameIndex) const343ac9a064cSDimitry Andric Register SystemZInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
34459d6cff9SDimitry Andric                                               int &FrameIndex) const {
34559d6cff9SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXStore);
34659d6cff9SDimitry Andric }
34759d6cff9SDimitry Andric 
isStackSlotCopy(const MachineInstr & MI,int & DestFrameIndex,int & SrcFrameIndex) const34801095a5dSDimitry Andric bool SystemZInstrInfo::isStackSlotCopy(const MachineInstr &MI,
349f8af5cf6SDimitry Andric                                        int &DestFrameIndex,
350f8af5cf6SDimitry Andric                                        int &SrcFrameIndex) const {
351f8af5cf6SDimitry Andric   // Check for MVC 0(Length,FI1),0(FI2)
352b915e9e0SDimitry Andric   const MachineFrameInfo &MFI = MI.getParent()->getParent()->getFrameInfo();
35301095a5dSDimitry Andric   if (MI.getOpcode() != SystemZ::MVC || !MI.getOperand(0).isFI() ||
35401095a5dSDimitry Andric       MI.getOperand(1).getImm() != 0 || !MI.getOperand(3).isFI() ||
35501095a5dSDimitry Andric       MI.getOperand(4).getImm() != 0)
356f8af5cf6SDimitry Andric     return false;
357f8af5cf6SDimitry Andric 
358f8af5cf6SDimitry Andric   // Check that Length covers the full slots.
35901095a5dSDimitry Andric   int64_t Length = MI.getOperand(2).getImm();
36001095a5dSDimitry Andric   unsigned FI1 = MI.getOperand(0).getIndex();
36101095a5dSDimitry Andric   unsigned FI2 = MI.getOperand(3).getIndex();
362b915e9e0SDimitry Andric   if (MFI.getObjectSize(FI1) != Length ||
363b915e9e0SDimitry Andric       MFI.getObjectSize(FI2) != Length)
364f8af5cf6SDimitry Andric     return false;
365f8af5cf6SDimitry Andric 
366f8af5cf6SDimitry Andric   DestFrameIndex = FI1;
367f8af5cf6SDimitry Andric   SrcFrameIndex = FI2;
368f8af5cf6SDimitry Andric   return true;
369f8af5cf6SDimitry Andric }
370f8af5cf6SDimitry Andric 
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const37101095a5dSDimitry Andric bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
37259d6cff9SDimitry Andric                                      MachineBasicBlock *&TBB,
37359d6cff9SDimitry Andric                                      MachineBasicBlock *&FBB,
37459d6cff9SDimitry Andric                                      SmallVectorImpl<MachineOperand> &Cond,
37559d6cff9SDimitry Andric                                      bool AllowModify) const {
37659d6cff9SDimitry Andric   // Most of the code and comments here are boilerplate.
37759d6cff9SDimitry Andric 
37859d6cff9SDimitry Andric   // Start from the bottom of the block and work up, examining the
37959d6cff9SDimitry Andric   // terminator instructions.
38059d6cff9SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
38159d6cff9SDimitry Andric   while (I != MBB.begin()) {
38259d6cff9SDimitry Andric     --I;
383eb11fae6SDimitry Andric     if (I->isDebugInstr())
38459d6cff9SDimitry Andric       continue;
38559d6cff9SDimitry Andric 
38659d6cff9SDimitry Andric     // Working from the bottom, when we see a non-terminator instruction, we're
38759d6cff9SDimitry Andric     // done.
38801095a5dSDimitry Andric     if (!isUnpredicatedTerminator(*I))
38959d6cff9SDimitry Andric       break;
39059d6cff9SDimitry Andric 
39159d6cff9SDimitry Andric     // A terminator that isn't a branch can't easily be handled by this
39259d6cff9SDimitry Andric     // analysis.
393f8af5cf6SDimitry Andric     if (!I->isBranch())
39459d6cff9SDimitry Andric       return true;
39559d6cff9SDimitry Andric 
39659d6cff9SDimitry Andric     // Can't handle indirect branches.
39701095a5dSDimitry Andric     SystemZII::Branch Branch(getBranchInfo(*I));
3981d5ae102SDimitry Andric     if (!Branch.hasMBBTarget())
39959d6cff9SDimitry Andric       return true;
40059d6cff9SDimitry Andric 
401f8af5cf6SDimitry Andric     // Punt on compound branches.
402f8af5cf6SDimitry Andric     if (Branch.Type != SystemZII::BranchNormal)
403f8af5cf6SDimitry Andric       return true;
404f8af5cf6SDimitry Andric 
405f8af5cf6SDimitry Andric     if (Branch.CCMask == SystemZ::CCMASK_ANY) {
40659d6cff9SDimitry Andric       // Handle unconditional branches.
40759d6cff9SDimitry Andric       if (!AllowModify) {
4081d5ae102SDimitry Andric         TBB = Branch.getMBBTarget();
40959d6cff9SDimitry Andric         continue;
41059d6cff9SDimitry Andric       }
41159d6cff9SDimitry Andric 
41259d6cff9SDimitry Andric       // If the block has any instructions after a JMP, delete them.
413145449b1SDimitry Andric       MBB.erase(std::next(I), MBB.end());
41459d6cff9SDimitry Andric 
41559d6cff9SDimitry Andric       Cond.clear();
4165ca98fd9SDimitry Andric       FBB = nullptr;
41759d6cff9SDimitry Andric 
41859d6cff9SDimitry Andric       // Delete the JMP if it's equivalent to a fall-through.
4191d5ae102SDimitry Andric       if (MBB.isLayoutSuccessor(Branch.getMBBTarget())) {
4205ca98fd9SDimitry Andric         TBB = nullptr;
42159d6cff9SDimitry Andric         I->eraseFromParent();
42259d6cff9SDimitry Andric         I = MBB.end();
42359d6cff9SDimitry Andric         continue;
42459d6cff9SDimitry Andric       }
42559d6cff9SDimitry Andric 
42659d6cff9SDimitry Andric       // TBB is used to indicate the unconditinal destination.
4271d5ae102SDimitry Andric       TBB = Branch.getMBBTarget();
42859d6cff9SDimitry Andric       continue;
42959d6cff9SDimitry Andric     }
43059d6cff9SDimitry Andric 
43159d6cff9SDimitry Andric     // Working from the bottom, handle the first conditional branch.
43259d6cff9SDimitry Andric     if (Cond.empty()) {
43359d6cff9SDimitry Andric       // FIXME: add X86-style branch swap
43459d6cff9SDimitry Andric       FBB = TBB;
4351d5ae102SDimitry Andric       TBB = Branch.getMBBTarget();
436f8af5cf6SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCValid));
437f8af5cf6SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
43859d6cff9SDimitry Andric       continue;
43959d6cff9SDimitry Andric     }
44059d6cff9SDimitry Andric 
44159d6cff9SDimitry Andric     // Handle subsequent conditional branches.
442f8af5cf6SDimitry Andric     assert(Cond.size() == 2 && TBB && "Should have seen a conditional branch");
44359d6cff9SDimitry Andric 
44459d6cff9SDimitry Andric     // Only handle the case where all conditional branches branch to the same
44559d6cff9SDimitry Andric     // destination.
4461d5ae102SDimitry Andric     if (TBB != Branch.getMBBTarget())
44759d6cff9SDimitry Andric       return true;
44859d6cff9SDimitry Andric 
44959d6cff9SDimitry Andric     // If the conditions are the same, we can leave them alone.
450f8af5cf6SDimitry Andric     unsigned OldCCValid = Cond[0].getImm();
451f8af5cf6SDimitry Andric     unsigned OldCCMask = Cond[1].getImm();
452f8af5cf6SDimitry Andric     if (OldCCValid == Branch.CCValid && OldCCMask == Branch.CCMask)
45359d6cff9SDimitry Andric       continue;
45459d6cff9SDimitry Andric 
45559d6cff9SDimitry Andric     // FIXME: Try combining conditions like X86 does.  Should be easy on Z!
456f8af5cf6SDimitry Andric     return false;
45759d6cff9SDimitry Andric   }
45859d6cff9SDimitry Andric 
45959d6cff9SDimitry Andric   return false;
46059d6cff9SDimitry Andric }
46159d6cff9SDimitry Andric 
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const462b915e9e0SDimitry Andric unsigned SystemZInstrInfo::removeBranch(MachineBasicBlock &MBB,
463b915e9e0SDimitry Andric                                         int *BytesRemoved) const {
464b915e9e0SDimitry Andric   assert(!BytesRemoved && "code size not handled");
465b915e9e0SDimitry Andric 
46659d6cff9SDimitry Andric   // Most of the code and comments here are boilerplate.
46759d6cff9SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
46859d6cff9SDimitry Andric   unsigned Count = 0;
46959d6cff9SDimitry Andric 
47059d6cff9SDimitry Andric   while (I != MBB.begin()) {
47159d6cff9SDimitry Andric     --I;
472eb11fae6SDimitry Andric     if (I->isDebugInstr())
47359d6cff9SDimitry Andric       continue;
474f8af5cf6SDimitry Andric     if (!I->isBranch())
47559d6cff9SDimitry Andric       break;
4761d5ae102SDimitry Andric     if (!getBranchInfo(*I).hasMBBTarget())
47759d6cff9SDimitry Andric       break;
47859d6cff9SDimitry Andric     // Remove the branch.
47959d6cff9SDimitry Andric     I->eraseFromParent();
48059d6cff9SDimitry Andric     I = MBB.end();
48159d6cff9SDimitry Andric     ++Count;
48259d6cff9SDimitry Andric   }
48359d6cff9SDimitry Andric 
48459d6cff9SDimitry Andric   return Count;
48559d6cff9SDimitry Andric }
48659d6cff9SDimitry Andric 
487f8af5cf6SDimitry Andric bool SystemZInstrInfo::
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const488b915e9e0SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
489f8af5cf6SDimitry Andric   assert(Cond.size() == 2 && "Invalid condition");
490f8af5cf6SDimitry Andric   Cond[1].setImm(Cond[1].getImm() ^ Cond[0].getImm());
491f8af5cf6SDimitry Andric   return false;
492f8af5cf6SDimitry Andric }
493f8af5cf6SDimitry Andric 
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const494b915e9e0SDimitry Andric unsigned SystemZInstrInfo::insertBranch(MachineBasicBlock &MBB,
49501095a5dSDimitry Andric                                         MachineBasicBlock *TBB,
49659d6cff9SDimitry Andric                                         MachineBasicBlock *FBB,
4973a0822f0SDimitry Andric                                         ArrayRef<MachineOperand> Cond,
498b915e9e0SDimitry Andric                                         const DebugLoc &DL,
499b915e9e0SDimitry Andric                                         int *BytesAdded) const {
50059d6cff9SDimitry Andric   // In this function we output 32-bit branches, which should always
50159d6cff9SDimitry Andric   // have enough range.  They can be shortened and relaxed by later code
50259d6cff9SDimitry Andric   // in the pipeline, if desired.
50359d6cff9SDimitry Andric 
50459d6cff9SDimitry Andric   // Shouldn't be a fall through.
505b915e9e0SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
506f8af5cf6SDimitry Andric   assert((Cond.size() == 2 || Cond.size() == 0) &&
50759d6cff9SDimitry Andric          "SystemZ branch conditions have one component!");
508b915e9e0SDimitry Andric   assert(!BytesAdded && "code size not handled");
50959d6cff9SDimitry Andric 
51059d6cff9SDimitry Andric   if (Cond.empty()) {
51159d6cff9SDimitry Andric     // Unconditional branch?
51259d6cff9SDimitry Andric     assert(!FBB && "Unconditional branch with multiple successors!");
513f8af5cf6SDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(TBB);
51459d6cff9SDimitry Andric     return 1;
51559d6cff9SDimitry Andric   }
51659d6cff9SDimitry Andric 
51759d6cff9SDimitry Andric   // Conditional branch.
51859d6cff9SDimitry Andric   unsigned Count = 0;
519f8af5cf6SDimitry Andric   unsigned CCValid = Cond[0].getImm();
520f8af5cf6SDimitry Andric   unsigned CCMask = Cond[1].getImm();
521f8af5cf6SDimitry Andric   BuildMI(&MBB, DL, get(SystemZ::BRC))
522f8af5cf6SDimitry Andric     .addImm(CCValid).addImm(CCMask).addMBB(TBB);
52359d6cff9SDimitry Andric   ++Count;
52459d6cff9SDimitry Andric 
52559d6cff9SDimitry Andric   if (FBB) {
52659d6cff9SDimitry Andric     // Two-way Conditional branch. Insert the second branch.
527f8af5cf6SDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(FBB);
52859d6cff9SDimitry Andric     ++Count;
52959d6cff9SDimitry Andric   }
53059d6cff9SDimitry Andric   return Count;
53159d6cff9SDimitry Andric }
53259d6cff9SDimitry Andric 
analyzeCompare(const MachineInstr & MI,Register & SrcReg,Register & SrcReg2,int64_t & Mask,int64_t & Value) const533cfca06d7SDimitry Andric bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
534c0981da4SDimitry Andric                                       Register &SrcReg2, int64_t &Mask,
535c0981da4SDimitry Andric                                       int64_t &Value) const {
53601095a5dSDimitry Andric   assert(MI.isCompare() && "Caller should have checked for a comparison");
537f8af5cf6SDimitry Andric 
53801095a5dSDimitry Andric   if (MI.getNumExplicitOperands() == 2 && MI.getOperand(0).isReg() &&
53901095a5dSDimitry Andric       MI.getOperand(1).isImm()) {
54001095a5dSDimitry Andric     SrcReg = MI.getOperand(0).getReg();
541f8af5cf6SDimitry Andric     SrcReg2 = 0;
54201095a5dSDimitry Andric     Value = MI.getOperand(1).getImm();
543f8af5cf6SDimitry Andric     Mask = ~0;
544f8af5cf6SDimitry Andric     return true;
545f8af5cf6SDimitry Andric   }
546f8af5cf6SDimitry Andric 
547f8af5cf6SDimitry Andric   return false;
548f8af5cf6SDimitry Andric }
549f8af5cf6SDimitry Andric 
canInsertSelect(const MachineBasicBlock & MBB,ArrayRef<MachineOperand> Pred,Register DstReg,Register TrueReg,Register FalseReg,int & CondCycles,int & TrueCycles,int & FalseCycles) const550b915e9e0SDimitry Andric bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
551b915e9e0SDimitry Andric                                        ArrayRef<MachineOperand> Pred,
552cfca06d7SDimitry Andric                                        Register DstReg, Register TrueReg,
553cfca06d7SDimitry Andric                                        Register FalseReg, int &CondCycles,
554cfca06d7SDimitry Andric                                        int &TrueCycles,
555b915e9e0SDimitry Andric                                        int &FalseCycles) const {
556b915e9e0SDimitry Andric   // Not all subtargets have LOCR instructions.
557b915e9e0SDimitry Andric   if (!STI.hasLoadStoreOnCond())
558b915e9e0SDimitry Andric     return false;
559b915e9e0SDimitry Andric   if (Pred.size() != 2)
560b915e9e0SDimitry Andric     return false;
561b915e9e0SDimitry Andric 
562b915e9e0SDimitry Andric   // Check register classes.
563b915e9e0SDimitry Andric   const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
564b915e9e0SDimitry Andric   const TargetRegisterClass *RC =
565b915e9e0SDimitry Andric     RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
566b915e9e0SDimitry Andric   if (!RC)
567b915e9e0SDimitry Andric     return false;
568b915e9e0SDimitry Andric 
569b915e9e0SDimitry Andric   // We have LOCR instructions for 32 and 64 bit general purpose registers.
570b915e9e0SDimitry Andric   if ((STI.hasLoadStoreOnCond2() &&
571b915e9e0SDimitry Andric        SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) ||
572b915e9e0SDimitry Andric       SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
573b915e9e0SDimitry Andric       SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {
574b915e9e0SDimitry Andric     CondCycles = 2;
575b915e9e0SDimitry Andric     TrueCycles = 2;
576b915e9e0SDimitry Andric     FalseCycles = 2;
577b915e9e0SDimitry Andric     return true;
578f8af5cf6SDimitry Andric   }
579f8af5cf6SDimitry Andric 
580b915e9e0SDimitry Andric   // Can't do anything else.
581b915e9e0SDimitry Andric   return false;
58201095a5dSDimitry Andric }
583b915e9e0SDimitry Andric 
insertSelect(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,Register DstReg,ArrayRef<MachineOperand> Pred,Register TrueReg,Register FalseReg) const584b915e9e0SDimitry Andric void SystemZInstrInfo::insertSelect(MachineBasicBlock &MBB,
585b915e9e0SDimitry Andric                                     MachineBasicBlock::iterator I,
586cfca06d7SDimitry Andric                                     const DebugLoc &DL, Register DstReg,
587b915e9e0SDimitry Andric                                     ArrayRef<MachineOperand> Pred,
588cfca06d7SDimitry Andric                                     Register TrueReg,
589cfca06d7SDimitry Andric                                     Register FalseReg) const {
590b915e9e0SDimitry Andric   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
591b915e9e0SDimitry Andric   const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
592b915e9e0SDimitry Andric 
593b915e9e0SDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
594b915e9e0SDimitry Andric   unsigned CCValid = Pred[0].getImm();
595b915e9e0SDimitry Andric   unsigned CCMask = Pred[1].getImm();
596b915e9e0SDimitry Andric 
597b915e9e0SDimitry Andric   unsigned Opc;
598b915e9e0SDimitry Andric   if (SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) {
599e6d15924SDimitry Andric     if (STI.hasMiscellaneousExtensions3())
600e6d15924SDimitry Andric       Opc = SystemZ::SELRMux;
601e6d15924SDimitry Andric     else if (STI.hasLoadStoreOnCond2())
602b915e9e0SDimitry Andric       Opc = SystemZ::LOCRMux;
603b915e9e0SDimitry Andric     else {
604b915e9e0SDimitry Andric       Opc = SystemZ::LOCR;
605b915e9e0SDimitry Andric       MRI.constrainRegClass(DstReg, &SystemZ::GR32BitRegClass);
6061d5ae102SDimitry Andric       Register TReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
6071d5ae102SDimitry Andric       Register FReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
60871d5a254SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), TReg).addReg(TrueReg);
60971d5a254SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), FReg).addReg(FalseReg);
61071d5a254SDimitry Andric       TrueReg = TReg;
61171d5a254SDimitry Andric       FalseReg = FReg;
612b915e9e0SDimitry Andric     }
613e6d15924SDimitry Andric   } else if (SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {
614e6d15924SDimitry Andric     if (STI.hasMiscellaneousExtensions3())
615e6d15924SDimitry Andric       Opc = SystemZ::SELGR;
616b915e9e0SDimitry Andric     else
617e6d15924SDimitry Andric       Opc = SystemZ::LOCGR;
618e6d15924SDimitry Andric   } else
619b915e9e0SDimitry Andric     llvm_unreachable("Invalid register class");
620b915e9e0SDimitry Andric 
621b915e9e0SDimitry Andric   BuildMI(MBB, I, DL, get(Opc), DstReg)
622b915e9e0SDimitry Andric     .addReg(FalseReg).addReg(TrueReg)
623b915e9e0SDimitry Andric     .addImm(CCValid).addImm(CCMask);
624b915e9e0SDimitry Andric }
625b915e9e0SDimitry Andric 
optimizeLoadInstr(MachineInstr & MI,const MachineRegisterInfo * MRI,Register & FoldAsLoadDefReg,MachineInstr * & DefMI) const626ac9a064cSDimitry Andric MachineInstr *SystemZInstrInfo::optimizeLoadInstr(MachineInstr &MI,
627ac9a064cSDimitry Andric                                                   const MachineRegisterInfo *MRI,
628ac9a064cSDimitry Andric                                                   Register &FoldAsLoadDefReg,
629ac9a064cSDimitry Andric                                                   MachineInstr *&DefMI) const {
630ac9a064cSDimitry Andric   // Check whether we can move the DefMI load, and that it only has one use.
631ac9a064cSDimitry Andric   DefMI = MRI->getVRegDef(FoldAsLoadDefReg);
632ac9a064cSDimitry Andric   assert(DefMI);
633ac9a064cSDimitry Andric   bool SawStore = false;
634ac9a064cSDimitry Andric   if (!DefMI->isSafeToMove(nullptr, SawStore) ||
635ac9a064cSDimitry Andric       !MRI->hasOneNonDBGUse(FoldAsLoadDefReg))
636ac9a064cSDimitry Andric     return nullptr;
637ac9a064cSDimitry Andric 
638ac9a064cSDimitry Andric   int UseOpIdx =
639ac9a064cSDimitry Andric       MI.findRegisterUseOperandIdx(FoldAsLoadDefReg, /*TRI=*/nullptr);
640ac9a064cSDimitry Andric   assert(UseOpIdx != -1 && "Expected FoldAsLoadDefReg to be used by MI.");
641ac9a064cSDimitry Andric 
642ac9a064cSDimitry Andric   // Check whether we can fold the load.
643ac9a064cSDimitry Andric   if (MachineInstr *FoldMI =
644ac9a064cSDimitry Andric           foldMemoryOperand(MI, {((unsigned)UseOpIdx)}, *DefMI)) {
645ac9a064cSDimitry Andric     FoldAsLoadDefReg = 0;
646ac9a064cSDimitry Andric     return FoldMI;
647ac9a064cSDimitry Andric   }
648ac9a064cSDimitry Andric 
649ac9a064cSDimitry Andric   return nullptr;
650ac9a064cSDimitry Andric }
651ac9a064cSDimitry Andric 
foldImmediate(MachineInstr & UseMI,MachineInstr & DefMI,Register Reg,MachineRegisterInfo * MRI) const652ac9a064cSDimitry Andric bool SystemZInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
653cfca06d7SDimitry Andric                                      Register Reg,
654b915e9e0SDimitry Andric                                      MachineRegisterInfo *MRI) const {
655b915e9e0SDimitry Andric   unsigned DefOpc = DefMI.getOpcode();
656ac9a064cSDimitry Andric 
657ac9a064cSDimitry Andric   if (DefOpc == SystemZ::VGBM) {
658ac9a064cSDimitry Andric     int64_t ImmVal = DefMI.getOperand(1).getImm();
659ac9a064cSDimitry Andric     if (ImmVal != 0) // TODO: Handle other values
660ac9a064cSDimitry Andric       return false;
661ac9a064cSDimitry Andric 
662ac9a064cSDimitry Andric     // Fold gr128 = COPY (vr128 VGBM imm)
663ac9a064cSDimitry Andric     //
664ac9a064cSDimitry Andric     // %tmp:gr64 = LGHI 0
665ac9a064cSDimitry Andric     // to  gr128 = REG_SEQUENCE %tmp, %tmp
666ac9a064cSDimitry Andric     assert(DefMI.getOperand(0).getReg() == Reg);
667ac9a064cSDimitry Andric 
668ac9a064cSDimitry Andric     if (!UseMI.isCopy())
669ac9a064cSDimitry Andric       return false;
670ac9a064cSDimitry Andric 
671ac9a064cSDimitry Andric     Register CopyDstReg = UseMI.getOperand(0).getReg();
672ac9a064cSDimitry Andric     if (CopyDstReg.isVirtual() &&
673ac9a064cSDimitry Andric         MRI->getRegClass(CopyDstReg) == &SystemZ::GR128BitRegClass &&
674ac9a064cSDimitry Andric         MRI->hasOneNonDBGUse(Reg)) {
675ac9a064cSDimitry Andric       // TODO: Handle physical registers
676ac9a064cSDimitry Andric       // TODO: Handle gr64 uses with subregister indexes
677ac9a064cSDimitry Andric       // TODO: Should this multi-use cases?
678ac9a064cSDimitry Andric       Register TmpReg = MRI->createVirtualRegister(&SystemZ::GR64BitRegClass);
679ac9a064cSDimitry Andric       MachineBasicBlock &MBB = *UseMI.getParent();
680ac9a064cSDimitry Andric 
681ac9a064cSDimitry Andric       loadImmediate(MBB, UseMI.getIterator(), TmpReg, ImmVal);
682ac9a064cSDimitry Andric 
683ac9a064cSDimitry Andric       UseMI.setDesc(get(SystemZ::REG_SEQUENCE));
684ac9a064cSDimitry Andric       UseMI.getOperand(1).setReg(TmpReg);
685ac9a064cSDimitry Andric       MachineInstrBuilder(*MBB.getParent(), &UseMI)
686ac9a064cSDimitry Andric           .addImm(SystemZ::subreg_h64)
687ac9a064cSDimitry Andric           .addReg(TmpReg)
688ac9a064cSDimitry Andric           .addImm(SystemZ::subreg_l64);
689ac9a064cSDimitry Andric 
690ac9a064cSDimitry Andric       if (MRI->use_nodbg_empty(Reg))
691ac9a064cSDimitry Andric         DefMI.eraseFromParent();
692ac9a064cSDimitry Andric       return true;
693ac9a064cSDimitry Andric     }
694ac9a064cSDimitry Andric 
695ac9a064cSDimitry Andric     return false;
696ac9a064cSDimitry Andric   }
697ac9a064cSDimitry Andric 
698b915e9e0SDimitry Andric   if (DefOpc != SystemZ::LHIMux && DefOpc != SystemZ::LHI &&
699b915e9e0SDimitry Andric       DefOpc != SystemZ::LGHI)
700b915e9e0SDimitry Andric     return false;
701b915e9e0SDimitry Andric   if (DefMI.getOperand(0).getReg() != Reg)
702b915e9e0SDimitry Andric     return false;
703b915e9e0SDimitry Andric   int32_t ImmVal = (int32_t)DefMI.getOperand(1).getImm();
704b915e9e0SDimitry Andric 
705b915e9e0SDimitry Andric   unsigned UseOpc = UseMI.getOpcode();
706b915e9e0SDimitry Andric   unsigned NewUseOpc;
707b915e9e0SDimitry Andric   unsigned UseIdx;
708b915e9e0SDimitry Andric   int CommuteIdx = -1;
709e6d15924SDimitry Andric   bool TieOps = false;
710b915e9e0SDimitry Andric   switch (UseOpc) {
711e6d15924SDimitry Andric   case SystemZ::SELRMux:
712e6d15924SDimitry Andric     TieOps = true;
713e3b55780SDimitry Andric     [[fallthrough]];
714b915e9e0SDimitry Andric   case SystemZ::LOCRMux:
715b915e9e0SDimitry Andric     if (!STI.hasLoadStoreOnCond2())
716b915e9e0SDimitry Andric       return false;
717b915e9e0SDimitry Andric     NewUseOpc = SystemZ::LOCHIMux;
718b915e9e0SDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
719b915e9e0SDimitry Andric       UseIdx = 2;
720b915e9e0SDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
721b915e9e0SDimitry Andric       UseIdx = 2, CommuteIdx = 1;
722b915e9e0SDimitry Andric     else
723b915e9e0SDimitry Andric       return false;
724b915e9e0SDimitry Andric     break;
725e6d15924SDimitry Andric   case SystemZ::SELGR:
726e6d15924SDimitry Andric     TieOps = true;
727e3b55780SDimitry Andric     [[fallthrough]];
728b915e9e0SDimitry Andric   case SystemZ::LOCGR:
729b915e9e0SDimitry Andric     if (!STI.hasLoadStoreOnCond2())
730b915e9e0SDimitry Andric       return false;
731b915e9e0SDimitry Andric     NewUseOpc = SystemZ::LOCGHI;
732b915e9e0SDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
733b915e9e0SDimitry Andric       UseIdx = 2;
734b915e9e0SDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
735b915e9e0SDimitry Andric       UseIdx = 2, CommuteIdx = 1;
736b915e9e0SDimitry Andric     else
737b915e9e0SDimitry Andric       return false;
738b915e9e0SDimitry Andric     break;
739b915e9e0SDimitry Andric   default:
740b915e9e0SDimitry Andric     return false;
741b915e9e0SDimitry Andric   }
742b915e9e0SDimitry Andric 
743b915e9e0SDimitry Andric   if (CommuteIdx != -1)
744b915e9e0SDimitry Andric     if (!commuteInstruction(UseMI, false, CommuteIdx, UseIdx))
745b915e9e0SDimitry Andric       return false;
746b915e9e0SDimitry Andric 
747b915e9e0SDimitry Andric   bool DeleteDef = MRI->hasOneNonDBGUse(Reg);
748b915e9e0SDimitry Andric   UseMI.setDesc(get(NewUseOpc));
749e6d15924SDimitry Andric   if (TieOps)
750e6d15924SDimitry Andric     UseMI.tieOperands(0, 1);
751b915e9e0SDimitry Andric   UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);
752b915e9e0SDimitry Andric   if (DeleteDef)
753b915e9e0SDimitry Andric     DefMI.eraseFromParent();
754b915e9e0SDimitry Andric 
755b915e9e0SDimitry Andric   return true;
75601095a5dSDimitry Andric }
75701095a5dSDimitry Andric 
isPredicable(const MachineInstr & MI) const75871d5a254SDimitry Andric bool SystemZInstrInfo::isPredicable(const MachineInstr &MI) const {
75901095a5dSDimitry Andric   unsigned Opcode = MI.getOpcode();
76001095a5dSDimitry Andric   if (Opcode == SystemZ::Return ||
761145449b1SDimitry Andric       Opcode == SystemZ::Return_XPLINK ||
76201095a5dSDimitry Andric       Opcode == SystemZ::Trap ||
76301095a5dSDimitry Andric       Opcode == SystemZ::CallJG ||
76401095a5dSDimitry Andric       Opcode == SystemZ::CallBR)
76501095a5dSDimitry Andric     return true;
76601095a5dSDimitry Andric   return false;
767f8af5cf6SDimitry Andric }
768f8af5cf6SDimitry Andric 
769f8af5cf6SDimitry Andric bool SystemZInstrInfo::
isProfitableToIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,unsigned ExtraPredCycles,BranchProbability Probability) const770f8af5cf6SDimitry Andric isProfitableToIfCvt(MachineBasicBlock &MBB,
771f8af5cf6SDimitry Andric                     unsigned NumCycles, unsigned ExtraPredCycles,
772dd58ef01SDimitry Andric                     BranchProbability Probability) const {
77301095a5dSDimitry Andric   // Avoid using conditional returns at the end of a loop (since then
77401095a5dSDimitry Andric   // we'd need to emit an unconditional branch to the beginning anyway,
77501095a5dSDimitry Andric   // making the loop body longer).  This doesn't apply for low-probability
77601095a5dSDimitry Andric   // loops (eg. compare-and-swap retry), so just decide based on branch
77701095a5dSDimitry Andric   // probability instead of looping structure.
77801095a5dSDimitry Andric   // However, since Compare and Trap instructions cost the same as a regular
77901095a5dSDimitry Andric   // Compare instruction, we should allow the if conversion to convert this
78001095a5dSDimitry Andric   // into a Conditional Compare regardless of the branch probability.
78101095a5dSDimitry Andric   if (MBB.getLastNonDebugInstr()->getOpcode() != SystemZ::Trap &&
78201095a5dSDimitry Andric       MBB.succ_empty() && Probability < BranchProbability(1, 8))
78301095a5dSDimitry Andric     return false;
784f8af5cf6SDimitry Andric   // For now only convert single instructions.
785f8af5cf6SDimitry Andric   return NumCycles == 1;
786f8af5cf6SDimitry Andric }
787f8af5cf6SDimitry Andric 
788f8af5cf6SDimitry Andric bool SystemZInstrInfo::
isProfitableToIfCvt(MachineBasicBlock & TMBB,unsigned NumCyclesT,unsigned ExtraPredCyclesT,MachineBasicBlock & FMBB,unsigned NumCyclesF,unsigned ExtraPredCyclesF,BranchProbability Probability) const789f8af5cf6SDimitry Andric isProfitableToIfCvt(MachineBasicBlock &TMBB,
790f8af5cf6SDimitry Andric                     unsigned NumCyclesT, unsigned ExtraPredCyclesT,
791f8af5cf6SDimitry Andric                     MachineBasicBlock &FMBB,
792f8af5cf6SDimitry Andric                     unsigned NumCyclesF, unsigned ExtraPredCyclesF,
793dd58ef01SDimitry Andric                     BranchProbability Probability) const {
794f8af5cf6SDimitry Andric   // For now avoid converting mutually-exclusive cases.
795f8af5cf6SDimitry Andric   return false;
796f8af5cf6SDimitry Andric }
797f8af5cf6SDimitry Andric 
798f8af5cf6SDimitry Andric bool SystemZInstrInfo::
isProfitableToDupForIfCvt(MachineBasicBlock & MBB,unsigned NumCycles,BranchProbability Probability) const79901095a5dSDimitry Andric isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
80001095a5dSDimitry Andric                           BranchProbability Probability) const {
80101095a5dSDimitry Andric   // For now only duplicate single instructions.
80201095a5dSDimitry Andric   return NumCycles == 1;
80301095a5dSDimitry Andric }
80401095a5dSDimitry Andric 
PredicateInstruction(MachineInstr & MI,ArrayRef<MachineOperand> Pred) const80501095a5dSDimitry Andric bool SystemZInstrInfo::PredicateInstruction(
80601095a5dSDimitry Andric     MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {
807f8af5cf6SDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
808f8af5cf6SDimitry Andric   unsigned CCValid = Pred[0].getImm();
809f8af5cf6SDimitry Andric   unsigned CCMask = Pred[1].getImm();
810f8af5cf6SDimitry Andric   assert(CCMask > 0 && CCMask < 15 && "Invalid predicate");
81101095a5dSDimitry Andric   unsigned Opcode = MI.getOpcode();
81201095a5dSDimitry Andric   if (Opcode == SystemZ::Trap) {
81301095a5dSDimitry Andric     MI.setDesc(get(SystemZ::CondTrap));
81401095a5dSDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
815f8af5cf6SDimitry Andric       .addImm(CCValid).addImm(CCMask)
8165ca98fd9SDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
817f8af5cf6SDimitry Andric     return true;
818f8af5cf6SDimitry Andric   }
819145449b1SDimitry Andric   if (Opcode == SystemZ::Return || Opcode == SystemZ::Return_XPLINK) {
820145449b1SDimitry Andric     MI.setDesc(get(Opcode == SystemZ::Return ? SystemZ::CondReturn
821145449b1SDimitry Andric                                              : SystemZ::CondReturn_XPLINK));
82201095a5dSDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
823145449b1SDimitry Andric         .addImm(CCValid)
824145449b1SDimitry Andric         .addImm(CCMask)
82501095a5dSDimitry Andric         .addReg(SystemZ::CC, RegState::Implicit);
82601095a5dSDimitry Andric     return true;
82701095a5dSDimitry Andric   }
82801095a5dSDimitry Andric   if (Opcode == SystemZ::CallJG) {
82901095a5dSDimitry Andric     MachineOperand FirstOp = MI.getOperand(0);
83001095a5dSDimitry Andric     const uint32_t *RegMask = MI.getOperand(1).getRegMask();
831145449b1SDimitry Andric     MI.removeOperand(1);
832145449b1SDimitry Andric     MI.removeOperand(0);
83301095a5dSDimitry Andric     MI.setDesc(get(SystemZ::CallBRCL));
83401095a5dSDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
83571d5a254SDimitry Andric         .addImm(CCValid)
83671d5a254SDimitry Andric         .addImm(CCMask)
83771d5a254SDimitry Andric         .add(FirstOp)
83801095a5dSDimitry Andric         .addRegMask(RegMask)
83901095a5dSDimitry Andric         .addReg(SystemZ::CC, RegState::Implicit);
84001095a5dSDimitry Andric     return true;
84101095a5dSDimitry Andric   }
84201095a5dSDimitry Andric   if (Opcode == SystemZ::CallBR) {
843b60736ecSDimitry Andric     MachineOperand Target = MI.getOperand(0);
844b60736ecSDimitry Andric     const uint32_t *RegMask = MI.getOperand(1).getRegMask();
845145449b1SDimitry Andric     MI.removeOperand(1);
846145449b1SDimitry Andric     MI.removeOperand(0);
84701095a5dSDimitry Andric     MI.setDesc(get(SystemZ::CallBCR));
84801095a5dSDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
84901095a5dSDimitry Andric       .addImm(CCValid).addImm(CCMask)
850b60736ecSDimitry Andric       .add(Target)
85101095a5dSDimitry Andric       .addRegMask(RegMask)
85201095a5dSDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
85301095a5dSDimitry Andric     return true;
854f8af5cf6SDimitry Andric   }
855f8af5cf6SDimitry Andric   return false;
856f8af5cf6SDimitry Andric }
857f8af5cf6SDimitry Andric 
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,const DebugLoc & DL,MCRegister DestReg,MCRegister SrcReg,bool KillSrc) const858dd58ef01SDimitry Andric void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
859dd58ef01SDimitry Andric                                    MachineBasicBlock::iterator MBBI,
860706b4fc4SDimitry Andric                                    const DebugLoc &DL, MCRegister DestReg,
861706b4fc4SDimitry Andric                                    MCRegister SrcReg, bool KillSrc) const {
862c46e6a59SDimitry Andric   // Split 128-bit GPR moves into two 64-bit moves. Add implicit uses of the
863c46e6a59SDimitry Andric   // super register in case one of the subregs is undefined.
864c46e6a59SDimitry Andric   // This handles ADDR128 too.
86559d6cff9SDimitry Andric   if (SystemZ::GR128BitRegClass.contains(DestReg, SrcReg)) {
866f8af5cf6SDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_h64),
867f8af5cf6SDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_h64), KillSrc);
868c46e6a59SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
869c46e6a59SDimitry Andric       .addReg(SrcReg, RegState::Implicit);
870f8af5cf6SDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_l64),
871f8af5cf6SDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_l64), KillSrc);
872c46e6a59SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
873c46e6a59SDimitry Andric       .addReg(SrcReg, (getKillRegState(KillSrc) | RegState::Implicit));
874f8af5cf6SDimitry Andric     return;
875f8af5cf6SDimitry Andric   }
876f8af5cf6SDimitry Andric 
877f8af5cf6SDimitry Andric   if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) {
87871d5a254SDimitry Andric     emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc,
87971d5a254SDimitry Andric                   false);
88059d6cff9SDimitry Andric     return;
88159d6cff9SDimitry Andric   }
88259d6cff9SDimitry Andric 
88393c91e39SDimitry Andric   // Move 128-bit floating-point values between VR128 and FP128.
88493c91e39SDimitry Andric   if (SystemZ::VR128BitRegClass.contains(DestReg) &&
88593c91e39SDimitry Andric       SystemZ::FP128BitRegClass.contains(SrcReg)) {
886706b4fc4SDimitry Andric     MCRegister SrcRegHi =
88793c91e39SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64),
888d8e91e46SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
889706b4fc4SDimitry Andric     MCRegister SrcRegLo =
89093c91e39SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64),
891d8e91e46SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
89293c91e39SDimitry Andric 
89393c91e39SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VMRHG), DestReg)
89493c91e39SDimitry Andric       .addReg(SrcRegHi, getKillRegState(KillSrc))
89593c91e39SDimitry Andric       .addReg(SrcRegLo, getKillRegState(KillSrc));
89693c91e39SDimitry Andric     return;
89793c91e39SDimitry Andric   }
89893c91e39SDimitry Andric   if (SystemZ::FP128BitRegClass.contains(DestReg) &&
89993c91e39SDimitry Andric       SystemZ::VR128BitRegClass.contains(SrcReg)) {
900706b4fc4SDimitry Andric     MCRegister DestRegHi =
90193c91e39SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_h64),
902d8e91e46SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
903706b4fc4SDimitry Andric     MCRegister DestRegLo =
90493c91e39SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_l64),
905d8e91e46SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
90693c91e39SDimitry Andric 
90793c91e39SDimitry Andric     if (DestRegHi != SrcReg)
90893c91e39SDimitry Andric       copyPhysReg(MBB, MBBI, DL, DestRegHi, SrcReg, false);
90993c91e39SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VREPG), DestRegLo)
91093c91e39SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1);
91193c91e39SDimitry Andric     return;
91293c91e39SDimitry Andric   }
91393c91e39SDimitry Andric 
914ac9a064cSDimitry Andric   if (SystemZ::FP128BitRegClass.contains(DestReg) &&
915ac9a064cSDimitry Andric       SystemZ::GR128BitRegClass.contains(SrcReg)) {
916ac9a064cSDimitry Andric     MCRegister DestRegHi = RI.getSubReg(DestReg, SystemZ::subreg_h64);
917ac9a064cSDimitry Andric     MCRegister DestRegLo = RI.getSubReg(DestReg, SystemZ::subreg_l64);
918ac9a064cSDimitry Andric     MCRegister SrcRegHi = RI.getSubReg(SrcReg, SystemZ::subreg_h64);
919ac9a064cSDimitry Andric     MCRegister SrcRegLo = RI.getSubReg(SrcReg, SystemZ::subreg_l64);
920ac9a064cSDimitry Andric 
921ac9a064cSDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegHi)
922ac9a064cSDimitry Andric         .addReg(SrcRegHi)
923ac9a064cSDimitry Andric         .addReg(DestReg, RegState::ImplicitDefine);
924ac9a064cSDimitry Andric 
925ac9a064cSDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegLo)
926ac9a064cSDimitry Andric         .addReg(SrcRegLo, getKillRegState(KillSrc));
927ac9a064cSDimitry Andric     return;
928ac9a064cSDimitry Andric   }
929ac9a064cSDimitry Andric 
930cfca06d7SDimitry Andric   // Move CC value from a GR32.
931eb11fae6SDimitry Andric   if (DestReg == SystemZ::CC) {
932cfca06d7SDimitry Andric     unsigned Opcode =
933cfca06d7SDimitry Andric       SystemZ::GR32BitRegClass.contains(SrcReg) ? SystemZ::TMLH : SystemZ::TMHH;
934cfca06d7SDimitry Andric     BuildMI(MBB, MBBI, DL, get(Opcode))
935eb11fae6SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc))
936eb11fae6SDimitry Andric       .addImm(3 << (SystemZ::IPM_CC - 16));
937eb11fae6SDimitry Andric     return;
938eb11fae6SDimitry Andric   }
939eb11fae6SDimitry Andric 
940ac9a064cSDimitry Andric   if (SystemZ::GR128BitRegClass.contains(DestReg) &&
941ac9a064cSDimitry Andric       SystemZ::VR128BitRegClass.contains(SrcReg)) {
942ac9a064cSDimitry Andric     MCRegister DestH64 = RI.getSubReg(DestReg, SystemZ::subreg_h64);
943ac9a064cSDimitry Andric     MCRegister DestL64 = RI.getSubReg(DestReg, SystemZ::subreg_l64);
944ac9a064cSDimitry Andric 
945ac9a064cSDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestH64)
946ac9a064cSDimitry Andric         .addReg(SrcReg)
947ac9a064cSDimitry Andric         .addReg(SystemZ::NoRegister)
948ac9a064cSDimitry Andric         .addImm(0)
949ac9a064cSDimitry Andric         .addDef(DestReg, RegState::Implicit);
950ac9a064cSDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestL64)
951ac9a064cSDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
952ac9a064cSDimitry Andric         .addReg(SystemZ::NoRegister)
953ac9a064cSDimitry Andric         .addImm(1);
954ac9a064cSDimitry Andric     return;
955ac9a064cSDimitry Andric   }
956ac9a064cSDimitry Andric 
957ac9a064cSDimitry Andric   if (SystemZ::VR128BitRegClass.contains(DestReg) &&
958ac9a064cSDimitry Andric       SystemZ::GR128BitRegClass.contains(SrcReg)) {
959ac9a064cSDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLVGP), DestReg)
960ac9a064cSDimitry Andric         .addReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64))
961ac9a064cSDimitry Andric         .addReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64));
962ac9a064cSDimitry Andric     return;
963ac9a064cSDimitry Andric   }
964ac9a064cSDimitry Andric 
96559d6cff9SDimitry Andric   // Everything else needs only one instruction.
96659d6cff9SDimitry Andric   unsigned Opcode;
967f8af5cf6SDimitry Andric   if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg))
96859d6cff9SDimitry Andric     Opcode = SystemZ::LGR;
96959d6cff9SDimitry Andric   else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg))
97001095a5dSDimitry Andric     // For z13 we prefer LDR over LER to avoid partial register dependencies.
97101095a5dSDimitry Andric     Opcode = STI.hasVector() ? SystemZ::LDR32 : SystemZ::LER;
97259d6cff9SDimitry Andric   else if (SystemZ::FP64BitRegClass.contains(DestReg, SrcReg))
97359d6cff9SDimitry Andric     Opcode = SystemZ::LDR;
97459d6cff9SDimitry Andric   else if (SystemZ::FP128BitRegClass.contains(DestReg, SrcReg))
97559d6cff9SDimitry Andric     Opcode = SystemZ::LXR;
9765a5ac124SDimitry Andric   else if (SystemZ::VR32BitRegClass.contains(DestReg, SrcReg))
9775a5ac124SDimitry Andric     Opcode = SystemZ::VLR32;
9785a5ac124SDimitry Andric   else if (SystemZ::VR64BitRegClass.contains(DestReg, SrcReg))
9795a5ac124SDimitry Andric     Opcode = SystemZ::VLR64;
9805a5ac124SDimitry Andric   else if (SystemZ::VR128BitRegClass.contains(DestReg, SrcReg))
9815a5ac124SDimitry Andric     Opcode = SystemZ::VLR;
982b915e9e0SDimitry Andric   else if (SystemZ::AR32BitRegClass.contains(DestReg, SrcReg))
983b915e9e0SDimitry Andric     Opcode = SystemZ::CPYA;
98459d6cff9SDimitry Andric   else
98559d6cff9SDimitry Andric     llvm_unreachable("Impossible reg-to-reg copy");
98659d6cff9SDimitry Andric 
98759d6cff9SDimitry Andric   BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
98859d6cff9SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc));
98959d6cff9SDimitry Andric }
99059d6cff9SDimitry Andric 
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,Register SrcReg,bool isKill,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const991dd58ef01SDimitry Andric void SystemZInstrInfo::storeRegToStackSlot(
992cfca06d7SDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
993dd58ef01SDimitry Andric     bool isKill, int FrameIdx, const TargetRegisterClass *RC,
994e3b55780SDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
99559d6cff9SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
99659d6cff9SDimitry Andric 
99759d6cff9SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
99859d6cff9SDimitry Andric   // together for now and lower them after register allocation.
99959d6cff9SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
100059d6cff9SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
100159d6cff9SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))
1002dd58ef01SDimitry Andric                         .addReg(SrcReg, getKillRegState(isKill)),
1003dd58ef01SDimitry Andric                     FrameIdx);
100459d6cff9SDimitry Andric }
100559d6cff9SDimitry Andric 
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,Register DestReg,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg) const1006e3b55780SDimitry Andric void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
1007e3b55780SDimitry Andric                                             MachineBasicBlock::iterator MBBI,
1008e3b55780SDimitry Andric                                             Register DestReg, int FrameIdx,
1009e3b55780SDimitry Andric                                             const TargetRegisterClass *RC,
1010e3b55780SDimitry Andric                                             const TargetRegisterInfo *TRI,
1011e3b55780SDimitry Andric                                             Register VReg) const {
101259d6cff9SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
101359d6cff9SDimitry Andric 
101459d6cff9SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
101559d6cff9SDimitry Andric   // together for now and lower them after register allocation.
101659d6cff9SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
101759d6cff9SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
101859d6cff9SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg),
101959d6cff9SDimitry Andric                     FrameIdx);
102059d6cff9SDimitry Andric }
102159d6cff9SDimitry Andric 
1022f8af5cf6SDimitry Andric // Return true if MI is a simple load or store with a 12-bit displacement
1023f8af5cf6SDimitry Andric // and no index.  Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
isSimpleBD12Move(const MachineInstr * MI,unsigned Flag)1024f8af5cf6SDimitry Andric static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) {
1025f8af5cf6SDimitry Andric   const MCInstrDesc &MCID = MI->getDesc();
1026f8af5cf6SDimitry Andric   return ((MCID.TSFlags & Flag) &&
1027f8af5cf6SDimitry Andric           isUInt<12>(MI->getOperand(2).getImm()) &&
1028f8af5cf6SDimitry Andric           MI->getOperand(3).getReg() == 0);
1029f8af5cf6SDimitry Andric }
1030f8af5cf6SDimitry Andric 
1031f8af5cf6SDimitry Andric namespace {
103271d5a254SDimitry Andric 
1033f8af5cf6SDimitry Andric struct LogicOp {
103471d5a254SDimitry Andric   LogicOp() = default;
LogicOp__anon07f439840311::LogicOp1035f8af5cf6SDimitry Andric   LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize)
1036f8af5cf6SDimitry Andric     : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {}
1037f8af5cf6SDimitry Andric 
operator bool__anon07f439840311::LogicOp10385a5ac124SDimitry Andric   explicit operator bool() const { return RegSize; }
1039f8af5cf6SDimitry Andric 
104071d5a254SDimitry Andric   unsigned RegSize = 0;
104171d5a254SDimitry Andric   unsigned ImmLSB = 0;
104271d5a254SDimitry Andric   unsigned ImmSize = 0;
1043f8af5cf6SDimitry Andric };
104471d5a254SDimitry Andric 
10455ca98fd9SDimitry Andric } // end anonymous namespace
1046f8af5cf6SDimitry Andric 
interpretAndImmediate(unsigned Opcode)1047f8af5cf6SDimitry Andric static LogicOp interpretAndImmediate(unsigned Opcode) {
1048f8af5cf6SDimitry Andric   switch (Opcode) {
1049f8af5cf6SDimitry Andric   case SystemZ::NILMux: return LogicOp(32,  0, 16);
1050f8af5cf6SDimitry Andric   case SystemZ::NIHMux: return LogicOp(32, 16, 16);
1051f8af5cf6SDimitry Andric   case SystemZ::NILL64: return LogicOp(64,  0, 16);
1052f8af5cf6SDimitry Andric   case SystemZ::NILH64: return LogicOp(64, 16, 16);
1053f8af5cf6SDimitry Andric   case SystemZ::NIHL64: return LogicOp(64, 32, 16);
1054f8af5cf6SDimitry Andric   case SystemZ::NIHH64: return LogicOp(64, 48, 16);
1055f8af5cf6SDimitry Andric   case SystemZ::NIFMux: return LogicOp(32,  0, 32);
1056f8af5cf6SDimitry Andric   case SystemZ::NILF64: return LogicOp(64,  0, 32);
1057f8af5cf6SDimitry Andric   case SystemZ::NIHF64: return LogicOp(64, 32, 32);
1058f8af5cf6SDimitry Andric   default:              return LogicOp();
1059f8af5cf6SDimitry Andric   }
1060f8af5cf6SDimitry Andric }
1061f8af5cf6SDimitry Andric 
transferDeadCC(MachineInstr * OldMI,MachineInstr * NewMI)106201095a5dSDimitry Andric static void transferDeadCC(MachineInstr *OldMI, MachineInstr *NewMI) {
1063ac9a064cSDimitry Andric   if (OldMI->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr)) {
1064ac9a064cSDimitry Andric     MachineOperand *CCDef =
1065ac9a064cSDimitry Andric         NewMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr);
106601095a5dSDimitry Andric     if (CCDef != nullptr)
106701095a5dSDimitry Andric       CCDef->setIsDead(true);
106801095a5dSDimitry Andric   }
106901095a5dSDimitry Andric }
107001095a5dSDimitry Andric 
transferMIFlag(MachineInstr * OldMI,MachineInstr * NewMI,MachineInstr::MIFlag Flag)1071706b4fc4SDimitry Andric static void transferMIFlag(MachineInstr *OldMI, MachineInstr *NewMI,
1072706b4fc4SDimitry Andric                            MachineInstr::MIFlag Flag) {
1073706b4fc4SDimitry Andric   if (OldMI->getFlag(Flag))
1074706b4fc4SDimitry Andric     NewMI->setFlag(Flag);
1075706b4fc4SDimitry Andric }
1076706b4fc4SDimitry Andric 
1077c0981da4SDimitry Andric MachineInstr *
convertToThreeAddress(MachineInstr & MI,LiveVariables * LV,LiveIntervals * LIS) const1078c0981da4SDimitry Andric SystemZInstrInfo::convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
1079c0981da4SDimitry Andric                                         LiveIntervals *LIS) const {
108001095a5dSDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
1081f8af5cf6SDimitry Andric 
1082f8af5cf6SDimitry Andric   // Try to convert an AND into an RISBG-type instruction.
1083e6d15924SDimitry Andric   // TODO: It might be beneficial to select RISBG and shorten to AND instead.
1084e6d15924SDimitry Andric   if (LogicOp And = interpretAndImmediate(MI.getOpcode())) {
108501095a5dSDimitry Andric     uint64_t Imm = MI.getOperand(2).getImm() << And.ImmLSB;
1086f8af5cf6SDimitry Andric     // AND IMMEDIATE leaves the other bits of the register unchanged.
1087f8af5cf6SDimitry Andric     Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB);
1088f8af5cf6SDimitry Andric     unsigned Start, End;
1089f8af5cf6SDimitry Andric     if (isRxSBGMask(Imm, And.RegSize, Start, End)) {
1090f8af5cf6SDimitry Andric       unsigned NewOpcode;
10915a5ac124SDimitry Andric       if (And.RegSize == 64) {
1092f8af5cf6SDimitry Andric         NewOpcode = SystemZ::RISBG;
10935a5ac124SDimitry Andric         // Prefer RISBGN if available, since it does not clobber CC.
10945a5ac124SDimitry Andric         if (STI.hasMiscellaneousExtensions())
10955a5ac124SDimitry Andric           NewOpcode = SystemZ::RISBGN;
10965a5ac124SDimitry Andric       } else {
1097f8af5cf6SDimitry Andric         NewOpcode = SystemZ::RISBMux;
1098f8af5cf6SDimitry Andric         Start &= 31;
1099f8af5cf6SDimitry Andric         End &= 31;
1100f8af5cf6SDimitry Andric       }
110101095a5dSDimitry Andric       MachineOperand &Dest = MI.getOperand(0);
110201095a5dSDimitry Andric       MachineOperand &Src = MI.getOperand(1);
1103f8af5cf6SDimitry Andric       MachineInstrBuilder MIB =
110401095a5dSDimitry Andric           BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpcode))
110571d5a254SDimitry Andric               .add(Dest)
110601095a5dSDimitry Andric               .addReg(0)
110701095a5dSDimitry Andric               .addReg(Src.getReg(), getKillRegState(Src.isKill()),
110801095a5dSDimitry Andric                       Src.getSubReg())
110901095a5dSDimitry Andric               .addImm(Start)
111001095a5dSDimitry Andric               .addImm(End + 128)
111101095a5dSDimitry Andric               .addImm(0);
1112e6d15924SDimitry Andric       if (LV) {
1113e6d15924SDimitry Andric         unsigned NumOps = MI.getNumOperands();
1114e6d15924SDimitry Andric         for (unsigned I = 1; I < NumOps; ++I) {
1115e6d15924SDimitry Andric           MachineOperand &Op = MI.getOperand(I);
1116e6d15924SDimitry Andric           if (Op.isReg() && Op.isKill())
1117e6d15924SDimitry Andric             LV->replaceKillInstruction(Op.getReg(), MI, *MIB);
1118e6d15924SDimitry Andric         }
1119e6d15924SDimitry Andric       }
1120c0981da4SDimitry Andric       if (LIS)
1121c0981da4SDimitry Andric         LIS->ReplaceMachineInstrInMaps(MI, *MIB);
1122e6d15924SDimitry Andric       transferDeadCC(&MI, MIB);
1123e6d15924SDimitry Andric       return MIB;
1124f8af5cf6SDimitry Andric     }
1125f8af5cf6SDimitry Andric   }
11265ca98fd9SDimitry Andric   return nullptr;
1127f8af5cf6SDimitry Andric }
1128f8af5cf6SDimitry Andric 
isAssociativeAndCommutative(const MachineInstr & Inst,bool Invert) const1129ac9a064cSDimitry Andric bool SystemZInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
1130ac9a064cSDimitry Andric                                                    bool Invert) const {
1131ac9a064cSDimitry Andric   unsigned Opc = Inst.getOpcode();
1132ac9a064cSDimitry Andric   if (Invert) {
1133ac9a064cSDimitry Andric     auto InverseOpcode = getInverseOpcode(Opc);
1134ac9a064cSDimitry Andric     if (!InverseOpcode)
1135ac9a064cSDimitry Andric       return false;
1136ac9a064cSDimitry Andric     Opc = *InverseOpcode;
1137ac9a064cSDimitry Andric   }
1138ac9a064cSDimitry Andric 
1139ac9a064cSDimitry Andric   switch (Opc) {
1140ac9a064cSDimitry Andric   default:
1141ac9a064cSDimitry Andric     break;
1142ac9a064cSDimitry Andric   // Adds and multiplications.
1143ac9a064cSDimitry Andric   case SystemZ::WFADB:
1144ac9a064cSDimitry Andric   case SystemZ::WFASB:
1145ac9a064cSDimitry Andric   case SystemZ::WFAXB:
1146ac9a064cSDimitry Andric   case SystemZ::VFADB:
1147ac9a064cSDimitry Andric   case SystemZ::VFASB:
1148ac9a064cSDimitry Andric   case SystemZ::WFMDB:
1149ac9a064cSDimitry Andric   case SystemZ::WFMSB:
1150ac9a064cSDimitry Andric   case SystemZ::WFMXB:
1151ac9a064cSDimitry Andric   case SystemZ::VFMDB:
1152ac9a064cSDimitry Andric   case SystemZ::VFMSB:
1153ac9a064cSDimitry Andric     return (Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&
1154ac9a064cSDimitry Andric             Inst.getFlag(MachineInstr::MIFlag::FmNsz));
1155ac9a064cSDimitry Andric   }
1156ac9a064cSDimitry Andric 
1157ac9a064cSDimitry Andric   return false;
1158ac9a064cSDimitry Andric }
1159ac9a064cSDimitry Andric 
1160ac9a064cSDimitry Andric std::optional<unsigned>
getInverseOpcode(unsigned Opcode) const1161ac9a064cSDimitry Andric SystemZInstrInfo::getInverseOpcode(unsigned Opcode) const {
1162ac9a064cSDimitry Andric   // fadd => fsub
1163ac9a064cSDimitry Andric   switch (Opcode) {
1164ac9a064cSDimitry Andric   case SystemZ::WFADB:
1165ac9a064cSDimitry Andric     return SystemZ::WFSDB;
1166ac9a064cSDimitry Andric   case SystemZ::WFASB:
1167ac9a064cSDimitry Andric     return SystemZ::WFSSB;
1168ac9a064cSDimitry Andric   case SystemZ::WFAXB:
1169ac9a064cSDimitry Andric     return SystemZ::WFSXB;
1170ac9a064cSDimitry Andric   case SystemZ::VFADB:
1171ac9a064cSDimitry Andric     return SystemZ::VFSDB;
1172ac9a064cSDimitry Andric   case SystemZ::VFASB:
1173ac9a064cSDimitry Andric     return SystemZ::VFSSB;
1174ac9a064cSDimitry Andric   // fsub => fadd
1175ac9a064cSDimitry Andric   case SystemZ::WFSDB:
1176ac9a064cSDimitry Andric     return SystemZ::WFADB;
1177ac9a064cSDimitry Andric   case SystemZ::WFSSB:
1178ac9a064cSDimitry Andric     return SystemZ::WFASB;
1179ac9a064cSDimitry Andric   case SystemZ::WFSXB:
1180ac9a064cSDimitry Andric     return SystemZ::WFAXB;
1181ac9a064cSDimitry Andric   case SystemZ::VFSDB:
1182ac9a064cSDimitry Andric     return SystemZ::VFADB;
1183ac9a064cSDimitry Andric   case SystemZ::VFSSB:
1184ac9a064cSDimitry Andric     return SystemZ::VFASB;
1185ac9a064cSDimitry Andric   default:
1186ac9a064cSDimitry Andric     return std::nullopt;
1187ac9a064cSDimitry Andric   }
1188ac9a064cSDimitry Andric }
1189ac9a064cSDimitry Andric 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,int FrameIndex,LiveIntervals * LIS,VirtRegMap * VRM) const119085d8b2bbSDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
119101095a5dSDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
119201095a5dSDimitry Andric     MachineBasicBlock::iterator InsertPt, int FrameIndex,
1193e6d15924SDimitry Andric     LiveIntervals *LIS, VirtRegMap *VRM) const {
119401095a5dSDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1195cfca06d7SDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
1196b915e9e0SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1197b915e9e0SDimitry Andric   unsigned Size = MFI.getObjectSize(FrameIndex);
119801095a5dSDimitry Andric   unsigned Opcode = MI.getOpcode();
1199f8af5cf6SDimitry Andric 
1200cfca06d7SDimitry Andric   // Check CC liveness if new instruction introduces a dead def of CC.
1201cfca06d7SDimitry Andric   SlotIndex MISlot = SlotIndex();
1202cfca06d7SDimitry Andric   LiveRange *CCLiveRange = nullptr;
1203cfca06d7SDimitry Andric   bool CCLiveAtMI = true;
1204cfca06d7SDimitry Andric   if (LIS) {
1205cfca06d7SDimitry Andric     MISlot = LIS->getSlotIndexes()->getInstructionIndex(MI).getRegSlot();
12067fa27ce4SDimitry Andric     auto CCUnits = TRI->regunits(MCRegister::from(SystemZ::CC));
12077fa27ce4SDimitry Andric     assert(range_size(CCUnits) == 1 && "CC only has one reg unit.");
12087fa27ce4SDimitry Andric     CCLiveRange = &LIS->getRegUnit(*CCUnits.begin());
1209cfca06d7SDimitry Andric     CCLiveAtMI = CCLiveRange->liveAt(MISlot);
1210cfca06d7SDimitry Andric   }
1211cfca06d7SDimitry Andric 
1212cfca06d7SDimitry Andric   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
1213cfca06d7SDimitry Andric     if (!CCLiveAtMI && (Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&
1214cfca06d7SDimitry Andric         isInt<8>(MI.getOperand(2).getImm()) && !MI.getOperand(3).getReg()) {
1215f8af5cf6SDimitry Andric       // LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST
121601095a5dSDimitry Andric       MachineInstr *BuiltMI = BuildMI(*InsertPt->getParent(), InsertPt,
121701095a5dSDimitry Andric                                       MI.getDebugLoc(), get(SystemZ::AGSI))
121885d8b2bbSDimitry Andric         .addFrameIndex(FrameIndex)
121985d8b2bbSDimitry Andric         .addImm(0)
122001095a5dSDimitry Andric         .addImm(MI.getOperand(2).getImm());
1221ac9a064cSDimitry Andric       BuiltMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr)
1222ac9a064cSDimitry Andric           ->setIsDead(true);
1223cfca06d7SDimitry Andric       CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());
122401095a5dSDimitry Andric       return BuiltMI;
122501095a5dSDimitry Andric     }
12265ca98fd9SDimitry Andric     return nullptr;
1227f8af5cf6SDimitry Andric   }
1228f8af5cf6SDimitry Andric 
1229f8af5cf6SDimitry Andric   // All other cases require a single operand.
1230f8af5cf6SDimitry Andric   if (Ops.size() != 1)
12315ca98fd9SDimitry Andric     return nullptr;
1232f8af5cf6SDimitry Andric 
1233f8af5cf6SDimitry Andric   unsigned OpNum = Ops[0];
123412f3ca4cSDimitry Andric   assert(Size * 8 ==
123512f3ca4cSDimitry Andric            TRI->getRegSizeInBits(*MF.getRegInfo()
123612f3ca4cSDimitry Andric                                .getRegClass(MI.getOperand(OpNum).getReg())) &&
1237f8af5cf6SDimitry Andric          "Invalid size combination");
1238f8af5cf6SDimitry Andric 
123901095a5dSDimitry Andric   if ((Opcode == SystemZ::AHI || Opcode == SystemZ::AGHI) && OpNum == 0 &&
124001095a5dSDimitry Andric       isInt<8>(MI.getOperand(2).getImm())) {
1241f8af5cf6SDimitry Andric     // A(G)HI %reg, CONST -> A(G)SI %mem, CONST
1242f8af5cf6SDimitry Andric     Opcode = (Opcode == SystemZ::AHI ? SystemZ::ASI : SystemZ::AGSI);
124301095a5dSDimitry Andric     MachineInstr *BuiltMI =
124401095a5dSDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
124585d8b2bbSDimitry Andric             .addFrameIndex(FrameIndex)
124685d8b2bbSDimitry Andric             .addImm(0)
124701095a5dSDimitry Andric             .addImm(MI.getOperand(2).getImm());
124801095a5dSDimitry Andric     transferDeadCC(&MI, BuiltMI);
1249706b4fc4SDimitry Andric     transferMIFlag(&MI, BuiltMI, MachineInstr::NoSWrap);
125001095a5dSDimitry Andric     return BuiltMI;
1251f8af5cf6SDimitry Andric   }
1252f8af5cf6SDimitry Andric 
1253eb11fae6SDimitry Andric   if ((Opcode == SystemZ::ALFI && OpNum == 0 &&
1254eb11fae6SDimitry Andric        isInt<8>((int32_t)MI.getOperand(2).getImm())) ||
1255eb11fae6SDimitry Andric       (Opcode == SystemZ::ALGFI && OpNum == 0 &&
1256eb11fae6SDimitry Andric        isInt<8>((int64_t)MI.getOperand(2).getImm()))) {
1257eb11fae6SDimitry Andric     // AL(G)FI %reg, CONST -> AL(G)SI %mem, CONST
1258eb11fae6SDimitry Andric     Opcode = (Opcode == SystemZ::ALFI ? SystemZ::ALSI : SystemZ::ALGSI);
1259eb11fae6SDimitry Andric     MachineInstr *BuiltMI =
1260eb11fae6SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
1261eb11fae6SDimitry Andric             .addFrameIndex(FrameIndex)
1262eb11fae6SDimitry Andric             .addImm(0)
1263eb11fae6SDimitry Andric             .addImm((int8_t)MI.getOperand(2).getImm());
1264eb11fae6SDimitry Andric     transferDeadCC(&MI, BuiltMI);
1265eb11fae6SDimitry Andric     return BuiltMI;
1266eb11fae6SDimitry Andric   }
1267eb11fae6SDimitry Andric 
1268eb11fae6SDimitry Andric   if ((Opcode == SystemZ::SLFI && OpNum == 0 &&
1269eb11fae6SDimitry Andric        isInt<8>((int32_t)-MI.getOperand(2).getImm())) ||
1270eb11fae6SDimitry Andric       (Opcode == SystemZ::SLGFI && OpNum == 0 &&
1271eb11fae6SDimitry Andric        isInt<8>((int64_t)-MI.getOperand(2).getImm()))) {
1272eb11fae6SDimitry Andric     // SL(G)FI %reg, CONST -> AL(G)SI %mem, -CONST
1273eb11fae6SDimitry Andric     Opcode = (Opcode == SystemZ::SLFI ? SystemZ::ALSI : SystemZ::ALGSI);
1274eb11fae6SDimitry Andric     MachineInstr *BuiltMI =
1275eb11fae6SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
1276eb11fae6SDimitry Andric             .addFrameIndex(FrameIndex)
1277eb11fae6SDimitry Andric             .addImm(0)
1278eb11fae6SDimitry Andric             .addImm((int8_t)-MI.getOperand(2).getImm());
1279eb11fae6SDimitry Andric     transferDeadCC(&MI, BuiltMI);
1280eb11fae6SDimitry Andric     return BuiltMI;
1281eb11fae6SDimitry Andric   }
1282eb11fae6SDimitry Andric 
1283cfca06d7SDimitry Andric   unsigned MemImmOpc = 0;
1284cfca06d7SDimitry Andric   switch (Opcode) {
1285cfca06d7SDimitry Andric   case SystemZ::LHIMux:
1286cfca06d7SDimitry Andric   case SystemZ::LHI:    MemImmOpc = SystemZ::MVHI;  break;
1287cfca06d7SDimitry Andric   case SystemZ::LGHI:   MemImmOpc = SystemZ::MVGHI; break;
1288cfca06d7SDimitry Andric   case SystemZ::CHIMux:
1289cfca06d7SDimitry Andric   case SystemZ::CHI:    MemImmOpc = SystemZ::CHSI;  break;
1290cfca06d7SDimitry Andric   case SystemZ::CGHI:   MemImmOpc = SystemZ::CGHSI; break;
1291cfca06d7SDimitry Andric   case SystemZ::CLFIMux:
1292cfca06d7SDimitry Andric   case SystemZ::CLFI:
1293cfca06d7SDimitry Andric     if (isUInt<16>(MI.getOperand(1).getImm()))
1294cfca06d7SDimitry Andric       MemImmOpc = SystemZ::CLFHSI;
1295cfca06d7SDimitry Andric     break;
1296cfca06d7SDimitry Andric   case SystemZ::CLGFI:
1297cfca06d7SDimitry Andric     if (isUInt<16>(MI.getOperand(1).getImm()))
1298cfca06d7SDimitry Andric       MemImmOpc = SystemZ::CLGHSI;
1299cfca06d7SDimitry Andric     break;
1300cfca06d7SDimitry Andric   default: break;
1301cfca06d7SDimitry Andric   }
1302cfca06d7SDimitry Andric   if (MemImmOpc)
1303cfca06d7SDimitry Andric     return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
1304cfca06d7SDimitry Andric                    get(MemImmOpc))
1305cfca06d7SDimitry Andric                .addFrameIndex(FrameIndex)
1306cfca06d7SDimitry Andric                .addImm(0)
1307cfca06d7SDimitry Andric                .addImm(MI.getOperand(1).getImm());
1308cfca06d7SDimitry Andric 
1309f8af5cf6SDimitry Andric   if (Opcode == SystemZ::LGDR || Opcode == SystemZ::LDGR) {
1310f8af5cf6SDimitry Andric     bool Op0IsGPR = (Opcode == SystemZ::LGDR);
1311f8af5cf6SDimitry Andric     bool Op1IsGPR = (Opcode == SystemZ::LDGR);
1312f8af5cf6SDimitry Andric     // If we're spilling the destination of an LDGR or LGDR, store the
1313f8af5cf6SDimitry Andric     // source register instead.
1314f8af5cf6SDimitry Andric     if (OpNum == 0) {
1315f8af5cf6SDimitry Andric       unsigned StoreOpcode = Op1IsGPR ? SystemZ::STG : SystemZ::STD;
131601095a5dSDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
131785d8b2bbSDimitry Andric                      get(StoreOpcode))
131871d5a254SDimitry Andric           .add(MI.getOperand(1))
131985d8b2bbSDimitry Andric           .addFrameIndex(FrameIndex)
132085d8b2bbSDimitry Andric           .addImm(0)
132185d8b2bbSDimitry Andric           .addReg(0);
1322f8af5cf6SDimitry Andric     }
1323f8af5cf6SDimitry Andric     // If we're spilling the source of an LDGR or LGDR, load the
1324f8af5cf6SDimitry Andric     // destination register instead.
1325f8af5cf6SDimitry Andric     if (OpNum == 1) {
1326f8af5cf6SDimitry Andric       unsigned LoadOpcode = Op0IsGPR ? SystemZ::LG : SystemZ::LD;
132701095a5dSDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
132871d5a254SDimitry Andric                      get(LoadOpcode))
132971d5a254SDimitry Andric         .add(MI.getOperand(0))
133085d8b2bbSDimitry Andric         .addFrameIndex(FrameIndex)
133185d8b2bbSDimitry Andric         .addImm(0)
133285d8b2bbSDimitry Andric         .addReg(0);
1333f8af5cf6SDimitry Andric     }
1334f8af5cf6SDimitry Andric   }
1335f8af5cf6SDimitry Andric 
1336f8af5cf6SDimitry Andric   // Look for cases where the source of a simple store or the destination
1337f8af5cf6SDimitry Andric   // of a simple load is being spilled.  Try to use MVC instead.
1338f8af5cf6SDimitry Andric   //
1339f8af5cf6SDimitry Andric   // Although MVC is in practice a fast choice in these cases, it is still
1340f8af5cf6SDimitry Andric   // logically a bytewise copy.  This means that we cannot use it if the
1341f8af5cf6SDimitry Andric   // load or store is volatile.  We also wouldn't be able to use MVC if
1342f8af5cf6SDimitry Andric   // the two memories partially overlap, but that case cannot occur here,
1343f8af5cf6SDimitry Andric   // because we know that one of the memories is a full frame index.
1344f8af5cf6SDimitry Andric   //
1345f8af5cf6SDimitry Andric   // For performance reasons, we also want to avoid using MVC if the addresses
1346f8af5cf6SDimitry Andric   // might be equal.  We don't worry about that case here, because spill slot
1347f8af5cf6SDimitry Andric   // coloring happens later, and because we have special code to remove
1348f8af5cf6SDimitry Andric   // MVCs that turn out to be redundant.
134901095a5dSDimitry Andric   if (OpNum == 0 && MI.hasOneMemOperand()) {
135001095a5dSDimitry Andric     MachineMemOperand *MMO = *MI.memoperands_begin();
1351e6d15924SDimitry Andric     if (MMO->getSize() == Size && !MMO->isVolatile() && !MMO->isAtomic()) {
1352f8af5cf6SDimitry Andric       // Handle conversion of loads.
135301095a5dSDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXLoad)) {
135401095a5dSDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
135585d8b2bbSDimitry Andric                        get(SystemZ::MVC))
135685d8b2bbSDimitry Andric             .addFrameIndex(FrameIndex)
135785d8b2bbSDimitry Andric             .addImm(0)
135885d8b2bbSDimitry Andric             .addImm(Size)
135971d5a254SDimitry Andric             .add(MI.getOperand(1))
136001095a5dSDimitry Andric             .addImm(MI.getOperand(2).getImm())
1361f8af5cf6SDimitry Andric             .addMemOperand(MMO);
1362f8af5cf6SDimitry Andric       }
1363f8af5cf6SDimitry Andric       // Handle conversion of stores.
136401095a5dSDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXStore)) {
136501095a5dSDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
136685d8b2bbSDimitry Andric                        get(SystemZ::MVC))
136771d5a254SDimitry Andric             .add(MI.getOperand(1))
136801095a5dSDimitry Andric             .addImm(MI.getOperand(2).getImm())
136985d8b2bbSDimitry Andric             .addImm(Size)
137085d8b2bbSDimitry Andric             .addFrameIndex(FrameIndex)
137185d8b2bbSDimitry Andric             .addImm(0)
1372f8af5cf6SDimitry Andric             .addMemOperand(MMO);
1373f8af5cf6SDimitry Andric       }
1374f8af5cf6SDimitry Andric     }
1375f8af5cf6SDimitry Andric   }
1376f8af5cf6SDimitry Andric 
1377e6d15924SDimitry Andric   // If the spilled operand is the final one or the instruction is
1378cfca06d7SDimitry Andric   // commutable, try to change <INSN>R into <INSN>.  Don't introduce a def of
1379cfca06d7SDimitry Andric   // CC if it is live and MI does not define it.
138001095a5dSDimitry Andric   unsigned NumOps = MI.getNumExplicitOperands();
1381e6d15924SDimitry Andric   int MemOpcode = SystemZ::getMemOpcode(Opcode);
1382cfca06d7SDimitry Andric   if (MemOpcode == -1 ||
1383ac9a064cSDimitry Andric       (CCLiveAtMI && !MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&
1384cfca06d7SDimitry Andric        get(MemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)))
1385cfca06d7SDimitry Andric     return nullptr;
1386cfca06d7SDimitry Andric 
1387cfca06d7SDimitry Andric   // Check if all other vregs have a usable allocation in the case of vector
1388cfca06d7SDimitry Andric   // to FP conversion.
1389cfca06d7SDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
1390cfca06d7SDimitry Andric   for (unsigned I = 0, E = MCID.getNumOperands(); I != E; ++I) {
1391e3b55780SDimitry Andric     const MCOperandInfo &MCOI = MCID.operands()[I];
1392cfca06d7SDimitry Andric     if (MCOI.OperandType != MCOI::OPERAND_REGISTER || I == OpNum)
1393cfca06d7SDimitry Andric       continue;
1394cfca06d7SDimitry Andric     const TargetRegisterClass *RC = TRI->getRegClass(MCOI.RegClass);
1395cfca06d7SDimitry Andric     if (RC == &SystemZ::VR32BitRegClass || RC == &SystemZ::VR64BitRegClass) {
1396cfca06d7SDimitry Andric       Register Reg = MI.getOperand(I).getReg();
1397e3b55780SDimitry Andric       Register PhysReg = Reg.isVirtual()
1398b60736ecSDimitry Andric                              ? (VRM ? Register(VRM->getPhys(Reg)) : Register())
1399cfca06d7SDimitry Andric                              : Reg;
1400cfca06d7SDimitry Andric       if (!PhysReg ||
1401cfca06d7SDimitry Andric           !(SystemZ::FP32BitRegClass.contains(PhysReg) ||
1402cfca06d7SDimitry Andric             SystemZ::FP64BitRegClass.contains(PhysReg) ||
1403cfca06d7SDimitry Andric             SystemZ::VF128BitRegClass.contains(PhysReg)))
1404cfca06d7SDimitry Andric         return nullptr;
1405cfca06d7SDimitry Andric     }
1406cfca06d7SDimitry Andric   }
1407cfca06d7SDimitry Andric   // Fused multiply and add/sub need to have the same dst and accumulator reg.
1408cfca06d7SDimitry Andric   bool FusedFPOp = (Opcode == SystemZ::WFMADB || Opcode == SystemZ::WFMASB ||
1409cfca06d7SDimitry Andric                     Opcode == SystemZ::WFMSDB || Opcode == SystemZ::WFMSSB);
1410cfca06d7SDimitry Andric   if (FusedFPOp) {
1411cfca06d7SDimitry Andric     Register DstReg = VRM->getPhys(MI.getOperand(0).getReg());
1412cfca06d7SDimitry Andric     Register AccReg = VRM->getPhys(MI.getOperand(3).getReg());
1413cfca06d7SDimitry Andric     if (OpNum == 0 || OpNum == 3 || DstReg != AccReg)
1414cfca06d7SDimitry Andric       return nullptr;
1415cfca06d7SDimitry Andric   }
1416cfca06d7SDimitry Andric 
1417cfca06d7SDimitry Andric   // Try to swap compare operands if possible.
1418cfca06d7SDimitry Andric   bool NeedsCommute = false;
1419cfca06d7SDimitry Andric   if ((MI.getOpcode() == SystemZ::CR || MI.getOpcode() == SystemZ::CGR ||
1420cfca06d7SDimitry Andric        MI.getOpcode() == SystemZ::CLR || MI.getOpcode() == SystemZ::CLGR ||
1421cfca06d7SDimitry Andric        MI.getOpcode() == SystemZ::WFCDB || MI.getOpcode() == SystemZ::WFCSB ||
1422cfca06d7SDimitry Andric        MI.getOpcode() == SystemZ::WFKDB || MI.getOpcode() == SystemZ::WFKSB) &&
1423cfca06d7SDimitry Andric       OpNum == 0 && prepareCompareSwapOperands(MI))
1424cfca06d7SDimitry Andric     NeedsCommute = true;
1425cfca06d7SDimitry Andric 
1426cfca06d7SDimitry Andric   bool CCOperands = false;
1427cfca06d7SDimitry Andric   if (MI.getOpcode() == SystemZ::LOCRMux || MI.getOpcode() == SystemZ::LOCGR ||
1428cfca06d7SDimitry Andric       MI.getOpcode() == SystemZ::SELRMux || MI.getOpcode() == SystemZ::SELGR) {
1429cfca06d7SDimitry Andric     assert(MI.getNumOperands() == 6 && NumOps == 5 &&
1430cfca06d7SDimitry Andric            "LOCR/SELR instruction operands corrupt?");
1431cfca06d7SDimitry Andric     NumOps -= 2;
1432cfca06d7SDimitry Andric     CCOperands = true;
1433cfca06d7SDimitry Andric   }
1434e6d15924SDimitry Andric 
1435e6d15924SDimitry Andric   // See if this is a 3-address instruction that is convertible to 2-address
1436e6d15924SDimitry Andric   // and suitable for folding below.  Only try this with virtual registers
1437e6d15924SDimitry Andric   // and a provided VRM (during regalloc).
1438cfca06d7SDimitry Andric   if (NumOps == 3 && SystemZ::getTargetMemOpcode(MemOpcode) != -1) {
1439e6d15924SDimitry Andric     if (VRM == nullptr)
1440cfca06d7SDimitry Andric       return nullptr;
1441e6d15924SDimitry Andric     else {
1442e6d15924SDimitry Andric       Register DstReg = MI.getOperand(0).getReg();
1443e6d15924SDimitry Andric       Register DstPhys =
1444e3b55780SDimitry Andric           (DstReg.isVirtual() ? Register(VRM->getPhys(DstReg)) : DstReg);
1445e6d15924SDimitry Andric       Register SrcReg = (OpNum == 2 ? MI.getOperand(1).getReg()
1446e6d15924SDimitry Andric                                     : ((OpNum == 1 && MI.isCommutable())
1447e6d15924SDimitry Andric                                            ? MI.getOperand(2).getReg()
1448e6d15924SDimitry Andric                                            : Register()));
1449e6d15924SDimitry Andric       if (DstPhys && !SystemZ::GRH32BitRegClass.contains(DstPhys) && SrcReg &&
1450e3b55780SDimitry Andric           SrcReg.isVirtual() && DstPhys == VRM->getPhys(SrcReg))
1451e6d15924SDimitry Andric         NeedsCommute = (OpNum == 1);
1452e6d15924SDimitry Andric       else
1453cfca06d7SDimitry Andric         return nullptr;
1454e6d15924SDimitry Andric     }
1455e6d15924SDimitry Andric   }
1456e6d15924SDimitry Andric 
1457cfca06d7SDimitry Andric   if ((OpNum == NumOps - 1) || NeedsCommute || FusedFPOp) {
1458f8af5cf6SDimitry Andric     const MCInstrDesc &MemDesc = get(MemOpcode);
1459f8af5cf6SDimitry Andric     uint64_t AccessBytes = SystemZII::getAccessSize(MemDesc.TSFlags);
1460f8af5cf6SDimitry Andric     assert(AccessBytes != 0 && "Size of access should be known");
1461f8af5cf6SDimitry Andric     assert(AccessBytes <= Size && "Access outside the frame index");
1462f8af5cf6SDimitry Andric     uint64_t Offset = Size - AccessBytes;
146385d8b2bbSDimitry Andric     MachineInstrBuilder MIB = BuildMI(*InsertPt->getParent(), InsertPt,
146401095a5dSDimitry Andric                                       MI.getDebugLoc(), get(MemOpcode));
1465cfca06d7SDimitry Andric     if (MI.isCompare()) {
1466cfca06d7SDimitry Andric       assert(NumOps == 2 && "Expected 2 register operands for a compare.");
1467cfca06d7SDimitry Andric       MIB.add(MI.getOperand(NeedsCommute ? 1 : 0));
1468cfca06d7SDimitry Andric     }
1469cfca06d7SDimitry Andric     else if (FusedFPOp) {
1470cfca06d7SDimitry Andric       MIB.add(MI.getOperand(0));
1471cfca06d7SDimitry Andric       MIB.add(MI.getOperand(3));
1472cfca06d7SDimitry Andric       MIB.add(MI.getOperand(OpNum == 1 ? 2 : 1));
1473cfca06d7SDimitry Andric     }
1474cfca06d7SDimitry Andric     else {
1475e6d15924SDimitry Andric       MIB.add(MI.getOperand(0));
1476e6d15924SDimitry Andric       if (NeedsCommute)
1477e6d15924SDimitry Andric         MIB.add(MI.getOperand(2));
1478e6d15924SDimitry Andric       else
1479e6d15924SDimitry Andric         for (unsigned I = 1; I < OpNum; ++I)
148071d5a254SDimitry Andric           MIB.add(MI.getOperand(I));
1481cfca06d7SDimitry Andric     }
1482f8af5cf6SDimitry Andric     MIB.addFrameIndex(FrameIndex).addImm(Offset);
1483f8af5cf6SDimitry Andric     if (MemDesc.TSFlags & SystemZII::HasIndex)
1484f8af5cf6SDimitry Andric       MIB.addReg(0);
1485cfca06d7SDimitry Andric     if (CCOperands) {
1486cfca06d7SDimitry Andric       unsigned CCValid = MI.getOperand(NumOps).getImm();
1487cfca06d7SDimitry Andric       unsigned CCMask = MI.getOperand(NumOps + 1).getImm();
1488cfca06d7SDimitry Andric       MIB.addImm(CCValid);
1489cfca06d7SDimitry Andric       MIB.addImm(NeedsCommute ? CCMask ^ CCValid : CCMask);
1490cfca06d7SDimitry Andric     }
1491ac9a064cSDimitry Andric     if (MIB->definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&
1492ac9a064cSDimitry Andric         (!MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) ||
1493ac9a064cSDimitry Andric          MI.registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))) {
1494cfca06d7SDimitry Andric       MIB->addRegisterDead(SystemZ::CC, TRI);
1495cfca06d7SDimitry Andric       if (CCLiveRange)
1496cfca06d7SDimitry Andric         CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());
1497cfca06d7SDimitry Andric     }
1498cfca06d7SDimitry Andric     // Constrain the register classes if converted from a vector opcode. The
1499cfca06d7SDimitry Andric     // allocated regs are in an FP reg-class per previous check above.
1500cfca06d7SDimitry Andric     for (const MachineOperand &MO : MIB->operands())
1501e3b55780SDimitry Andric       if (MO.isReg() && MO.getReg().isVirtual()) {
15026f8fc217SDimitry Andric         Register Reg = MO.getReg();
1503cfca06d7SDimitry Andric         if (MRI.getRegClass(Reg) == &SystemZ::VR32BitRegClass)
1504cfca06d7SDimitry Andric           MRI.setRegClass(Reg, &SystemZ::FP32BitRegClass);
1505cfca06d7SDimitry Andric         else if (MRI.getRegClass(Reg) == &SystemZ::VR64BitRegClass)
1506cfca06d7SDimitry Andric           MRI.setRegClass(Reg, &SystemZ::FP64BitRegClass);
1507cfca06d7SDimitry Andric         else if (MRI.getRegClass(Reg) == &SystemZ::VR128BitRegClass)
1508cfca06d7SDimitry Andric           MRI.setRegClass(Reg, &SystemZ::VF128BitRegClass);
1509cfca06d7SDimitry Andric       }
1510cfca06d7SDimitry Andric 
151101095a5dSDimitry Andric     transferDeadCC(&MI, MIB);
1512706b4fc4SDimitry Andric     transferMIFlag(&MI, MIB, MachineInstr::NoSWrap);
1513cfca06d7SDimitry Andric     transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);
1514f8af5cf6SDimitry Andric     return MIB;
1515f8af5cf6SDimitry Andric   }
1516f8af5cf6SDimitry Andric 
15175ca98fd9SDimitry Andric   return nullptr;
1518f8af5cf6SDimitry Andric }
1519f8af5cf6SDimitry Andric 
foldMemoryOperandImpl(MachineFunction & MF,MachineInstr & MI,ArrayRef<unsigned> Ops,MachineBasicBlock::iterator InsertPt,MachineInstr & LoadMI,LiveIntervals * LIS) const152085d8b2bbSDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
152101095a5dSDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
152201095a5dSDimitry Andric     MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
152301095a5dSDimitry Andric     LiveIntervals *LIS) const {
1524ac9a064cSDimitry Andric   MachineRegisterInfo *MRI = &MF.getRegInfo();
1525ac9a064cSDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
1526ac9a064cSDimitry Andric 
1527ac9a064cSDimitry Andric   // For reassociable FP operations, any loads have been purposefully left
1528ac9a064cSDimitry Andric   // unfolded so that MachineCombiner can do its work on reg/reg
1529ac9a064cSDimitry Andric   // opcodes. After that, as many loads as possible are now folded.
1530ac9a064cSDimitry Andric   // TODO: This may be beneficial with other opcodes as well as machine-sink
1531ac9a064cSDimitry Andric   // can move loads close to their user in a different MBB, which the isel
1532ac9a064cSDimitry Andric   // matcher did not see.
1533ac9a064cSDimitry Andric   unsigned LoadOpc = 0;
1534ac9a064cSDimitry Andric   unsigned RegMemOpcode = 0;
1535ac9a064cSDimitry Andric   const TargetRegisterClass *FPRC = nullptr;
1536ac9a064cSDimitry Andric   RegMemOpcode = MI.getOpcode() == SystemZ::WFADB   ? SystemZ::ADB
1537ac9a064cSDimitry Andric                  : MI.getOpcode() == SystemZ::WFSDB ? SystemZ::SDB
1538ac9a064cSDimitry Andric                  : MI.getOpcode() == SystemZ::WFMDB ? SystemZ::MDB
1539ac9a064cSDimitry Andric                                                     : 0;
1540ac9a064cSDimitry Andric   if (RegMemOpcode) {
1541ac9a064cSDimitry Andric     LoadOpc = SystemZ::VL64;
1542ac9a064cSDimitry Andric     FPRC = &SystemZ::FP64BitRegClass;
1543ac9a064cSDimitry Andric   } else {
1544ac9a064cSDimitry Andric     RegMemOpcode = MI.getOpcode() == SystemZ::WFASB   ? SystemZ::AEB
1545ac9a064cSDimitry Andric                    : MI.getOpcode() == SystemZ::WFSSB ? SystemZ::SEB
1546ac9a064cSDimitry Andric                    : MI.getOpcode() == SystemZ::WFMSB ? SystemZ::MEEB
1547ac9a064cSDimitry Andric                                                       : 0;
1548ac9a064cSDimitry Andric     if (RegMemOpcode) {
1549ac9a064cSDimitry Andric       LoadOpc = SystemZ::VL32;
1550ac9a064cSDimitry Andric       FPRC = &SystemZ::FP32BitRegClass;
1551ac9a064cSDimitry Andric     }
1552ac9a064cSDimitry Andric   }
1553ac9a064cSDimitry Andric   if (!RegMemOpcode || LoadMI.getOpcode() != LoadOpc)
15545ca98fd9SDimitry Andric     return nullptr;
1555ac9a064cSDimitry Andric 
1556ac9a064cSDimitry Andric   // If RegMemOpcode clobbers CC, first make sure CC is not live at this point.
1557ac9a064cSDimitry Andric   if (get(RegMemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)) {
1558ac9a064cSDimitry Andric     assert(LoadMI.getParent() == MI.getParent() && "Assuming a local fold.");
1559ac9a064cSDimitry Andric     assert(LoadMI != InsertPt && "Assuming InsertPt not to be first in MBB.");
1560ac9a064cSDimitry Andric     for (MachineBasicBlock::iterator MII = std::prev(InsertPt);;
1561ac9a064cSDimitry Andric          --MII) {
1562ac9a064cSDimitry Andric       if (MII->definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {
1563ac9a064cSDimitry Andric         if (!MII->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))
1564ac9a064cSDimitry Andric           return nullptr;
1565ac9a064cSDimitry Andric         break;
1566ac9a064cSDimitry Andric       }
1567ac9a064cSDimitry Andric       if (MII == MBB->begin()) {
1568ac9a064cSDimitry Andric         if (MBB->isLiveIn(SystemZ::CC))
1569ac9a064cSDimitry Andric           return nullptr;
1570ac9a064cSDimitry Andric         break;
1571ac9a064cSDimitry Andric       }
1572ac9a064cSDimitry Andric     }
1573ac9a064cSDimitry Andric   }
1574ac9a064cSDimitry Andric 
1575ac9a064cSDimitry Andric   Register FoldAsLoadDefReg = LoadMI.getOperand(0).getReg();
1576ac9a064cSDimitry Andric   if (Ops.size() != 1 || FoldAsLoadDefReg != MI.getOperand(Ops[0]).getReg())
1577ac9a064cSDimitry Andric     return nullptr;
1578ac9a064cSDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1579ac9a064cSDimitry Andric   MachineOperand LHS = MI.getOperand(1);
1580ac9a064cSDimitry Andric   MachineOperand RHS = MI.getOperand(2);
1581ac9a064cSDimitry Andric   MachineOperand &RegMO = RHS.getReg() == FoldAsLoadDefReg ? LHS : RHS;
1582ac9a064cSDimitry Andric   if ((RegMemOpcode == SystemZ::SDB || RegMemOpcode == SystemZ::SEB) &&
1583ac9a064cSDimitry Andric       FoldAsLoadDefReg != RHS.getReg())
1584ac9a064cSDimitry Andric     return nullptr;
1585ac9a064cSDimitry Andric 
1586ac9a064cSDimitry Andric   MachineOperand &Base = LoadMI.getOperand(1);
1587ac9a064cSDimitry Andric   MachineOperand &Disp = LoadMI.getOperand(2);
1588ac9a064cSDimitry Andric   MachineOperand &Indx = LoadMI.getOperand(3);
1589ac9a064cSDimitry Andric   MachineInstrBuilder MIB =
1590ac9a064cSDimitry Andric       BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(RegMemOpcode), DstReg)
1591ac9a064cSDimitry Andric           .add(RegMO)
1592ac9a064cSDimitry Andric           .add(Base)
1593ac9a064cSDimitry Andric           .add(Disp)
1594ac9a064cSDimitry Andric           .add(Indx);
1595ac9a064cSDimitry Andric   MIB->addRegisterDead(SystemZ::CC, &RI);
1596ac9a064cSDimitry Andric   MRI->setRegClass(DstReg, FPRC);
1597ac9a064cSDimitry Andric   MRI->setRegClass(RegMO.getReg(), FPRC);
1598ac9a064cSDimitry Andric   transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);
1599ac9a064cSDimitry Andric 
1600ac9a064cSDimitry Andric   return MIB;
1601f8af5cf6SDimitry Andric }
1602f8af5cf6SDimitry Andric 
expandPostRAPseudo(MachineInstr & MI) const160301095a5dSDimitry Andric bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
160401095a5dSDimitry Andric   switch (MI.getOpcode()) {
160559d6cff9SDimitry Andric   case SystemZ::L128:
160659d6cff9SDimitry Andric     splitMove(MI, SystemZ::LG);
160759d6cff9SDimitry Andric     return true;
160859d6cff9SDimitry Andric 
160959d6cff9SDimitry Andric   case SystemZ::ST128:
161059d6cff9SDimitry Andric     splitMove(MI, SystemZ::STG);
161159d6cff9SDimitry Andric     return true;
161259d6cff9SDimitry Andric 
161359d6cff9SDimitry Andric   case SystemZ::LX:
161459d6cff9SDimitry Andric     splitMove(MI, SystemZ::LD);
161559d6cff9SDimitry Andric     return true;
161659d6cff9SDimitry Andric 
161759d6cff9SDimitry Andric   case SystemZ::STX:
161859d6cff9SDimitry Andric     splitMove(MI, SystemZ::STD);
161959d6cff9SDimitry Andric     return true;
162059d6cff9SDimitry Andric 
1621f8af5cf6SDimitry Andric   case SystemZ::LBMux:
1622f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::LB, SystemZ::LBH);
1623f8af5cf6SDimitry Andric     return true;
1624f8af5cf6SDimitry Andric 
1625f8af5cf6SDimitry Andric   case SystemZ::LHMux:
1626f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::LH, SystemZ::LHH);
1627f8af5cf6SDimitry Andric     return true;
1628f8af5cf6SDimitry Andric 
1629f8af5cf6SDimitry Andric   case SystemZ::LLCRMux:
1630f8af5cf6SDimitry Andric     expandZExtPseudo(MI, SystemZ::LLCR, 8);
1631f8af5cf6SDimitry Andric     return true;
1632f8af5cf6SDimitry Andric 
1633f8af5cf6SDimitry Andric   case SystemZ::LLHRMux:
1634f8af5cf6SDimitry Andric     expandZExtPseudo(MI, SystemZ::LLHR, 16);
1635f8af5cf6SDimitry Andric     return true;
1636f8af5cf6SDimitry Andric 
1637f8af5cf6SDimitry Andric   case SystemZ::LLCMux:
1638f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::LLC, SystemZ::LLCH);
1639f8af5cf6SDimitry Andric     return true;
1640f8af5cf6SDimitry Andric 
1641f8af5cf6SDimitry Andric   case SystemZ::LLHMux:
1642f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::LLH, SystemZ::LLHH);
1643f8af5cf6SDimitry Andric     return true;
1644f8af5cf6SDimitry Andric 
1645f8af5cf6SDimitry Andric   case SystemZ::LMux:
1646f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::L, SystemZ::LFH);
1647f8af5cf6SDimitry Andric     return true;
1648f8af5cf6SDimitry Andric 
1649b915e9e0SDimitry Andric   case SystemZ::LOCMux:
1650b915e9e0SDimitry Andric     expandLOCPseudo(MI, SystemZ::LOC, SystemZ::LOCFH);
1651b915e9e0SDimitry Andric     return true;
1652b915e9e0SDimitry Andric 
1653b915e9e0SDimitry Andric   case SystemZ::LOCHIMux:
1654b915e9e0SDimitry Andric     expandLOCPseudo(MI, SystemZ::LOCHI, SystemZ::LOCHHI);
1655b915e9e0SDimitry Andric     return true;
1656b915e9e0SDimitry Andric 
1657f8af5cf6SDimitry Andric   case SystemZ::STCMux:
1658f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::STC, SystemZ::STCH);
1659f8af5cf6SDimitry Andric     return true;
1660f8af5cf6SDimitry Andric 
1661f8af5cf6SDimitry Andric   case SystemZ::STHMux:
1662f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::STH, SystemZ::STHH);
1663f8af5cf6SDimitry Andric     return true;
1664f8af5cf6SDimitry Andric 
1665f8af5cf6SDimitry Andric   case SystemZ::STMux:
1666f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH);
1667f8af5cf6SDimitry Andric     return true;
1668f8af5cf6SDimitry Andric 
1669b915e9e0SDimitry Andric   case SystemZ::STOCMux:
1670b915e9e0SDimitry Andric     expandLOCPseudo(MI, SystemZ::STOC, SystemZ::STOCFH);
1671b915e9e0SDimitry Andric     return true;
1672b915e9e0SDimitry Andric 
1673f8af5cf6SDimitry Andric   case SystemZ::LHIMux:
1674f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::LHI, SystemZ::IIHF, true);
1675f8af5cf6SDimitry Andric     return true;
1676f8af5cf6SDimitry Andric 
1677f8af5cf6SDimitry Andric   case SystemZ::IIFMux:
1678f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false);
1679f8af5cf6SDimitry Andric     return true;
1680f8af5cf6SDimitry Andric 
1681f8af5cf6SDimitry Andric   case SystemZ::IILMux:
1682f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::IILL, SystemZ::IIHL, false);
1683f8af5cf6SDimitry Andric     return true;
1684f8af5cf6SDimitry Andric 
1685f8af5cf6SDimitry Andric   case SystemZ::IIHMux:
1686f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false);
1687f8af5cf6SDimitry Andric     return true;
1688f8af5cf6SDimitry Andric 
1689f8af5cf6SDimitry Andric   case SystemZ::NIFMux:
1690f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::NILF, SystemZ::NIHF, false);
1691f8af5cf6SDimitry Andric     return true;
1692f8af5cf6SDimitry Andric 
1693f8af5cf6SDimitry Andric   case SystemZ::NILMux:
1694f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::NILL, SystemZ::NIHL, false);
1695f8af5cf6SDimitry Andric     return true;
1696f8af5cf6SDimitry Andric 
1697f8af5cf6SDimitry Andric   case SystemZ::NIHMux:
1698f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::NILH, SystemZ::NIHH, false);
1699f8af5cf6SDimitry Andric     return true;
1700f8af5cf6SDimitry Andric 
1701f8af5cf6SDimitry Andric   case SystemZ::OIFMux:
1702f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::OILF, SystemZ::OIHF, false);
1703f8af5cf6SDimitry Andric     return true;
1704f8af5cf6SDimitry Andric 
1705f8af5cf6SDimitry Andric   case SystemZ::OILMux:
1706f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::OILL, SystemZ::OIHL, false);
1707f8af5cf6SDimitry Andric     return true;
1708f8af5cf6SDimitry Andric 
1709f8af5cf6SDimitry Andric   case SystemZ::OIHMux:
1710f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::OILH, SystemZ::OIHH, false);
1711f8af5cf6SDimitry Andric     return true;
1712f8af5cf6SDimitry Andric 
1713f8af5cf6SDimitry Andric   case SystemZ::XIFMux:
1714f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::XILF, SystemZ::XIHF, false);
1715f8af5cf6SDimitry Andric     return true;
1716f8af5cf6SDimitry Andric 
1717f8af5cf6SDimitry Andric   case SystemZ::TMLMux:
1718f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::TMLL, SystemZ::TMHL, false);
1719f8af5cf6SDimitry Andric     return true;
1720f8af5cf6SDimitry Andric 
1721f8af5cf6SDimitry Andric   case SystemZ::TMHMux:
1722f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::TMLH, SystemZ::TMHH, false);
1723f8af5cf6SDimitry Andric     return true;
1724f8af5cf6SDimitry Andric 
1725f8af5cf6SDimitry Andric   case SystemZ::AHIMux:
1726f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::AHI, SystemZ::AIH, false);
1727f8af5cf6SDimitry Andric     return true;
1728f8af5cf6SDimitry Andric 
1729f8af5cf6SDimitry Andric   case SystemZ::AHIMuxK:
1730f8af5cf6SDimitry Andric     expandRIEPseudo(MI, SystemZ::AHI, SystemZ::AHIK, SystemZ::AIH);
1731f8af5cf6SDimitry Andric     return true;
1732f8af5cf6SDimitry Andric 
1733f8af5cf6SDimitry Andric   case SystemZ::AFIMux:
1734f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false);
1735f8af5cf6SDimitry Andric     return true;
1736f8af5cf6SDimitry Andric 
1737b915e9e0SDimitry Andric   case SystemZ::CHIMux:
1738b915e9e0SDimitry Andric     expandRIPseudo(MI, SystemZ::CHI, SystemZ::CIH, false);
1739b915e9e0SDimitry Andric     return true;
1740b915e9e0SDimitry Andric 
1741f8af5cf6SDimitry Andric   case SystemZ::CFIMux:
1742f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false);
1743f8af5cf6SDimitry Andric     return true;
1744f8af5cf6SDimitry Andric 
1745f8af5cf6SDimitry Andric   case SystemZ::CLFIMux:
1746f8af5cf6SDimitry Andric     expandRIPseudo(MI, SystemZ::CLFI, SystemZ::CLIH, false);
1747f8af5cf6SDimitry Andric     return true;
1748f8af5cf6SDimitry Andric 
1749f8af5cf6SDimitry Andric   case SystemZ::CMux:
1750f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::C, SystemZ::CHF);
1751f8af5cf6SDimitry Andric     return true;
1752f8af5cf6SDimitry Andric 
1753f8af5cf6SDimitry Andric   case SystemZ::CLMux:
1754f8af5cf6SDimitry Andric     expandRXYPseudo(MI, SystemZ::CL, SystemZ::CLHF);
1755f8af5cf6SDimitry Andric     return true;
1756f8af5cf6SDimitry Andric 
1757f8af5cf6SDimitry Andric   case SystemZ::RISBMux: {
17581d5ae102SDimitry Andric     bool DestIsHigh = SystemZ::isHighReg(MI.getOperand(0).getReg());
17591d5ae102SDimitry Andric     bool SrcIsHigh = SystemZ::isHighReg(MI.getOperand(2).getReg());
1760f8af5cf6SDimitry Andric     if (SrcIsHigh == DestIsHigh)
176101095a5dSDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHH : SystemZ::RISBLL));
1762f8af5cf6SDimitry Andric     else {
176301095a5dSDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHL : SystemZ::RISBLH));
176401095a5dSDimitry Andric       MI.getOperand(5).setImm(MI.getOperand(5).getImm() ^ 32);
1765f8af5cf6SDimitry Andric     }
1766f8af5cf6SDimitry Andric     return true;
1767f8af5cf6SDimitry Andric   }
1768f8af5cf6SDimitry Andric 
176959d6cff9SDimitry Andric   case SystemZ::ADJDYNALLOC:
177059d6cff9SDimitry Andric     splitAdjDynAlloc(MI);
177159d6cff9SDimitry Andric     return true;
177259d6cff9SDimitry Andric 
177301095a5dSDimitry Andric   case TargetOpcode::LOAD_STACK_GUARD:
177401095a5dSDimitry Andric     expandLoadStackGuard(&MI);
177501095a5dSDimitry Andric     return true;
177601095a5dSDimitry Andric 
177759d6cff9SDimitry Andric   default:
177859d6cff9SDimitry Andric     return false;
177959d6cff9SDimitry Andric   }
178059d6cff9SDimitry Andric }
178159d6cff9SDimitry Andric 
getInstSizeInBytes(const MachineInstr & MI) const1782b915e9e0SDimitry Andric unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
1783e6d15924SDimitry Andric   if (MI.isInlineAsm()) {
178401095a5dSDimitry Andric     const MachineFunction *MF = MI.getParent()->getParent();
178501095a5dSDimitry Andric     const char *AsmStr = MI.getOperand(0).getSymbolName();
1786f8af5cf6SDimitry Andric     return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
1787f8af5cf6SDimitry Andric   }
1788c0981da4SDimitry Andric   else if (MI.getOpcode() == SystemZ::PATCHPOINT)
1789c0981da4SDimitry Andric     return PatchPointOpers(&MI).getNumPatchBytes();
1790c0981da4SDimitry Andric   else if (MI.getOpcode() == SystemZ::STACKMAP)
1791c0981da4SDimitry Andric     return MI.getOperand(1).getImm();
1792c0981da4SDimitry Andric   else if (MI.getOpcode() == SystemZ::FENTRY_CALL)
1793c0981da4SDimitry Andric     return 6;
1794c0981da4SDimitry Andric 
179501095a5dSDimitry Andric   return MI.getDesc().getSize();
179659d6cff9SDimitry Andric }
179759d6cff9SDimitry Andric 
1798f8af5cf6SDimitry Andric SystemZII::Branch
getBranchInfo(const MachineInstr & MI) const179901095a5dSDimitry Andric SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {
180001095a5dSDimitry Andric   switch (MI.getOpcode()) {
180159d6cff9SDimitry Andric   case SystemZ::BR:
180293c91e39SDimitry Andric   case SystemZ::BI:
180359d6cff9SDimitry Andric   case SystemZ::J:
180459d6cff9SDimitry Andric   case SystemZ::JG:
1805f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
180601095a5dSDimitry Andric                              SystemZ::CCMASK_ANY, &MI.getOperand(0));
180759d6cff9SDimitry Andric 
180859d6cff9SDimitry Andric   case SystemZ::BRC:
180959d6cff9SDimitry Andric   case SystemZ::BRCL:
181001095a5dSDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, MI.getOperand(0).getImm(),
181101095a5dSDimitry Andric                              MI.getOperand(1).getImm(), &MI.getOperand(2));
1812f8af5cf6SDimitry Andric 
1813f8af5cf6SDimitry Andric   case SystemZ::BRCT:
1814b915e9e0SDimitry Andric   case SystemZ::BRCTH:
1815f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCT, SystemZ::CCMASK_ICMP,
181601095a5dSDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
1817f8af5cf6SDimitry Andric 
1818f8af5cf6SDimitry Andric   case SystemZ::BRCTG:
1819f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCTG, SystemZ::CCMASK_ICMP,
182001095a5dSDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
1821f8af5cf6SDimitry Andric 
1822f8af5cf6SDimitry Andric   case SystemZ::CIJ:
1823f8af5cf6SDimitry Andric   case SystemZ::CRJ:
1824f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchC, SystemZ::CCMASK_ICMP,
182501095a5dSDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1826f8af5cf6SDimitry Andric 
1827f8af5cf6SDimitry Andric   case SystemZ::CLIJ:
1828f8af5cf6SDimitry Andric   case SystemZ::CLRJ:
1829f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCL, SystemZ::CCMASK_ICMP,
183001095a5dSDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1831f8af5cf6SDimitry Andric 
1832f8af5cf6SDimitry Andric   case SystemZ::CGIJ:
1833f8af5cf6SDimitry Andric   case SystemZ::CGRJ:
1834f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCG, SystemZ::CCMASK_ICMP,
183501095a5dSDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
1836f8af5cf6SDimitry Andric 
1837f8af5cf6SDimitry Andric   case SystemZ::CLGIJ:
1838f8af5cf6SDimitry Andric   case SystemZ::CLGRJ:
1839f8af5cf6SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP,
184001095a5dSDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
184159d6cff9SDimitry Andric 
18421d5ae102SDimitry Andric   case SystemZ::INLINEASM_BR:
18431d5ae102SDimitry Andric     // Don't try to analyze asm goto, so pass nullptr as branch target argument.
18441d5ae102SDimitry Andric     return SystemZII::Branch(SystemZII::AsmGoto, 0, 0, nullptr);
18451d5ae102SDimitry Andric 
184659d6cff9SDimitry Andric   default:
1847f8af5cf6SDimitry Andric     llvm_unreachable("Unrecognized branch opcode");
184859d6cff9SDimitry Andric   }
184959d6cff9SDimitry Andric }
185059d6cff9SDimitry Andric 
getLoadStoreOpcodes(const TargetRegisterClass * RC,unsigned & LoadOpcode,unsigned & StoreOpcode) const185159d6cff9SDimitry Andric void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
185259d6cff9SDimitry Andric                                            unsigned &LoadOpcode,
185359d6cff9SDimitry Andric                                            unsigned &StoreOpcode) const {
185459d6cff9SDimitry Andric   if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {
185559d6cff9SDimitry Andric     LoadOpcode = SystemZ::L;
1856f8af5cf6SDimitry Andric     StoreOpcode = SystemZ::ST;
1857f8af5cf6SDimitry Andric   } else if (RC == &SystemZ::GRH32BitRegClass) {
1858f8af5cf6SDimitry Andric     LoadOpcode = SystemZ::LFH;
1859f8af5cf6SDimitry Andric     StoreOpcode = SystemZ::STFH;
1860f8af5cf6SDimitry Andric   } else if (RC == &SystemZ::GRX32BitRegClass) {
1861f8af5cf6SDimitry Andric     LoadOpcode = SystemZ::LMux;
1862f8af5cf6SDimitry Andric     StoreOpcode = SystemZ::STMux;
186359d6cff9SDimitry Andric   } else if (RC == &SystemZ::GR64BitRegClass ||
186459d6cff9SDimitry Andric              RC == &SystemZ::ADDR64BitRegClass) {
186559d6cff9SDimitry Andric     LoadOpcode = SystemZ::LG;
186659d6cff9SDimitry Andric     StoreOpcode = SystemZ::STG;
186759d6cff9SDimitry Andric   } else if (RC == &SystemZ::GR128BitRegClass ||
186859d6cff9SDimitry Andric              RC == &SystemZ::ADDR128BitRegClass) {
186959d6cff9SDimitry Andric     LoadOpcode = SystemZ::L128;
187059d6cff9SDimitry Andric     StoreOpcode = SystemZ::ST128;
187159d6cff9SDimitry Andric   } else if (RC == &SystemZ::FP32BitRegClass) {
187259d6cff9SDimitry Andric     LoadOpcode = SystemZ::LE;
187359d6cff9SDimitry Andric     StoreOpcode = SystemZ::STE;
187459d6cff9SDimitry Andric   } else if (RC == &SystemZ::FP64BitRegClass) {
187559d6cff9SDimitry Andric     LoadOpcode = SystemZ::LD;
187659d6cff9SDimitry Andric     StoreOpcode = SystemZ::STD;
187759d6cff9SDimitry Andric   } else if (RC == &SystemZ::FP128BitRegClass) {
187859d6cff9SDimitry Andric     LoadOpcode = SystemZ::LX;
187959d6cff9SDimitry Andric     StoreOpcode = SystemZ::STX;
18805a5ac124SDimitry Andric   } else if (RC == &SystemZ::VR32BitRegClass) {
18815a5ac124SDimitry Andric     LoadOpcode = SystemZ::VL32;
18825a5ac124SDimitry Andric     StoreOpcode = SystemZ::VST32;
18835a5ac124SDimitry Andric   } else if (RC == &SystemZ::VR64BitRegClass) {
18845a5ac124SDimitry Andric     LoadOpcode = SystemZ::VL64;
18855a5ac124SDimitry Andric     StoreOpcode = SystemZ::VST64;
18865a5ac124SDimitry Andric   } else if (RC == &SystemZ::VF128BitRegClass ||
18875a5ac124SDimitry Andric              RC == &SystemZ::VR128BitRegClass) {
18885a5ac124SDimitry Andric     LoadOpcode = SystemZ::VL;
18895a5ac124SDimitry Andric     StoreOpcode = SystemZ::VST;
189059d6cff9SDimitry Andric   } else
189159d6cff9SDimitry Andric     llvm_unreachable("Unsupported regclass to load or store");
189259d6cff9SDimitry Andric }
189359d6cff9SDimitry Andric 
getOpcodeForOffset(unsigned Opcode,int64_t Offset,const MachineInstr * MI) const189459d6cff9SDimitry Andric unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
1895145449b1SDimitry Andric                                               int64_t Offset,
1896145449b1SDimitry Andric                                               const MachineInstr *MI) const {
189759d6cff9SDimitry Andric   const MCInstrDesc &MCID = get(Opcode);
189859d6cff9SDimitry Andric   int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);
189959d6cff9SDimitry Andric   if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {
190059d6cff9SDimitry Andric     // Get the instruction to use for unsigned 12-bit displacements.
190159d6cff9SDimitry Andric     int Disp12Opcode = SystemZ::getDisp12Opcode(Opcode);
190259d6cff9SDimitry Andric     if (Disp12Opcode >= 0)
190359d6cff9SDimitry Andric       return Disp12Opcode;
190459d6cff9SDimitry Andric 
190559d6cff9SDimitry Andric     // All address-related instructions can use unsigned 12-bit
190659d6cff9SDimitry Andric     // displacements.
190759d6cff9SDimitry Andric     return Opcode;
190859d6cff9SDimitry Andric   }
190959d6cff9SDimitry Andric   if (isInt<20>(Offset) && isInt<20>(Offset2)) {
191059d6cff9SDimitry Andric     // Get the instruction to use for signed 20-bit displacements.
191159d6cff9SDimitry Andric     int Disp20Opcode = SystemZ::getDisp20Opcode(Opcode);
191259d6cff9SDimitry Andric     if (Disp20Opcode >= 0)
191359d6cff9SDimitry Andric       return Disp20Opcode;
191459d6cff9SDimitry Andric 
191559d6cff9SDimitry Andric     // Check whether Opcode allows signed 20-bit displacements.
191659d6cff9SDimitry Andric     if (MCID.TSFlags & SystemZII::Has20BitOffset)
191759d6cff9SDimitry Andric       return Opcode;
1918145449b1SDimitry Andric 
1919145449b1SDimitry Andric     // If a VR32/VR64 reg ended up in an FP register, use the FP opcode.
1920145449b1SDimitry Andric     if (MI && MI->getOperand(0).isReg()) {
1921145449b1SDimitry Andric       Register Reg = MI->getOperand(0).getReg();
1922145449b1SDimitry Andric       if (Reg.isPhysical() && SystemZMC::getFirstReg(Reg) < 16) {
1923145449b1SDimitry Andric         switch (Opcode) {
1924145449b1SDimitry Andric         case SystemZ::VL32:
1925145449b1SDimitry Andric           return SystemZ::LEY;
1926145449b1SDimitry Andric         case SystemZ::VST32:
1927145449b1SDimitry Andric           return SystemZ::STEY;
1928145449b1SDimitry Andric         case SystemZ::VL64:
1929145449b1SDimitry Andric           return SystemZ::LDY;
1930145449b1SDimitry Andric         case SystemZ::VST64:
1931145449b1SDimitry Andric           return SystemZ::STDY;
1932145449b1SDimitry Andric         default: break;
1933145449b1SDimitry Andric         }
1934145449b1SDimitry Andric       }
1935145449b1SDimitry Andric     }
193659d6cff9SDimitry Andric   }
193759d6cff9SDimitry Andric   return 0;
193859d6cff9SDimitry Andric }
193959d6cff9SDimitry Andric 
hasDisplacementPairInsn(unsigned Opcode) const1940ecbca9f5SDimitry Andric bool SystemZInstrInfo::hasDisplacementPairInsn(unsigned Opcode) const {
1941ecbca9f5SDimitry Andric   const MCInstrDesc &MCID = get(Opcode);
1942ecbca9f5SDimitry Andric   if (MCID.TSFlags & SystemZII::Has20BitOffset)
1943ecbca9f5SDimitry Andric     return SystemZ::getDisp12Opcode(Opcode) >= 0;
1944ecbca9f5SDimitry Andric   return SystemZ::getDisp20Opcode(Opcode) >= 0;
1945ecbca9f5SDimitry Andric }
1946ecbca9f5SDimitry Andric 
getLoadAndTest(unsigned Opcode) const1947f8af5cf6SDimitry Andric unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
1948f8af5cf6SDimitry Andric   switch (Opcode) {
1949f8af5cf6SDimitry Andric   case SystemZ::L:      return SystemZ::LT;
1950f8af5cf6SDimitry Andric   case SystemZ::LY:     return SystemZ::LT;
1951f8af5cf6SDimitry Andric   case SystemZ::LG:     return SystemZ::LTG;
1952f8af5cf6SDimitry Andric   case SystemZ::LGF:    return SystemZ::LTGF;
1953f8af5cf6SDimitry Andric   case SystemZ::LR:     return SystemZ::LTR;
1954f8af5cf6SDimitry Andric   case SystemZ::LGFR:   return SystemZ::LTGFR;
1955f8af5cf6SDimitry Andric   case SystemZ::LGR:    return SystemZ::LTGR;
1956dd58ef01SDimitry Andric   case SystemZ::LCDFR:  return SystemZ::LCDBR;
1957dd58ef01SDimitry Andric   case SystemZ::LPDFR:  return SystemZ::LPDBR;
1958dd58ef01SDimitry Andric   case SystemZ::LNDFR:  return SystemZ::LNDBR;
1959dd58ef01SDimitry Andric   case SystemZ::LCDFR_32:  return SystemZ::LCEBR;
1960dd58ef01SDimitry Andric   case SystemZ::LPDFR_32:  return SystemZ::LPEBR;
1961dd58ef01SDimitry Andric   case SystemZ::LNDFR_32:  return SystemZ::LNEBR;
19625a5ac124SDimitry Andric   // On zEC12 we prefer to use RISBGN.  But if there is a chance to
19635a5ac124SDimitry Andric   // actually use the condition code, we may turn it back into RISGB.
19645a5ac124SDimitry Andric   // Note that RISBG is not really a "load-and-test" instruction,
19655a5ac124SDimitry Andric   // but sets the same condition code values, so is OK to use here.
19665a5ac124SDimitry Andric   case SystemZ::RISBGN: return SystemZ::RISBG;
1967f8af5cf6SDimitry Andric   default:              return 0;
1968f8af5cf6SDimitry Andric   }
1969f8af5cf6SDimitry Andric }
1970f8af5cf6SDimitry Andric 
isRxSBGMask(uint64_t Mask,unsigned BitSize,unsigned & Start,unsigned & End) const1971f8af5cf6SDimitry Andric bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
1972f8af5cf6SDimitry Andric                                    unsigned &Start, unsigned &End) const {
1973f8af5cf6SDimitry Andric   // Reject trivial all-zero masks.
19745a5ac124SDimitry Andric   Mask &= allOnes(BitSize);
1975f8af5cf6SDimitry Andric   if (Mask == 0)
1976f8af5cf6SDimitry Andric     return false;
1977f8af5cf6SDimitry Andric 
1978f8af5cf6SDimitry Andric   // Handle the 1+0+ or 0+1+0* cases.  Start then specifies the index of
1979f8af5cf6SDimitry Andric   // the msb and End specifies the index of the lsb.
1980f8af5cf6SDimitry Andric   unsigned LSB, Length;
1981e3b55780SDimitry Andric   if (isShiftedMask_64(Mask, LSB, Length)) {
1982f8af5cf6SDimitry Andric     Start = 63 - (LSB + Length - 1);
1983f8af5cf6SDimitry Andric     End = 63 - LSB;
1984f8af5cf6SDimitry Andric     return true;
1985f8af5cf6SDimitry Andric   }
1986f8af5cf6SDimitry Andric 
1987f8af5cf6SDimitry Andric   // Handle the wrap-around 1+0+1+ cases.  Start then specifies the msb
1988f8af5cf6SDimitry Andric   // of the low 1s and End specifies the lsb of the high 1s.
1989e3b55780SDimitry Andric   if (isShiftedMask_64(Mask ^ allOnes(BitSize), LSB, Length)) {
1990f8af5cf6SDimitry Andric     assert(LSB > 0 && "Bottom bit must be set");
1991f8af5cf6SDimitry Andric     assert(LSB + Length < BitSize && "Top bit must be set");
1992f8af5cf6SDimitry Andric     Start = 63 - (LSB - 1);
1993f8af5cf6SDimitry Andric     End = 63 - (LSB + Length);
1994f8af5cf6SDimitry Andric     return true;
1995f8af5cf6SDimitry Andric   }
1996f8af5cf6SDimitry Andric 
1997f8af5cf6SDimitry Andric   return false;
1998f8af5cf6SDimitry Andric }
1999f8af5cf6SDimitry Andric 
getFusedCompare(unsigned Opcode,SystemZII::FusedCompareType Type,const MachineInstr * MI) const200001095a5dSDimitry Andric unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
200101095a5dSDimitry Andric                                            SystemZII::FusedCompareType Type,
2002f8af5cf6SDimitry Andric                                            const MachineInstr *MI) const {
2003f8af5cf6SDimitry Andric   switch (Opcode) {
200401095a5dSDimitry Andric   case SystemZ::CHI:
200501095a5dSDimitry Andric   case SystemZ::CGHI:
200601095a5dSDimitry Andric     if (!(MI && isInt<8>(MI->getOperand(1).getImm())))
200701095a5dSDimitry Andric       return 0;
200801095a5dSDimitry Andric     break;
200901095a5dSDimitry Andric   case SystemZ::CLFI:
201001095a5dSDimitry Andric   case SystemZ::CLGFI:
201101095a5dSDimitry Andric     if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
201201095a5dSDimitry Andric       return 0;
2013b915e9e0SDimitry Andric     break;
2014b915e9e0SDimitry Andric   case SystemZ::CL:
2015b915e9e0SDimitry Andric   case SystemZ::CLG:
2016b915e9e0SDimitry Andric     if (!STI.hasMiscellaneousExtensions())
2017b915e9e0SDimitry Andric       return 0;
2018b915e9e0SDimitry Andric     if (!(MI && MI->getOperand(3).getReg() == 0))
2019b915e9e0SDimitry Andric       return 0;
2020b915e9e0SDimitry Andric     break;
202101095a5dSDimitry Andric   }
202201095a5dSDimitry Andric   switch (Type) {
202301095a5dSDimitry Andric   case SystemZII::CompareAndBranch:
202401095a5dSDimitry Andric     switch (Opcode) {
2025f8af5cf6SDimitry Andric     case SystemZ::CR:
2026f8af5cf6SDimitry Andric       return SystemZ::CRJ;
2027f8af5cf6SDimitry Andric     case SystemZ::CGR:
2028f8af5cf6SDimitry Andric       return SystemZ::CGRJ;
2029f8af5cf6SDimitry Andric     case SystemZ::CHI:
203001095a5dSDimitry Andric       return SystemZ::CIJ;
2031f8af5cf6SDimitry Andric     case SystemZ::CGHI:
203201095a5dSDimitry Andric       return SystemZ::CGIJ;
2033f8af5cf6SDimitry Andric     case SystemZ::CLR:
2034f8af5cf6SDimitry Andric       return SystemZ::CLRJ;
2035f8af5cf6SDimitry Andric     case SystemZ::CLGR:
2036f8af5cf6SDimitry Andric       return SystemZ::CLGRJ;
2037f8af5cf6SDimitry Andric     case SystemZ::CLFI:
203801095a5dSDimitry Andric       return SystemZ::CLIJ;
2039f8af5cf6SDimitry Andric     case SystemZ::CLGFI:
204001095a5dSDimitry Andric       return SystemZ::CLGIJ;
2041f8af5cf6SDimitry Andric     default:
2042f8af5cf6SDimitry Andric       return 0;
2043f8af5cf6SDimitry Andric     }
204401095a5dSDimitry Andric   case SystemZII::CompareAndReturn:
204501095a5dSDimitry Andric     switch (Opcode) {
204601095a5dSDimitry Andric     case SystemZ::CR:
204701095a5dSDimitry Andric       return SystemZ::CRBReturn;
204801095a5dSDimitry Andric     case SystemZ::CGR:
204901095a5dSDimitry Andric       return SystemZ::CGRBReturn;
205001095a5dSDimitry Andric     case SystemZ::CHI:
205101095a5dSDimitry Andric       return SystemZ::CIBReturn;
205201095a5dSDimitry Andric     case SystemZ::CGHI:
205301095a5dSDimitry Andric       return SystemZ::CGIBReturn;
205401095a5dSDimitry Andric     case SystemZ::CLR:
205501095a5dSDimitry Andric       return SystemZ::CLRBReturn;
205601095a5dSDimitry Andric     case SystemZ::CLGR:
205701095a5dSDimitry Andric       return SystemZ::CLGRBReturn;
205801095a5dSDimitry Andric     case SystemZ::CLFI:
205901095a5dSDimitry Andric       return SystemZ::CLIBReturn;
206001095a5dSDimitry Andric     case SystemZ::CLGFI:
206101095a5dSDimitry Andric       return SystemZ::CLGIBReturn;
206201095a5dSDimitry Andric     default:
206301095a5dSDimitry Andric       return 0;
206401095a5dSDimitry Andric     }
206501095a5dSDimitry Andric   case SystemZII::CompareAndSibcall:
206601095a5dSDimitry Andric     switch (Opcode) {
206701095a5dSDimitry Andric     case SystemZ::CR:
206801095a5dSDimitry Andric       return SystemZ::CRBCall;
206901095a5dSDimitry Andric     case SystemZ::CGR:
207001095a5dSDimitry Andric       return SystemZ::CGRBCall;
207101095a5dSDimitry Andric     case SystemZ::CHI:
207201095a5dSDimitry Andric       return SystemZ::CIBCall;
207301095a5dSDimitry Andric     case SystemZ::CGHI:
207401095a5dSDimitry Andric       return SystemZ::CGIBCall;
207501095a5dSDimitry Andric     case SystemZ::CLR:
207601095a5dSDimitry Andric       return SystemZ::CLRBCall;
207701095a5dSDimitry Andric     case SystemZ::CLGR:
207801095a5dSDimitry Andric       return SystemZ::CLGRBCall;
207901095a5dSDimitry Andric     case SystemZ::CLFI:
208001095a5dSDimitry Andric       return SystemZ::CLIBCall;
208101095a5dSDimitry Andric     case SystemZ::CLGFI:
208201095a5dSDimitry Andric       return SystemZ::CLGIBCall;
208301095a5dSDimitry Andric     default:
208401095a5dSDimitry Andric       return 0;
208501095a5dSDimitry Andric     }
208601095a5dSDimitry Andric   case SystemZII::CompareAndTrap:
208701095a5dSDimitry Andric     switch (Opcode) {
208801095a5dSDimitry Andric     case SystemZ::CR:
208901095a5dSDimitry Andric       return SystemZ::CRT;
209001095a5dSDimitry Andric     case SystemZ::CGR:
209101095a5dSDimitry Andric       return SystemZ::CGRT;
209201095a5dSDimitry Andric     case SystemZ::CHI:
209301095a5dSDimitry Andric       return SystemZ::CIT;
209401095a5dSDimitry Andric     case SystemZ::CGHI:
209501095a5dSDimitry Andric       return SystemZ::CGIT;
209601095a5dSDimitry Andric     case SystemZ::CLR:
209701095a5dSDimitry Andric       return SystemZ::CLRT;
209801095a5dSDimitry Andric     case SystemZ::CLGR:
209901095a5dSDimitry Andric       return SystemZ::CLGRT;
210001095a5dSDimitry Andric     case SystemZ::CLFI:
210101095a5dSDimitry Andric       return SystemZ::CLFIT;
210201095a5dSDimitry Andric     case SystemZ::CLGFI:
210301095a5dSDimitry Andric       return SystemZ::CLGIT;
2104b915e9e0SDimitry Andric     case SystemZ::CL:
2105b915e9e0SDimitry Andric       return SystemZ::CLT;
2106b915e9e0SDimitry Andric     case SystemZ::CLG:
2107b915e9e0SDimitry Andric       return SystemZ::CLGT;
210801095a5dSDimitry Andric     default:
210901095a5dSDimitry Andric       return 0;
211001095a5dSDimitry Andric     }
211101095a5dSDimitry Andric   }
211201095a5dSDimitry Andric   return 0;
2113f8af5cf6SDimitry Andric }
2114f8af5cf6SDimitry Andric 
2115cfca06d7SDimitry Andric bool SystemZInstrInfo::
prepareCompareSwapOperands(MachineBasicBlock::iterator const MBBI) const2116cfca06d7SDimitry Andric prepareCompareSwapOperands(MachineBasicBlock::iterator const MBBI) const {
2117cfca06d7SDimitry Andric   assert(MBBI->isCompare() && MBBI->getOperand(0).isReg() &&
2118cfca06d7SDimitry Andric          MBBI->getOperand(1).isReg() && !MBBI->mayLoad() &&
2119cfca06d7SDimitry Andric          "Not a compare reg/reg.");
2120cfca06d7SDimitry Andric 
2121cfca06d7SDimitry Andric   MachineBasicBlock *MBB = MBBI->getParent();
2122cfca06d7SDimitry Andric   bool CCLive = true;
2123cfca06d7SDimitry Andric   SmallVector<MachineInstr *, 4> CCUsers;
2124e3b55780SDimitry Andric   for (MachineInstr &MI : llvm::make_range(std::next(MBBI), MBB->end())) {
2125ac9a064cSDimitry Andric     if (MI.readsRegister(SystemZ::CC, /*TRI=*/nullptr)) {
2126e3b55780SDimitry Andric       unsigned Flags = MI.getDesc().TSFlags;
2127cfca06d7SDimitry Andric       if ((Flags & SystemZII::CCMaskFirst) || (Flags & SystemZII::CCMaskLast))
2128e3b55780SDimitry Andric         CCUsers.push_back(&MI);
2129cfca06d7SDimitry Andric       else
2130cfca06d7SDimitry Andric         return false;
2131cfca06d7SDimitry Andric     }
2132ac9a064cSDimitry Andric     if (MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {
2133cfca06d7SDimitry Andric       CCLive = false;
2134cfca06d7SDimitry Andric       break;
2135cfca06d7SDimitry Andric     }
2136cfca06d7SDimitry Andric   }
2137cfca06d7SDimitry Andric   if (CCLive) {
2138ac9a064cSDimitry Andric     LiveRegUnits LiveRegs(*MBB->getParent()->getSubtarget().getRegisterInfo());
2139cfca06d7SDimitry Andric     LiveRegs.addLiveOuts(*MBB);
2140ac9a064cSDimitry Andric     if (!LiveRegs.available(SystemZ::CC))
2141cfca06d7SDimitry Andric       return false;
2142cfca06d7SDimitry Andric   }
2143cfca06d7SDimitry Andric 
2144cfca06d7SDimitry Andric   // Update all CC users.
2145cfca06d7SDimitry Andric   for (unsigned Idx = 0; Idx < CCUsers.size(); ++Idx) {
2146cfca06d7SDimitry Andric     unsigned Flags = CCUsers[Idx]->getDesc().TSFlags;
2147cfca06d7SDimitry Andric     unsigned FirstOpNum = ((Flags & SystemZII::CCMaskFirst) ?
2148cfca06d7SDimitry Andric                            0 : CCUsers[Idx]->getNumExplicitOperands() - 2);
2149cfca06d7SDimitry Andric     MachineOperand &CCMaskMO = CCUsers[Idx]->getOperand(FirstOpNum + 1);
2150cfca06d7SDimitry Andric     unsigned NewCCMask = SystemZ::reverseCCMask(CCMaskMO.getImm());
2151cfca06d7SDimitry Andric     CCMaskMO.setImm(NewCCMask);
2152cfca06d7SDimitry Andric   }
2153cfca06d7SDimitry Andric 
2154cfca06d7SDimitry Andric   return true;
2155cfca06d7SDimitry Andric }
2156cfca06d7SDimitry Andric 
reverseCCMask(unsigned CCMask)2157cfca06d7SDimitry Andric unsigned SystemZ::reverseCCMask(unsigned CCMask) {
2158cfca06d7SDimitry Andric   return ((CCMask & SystemZ::CCMASK_CMP_EQ) |
2159ac9a064cSDimitry Andric           ((CCMask & SystemZ::CCMASK_CMP_GT) ? SystemZ::CCMASK_CMP_LT : 0) |
2160ac9a064cSDimitry Andric           ((CCMask & SystemZ::CCMASK_CMP_LT) ? SystemZ::CCMASK_CMP_GT : 0) |
2161cfca06d7SDimitry Andric           (CCMask & SystemZ::CCMASK_CMP_UO));
2162cfca06d7SDimitry Andric }
2163cfca06d7SDimitry Andric 
emitBlockAfter(MachineBasicBlock * MBB)2164cfca06d7SDimitry Andric MachineBasicBlock *SystemZ::emitBlockAfter(MachineBasicBlock *MBB) {
2165cfca06d7SDimitry Andric   MachineFunction &MF = *MBB->getParent();
2166cfca06d7SDimitry Andric   MachineBasicBlock *NewMBB = MF.CreateMachineBasicBlock(MBB->getBasicBlock());
2167cfca06d7SDimitry Andric   MF.insert(std::next(MachineFunction::iterator(MBB)), NewMBB);
2168cfca06d7SDimitry Andric   return NewMBB;
2169cfca06d7SDimitry Andric }
2170cfca06d7SDimitry Andric 
splitBlockAfter(MachineBasicBlock::iterator MI,MachineBasicBlock * MBB)2171cfca06d7SDimitry Andric MachineBasicBlock *SystemZ::splitBlockAfter(MachineBasicBlock::iterator MI,
2172cfca06d7SDimitry Andric                                             MachineBasicBlock *MBB) {
2173cfca06d7SDimitry Andric   MachineBasicBlock *NewMBB = emitBlockAfter(MBB);
2174cfca06d7SDimitry Andric   NewMBB->splice(NewMBB->begin(), MBB,
2175cfca06d7SDimitry Andric                  std::next(MachineBasicBlock::iterator(MI)), MBB->end());
2176cfca06d7SDimitry Andric   NewMBB->transferSuccessorsAndUpdatePHIs(MBB);
2177cfca06d7SDimitry Andric   return NewMBB;
2178cfca06d7SDimitry Andric }
2179cfca06d7SDimitry Andric 
splitBlockBefore(MachineBasicBlock::iterator MI,MachineBasicBlock * MBB)2180cfca06d7SDimitry Andric MachineBasicBlock *SystemZ::splitBlockBefore(MachineBasicBlock::iterator MI,
2181cfca06d7SDimitry Andric                                              MachineBasicBlock *MBB) {
2182cfca06d7SDimitry Andric   MachineBasicBlock *NewMBB = emitBlockAfter(MBB);
2183cfca06d7SDimitry Andric   NewMBB->splice(NewMBB->begin(), MBB, MI, MBB->end());
2184cfca06d7SDimitry Andric   NewMBB->transferSuccessorsAndUpdatePHIs(MBB);
2185cfca06d7SDimitry Andric   return NewMBB;
2186cfca06d7SDimitry Andric }
2187cfca06d7SDimitry Andric 
getLoadAndTrap(unsigned Opcode) const2188b915e9e0SDimitry Andric unsigned SystemZInstrInfo::getLoadAndTrap(unsigned Opcode) const {
2189b915e9e0SDimitry Andric   if (!STI.hasLoadAndTrap())
2190b915e9e0SDimitry Andric     return 0;
2191b915e9e0SDimitry Andric   switch (Opcode) {
2192b915e9e0SDimitry Andric   case SystemZ::L:
2193b915e9e0SDimitry Andric   case SystemZ::LY:
2194b915e9e0SDimitry Andric     return SystemZ::LAT;
2195b915e9e0SDimitry Andric   case SystemZ::LG:
2196b915e9e0SDimitry Andric     return SystemZ::LGAT;
2197b915e9e0SDimitry Andric   case SystemZ::LFH:
2198b915e9e0SDimitry Andric     return SystemZ::LFHAT;
2199b915e9e0SDimitry Andric   case SystemZ::LLGF:
2200b915e9e0SDimitry Andric     return SystemZ::LLGFAT;
2201b915e9e0SDimitry Andric   case SystemZ::LLGT:
2202b915e9e0SDimitry Andric     return SystemZ::LLGTAT;
2203b915e9e0SDimitry Andric   }
2204b915e9e0SDimitry Andric   return 0;
2205b915e9e0SDimitry Andric }
2206b915e9e0SDimitry Andric 
loadImmediate(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Reg,uint64_t Value) const220759d6cff9SDimitry Andric void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
220859d6cff9SDimitry Andric                                      MachineBasicBlock::iterator MBBI,
220959d6cff9SDimitry Andric                                      unsigned Reg, uint64_t Value) const {
221059d6cff9SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
2211c0981da4SDimitry Andric   unsigned Opcode = 0;
221259d6cff9SDimitry Andric   if (isInt<16>(Value))
221359d6cff9SDimitry Andric     Opcode = SystemZ::LGHI;
221459d6cff9SDimitry Andric   else if (SystemZ::isImmLL(Value))
221559d6cff9SDimitry Andric     Opcode = SystemZ::LLILL;
221659d6cff9SDimitry Andric   else if (SystemZ::isImmLH(Value)) {
221759d6cff9SDimitry Andric     Opcode = SystemZ::LLILH;
221859d6cff9SDimitry Andric     Value >>= 16;
221959d6cff9SDimitry Andric   }
2220c0981da4SDimitry Andric   else if (isInt<32>(Value))
2221c0981da4SDimitry Andric     Opcode = SystemZ::LGFI;
2222c0981da4SDimitry Andric   if (Opcode) {
222359d6cff9SDimitry Andric     BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);
2224c0981da4SDimitry Andric     return;
2225c0981da4SDimitry Andric   }
2226c0981da4SDimitry Andric 
2227c0981da4SDimitry Andric   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
2228c0981da4SDimitry Andric   assert (MRI.isSSA() &&  "Huge values only handled before reg-alloc .");
2229c0981da4SDimitry Andric   Register Reg0 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);
2230c0981da4SDimitry Andric   Register Reg1 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);
2231c0981da4SDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IMPLICIT_DEF), Reg0);
2232c0981da4SDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IIHF64), Reg1)
2233c0981da4SDimitry Andric     .addReg(Reg0).addImm(Value >> 32);
2234c0981da4SDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IILF64), Reg)
2235c0981da4SDimitry Andric     .addReg(Reg1).addImm(Value & ((uint64_t(1) << 32) - 1));
223659d6cff9SDimitry Andric }
2237b915e9e0SDimitry Andric 
verifyInstruction(const MachineInstr & MI,StringRef & ErrInfo) const2238706b4fc4SDimitry Andric bool SystemZInstrInfo::verifyInstruction(const MachineInstr &MI,
2239706b4fc4SDimitry Andric                                          StringRef &ErrInfo) const {
2240706b4fc4SDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
2241706b4fc4SDimitry Andric   for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
2242706b4fc4SDimitry Andric     if (I >= MCID.getNumOperands())
2243706b4fc4SDimitry Andric       break;
2244706b4fc4SDimitry Andric     const MachineOperand &Op = MI.getOperand(I);
2245e3b55780SDimitry Andric     const MCOperandInfo &MCOI = MCID.operands()[I];
2246706b4fc4SDimitry Andric     // Addressing modes have register and immediate operands. Op should be a
2247706b4fc4SDimitry Andric     // register (or frame index) operand if MCOI.RegClass contains a valid
2248706b4fc4SDimitry Andric     // register class, or an immediate otherwise.
2249706b4fc4SDimitry Andric     if (MCOI.OperandType == MCOI::OPERAND_MEMORY &&
2250706b4fc4SDimitry Andric         ((MCOI.RegClass != -1 && !Op.isReg() && !Op.isFI()) ||
2251706b4fc4SDimitry Andric          (MCOI.RegClass == -1 && !Op.isImm()))) {
2252706b4fc4SDimitry Andric       ErrInfo = "Addressing mode operands corrupt!";
2253706b4fc4SDimitry Andric       return false;
2254706b4fc4SDimitry Andric     }
2255706b4fc4SDimitry Andric   }
2256706b4fc4SDimitry Andric 
2257706b4fc4SDimitry Andric   return true;
2258706b4fc4SDimitry Andric }
2259706b4fc4SDimitry Andric 
2260b915e9e0SDimitry Andric bool SystemZInstrInfo::
areMemAccessesTriviallyDisjoint(const MachineInstr & MIa,const MachineInstr & MIb) const2261e6d15924SDimitry Andric areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
22621d5ae102SDimitry Andric                                 const MachineInstr &MIb) const {
2263b915e9e0SDimitry Andric 
2264b915e9e0SDimitry Andric   if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand())
2265b915e9e0SDimitry Andric     return false;
2266b915e9e0SDimitry Andric 
2267b915e9e0SDimitry Andric   // If mem-operands show that the same address Value is used by both
2268b915e9e0SDimitry Andric   // instructions, check for non-overlapping offsets and widths. Not
2269b915e9e0SDimitry Andric   // sure if a register based analysis would be an improvement...
2270b915e9e0SDimitry Andric 
2271b915e9e0SDimitry Andric   MachineMemOperand *MMOa = *MIa.memoperands_begin();
2272b915e9e0SDimitry Andric   MachineMemOperand *MMOb = *MIb.memoperands_begin();
2273b915e9e0SDimitry Andric   const Value *VALa = MMOa->getValue();
2274b915e9e0SDimitry Andric   const Value *VALb = MMOb->getValue();
2275b915e9e0SDimitry Andric   bool SameVal = (VALa && VALb && (VALa == VALb));
2276b915e9e0SDimitry Andric   if (!SameVal) {
2277b915e9e0SDimitry Andric     const PseudoSourceValue *PSVa = MMOa->getPseudoValue();
2278b915e9e0SDimitry Andric     const PseudoSourceValue *PSVb = MMOb->getPseudoValue();
2279b915e9e0SDimitry Andric     if (PSVa && PSVb && (PSVa == PSVb))
2280b915e9e0SDimitry Andric       SameVal = true;
2281b915e9e0SDimitry Andric   }
2282b915e9e0SDimitry Andric   if (SameVal) {
2283b915e9e0SDimitry Andric     int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset();
2284ac9a064cSDimitry Andric     LocationSize WidthA = MMOa->getSize(), WidthB = MMOb->getSize();
2285b915e9e0SDimitry Andric     int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
2286b915e9e0SDimitry Andric     int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
2287ac9a064cSDimitry Andric     LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
2288ac9a064cSDimitry Andric     if (LowWidth.hasValue() &&
2289ac9a064cSDimitry Andric         LowOffset + (int)LowWidth.getValue() <= HighOffset)
2290b915e9e0SDimitry Andric       return true;
2291b915e9e0SDimitry Andric   }
2292b915e9e0SDimitry Andric 
2293b915e9e0SDimitry Andric   return false;
2294b915e9e0SDimitry Andric }
2295ac9a064cSDimitry Andric 
getConstValDefinedInReg(const MachineInstr & MI,const Register Reg,int64_t & ImmVal) const2296ac9a064cSDimitry Andric bool SystemZInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,
2297ac9a064cSDimitry Andric                                                const Register Reg,
2298ac9a064cSDimitry Andric                                                int64_t &ImmVal) const {
2299ac9a064cSDimitry Andric 
2300ac9a064cSDimitry Andric   if (MI.getOpcode() == SystemZ::VGBM && Reg == MI.getOperand(0).getReg()) {
2301ac9a064cSDimitry Andric     ImmVal = MI.getOperand(1).getImm();
2302ac9a064cSDimitry Andric     // TODO: Handle non-0 values
2303ac9a064cSDimitry Andric     return ImmVal == 0;
2304ac9a064cSDimitry Andric   }
2305ac9a064cSDimitry Andric 
2306ac9a064cSDimitry Andric   return false;
2307ac9a064cSDimitry Andric }
2308