xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- SystemZInstrInfo.cpp - SystemZ instruction information ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the SystemZ implementation of the TargetInstrInfo class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "SystemZInstrInfo.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
150b57cec5SDimitry Andric #include "SystemZ.h"
160b57cec5SDimitry Andric #include "SystemZInstrBuilder.h"
170b57cec5SDimitry Andric #include "SystemZSubtarget.h"
180b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveRegUnits.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
300b57cec5SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
31349cc55cSDimitry Andric #include "llvm/CodeGen/StackMaps.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
3481ad6265SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
370b57cec5SDimitry Andric #include "llvm/Support/BranchProbability.h"
380b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
390b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
400b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
410b57cec5SDimitry Andric #include <cassert>
420b57cec5SDimitry Andric #include <cstdint>
430b57cec5SDimitry Andric #include <iterator>
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using namespace llvm;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
480b57cec5SDimitry Andric #define GET_INSTRMAP_INFO
490b57cec5SDimitry Andric #include "SystemZGenInstrInfo.inc"
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric #define DEBUG_TYPE "systemz-II"
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric // Return a mask with Count low bits set.
540b57cec5SDimitry Andric static uint64_t allOnes(unsigned int Count) {
550b57cec5SDimitry Andric   return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric // Pin the vtable to this file.
590b57cec5SDimitry Andric void SystemZInstrInfo::anchor() {}
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti)
62*0fca6ea1SDimitry Andric     : SystemZGenInstrInfo(-1, -1),
63fe6060f1SDimitry Andric       RI(sti.getSpecialRegisters()->getReturnFunctionAddressRegister()),
64fe6060f1SDimitry Andric       STI(sti) {}
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // MI is a 128-bit load or store.  Split it into two 64-bit loads or stores,
670b57cec5SDimitry Andric // each having the opcode given by NewOpcode.
680b57cec5SDimitry Andric void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,
690b57cec5SDimitry Andric                                  unsigned NewOpcode) const {
700b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
710b57cec5SDimitry Andric   MachineFunction &MF = *MBB->getParent();
720b57cec5SDimitry Andric 
733a079333SDimitry Andric   // Get two load or store instructions.  Use the original instruction for
743a079333SDimitry Andric   // one of them and create a clone for the other.
753a079333SDimitry Andric   MachineInstr *HighPartMI = MF.CloneMachineInstr(&*MI);
763a079333SDimitry Andric   MachineInstr *LowPartMI = &*MI;
773a079333SDimitry Andric   MBB->insert(LowPartMI, HighPartMI);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   // Set up the two 64-bit registers and remember super reg and its flags.
803a079333SDimitry Andric   MachineOperand &HighRegOp = HighPartMI->getOperand(0);
813a079333SDimitry Andric   MachineOperand &LowRegOp = LowPartMI->getOperand(0);
828bcb0991SDimitry Andric   Register Reg128 = LowRegOp.getReg();
830b57cec5SDimitry Andric   unsigned Reg128Killed = getKillRegState(LowRegOp.isKill());
840b57cec5SDimitry Andric   unsigned Reg128Undef  = getUndefRegState(LowRegOp.isUndef());
850b57cec5SDimitry Andric   HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64));
860b57cec5SDimitry Andric   LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64));
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   // The address in the first (high) instruction is already correct.
890b57cec5SDimitry Andric   // Adjust the offset in the second (low) instruction.
903a079333SDimitry Andric   MachineOperand &HighOffsetOp = HighPartMI->getOperand(2);
913a079333SDimitry Andric   MachineOperand &LowOffsetOp = LowPartMI->getOperand(2);
920b57cec5SDimitry Andric   LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   // Set the opcodes.
950b57cec5SDimitry Andric   unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());
960b57cec5SDimitry Andric   unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());
970b57cec5SDimitry Andric   assert(HighOpcode && LowOpcode && "Both offsets should be in range");
983a079333SDimitry Andric   HighPartMI->setDesc(get(HighOpcode));
993a079333SDimitry Andric   LowPartMI->setDesc(get(LowOpcode));
1000b57cec5SDimitry Andric 
1013a079333SDimitry Andric   MachineInstr *FirstMI = HighPartMI;
1023a079333SDimitry Andric   if (MI->mayStore()) {
1033a079333SDimitry Andric     FirstMI->getOperand(0).setIsKill(false);
1043a079333SDimitry Andric     // Add implicit uses of the super register in case one of the subregs is
1053a079333SDimitry Andric     // undefined. We could track liveness and skip storing an undefined
1063a079333SDimitry Andric     // subreg, but this is hopefully rare (discovered with llvm-stress).
1073a079333SDimitry Andric     // If Reg128 was killed, set kill flag on MI.
1083a079333SDimitry Andric     unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);
1093a079333SDimitry Andric     MachineInstrBuilder(MF, HighPartMI).addReg(Reg128, Reg128UndefImpl);
1103a079333SDimitry Andric     MachineInstrBuilder(MF, LowPartMI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));
1113a079333SDimitry Andric   } else {
1123a079333SDimitry Andric     // If HighPartMI clobbers any of the address registers, it needs to come
1133a079333SDimitry Andric     // after LowPartMI.
1143a079333SDimitry Andric     auto overlapsAddressReg = [&](Register Reg) -> bool {
1153a079333SDimitry Andric       return RI.regsOverlap(Reg, MI->getOperand(1).getReg()) ||
1163a079333SDimitry Andric              RI.regsOverlap(Reg, MI->getOperand(3).getReg());
1173a079333SDimitry Andric     };
1183a079333SDimitry Andric     if (overlapsAddressReg(HighRegOp.getReg())) {
1193a079333SDimitry Andric       assert(!overlapsAddressReg(LowRegOp.getReg()) &&
1203a079333SDimitry Andric              "Both loads clobber address!");
1213a079333SDimitry Andric       MBB->splice(HighPartMI, MBB, LowPartMI);
1223a079333SDimitry Andric       FirstMI = LowPartMI;
1233a079333SDimitry Andric     }
1243a079333SDimitry Andric   }
1253a079333SDimitry Andric 
1263a079333SDimitry Andric   // Clear the kill flags on the address registers in the first instruction.
1273a079333SDimitry Andric   FirstMI->getOperand(1).setIsKill(false);
1283a079333SDimitry Andric   FirstMI->getOperand(3).setIsKill(false);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric // Split ADJDYNALLOC instruction MI.
1320b57cec5SDimitry Andric void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {
1330b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
1340b57cec5SDimitry Andric   MachineFunction &MF = *MBB->getParent();
1350b57cec5SDimitry Andric   MachineFrameInfo &MFFrame = MF.getFrameInfo();
1360b57cec5SDimitry Andric   MachineOperand &OffsetMO = MI->getOperand(2);
13781ad6265SDimitry Andric   SystemZCallingConventionRegisters *Regs = STI.getSpecialRegisters();
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   uint64_t Offset = (MFFrame.getMaxCallFrameSize() +
14081ad6265SDimitry Andric                      Regs->getCallFrameSize() +
14181ad6265SDimitry Andric                      Regs->getStackPointerBias() +
1420b57cec5SDimitry Andric                      OffsetMO.getImm());
1430b57cec5SDimitry Andric   unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);
1440b57cec5SDimitry Andric   assert(NewOpcode && "No support for huge argument lists yet");
1450b57cec5SDimitry Andric   MI->setDesc(get(NewOpcode));
1460b57cec5SDimitry Andric   OffsetMO.setImm(Offset);
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric // MI is an RI-style pseudo instruction.  Replace it with LowOpcode
1500b57cec5SDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
1510b57cec5SDimitry Andric // is a high GR32.  ConvertHigh is true if LowOpcode takes a signed operand
1520b57cec5SDimitry Andric // and HighOpcode takes an unsigned 32-bit operand.  In those cases,
1530b57cec5SDimitry Andric // MI has the same kind of operand as LowOpcode, so needs to be converted
1540b57cec5SDimitry Andric // if HighOpcode is used.
1550b57cec5SDimitry Andric void SystemZInstrInfo::expandRIPseudo(MachineInstr &MI, unsigned LowOpcode,
1560b57cec5SDimitry Andric                                       unsigned HighOpcode,
1570b57cec5SDimitry Andric                                       bool ConvertHigh) const {
1588bcb0991SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
1598bcb0991SDimitry Andric   bool IsHigh = SystemZ::isHighReg(Reg);
1600b57cec5SDimitry Andric   MI.setDesc(get(IsHigh ? HighOpcode : LowOpcode));
1610b57cec5SDimitry Andric   if (IsHigh && ConvertHigh)
1620b57cec5SDimitry Andric     MI.getOperand(1).setImm(uint32_t(MI.getOperand(1).getImm()));
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric // MI is a three-operand RIE-style pseudo instruction.  Replace it with
1660b57cec5SDimitry Andric // LowOpcodeK if the registers are both low GR32s, otherwise use a move
1670b57cec5SDimitry Andric // followed by HighOpcode or LowOpcode, depending on whether the target
1680b57cec5SDimitry Andric // is a high or low GR32.
1690b57cec5SDimitry Andric void SystemZInstrInfo::expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,
1700b57cec5SDimitry Andric                                        unsigned LowOpcodeK,
1710b57cec5SDimitry Andric                                        unsigned HighOpcode) const {
1728bcb0991SDimitry Andric   Register DestReg = MI.getOperand(0).getReg();
1738bcb0991SDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
1748bcb0991SDimitry Andric   bool DestIsHigh = SystemZ::isHighReg(DestReg);
1758bcb0991SDimitry Andric   bool SrcIsHigh = SystemZ::isHighReg(SrcReg);
1760b57cec5SDimitry Andric   if (!DestIsHigh && !SrcIsHigh)
1770b57cec5SDimitry Andric     MI.setDesc(get(LowOpcodeK));
1780b57cec5SDimitry Andric   else {
1790b57cec5SDimitry Andric     if (DestReg != SrcReg) {
1800b57cec5SDimitry Andric       emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), DestReg, SrcReg,
1810b57cec5SDimitry Andric                     SystemZ::LR, 32, MI.getOperand(1).isKill(),
1820b57cec5SDimitry Andric                     MI.getOperand(1).isUndef());
1830b57cec5SDimitry Andric       MI.getOperand(1).setReg(DestReg);
1840b57cec5SDimitry Andric     }
1850b57cec5SDimitry Andric     MI.setDesc(get(DestIsHigh ? HighOpcode : LowOpcode));
1860b57cec5SDimitry Andric     MI.tieOperands(0, 1);
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric // MI is an RXY-style pseudo instruction.  Replace it with LowOpcode
1910b57cec5SDimitry Andric // if the first operand is a low GR32 and HighOpcode if the first operand
1920b57cec5SDimitry Andric // is a high GR32.
1930b57cec5SDimitry Andric void SystemZInstrInfo::expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,
1940b57cec5SDimitry Andric                                        unsigned HighOpcode) const {
1958bcb0991SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
1968bcb0991SDimitry Andric   unsigned Opcode = getOpcodeForOffset(
1978bcb0991SDimitry Andric       SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode,
1980b57cec5SDimitry Andric       MI.getOperand(2).getImm());
1990b57cec5SDimitry Andric   MI.setDesc(get(Opcode));
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric // MI is a load-on-condition pseudo instruction with a single register
2030b57cec5SDimitry Andric // (source or destination) operand.  Replace it with LowOpcode if the
2040b57cec5SDimitry Andric // register is a low GR32 and HighOpcode if the register is a high GR32.
2050b57cec5SDimitry Andric void SystemZInstrInfo::expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,
2060b57cec5SDimitry Andric                                        unsigned HighOpcode) const {
2078bcb0991SDimitry Andric   Register Reg = MI.getOperand(0).getReg();
2088bcb0991SDimitry Andric   unsigned Opcode = SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode;
2090b57cec5SDimitry Andric   MI.setDesc(get(Opcode));
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric // MI is an RR-style pseudo instruction that zero-extends the low Size bits
2130b57cec5SDimitry Andric // of one GRX32 into another.  Replace it with LowOpcode if both operands
2140b57cec5SDimitry Andric // are low registers, otherwise use RISB[LH]G.
2150b57cec5SDimitry Andric void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,
2160b57cec5SDimitry Andric                                         unsigned Size) const {
2170b57cec5SDimitry Andric   MachineInstrBuilder MIB =
2180b57cec5SDimitry Andric     emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(),
2190b57cec5SDimitry Andric                MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), LowOpcode,
2200b57cec5SDimitry Andric                Size, MI.getOperand(1).isKill(), MI.getOperand(1).isUndef());
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   // Keep the remaining operands as-is.
2234824e7fdSDimitry Andric   for (const MachineOperand &MO : llvm::drop_begin(MI.operands(), 2))
2244824e7fdSDimitry Andric     MIB.add(MO);
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   MI.eraseFromParent();
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const {
2300b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI->getParent();
2310b57cec5SDimitry Andric   MachineFunction &MF = *MBB->getParent();
2328bcb0991SDimitry Andric   const Register Reg64 = MI->getOperand(0).getReg();
2338bcb0991SDimitry Andric   const Register Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   // EAR can only load the low subregister so us a shift for %a0 to produce
2360b57cec5SDimitry Andric   // the GR containing %a0 and %a1.
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric   // ear <reg>, %a0
2390b57cec5SDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
2400b57cec5SDimitry Andric     .addReg(SystemZ::A0)
2410b57cec5SDimitry Andric     .addReg(Reg64, RegState::ImplicitDefine);
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   // sllg <reg>, <reg>, 32
2440b57cec5SDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64)
2450b57cec5SDimitry Andric     .addReg(Reg64)
2460b57cec5SDimitry Andric     .addReg(0)
2470b57cec5SDimitry Andric     .addImm(32);
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   // ear <reg>, %a1
2500b57cec5SDimitry Andric   BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)
2510b57cec5SDimitry Andric     .addReg(SystemZ::A1);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   // lg <reg>, 40(<reg>)
2540b57cec5SDimitry Andric   MI->setDesc(get(SystemZ::LG));
2550b57cec5SDimitry Andric   MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0);
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric // Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR
2590b57cec5SDimitry Andric // DestReg before MBBI in MBB.  Use LowLowOpcode when both DestReg and SrcReg
2600b57cec5SDimitry Andric // are low registers, otherwise use RISB[LH]G.  Size is the number of bits
2610b57cec5SDimitry Andric // taken from the low end of SrcReg (8 for LLCR, 16 for LLHR and 32 for LR).
2620b57cec5SDimitry Andric // KillSrc is true if this move is the last use of SrcReg.
2630b57cec5SDimitry Andric MachineInstrBuilder
2640b57cec5SDimitry Andric SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB,
2650b57cec5SDimitry Andric                                 MachineBasicBlock::iterator MBBI,
2660b57cec5SDimitry Andric                                 const DebugLoc &DL, unsigned DestReg,
2670b57cec5SDimitry Andric                                 unsigned SrcReg, unsigned LowLowOpcode,
2680b57cec5SDimitry Andric                                 unsigned Size, bool KillSrc,
2690b57cec5SDimitry Andric                                 bool UndefSrc) const {
2700b57cec5SDimitry Andric   unsigned Opcode;
2718bcb0991SDimitry Andric   bool DestIsHigh = SystemZ::isHighReg(DestReg);
2728bcb0991SDimitry Andric   bool SrcIsHigh = SystemZ::isHighReg(SrcReg);
2730b57cec5SDimitry Andric   if (DestIsHigh && SrcIsHigh)
2740b57cec5SDimitry Andric     Opcode = SystemZ::RISBHH;
2750b57cec5SDimitry Andric   else if (DestIsHigh && !SrcIsHigh)
2760b57cec5SDimitry Andric     Opcode = SystemZ::RISBHL;
2770b57cec5SDimitry Andric   else if (!DestIsHigh && SrcIsHigh)
2780b57cec5SDimitry Andric     Opcode = SystemZ::RISBLH;
2790b57cec5SDimitry Andric   else {
2800b57cec5SDimitry Andric     return BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg)
2810b57cec5SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc));
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric   unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0);
2840b57cec5SDimitry Andric   return BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
2850b57cec5SDimitry Andric     .addReg(DestReg, RegState::Undef)
2860b57cec5SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc))
2870b57cec5SDimitry Andric     .addImm(32 - Size).addImm(128 + 31).addImm(Rotate);
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric MachineInstr *SystemZInstrInfo::commuteInstructionImpl(MachineInstr &MI,
2910b57cec5SDimitry Andric                                                        bool NewMI,
2920b57cec5SDimitry Andric                                                        unsigned OpIdx1,
2930b57cec5SDimitry Andric                                                        unsigned OpIdx2) const {
2940b57cec5SDimitry Andric   auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {
2950b57cec5SDimitry Andric     if (NewMI)
2960b57cec5SDimitry Andric       return *MI.getParent()->getParent()->CloneMachineInstr(&MI);
2970b57cec5SDimitry Andric     return MI;
2980b57cec5SDimitry Andric   };
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   switch (MI.getOpcode()) {
3010b57cec5SDimitry Andric   case SystemZ::SELRMux:
3020b57cec5SDimitry Andric   case SystemZ::SELFHR:
3030b57cec5SDimitry Andric   case SystemZ::SELR:
3040b57cec5SDimitry Andric   case SystemZ::SELGR:
3050b57cec5SDimitry Andric   case SystemZ::LOCRMux:
3060b57cec5SDimitry Andric   case SystemZ::LOCFHR:
3070b57cec5SDimitry Andric   case SystemZ::LOCR:
3080b57cec5SDimitry Andric   case SystemZ::LOCGR: {
3090b57cec5SDimitry Andric     auto &WorkingMI = cloneIfNew(MI);
3100b57cec5SDimitry Andric     // Invert condition.
3110b57cec5SDimitry Andric     unsigned CCValid = WorkingMI.getOperand(3).getImm();
3120b57cec5SDimitry Andric     unsigned CCMask = WorkingMI.getOperand(4).getImm();
3130b57cec5SDimitry Andric     WorkingMI.getOperand(4).setImm(CCMask ^ CCValid);
3140b57cec5SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
3150b57cec5SDimitry Andric                                                    OpIdx1, OpIdx2);
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric   default:
3180b57cec5SDimitry Andric     return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric // If MI is a simple load or store for a frame object, return the register
3230b57cec5SDimitry Andric // it loads or stores and set FrameIndex to the index of the frame object.
3240b57cec5SDimitry Andric // Return 0 otherwise.
3250b57cec5SDimitry Andric //
3260b57cec5SDimitry Andric // Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
3270b57cec5SDimitry Andric static int isSimpleMove(const MachineInstr &MI, int &FrameIndex,
3280b57cec5SDimitry Andric                         unsigned Flag) {
3290b57cec5SDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
3300b57cec5SDimitry Andric   if ((MCID.TSFlags & Flag) && MI.getOperand(1).isFI() &&
3310b57cec5SDimitry Andric       MI.getOperand(2).getImm() == 0 && MI.getOperand(3).getReg() == 0) {
3320b57cec5SDimitry Andric     FrameIndex = MI.getOperand(1).getIndex();
3330b57cec5SDimitry Andric     return MI.getOperand(0).getReg();
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric   return 0;
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
338*0fca6ea1SDimitry Andric Register SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
3390b57cec5SDimitry Andric                                                int &FrameIndex) const {
3400b57cec5SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXLoad);
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric 
343*0fca6ea1SDimitry Andric Register SystemZInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
3440b57cec5SDimitry Andric                                               int &FrameIndex) const {
3450b57cec5SDimitry Andric   return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXStore);
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric bool SystemZInstrInfo::isStackSlotCopy(const MachineInstr &MI,
3490b57cec5SDimitry Andric                                        int &DestFrameIndex,
3500b57cec5SDimitry Andric                                        int &SrcFrameIndex) const {
3510b57cec5SDimitry Andric   // Check for MVC 0(Length,FI1),0(FI2)
3520b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MI.getParent()->getParent()->getFrameInfo();
3530b57cec5SDimitry Andric   if (MI.getOpcode() != SystemZ::MVC || !MI.getOperand(0).isFI() ||
3540b57cec5SDimitry Andric       MI.getOperand(1).getImm() != 0 || !MI.getOperand(3).isFI() ||
3550b57cec5SDimitry Andric       MI.getOperand(4).getImm() != 0)
3560b57cec5SDimitry Andric     return false;
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   // Check that Length covers the full slots.
3590b57cec5SDimitry Andric   int64_t Length = MI.getOperand(2).getImm();
3600b57cec5SDimitry Andric   unsigned FI1 = MI.getOperand(0).getIndex();
3610b57cec5SDimitry Andric   unsigned FI2 = MI.getOperand(3).getIndex();
3620b57cec5SDimitry Andric   if (MFI.getObjectSize(FI1) != Length ||
3630b57cec5SDimitry Andric       MFI.getObjectSize(FI2) != Length)
3640b57cec5SDimitry Andric     return false;
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   DestFrameIndex = FI1;
3670b57cec5SDimitry Andric   SrcFrameIndex = FI2;
3680b57cec5SDimitry Andric   return true;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
3720b57cec5SDimitry Andric                                      MachineBasicBlock *&TBB,
3730b57cec5SDimitry Andric                                      MachineBasicBlock *&FBB,
3740b57cec5SDimitry Andric                                      SmallVectorImpl<MachineOperand> &Cond,
3750b57cec5SDimitry Andric                                      bool AllowModify) const {
3760b57cec5SDimitry Andric   // Most of the code and comments here are boilerplate.
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   // Start from the bottom of the block and work up, examining the
3790b57cec5SDimitry Andric   // terminator instructions.
3800b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
3810b57cec5SDimitry Andric   while (I != MBB.begin()) {
3820b57cec5SDimitry Andric     --I;
3830b57cec5SDimitry Andric     if (I->isDebugInstr())
3840b57cec5SDimitry Andric       continue;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     // Working from the bottom, when we see a non-terminator instruction, we're
3870b57cec5SDimitry Andric     // done.
3880b57cec5SDimitry Andric     if (!isUnpredicatedTerminator(*I))
3890b57cec5SDimitry Andric       break;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     // A terminator that isn't a branch can't easily be handled by this
3920b57cec5SDimitry Andric     // analysis.
3930b57cec5SDimitry Andric     if (!I->isBranch())
3940b57cec5SDimitry Andric       return true;
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     // Can't handle indirect branches.
3970b57cec5SDimitry Andric     SystemZII::Branch Branch(getBranchInfo(*I));
3980b57cec5SDimitry Andric     if (!Branch.hasMBBTarget())
3990b57cec5SDimitry Andric       return true;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric     // Punt on compound branches.
4020b57cec5SDimitry Andric     if (Branch.Type != SystemZII::BranchNormal)
4030b57cec5SDimitry Andric       return true;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric     if (Branch.CCMask == SystemZ::CCMASK_ANY) {
4060b57cec5SDimitry Andric       // Handle unconditional branches.
4070b57cec5SDimitry Andric       if (!AllowModify) {
4080b57cec5SDimitry Andric         TBB = Branch.getMBBTarget();
4090b57cec5SDimitry Andric         continue;
4100b57cec5SDimitry Andric       }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric       // If the block has any instructions after a JMP, delete them.
41381ad6265SDimitry Andric       MBB.erase(std::next(I), MBB.end());
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric       Cond.clear();
4160b57cec5SDimitry Andric       FBB = nullptr;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric       // Delete the JMP if it's equivalent to a fall-through.
4190b57cec5SDimitry Andric       if (MBB.isLayoutSuccessor(Branch.getMBBTarget())) {
4200b57cec5SDimitry Andric         TBB = nullptr;
4210b57cec5SDimitry Andric         I->eraseFromParent();
4220b57cec5SDimitry Andric         I = MBB.end();
4230b57cec5SDimitry Andric         continue;
4240b57cec5SDimitry Andric       }
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric       // TBB is used to indicate the unconditinal destination.
4270b57cec5SDimitry Andric       TBB = Branch.getMBBTarget();
4280b57cec5SDimitry Andric       continue;
4290b57cec5SDimitry Andric     }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric     // Working from the bottom, handle the first conditional branch.
4320b57cec5SDimitry Andric     if (Cond.empty()) {
4330b57cec5SDimitry Andric       // FIXME: add X86-style branch swap
4340b57cec5SDimitry Andric       FBB = TBB;
4350b57cec5SDimitry Andric       TBB = Branch.getMBBTarget();
4360b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCValid));
4370b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
4380b57cec5SDimitry Andric       continue;
4390b57cec5SDimitry Andric     }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric     // Handle subsequent conditional branches.
4420b57cec5SDimitry Andric     assert(Cond.size() == 2 && TBB && "Should have seen a conditional branch");
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     // Only handle the case where all conditional branches branch to the same
4450b57cec5SDimitry Andric     // destination.
4460b57cec5SDimitry Andric     if (TBB != Branch.getMBBTarget())
4470b57cec5SDimitry Andric       return true;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     // If the conditions are the same, we can leave them alone.
4500b57cec5SDimitry Andric     unsigned OldCCValid = Cond[0].getImm();
4510b57cec5SDimitry Andric     unsigned OldCCMask = Cond[1].getImm();
4520b57cec5SDimitry Andric     if (OldCCValid == Branch.CCValid && OldCCMask == Branch.CCMask)
4530b57cec5SDimitry Andric       continue;
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric     // FIXME: Try combining conditions like X86 does.  Should be easy on Z!
4560b57cec5SDimitry Andric     return false;
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   return false;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric unsigned SystemZInstrInfo::removeBranch(MachineBasicBlock &MBB,
4630b57cec5SDimitry Andric                                         int *BytesRemoved) const {
4640b57cec5SDimitry Andric   assert(!BytesRemoved && "code size not handled");
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   // Most of the code and comments here are boilerplate.
4670b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
4680b57cec5SDimitry Andric   unsigned Count = 0;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   while (I != MBB.begin()) {
4710b57cec5SDimitry Andric     --I;
4720b57cec5SDimitry Andric     if (I->isDebugInstr())
4730b57cec5SDimitry Andric       continue;
4740b57cec5SDimitry Andric     if (!I->isBranch())
4750b57cec5SDimitry Andric       break;
4760b57cec5SDimitry Andric     if (!getBranchInfo(*I).hasMBBTarget())
4770b57cec5SDimitry Andric       break;
4780b57cec5SDimitry Andric     // Remove the branch.
4790b57cec5SDimitry Andric     I->eraseFromParent();
4800b57cec5SDimitry Andric     I = MBB.end();
4810b57cec5SDimitry Andric     ++Count;
4820b57cec5SDimitry Andric   }
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   return Count;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric bool SystemZInstrInfo::
4880b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
4890b57cec5SDimitry Andric   assert(Cond.size() == 2 && "Invalid condition");
4900b57cec5SDimitry Andric   Cond[1].setImm(Cond[1].getImm() ^ Cond[0].getImm());
4910b57cec5SDimitry Andric   return false;
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric unsigned SystemZInstrInfo::insertBranch(MachineBasicBlock &MBB,
4950b57cec5SDimitry Andric                                         MachineBasicBlock *TBB,
4960b57cec5SDimitry Andric                                         MachineBasicBlock *FBB,
4970b57cec5SDimitry Andric                                         ArrayRef<MachineOperand> Cond,
4980b57cec5SDimitry Andric                                         const DebugLoc &DL,
4990b57cec5SDimitry Andric                                         int *BytesAdded) const {
5000b57cec5SDimitry Andric   // In this function we output 32-bit branches, which should always
5010b57cec5SDimitry Andric   // have enough range.  They can be shortened and relaxed by later code
5020b57cec5SDimitry Andric   // in the pipeline, if desired.
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   // Shouldn't be a fall through.
5050b57cec5SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
5060b57cec5SDimitry Andric   assert((Cond.size() == 2 || Cond.size() == 0) &&
5070b57cec5SDimitry Andric          "SystemZ branch conditions have one component!");
5080b57cec5SDimitry Andric   assert(!BytesAdded && "code size not handled");
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   if (Cond.empty()) {
5110b57cec5SDimitry Andric     // Unconditional branch?
5120b57cec5SDimitry Andric     assert(!FBB && "Unconditional branch with multiple successors!");
5130b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(TBB);
5140b57cec5SDimitry Andric     return 1;
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   // Conditional branch.
5180b57cec5SDimitry Andric   unsigned Count = 0;
5190b57cec5SDimitry Andric   unsigned CCValid = Cond[0].getImm();
5200b57cec5SDimitry Andric   unsigned CCMask = Cond[1].getImm();
5210b57cec5SDimitry Andric   BuildMI(&MBB, DL, get(SystemZ::BRC))
5220b57cec5SDimitry Andric     .addImm(CCValid).addImm(CCMask).addMBB(TBB);
5230b57cec5SDimitry Andric   ++Count;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   if (FBB) {
5260b57cec5SDimitry Andric     // Two-way Conditional branch. Insert the second branch.
5270b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(FBB);
5280b57cec5SDimitry Andric     ++Count;
5290b57cec5SDimitry Andric   }
5300b57cec5SDimitry Andric   return Count;
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric 
5335ffd83dbSDimitry Andric bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
534349cc55cSDimitry Andric                                       Register &SrcReg2, int64_t &Mask,
535349cc55cSDimitry Andric                                       int64_t &Value) const {
5360b57cec5SDimitry Andric   assert(MI.isCompare() && "Caller should have checked for a comparison");
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   if (MI.getNumExplicitOperands() == 2 && MI.getOperand(0).isReg() &&
5390b57cec5SDimitry Andric       MI.getOperand(1).isImm()) {
5400b57cec5SDimitry Andric     SrcReg = MI.getOperand(0).getReg();
5410b57cec5SDimitry Andric     SrcReg2 = 0;
5420b57cec5SDimitry Andric     Value = MI.getOperand(1).getImm();
5430b57cec5SDimitry Andric     Mask = ~0;
5440b57cec5SDimitry Andric     return true;
5450b57cec5SDimitry Andric   }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   return false;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
5510b57cec5SDimitry Andric                                        ArrayRef<MachineOperand> Pred,
5525ffd83dbSDimitry Andric                                        Register DstReg, Register TrueReg,
5535ffd83dbSDimitry Andric                                        Register FalseReg, int &CondCycles,
5545ffd83dbSDimitry Andric                                        int &TrueCycles,
5550b57cec5SDimitry Andric                                        int &FalseCycles) const {
5560b57cec5SDimitry Andric   // Not all subtargets have LOCR instructions.
5570b57cec5SDimitry Andric   if (!STI.hasLoadStoreOnCond())
5580b57cec5SDimitry Andric     return false;
5590b57cec5SDimitry Andric   if (Pred.size() != 2)
5600b57cec5SDimitry Andric     return false;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   // Check register classes.
5630b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
5640b57cec5SDimitry Andric   const TargetRegisterClass *RC =
5650b57cec5SDimitry Andric     RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
5660b57cec5SDimitry Andric   if (!RC)
5670b57cec5SDimitry Andric     return false;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   // We have LOCR instructions for 32 and 64 bit general purpose registers.
5700b57cec5SDimitry Andric   if ((STI.hasLoadStoreOnCond2() &&
5710b57cec5SDimitry Andric        SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) ||
5720b57cec5SDimitry Andric       SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||
5730b57cec5SDimitry Andric       SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {
5740b57cec5SDimitry Andric     CondCycles = 2;
5750b57cec5SDimitry Andric     TrueCycles = 2;
5760b57cec5SDimitry Andric     FalseCycles = 2;
5770b57cec5SDimitry Andric     return true;
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   // Can't do anything else.
5810b57cec5SDimitry Andric   return false;
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric void SystemZInstrInfo::insertSelect(MachineBasicBlock &MBB,
5850b57cec5SDimitry Andric                                     MachineBasicBlock::iterator I,
5865ffd83dbSDimitry Andric                                     const DebugLoc &DL, Register DstReg,
5870b57cec5SDimitry Andric                                     ArrayRef<MachineOperand> Pred,
5885ffd83dbSDimitry Andric                                     Register TrueReg,
5895ffd83dbSDimitry Andric                                     Register FalseReg) const {
5900b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
5910b57cec5SDimitry Andric   const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
5940b57cec5SDimitry Andric   unsigned CCValid = Pred[0].getImm();
5950b57cec5SDimitry Andric   unsigned CCMask = Pred[1].getImm();
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   unsigned Opc;
5980b57cec5SDimitry Andric   if (SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) {
5990b57cec5SDimitry Andric     if (STI.hasMiscellaneousExtensions3())
6000b57cec5SDimitry Andric       Opc = SystemZ::SELRMux;
6010b57cec5SDimitry Andric     else if (STI.hasLoadStoreOnCond2())
6020b57cec5SDimitry Andric       Opc = SystemZ::LOCRMux;
6030b57cec5SDimitry Andric     else {
6040b57cec5SDimitry Andric       Opc = SystemZ::LOCR;
6050b57cec5SDimitry Andric       MRI.constrainRegClass(DstReg, &SystemZ::GR32BitRegClass);
6068bcb0991SDimitry Andric       Register TReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
6078bcb0991SDimitry Andric       Register FReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
6080b57cec5SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), TReg).addReg(TrueReg);
6090b57cec5SDimitry Andric       BuildMI(MBB, I, DL, get(TargetOpcode::COPY), FReg).addReg(FalseReg);
6100b57cec5SDimitry Andric       TrueReg = TReg;
6110b57cec5SDimitry Andric       FalseReg = FReg;
6120b57cec5SDimitry Andric     }
6130b57cec5SDimitry Andric   } else if (SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {
6140b57cec5SDimitry Andric     if (STI.hasMiscellaneousExtensions3())
6150b57cec5SDimitry Andric       Opc = SystemZ::SELGR;
6160b57cec5SDimitry Andric     else
6170b57cec5SDimitry Andric       Opc = SystemZ::LOCGR;
6180b57cec5SDimitry Andric   } else
6190b57cec5SDimitry Andric     llvm_unreachable("Invalid register class");
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   BuildMI(MBB, I, DL, get(Opc), DstReg)
6220b57cec5SDimitry Andric     .addReg(FalseReg).addReg(TrueReg)
6230b57cec5SDimitry Andric     .addImm(CCValid).addImm(CCMask);
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric 
626*0fca6ea1SDimitry Andric MachineInstr *SystemZInstrInfo::optimizeLoadInstr(MachineInstr &MI,
627*0fca6ea1SDimitry Andric                                                   const MachineRegisterInfo *MRI,
628*0fca6ea1SDimitry Andric                                                   Register &FoldAsLoadDefReg,
629*0fca6ea1SDimitry Andric                                                   MachineInstr *&DefMI) const {
630*0fca6ea1SDimitry Andric   // Check whether we can move the DefMI load, and that it only has one use.
631*0fca6ea1SDimitry Andric   DefMI = MRI->getVRegDef(FoldAsLoadDefReg);
632*0fca6ea1SDimitry Andric   assert(DefMI);
633*0fca6ea1SDimitry Andric   bool SawStore = false;
634*0fca6ea1SDimitry Andric   if (!DefMI->isSafeToMove(nullptr, SawStore) ||
635*0fca6ea1SDimitry Andric       !MRI->hasOneNonDBGUse(FoldAsLoadDefReg))
636*0fca6ea1SDimitry Andric     return nullptr;
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric   int UseOpIdx =
639*0fca6ea1SDimitry Andric       MI.findRegisterUseOperandIdx(FoldAsLoadDefReg, /*TRI=*/nullptr);
640*0fca6ea1SDimitry Andric   assert(UseOpIdx != -1 && "Expected FoldAsLoadDefReg to be used by MI.");
641*0fca6ea1SDimitry Andric 
642*0fca6ea1SDimitry Andric   // Check whether we can fold the load.
643*0fca6ea1SDimitry Andric   if (MachineInstr *FoldMI =
644*0fca6ea1SDimitry Andric           foldMemoryOperand(MI, {((unsigned)UseOpIdx)}, *DefMI)) {
645*0fca6ea1SDimitry Andric     FoldAsLoadDefReg = 0;
646*0fca6ea1SDimitry Andric     return FoldMI;
647*0fca6ea1SDimitry Andric   }
648*0fca6ea1SDimitry Andric 
649*0fca6ea1SDimitry Andric   return nullptr;
650*0fca6ea1SDimitry Andric }
651*0fca6ea1SDimitry Andric 
652*0fca6ea1SDimitry Andric bool SystemZInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
6535ffd83dbSDimitry Andric                                      Register Reg,
6540b57cec5SDimitry Andric                                      MachineRegisterInfo *MRI) const {
6550b57cec5SDimitry Andric   unsigned DefOpc = DefMI.getOpcode();
656*0fca6ea1SDimitry Andric 
657*0fca6ea1SDimitry Andric   if (DefOpc == SystemZ::VGBM) {
658*0fca6ea1SDimitry Andric     int64_t ImmVal = DefMI.getOperand(1).getImm();
659*0fca6ea1SDimitry Andric     if (ImmVal != 0) // TODO: Handle other values
660*0fca6ea1SDimitry Andric       return false;
661*0fca6ea1SDimitry Andric 
662*0fca6ea1SDimitry Andric     // Fold gr128 = COPY (vr128 VGBM imm)
663*0fca6ea1SDimitry Andric     //
664*0fca6ea1SDimitry Andric     // %tmp:gr64 = LGHI 0
665*0fca6ea1SDimitry Andric     // to  gr128 = REG_SEQUENCE %tmp, %tmp
666*0fca6ea1SDimitry Andric     assert(DefMI.getOperand(0).getReg() == Reg);
667*0fca6ea1SDimitry Andric 
668*0fca6ea1SDimitry Andric     if (!UseMI.isCopy())
669*0fca6ea1SDimitry Andric       return false;
670*0fca6ea1SDimitry Andric 
671*0fca6ea1SDimitry Andric     Register CopyDstReg = UseMI.getOperand(0).getReg();
672*0fca6ea1SDimitry Andric     if (CopyDstReg.isVirtual() &&
673*0fca6ea1SDimitry Andric         MRI->getRegClass(CopyDstReg) == &SystemZ::GR128BitRegClass &&
674*0fca6ea1SDimitry Andric         MRI->hasOneNonDBGUse(Reg)) {
675*0fca6ea1SDimitry Andric       // TODO: Handle physical registers
676*0fca6ea1SDimitry Andric       // TODO: Handle gr64 uses with subregister indexes
677*0fca6ea1SDimitry Andric       // TODO: Should this multi-use cases?
678*0fca6ea1SDimitry Andric       Register TmpReg = MRI->createVirtualRegister(&SystemZ::GR64BitRegClass);
679*0fca6ea1SDimitry Andric       MachineBasicBlock &MBB = *UseMI.getParent();
680*0fca6ea1SDimitry Andric 
681*0fca6ea1SDimitry Andric       loadImmediate(MBB, UseMI.getIterator(), TmpReg, ImmVal);
682*0fca6ea1SDimitry Andric 
683*0fca6ea1SDimitry Andric       UseMI.setDesc(get(SystemZ::REG_SEQUENCE));
684*0fca6ea1SDimitry Andric       UseMI.getOperand(1).setReg(TmpReg);
685*0fca6ea1SDimitry Andric       MachineInstrBuilder(*MBB.getParent(), &UseMI)
686*0fca6ea1SDimitry Andric           .addImm(SystemZ::subreg_h64)
687*0fca6ea1SDimitry Andric           .addReg(TmpReg)
688*0fca6ea1SDimitry Andric           .addImm(SystemZ::subreg_l64);
689*0fca6ea1SDimitry Andric 
690*0fca6ea1SDimitry Andric       if (MRI->use_nodbg_empty(Reg))
691*0fca6ea1SDimitry Andric         DefMI.eraseFromParent();
692*0fca6ea1SDimitry Andric       return true;
693*0fca6ea1SDimitry Andric     }
694*0fca6ea1SDimitry Andric 
695*0fca6ea1SDimitry Andric     return false;
696*0fca6ea1SDimitry Andric   }
697*0fca6ea1SDimitry Andric 
6980b57cec5SDimitry Andric   if (DefOpc != SystemZ::LHIMux && DefOpc != SystemZ::LHI &&
6990b57cec5SDimitry Andric       DefOpc != SystemZ::LGHI)
7000b57cec5SDimitry Andric     return false;
7010b57cec5SDimitry Andric   if (DefMI.getOperand(0).getReg() != Reg)
7020b57cec5SDimitry Andric     return false;
7030b57cec5SDimitry Andric   int32_t ImmVal = (int32_t)DefMI.getOperand(1).getImm();
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   unsigned UseOpc = UseMI.getOpcode();
7060b57cec5SDimitry Andric   unsigned NewUseOpc;
7070b57cec5SDimitry Andric   unsigned UseIdx;
7080b57cec5SDimitry Andric   int CommuteIdx = -1;
7090b57cec5SDimitry Andric   bool TieOps = false;
7100b57cec5SDimitry Andric   switch (UseOpc) {
7110b57cec5SDimitry Andric   case SystemZ::SELRMux:
7120b57cec5SDimitry Andric     TieOps = true;
713bdd1243dSDimitry Andric     [[fallthrough]];
7140b57cec5SDimitry Andric   case SystemZ::LOCRMux:
7150b57cec5SDimitry Andric     if (!STI.hasLoadStoreOnCond2())
7160b57cec5SDimitry Andric       return false;
7170b57cec5SDimitry Andric     NewUseOpc = SystemZ::LOCHIMux;
7180b57cec5SDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
7190b57cec5SDimitry Andric       UseIdx = 2;
7200b57cec5SDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
7210b57cec5SDimitry Andric       UseIdx = 2, CommuteIdx = 1;
7220b57cec5SDimitry Andric     else
7230b57cec5SDimitry Andric       return false;
7240b57cec5SDimitry Andric     break;
7250b57cec5SDimitry Andric   case SystemZ::SELGR:
7260b57cec5SDimitry Andric     TieOps = true;
727bdd1243dSDimitry Andric     [[fallthrough]];
7280b57cec5SDimitry Andric   case SystemZ::LOCGR:
7290b57cec5SDimitry Andric     if (!STI.hasLoadStoreOnCond2())
7300b57cec5SDimitry Andric       return false;
7310b57cec5SDimitry Andric     NewUseOpc = SystemZ::LOCGHI;
7320b57cec5SDimitry Andric     if (UseMI.getOperand(2).getReg() == Reg)
7330b57cec5SDimitry Andric       UseIdx = 2;
7340b57cec5SDimitry Andric     else if (UseMI.getOperand(1).getReg() == Reg)
7350b57cec5SDimitry Andric       UseIdx = 2, CommuteIdx = 1;
7360b57cec5SDimitry Andric     else
7370b57cec5SDimitry Andric       return false;
7380b57cec5SDimitry Andric     break;
7390b57cec5SDimitry Andric   default:
7400b57cec5SDimitry Andric     return false;
7410b57cec5SDimitry Andric   }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   if (CommuteIdx != -1)
7440b57cec5SDimitry Andric     if (!commuteInstruction(UseMI, false, CommuteIdx, UseIdx))
7450b57cec5SDimitry Andric       return false;
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   bool DeleteDef = MRI->hasOneNonDBGUse(Reg);
7480b57cec5SDimitry Andric   UseMI.setDesc(get(NewUseOpc));
7490b57cec5SDimitry Andric   if (TieOps)
7500b57cec5SDimitry Andric     UseMI.tieOperands(0, 1);
7510b57cec5SDimitry Andric   UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);
7520b57cec5SDimitry Andric   if (DeleteDef)
7530b57cec5SDimitry Andric     DefMI.eraseFromParent();
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   return true;
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric bool SystemZInstrInfo::isPredicable(const MachineInstr &MI) const {
7590b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
7600b57cec5SDimitry Andric   if (Opcode == SystemZ::Return ||
76181ad6265SDimitry Andric       Opcode == SystemZ::Return_XPLINK ||
7620b57cec5SDimitry Andric       Opcode == SystemZ::Trap ||
7630b57cec5SDimitry Andric       Opcode == SystemZ::CallJG ||
7640b57cec5SDimitry Andric       Opcode == SystemZ::CallBR)
7650b57cec5SDimitry Andric     return true;
7660b57cec5SDimitry Andric   return false;
7670b57cec5SDimitry Andric }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric bool SystemZInstrInfo::
7700b57cec5SDimitry Andric isProfitableToIfCvt(MachineBasicBlock &MBB,
7710b57cec5SDimitry Andric                     unsigned NumCycles, unsigned ExtraPredCycles,
7720b57cec5SDimitry Andric                     BranchProbability Probability) const {
7730b57cec5SDimitry Andric   // Avoid using conditional returns at the end of a loop (since then
7740b57cec5SDimitry Andric   // we'd need to emit an unconditional branch to the beginning anyway,
7750b57cec5SDimitry Andric   // making the loop body longer).  This doesn't apply for low-probability
7760b57cec5SDimitry Andric   // loops (eg. compare-and-swap retry), so just decide based on branch
7770b57cec5SDimitry Andric   // probability instead of looping structure.
7780b57cec5SDimitry Andric   // However, since Compare and Trap instructions cost the same as a regular
7790b57cec5SDimitry Andric   // Compare instruction, we should allow the if conversion to convert this
7800b57cec5SDimitry Andric   // into a Conditional Compare regardless of the branch probability.
7810b57cec5SDimitry Andric   if (MBB.getLastNonDebugInstr()->getOpcode() != SystemZ::Trap &&
7820b57cec5SDimitry Andric       MBB.succ_empty() && Probability < BranchProbability(1, 8))
7830b57cec5SDimitry Andric     return false;
7840b57cec5SDimitry Andric   // For now only convert single instructions.
7850b57cec5SDimitry Andric   return NumCycles == 1;
7860b57cec5SDimitry Andric }
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric bool SystemZInstrInfo::
7890b57cec5SDimitry Andric isProfitableToIfCvt(MachineBasicBlock &TMBB,
7900b57cec5SDimitry Andric                     unsigned NumCyclesT, unsigned ExtraPredCyclesT,
7910b57cec5SDimitry Andric                     MachineBasicBlock &FMBB,
7920b57cec5SDimitry Andric                     unsigned NumCyclesF, unsigned ExtraPredCyclesF,
7930b57cec5SDimitry Andric                     BranchProbability Probability) const {
7940b57cec5SDimitry Andric   // For now avoid converting mutually-exclusive cases.
7950b57cec5SDimitry Andric   return false;
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric bool SystemZInstrInfo::
7990b57cec5SDimitry Andric isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
8000b57cec5SDimitry Andric                           BranchProbability Probability) const {
8010b57cec5SDimitry Andric   // For now only duplicate single instructions.
8020b57cec5SDimitry Andric   return NumCycles == 1;
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric bool SystemZInstrInfo::PredicateInstruction(
8060b57cec5SDimitry Andric     MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {
8070b57cec5SDimitry Andric   assert(Pred.size() == 2 && "Invalid condition");
8080b57cec5SDimitry Andric   unsigned CCValid = Pred[0].getImm();
8090b57cec5SDimitry Andric   unsigned CCMask = Pred[1].getImm();
8100b57cec5SDimitry Andric   assert(CCMask > 0 && CCMask < 15 && "Invalid predicate");
8110b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
8120b57cec5SDimitry Andric   if (Opcode == SystemZ::Trap) {
8130b57cec5SDimitry Andric     MI.setDesc(get(SystemZ::CondTrap));
8140b57cec5SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
8150b57cec5SDimitry Andric       .addImm(CCValid).addImm(CCMask)
8160b57cec5SDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
8170b57cec5SDimitry Andric     return true;
8180b57cec5SDimitry Andric   }
81981ad6265SDimitry Andric   if (Opcode == SystemZ::Return || Opcode == SystemZ::Return_XPLINK) {
82081ad6265SDimitry Andric     MI.setDesc(get(Opcode == SystemZ::Return ? SystemZ::CondReturn
82181ad6265SDimitry Andric                                              : SystemZ::CondReturn_XPLINK));
8220b57cec5SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
82381ad6265SDimitry Andric         .addImm(CCValid)
82481ad6265SDimitry Andric         .addImm(CCMask)
8250b57cec5SDimitry Andric         .addReg(SystemZ::CC, RegState::Implicit);
8260b57cec5SDimitry Andric     return true;
8270b57cec5SDimitry Andric   }
8280b57cec5SDimitry Andric   if (Opcode == SystemZ::CallJG) {
8290b57cec5SDimitry Andric     MachineOperand FirstOp = MI.getOperand(0);
8300b57cec5SDimitry Andric     const uint32_t *RegMask = MI.getOperand(1).getRegMask();
83181ad6265SDimitry Andric     MI.removeOperand(1);
83281ad6265SDimitry Andric     MI.removeOperand(0);
8330b57cec5SDimitry Andric     MI.setDesc(get(SystemZ::CallBRCL));
8340b57cec5SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
8350b57cec5SDimitry Andric         .addImm(CCValid)
8360b57cec5SDimitry Andric         .addImm(CCMask)
8370b57cec5SDimitry Andric         .add(FirstOp)
8380b57cec5SDimitry Andric         .addRegMask(RegMask)
8390b57cec5SDimitry Andric         .addReg(SystemZ::CC, RegState::Implicit);
8400b57cec5SDimitry Andric     return true;
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric   if (Opcode == SystemZ::CallBR) {
843e8d8bef9SDimitry Andric     MachineOperand Target = MI.getOperand(0);
844e8d8bef9SDimitry Andric     const uint32_t *RegMask = MI.getOperand(1).getRegMask();
84581ad6265SDimitry Andric     MI.removeOperand(1);
84681ad6265SDimitry Andric     MI.removeOperand(0);
8470b57cec5SDimitry Andric     MI.setDesc(get(SystemZ::CallBCR));
8480b57cec5SDimitry Andric     MachineInstrBuilder(*MI.getParent()->getParent(), MI)
8490b57cec5SDimitry Andric       .addImm(CCValid).addImm(CCMask)
850e8d8bef9SDimitry Andric       .add(Target)
8510b57cec5SDimitry Andric       .addRegMask(RegMask)
8520b57cec5SDimitry Andric       .addReg(SystemZ::CC, RegState::Implicit);
8530b57cec5SDimitry Andric     return true;
8540b57cec5SDimitry Andric   }
8550b57cec5SDimitry Andric   return false;
8560b57cec5SDimitry Andric }
8570b57cec5SDimitry Andric 
8580b57cec5SDimitry Andric void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
8590b57cec5SDimitry Andric                                    MachineBasicBlock::iterator MBBI,
860480093f4SDimitry Andric                                    const DebugLoc &DL, MCRegister DestReg,
861480093f4SDimitry Andric                                    MCRegister SrcReg, bool KillSrc) const {
8620b57cec5SDimitry Andric   // Split 128-bit GPR moves into two 64-bit moves. Add implicit uses of the
8630b57cec5SDimitry Andric   // super register in case one of the subregs is undefined.
8640b57cec5SDimitry Andric   // This handles ADDR128 too.
8650b57cec5SDimitry Andric   if (SystemZ::GR128BitRegClass.contains(DestReg, SrcReg)) {
8660b57cec5SDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_h64),
8670b57cec5SDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_h64), KillSrc);
8680b57cec5SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
8690b57cec5SDimitry Andric       .addReg(SrcReg, RegState::Implicit);
8700b57cec5SDimitry Andric     copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_l64),
8710b57cec5SDimitry Andric                 RI.getSubReg(SrcReg, SystemZ::subreg_l64), KillSrc);
8720b57cec5SDimitry Andric     MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))
8730b57cec5SDimitry Andric       .addReg(SrcReg, (getKillRegState(KillSrc) | RegState::Implicit));
8740b57cec5SDimitry Andric     return;
8750b57cec5SDimitry Andric   }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) {
8780b57cec5SDimitry Andric     emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc,
8790b57cec5SDimitry Andric                   false);
8800b57cec5SDimitry Andric     return;
8810b57cec5SDimitry Andric   }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   // Move 128-bit floating-point values between VR128 and FP128.
8840b57cec5SDimitry Andric   if (SystemZ::VR128BitRegClass.contains(DestReg) &&
8850b57cec5SDimitry Andric       SystemZ::FP128BitRegClass.contains(SrcReg)) {
886480093f4SDimitry Andric     MCRegister SrcRegHi =
8870b57cec5SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64),
8880b57cec5SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
889480093f4SDimitry Andric     MCRegister SrcRegLo =
8900b57cec5SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64),
8910b57cec5SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VMRHG), DestReg)
8940b57cec5SDimitry Andric       .addReg(SrcRegHi, getKillRegState(KillSrc))
8950b57cec5SDimitry Andric       .addReg(SrcRegLo, getKillRegState(KillSrc));
8960b57cec5SDimitry Andric     return;
8970b57cec5SDimitry Andric   }
8980b57cec5SDimitry Andric   if (SystemZ::FP128BitRegClass.contains(DestReg) &&
8990b57cec5SDimitry Andric       SystemZ::VR128BitRegClass.contains(SrcReg)) {
900480093f4SDimitry Andric     MCRegister DestRegHi =
9010b57cec5SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_h64),
9020b57cec5SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
903480093f4SDimitry Andric     MCRegister DestRegLo =
9040b57cec5SDimitry Andric         RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_l64),
9050b57cec5SDimitry Andric                                SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);
9060b57cec5SDimitry Andric 
9070b57cec5SDimitry Andric     if (DestRegHi != SrcReg)
9080b57cec5SDimitry Andric       copyPhysReg(MBB, MBBI, DL, DestRegHi, SrcReg, false);
9090b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VREPG), DestRegLo)
9100b57cec5SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1);
9110b57cec5SDimitry Andric     return;
9120b57cec5SDimitry Andric   }
9130b57cec5SDimitry Andric 
914*0fca6ea1SDimitry Andric   if (SystemZ::FP128BitRegClass.contains(DestReg) &&
915*0fca6ea1SDimitry Andric       SystemZ::GR128BitRegClass.contains(SrcReg)) {
916*0fca6ea1SDimitry Andric     MCRegister DestRegHi = RI.getSubReg(DestReg, SystemZ::subreg_h64);
917*0fca6ea1SDimitry Andric     MCRegister DestRegLo = RI.getSubReg(DestReg, SystemZ::subreg_l64);
918*0fca6ea1SDimitry Andric     MCRegister SrcRegHi = RI.getSubReg(SrcReg, SystemZ::subreg_h64);
919*0fca6ea1SDimitry Andric     MCRegister SrcRegLo = RI.getSubReg(SrcReg, SystemZ::subreg_l64);
920*0fca6ea1SDimitry Andric 
921*0fca6ea1SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegHi)
922*0fca6ea1SDimitry Andric         .addReg(SrcRegHi)
923*0fca6ea1SDimitry Andric         .addReg(DestReg, RegState::ImplicitDefine);
924*0fca6ea1SDimitry Andric 
925*0fca6ea1SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegLo)
926*0fca6ea1SDimitry Andric         .addReg(SrcRegLo, getKillRegState(KillSrc));
927*0fca6ea1SDimitry Andric     return;
928*0fca6ea1SDimitry Andric   }
929*0fca6ea1SDimitry Andric 
9305ffd83dbSDimitry Andric   // Move CC value from a GR32.
9310b57cec5SDimitry Andric   if (DestReg == SystemZ::CC) {
9325ffd83dbSDimitry Andric     unsigned Opcode =
9335ffd83dbSDimitry Andric       SystemZ::GR32BitRegClass.contains(SrcReg) ? SystemZ::TMLH : SystemZ::TMHH;
9345ffd83dbSDimitry Andric     BuildMI(MBB, MBBI, DL, get(Opcode))
9350b57cec5SDimitry Andric       .addReg(SrcReg, getKillRegState(KillSrc))
9360b57cec5SDimitry Andric       .addImm(3 << (SystemZ::IPM_CC - 16));
9370b57cec5SDimitry Andric     return;
9380b57cec5SDimitry Andric   }
9390b57cec5SDimitry Andric 
940*0fca6ea1SDimitry Andric   if (SystemZ::GR128BitRegClass.contains(DestReg) &&
941*0fca6ea1SDimitry Andric       SystemZ::VR128BitRegClass.contains(SrcReg)) {
942*0fca6ea1SDimitry Andric     MCRegister DestH64 = RI.getSubReg(DestReg, SystemZ::subreg_h64);
943*0fca6ea1SDimitry Andric     MCRegister DestL64 = RI.getSubReg(DestReg, SystemZ::subreg_l64);
944*0fca6ea1SDimitry Andric 
945*0fca6ea1SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestH64)
946*0fca6ea1SDimitry Andric         .addReg(SrcReg)
947*0fca6ea1SDimitry Andric         .addReg(SystemZ::NoRegister)
948*0fca6ea1SDimitry Andric         .addImm(0)
949*0fca6ea1SDimitry Andric         .addDef(DestReg, RegState::Implicit);
950*0fca6ea1SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestL64)
951*0fca6ea1SDimitry Andric         .addReg(SrcReg, getKillRegState(KillSrc))
952*0fca6ea1SDimitry Andric         .addReg(SystemZ::NoRegister)
953*0fca6ea1SDimitry Andric         .addImm(1);
954*0fca6ea1SDimitry Andric     return;
955*0fca6ea1SDimitry Andric   }
956*0fca6ea1SDimitry Andric 
957*0fca6ea1SDimitry Andric   if (SystemZ::VR128BitRegClass.contains(DestReg) &&
958*0fca6ea1SDimitry Andric       SystemZ::GR128BitRegClass.contains(SrcReg)) {
959*0fca6ea1SDimitry Andric     BuildMI(MBB, MBBI, DL, get(SystemZ::VLVGP), DestReg)
960*0fca6ea1SDimitry Andric         .addReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64))
961*0fca6ea1SDimitry Andric         .addReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64));
962*0fca6ea1SDimitry Andric     return;
963*0fca6ea1SDimitry Andric   }
964*0fca6ea1SDimitry Andric 
9650b57cec5SDimitry Andric   // Everything else needs only one instruction.
9660b57cec5SDimitry Andric   unsigned Opcode;
9670b57cec5SDimitry Andric   if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg))
9680b57cec5SDimitry Andric     Opcode = SystemZ::LGR;
9690b57cec5SDimitry Andric   else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg))
9700b57cec5SDimitry Andric     // For z13 we prefer LDR over LER to avoid partial register dependencies.
9710b57cec5SDimitry Andric     Opcode = STI.hasVector() ? SystemZ::LDR32 : SystemZ::LER;
9720b57cec5SDimitry Andric   else if (SystemZ::FP64BitRegClass.contains(DestReg, SrcReg))
9730b57cec5SDimitry Andric     Opcode = SystemZ::LDR;
9740b57cec5SDimitry Andric   else if (SystemZ::FP128BitRegClass.contains(DestReg, SrcReg))
9750b57cec5SDimitry Andric     Opcode = SystemZ::LXR;
9760b57cec5SDimitry Andric   else if (SystemZ::VR32BitRegClass.contains(DestReg, SrcReg))
9770b57cec5SDimitry Andric     Opcode = SystemZ::VLR32;
9780b57cec5SDimitry Andric   else if (SystemZ::VR64BitRegClass.contains(DestReg, SrcReg))
9790b57cec5SDimitry Andric     Opcode = SystemZ::VLR64;
9800b57cec5SDimitry Andric   else if (SystemZ::VR128BitRegClass.contains(DestReg, SrcReg))
9810b57cec5SDimitry Andric     Opcode = SystemZ::VLR;
9820b57cec5SDimitry Andric   else if (SystemZ::AR32BitRegClass.contains(DestReg, SrcReg))
9830b57cec5SDimitry Andric     Opcode = SystemZ::CPYA;
9840b57cec5SDimitry Andric   else
9850b57cec5SDimitry Andric     llvm_unreachable("Impossible reg-to-reg copy");
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)
9880b57cec5SDimitry Andric     .addReg(SrcReg, getKillRegState(KillSrc));
9890b57cec5SDimitry Andric }
9900b57cec5SDimitry Andric 
9910b57cec5SDimitry Andric void SystemZInstrInfo::storeRegToStackSlot(
9925ffd83dbSDimitry Andric     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
9930b57cec5SDimitry Andric     bool isKill, int FrameIdx, const TargetRegisterClass *RC,
994bdd1243dSDimitry Andric     const TargetRegisterInfo *TRI, Register VReg) const {
9950b57cec5SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
9980b57cec5SDimitry Andric   // together for now and lower them after register allocation.
9990b57cec5SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
10000b57cec5SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
10010b57cec5SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))
10020b57cec5SDimitry Andric                         .addReg(SrcReg, getKillRegState(isKill)),
10030b57cec5SDimitry Andric                     FrameIdx);
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
1006bdd1243dSDimitry Andric void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
1007bdd1243dSDimitry Andric                                             MachineBasicBlock::iterator MBBI,
1008bdd1243dSDimitry Andric                                             Register DestReg, int FrameIdx,
1009bdd1243dSDimitry Andric                                             const TargetRegisterClass *RC,
1010bdd1243dSDimitry Andric                                             const TargetRegisterInfo *TRI,
1011bdd1243dSDimitry Andric                                             Register VReg) const {
10120b57cec5SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   // Callers may expect a single instruction, so keep 128-bit moves
10150b57cec5SDimitry Andric   // together for now and lower them after register allocation.
10160b57cec5SDimitry Andric   unsigned LoadOpcode, StoreOpcode;
10170b57cec5SDimitry Andric   getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);
10180b57cec5SDimitry Andric   addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg),
10190b57cec5SDimitry Andric                     FrameIdx);
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric // Return true if MI is a simple load or store with a 12-bit displacement
10230b57cec5SDimitry Andric // and no index.  Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.
10240b57cec5SDimitry Andric static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) {
10250b57cec5SDimitry Andric   const MCInstrDesc &MCID = MI->getDesc();
10260b57cec5SDimitry Andric   return ((MCID.TSFlags & Flag) &&
10270b57cec5SDimitry Andric           isUInt<12>(MI->getOperand(2).getImm()) &&
10280b57cec5SDimitry Andric           MI->getOperand(3).getReg() == 0);
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric namespace {
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric struct LogicOp {
10340b57cec5SDimitry Andric   LogicOp() = default;
10350b57cec5SDimitry Andric   LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize)
10360b57cec5SDimitry Andric     : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {}
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   explicit operator bool() const { return RegSize; }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   unsigned RegSize = 0;
10410b57cec5SDimitry Andric   unsigned ImmLSB = 0;
10420b57cec5SDimitry Andric   unsigned ImmSize = 0;
10430b57cec5SDimitry Andric };
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric } // end anonymous namespace
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric static LogicOp interpretAndImmediate(unsigned Opcode) {
10480b57cec5SDimitry Andric   switch (Opcode) {
10490b57cec5SDimitry Andric   case SystemZ::NILMux: return LogicOp(32,  0, 16);
10500b57cec5SDimitry Andric   case SystemZ::NIHMux: return LogicOp(32, 16, 16);
10510b57cec5SDimitry Andric   case SystemZ::NILL64: return LogicOp(64,  0, 16);
10520b57cec5SDimitry Andric   case SystemZ::NILH64: return LogicOp(64, 16, 16);
10530b57cec5SDimitry Andric   case SystemZ::NIHL64: return LogicOp(64, 32, 16);
10540b57cec5SDimitry Andric   case SystemZ::NIHH64: return LogicOp(64, 48, 16);
10550b57cec5SDimitry Andric   case SystemZ::NIFMux: return LogicOp(32,  0, 32);
10560b57cec5SDimitry Andric   case SystemZ::NILF64: return LogicOp(64,  0, 32);
10570b57cec5SDimitry Andric   case SystemZ::NIHF64: return LogicOp(64, 32, 32);
10580b57cec5SDimitry Andric   default:              return LogicOp();
10590b57cec5SDimitry Andric   }
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric static void transferDeadCC(MachineInstr *OldMI, MachineInstr *NewMI) {
1063*0fca6ea1SDimitry Andric   if (OldMI->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr)) {
1064*0fca6ea1SDimitry Andric     MachineOperand *CCDef =
1065*0fca6ea1SDimitry Andric         NewMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr);
10660b57cec5SDimitry Andric     if (CCDef != nullptr)
10670b57cec5SDimitry Andric       CCDef->setIsDead(true);
10680b57cec5SDimitry Andric   }
10690b57cec5SDimitry Andric }
10700b57cec5SDimitry Andric 
1071480093f4SDimitry Andric static void transferMIFlag(MachineInstr *OldMI, MachineInstr *NewMI,
1072480093f4SDimitry Andric                            MachineInstr::MIFlag Flag) {
1073480093f4SDimitry Andric   if (OldMI->getFlag(Flag))
1074480093f4SDimitry Andric     NewMI->setFlag(Flag);
1075480093f4SDimitry Andric }
1076480093f4SDimitry Andric 
1077349cc55cSDimitry Andric MachineInstr *
1078349cc55cSDimitry Andric SystemZInstrInfo::convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
1079349cc55cSDimitry Andric                                         LiveIntervals *LIS) const {
10800b57cec5SDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   // Try to convert an AND into an RISBG-type instruction.
10830b57cec5SDimitry Andric   // TODO: It might be beneficial to select RISBG and shorten to AND instead.
10840b57cec5SDimitry Andric   if (LogicOp And = interpretAndImmediate(MI.getOpcode())) {
10850b57cec5SDimitry Andric     uint64_t Imm = MI.getOperand(2).getImm() << And.ImmLSB;
10860b57cec5SDimitry Andric     // AND IMMEDIATE leaves the other bits of the register unchanged.
10870b57cec5SDimitry Andric     Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB);
10880b57cec5SDimitry Andric     unsigned Start, End;
10890b57cec5SDimitry Andric     if (isRxSBGMask(Imm, And.RegSize, Start, End)) {
10900b57cec5SDimitry Andric       unsigned NewOpcode;
10910b57cec5SDimitry Andric       if (And.RegSize == 64) {
10920b57cec5SDimitry Andric         NewOpcode = SystemZ::RISBG;
10930b57cec5SDimitry Andric         // Prefer RISBGN if available, since it does not clobber CC.
10940b57cec5SDimitry Andric         if (STI.hasMiscellaneousExtensions())
10950b57cec5SDimitry Andric           NewOpcode = SystemZ::RISBGN;
10960b57cec5SDimitry Andric       } else {
10970b57cec5SDimitry Andric         NewOpcode = SystemZ::RISBMux;
10980b57cec5SDimitry Andric         Start &= 31;
10990b57cec5SDimitry Andric         End &= 31;
11000b57cec5SDimitry Andric       }
11010b57cec5SDimitry Andric       MachineOperand &Dest = MI.getOperand(0);
11020b57cec5SDimitry Andric       MachineOperand &Src = MI.getOperand(1);
11030b57cec5SDimitry Andric       MachineInstrBuilder MIB =
11040b57cec5SDimitry Andric           BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpcode))
11050b57cec5SDimitry Andric               .add(Dest)
11060b57cec5SDimitry Andric               .addReg(0)
11070b57cec5SDimitry Andric               .addReg(Src.getReg(), getKillRegState(Src.isKill()),
11080b57cec5SDimitry Andric                       Src.getSubReg())
11090b57cec5SDimitry Andric               .addImm(Start)
11100b57cec5SDimitry Andric               .addImm(End + 128)
11110b57cec5SDimitry Andric               .addImm(0);
11120b57cec5SDimitry Andric       if (LV) {
11130b57cec5SDimitry Andric         unsigned NumOps = MI.getNumOperands();
11140b57cec5SDimitry Andric         for (unsigned I = 1; I < NumOps; ++I) {
11150b57cec5SDimitry Andric           MachineOperand &Op = MI.getOperand(I);
11160b57cec5SDimitry Andric           if (Op.isReg() && Op.isKill())
11170b57cec5SDimitry Andric             LV->replaceKillInstruction(Op.getReg(), MI, *MIB);
11180b57cec5SDimitry Andric         }
11190b57cec5SDimitry Andric       }
1120349cc55cSDimitry Andric       if (LIS)
1121349cc55cSDimitry Andric         LIS->ReplaceMachineInstrInMaps(MI, *MIB);
11220b57cec5SDimitry Andric       transferDeadCC(&MI, MIB);
11230b57cec5SDimitry Andric       return MIB;
11240b57cec5SDimitry Andric     }
11250b57cec5SDimitry Andric   }
11260b57cec5SDimitry Andric   return nullptr;
11270b57cec5SDimitry Andric }
11280b57cec5SDimitry Andric 
1129*0fca6ea1SDimitry Andric bool SystemZInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
1130*0fca6ea1SDimitry Andric                                                    bool Invert) const {
1131*0fca6ea1SDimitry Andric   unsigned Opc = Inst.getOpcode();
1132*0fca6ea1SDimitry Andric   if (Invert) {
1133*0fca6ea1SDimitry Andric     auto InverseOpcode = getInverseOpcode(Opc);
1134*0fca6ea1SDimitry Andric     if (!InverseOpcode)
1135*0fca6ea1SDimitry Andric       return false;
1136*0fca6ea1SDimitry Andric     Opc = *InverseOpcode;
1137*0fca6ea1SDimitry Andric   }
1138*0fca6ea1SDimitry Andric 
1139*0fca6ea1SDimitry Andric   switch (Opc) {
1140*0fca6ea1SDimitry Andric   default:
1141*0fca6ea1SDimitry Andric     break;
1142*0fca6ea1SDimitry Andric   // Adds and multiplications.
1143*0fca6ea1SDimitry Andric   case SystemZ::WFADB:
1144*0fca6ea1SDimitry Andric   case SystemZ::WFASB:
1145*0fca6ea1SDimitry Andric   case SystemZ::WFAXB:
1146*0fca6ea1SDimitry Andric   case SystemZ::VFADB:
1147*0fca6ea1SDimitry Andric   case SystemZ::VFASB:
1148*0fca6ea1SDimitry Andric   case SystemZ::WFMDB:
1149*0fca6ea1SDimitry Andric   case SystemZ::WFMSB:
1150*0fca6ea1SDimitry Andric   case SystemZ::WFMXB:
1151*0fca6ea1SDimitry Andric   case SystemZ::VFMDB:
1152*0fca6ea1SDimitry Andric   case SystemZ::VFMSB:
1153*0fca6ea1SDimitry Andric     return (Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&
1154*0fca6ea1SDimitry Andric             Inst.getFlag(MachineInstr::MIFlag::FmNsz));
1155*0fca6ea1SDimitry Andric   }
1156*0fca6ea1SDimitry Andric 
1157*0fca6ea1SDimitry Andric   return false;
1158*0fca6ea1SDimitry Andric }
1159*0fca6ea1SDimitry Andric 
1160*0fca6ea1SDimitry Andric std::optional<unsigned>
1161*0fca6ea1SDimitry Andric SystemZInstrInfo::getInverseOpcode(unsigned Opcode) const {
1162*0fca6ea1SDimitry Andric   // fadd => fsub
1163*0fca6ea1SDimitry Andric   switch (Opcode) {
1164*0fca6ea1SDimitry Andric   case SystemZ::WFADB:
1165*0fca6ea1SDimitry Andric     return SystemZ::WFSDB;
1166*0fca6ea1SDimitry Andric   case SystemZ::WFASB:
1167*0fca6ea1SDimitry Andric     return SystemZ::WFSSB;
1168*0fca6ea1SDimitry Andric   case SystemZ::WFAXB:
1169*0fca6ea1SDimitry Andric     return SystemZ::WFSXB;
1170*0fca6ea1SDimitry Andric   case SystemZ::VFADB:
1171*0fca6ea1SDimitry Andric     return SystemZ::VFSDB;
1172*0fca6ea1SDimitry Andric   case SystemZ::VFASB:
1173*0fca6ea1SDimitry Andric     return SystemZ::VFSSB;
1174*0fca6ea1SDimitry Andric   // fsub => fadd
1175*0fca6ea1SDimitry Andric   case SystemZ::WFSDB:
1176*0fca6ea1SDimitry Andric     return SystemZ::WFADB;
1177*0fca6ea1SDimitry Andric   case SystemZ::WFSSB:
1178*0fca6ea1SDimitry Andric     return SystemZ::WFASB;
1179*0fca6ea1SDimitry Andric   case SystemZ::WFSXB:
1180*0fca6ea1SDimitry Andric     return SystemZ::WFAXB;
1181*0fca6ea1SDimitry Andric   case SystemZ::VFSDB:
1182*0fca6ea1SDimitry Andric     return SystemZ::VFADB;
1183*0fca6ea1SDimitry Andric   case SystemZ::VFSSB:
1184*0fca6ea1SDimitry Andric     return SystemZ::VFASB;
1185*0fca6ea1SDimitry Andric   default:
1186*0fca6ea1SDimitry Andric     return std::nullopt;
1187*0fca6ea1SDimitry Andric   }
1188*0fca6ea1SDimitry Andric }
1189*0fca6ea1SDimitry Andric 
11900b57cec5SDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
11910b57cec5SDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
11920b57cec5SDimitry Andric     MachineBasicBlock::iterator InsertPt, int FrameIndex,
11930b57cec5SDimitry Andric     LiveIntervals *LIS, VirtRegMap *VRM) const {
11940b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
11955ffd83dbSDimitry Andric   MachineRegisterInfo &MRI = MF.getRegInfo();
11960b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
11970b57cec5SDimitry Andric   unsigned Size = MFI.getObjectSize(FrameIndex);
11980b57cec5SDimitry Andric   unsigned Opcode = MI.getOpcode();
11990b57cec5SDimitry Andric 
12005ffd83dbSDimitry Andric   // Check CC liveness if new instruction introduces a dead def of CC.
12015ffd83dbSDimitry Andric   SlotIndex MISlot = SlotIndex();
12025ffd83dbSDimitry Andric   LiveRange *CCLiveRange = nullptr;
12035ffd83dbSDimitry Andric   bool CCLiveAtMI = true;
12045ffd83dbSDimitry Andric   if (LIS) {
12055ffd83dbSDimitry Andric     MISlot = LIS->getSlotIndexes()->getInstructionIndex(MI).getRegSlot();
120606c3fb27SDimitry Andric     auto CCUnits = TRI->regunits(MCRegister::from(SystemZ::CC));
120706c3fb27SDimitry Andric     assert(range_size(CCUnits) == 1 && "CC only has one reg unit.");
120806c3fb27SDimitry Andric     CCLiveRange = &LIS->getRegUnit(*CCUnits.begin());
12095ffd83dbSDimitry Andric     CCLiveAtMI = CCLiveRange->liveAt(MISlot);
12105ffd83dbSDimitry Andric   }
12115ffd83dbSDimitry Andric 
12125ffd83dbSDimitry Andric   if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {
12135ffd83dbSDimitry Andric     if (!CCLiveAtMI && (Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&
12145ffd83dbSDimitry Andric         isInt<8>(MI.getOperand(2).getImm()) && !MI.getOperand(3).getReg()) {
12150b57cec5SDimitry Andric       // LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST
12160b57cec5SDimitry Andric       MachineInstr *BuiltMI = BuildMI(*InsertPt->getParent(), InsertPt,
12170b57cec5SDimitry Andric                                       MI.getDebugLoc(), get(SystemZ::AGSI))
12180b57cec5SDimitry Andric         .addFrameIndex(FrameIndex)
12190b57cec5SDimitry Andric         .addImm(0)
12200b57cec5SDimitry Andric         .addImm(MI.getOperand(2).getImm());
1221*0fca6ea1SDimitry Andric       BuiltMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr)
1222*0fca6ea1SDimitry Andric           ->setIsDead(true);
12235ffd83dbSDimitry Andric       CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());
12240b57cec5SDimitry Andric       return BuiltMI;
12250b57cec5SDimitry Andric     }
12260b57cec5SDimitry Andric     return nullptr;
12270b57cec5SDimitry Andric   }
12280b57cec5SDimitry Andric 
12290b57cec5SDimitry Andric   // All other cases require a single operand.
12300b57cec5SDimitry Andric   if (Ops.size() != 1)
12310b57cec5SDimitry Andric     return nullptr;
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   unsigned OpNum = Ops[0];
12340b57cec5SDimitry Andric   assert(Size * 8 ==
12350b57cec5SDimitry Andric            TRI->getRegSizeInBits(*MF.getRegInfo()
12360b57cec5SDimitry Andric                                .getRegClass(MI.getOperand(OpNum).getReg())) &&
12370b57cec5SDimitry Andric          "Invalid size combination");
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   if ((Opcode == SystemZ::AHI || Opcode == SystemZ::AGHI) && OpNum == 0 &&
12400b57cec5SDimitry Andric       isInt<8>(MI.getOperand(2).getImm())) {
12410b57cec5SDimitry Andric     // A(G)HI %reg, CONST -> A(G)SI %mem, CONST
12420b57cec5SDimitry Andric     Opcode = (Opcode == SystemZ::AHI ? SystemZ::ASI : SystemZ::AGSI);
12430b57cec5SDimitry Andric     MachineInstr *BuiltMI =
12440b57cec5SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
12450b57cec5SDimitry Andric             .addFrameIndex(FrameIndex)
12460b57cec5SDimitry Andric             .addImm(0)
12470b57cec5SDimitry Andric             .addImm(MI.getOperand(2).getImm());
12480b57cec5SDimitry Andric     transferDeadCC(&MI, BuiltMI);
1249480093f4SDimitry Andric     transferMIFlag(&MI, BuiltMI, MachineInstr::NoSWrap);
12500b57cec5SDimitry Andric     return BuiltMI;
12510b57cec5SDimitry Andric   }
12520b57cec5SDimitry Andric 
12530b57cec5SDimitry Andric   if ((Opcode == SystemZ::ALFI && OpNum == 0 &&
12540b57cec5SDimitry Andric        isInt<8>((int32_t)MI.getOperand(2).getImm())) ||
12550b57cec5SDimitry Andric       (Opcode == SystemZ::ALGFI && OpNum == 0 &&
12560b57cec5SDimitry Andric        isInt<8>((int64_t)MI.getOperand(2).getImm()))) {
12570b57cec5SDimitry Andric     // AL(G)FI %reg, CONST -> AL(G)SI %mem, CONST
12580b57cec5SDimitry Andric     Opcode = (Opcode == SystemZ::ALFI ? SystemZ::ALSI : SystemZ::ALGSI);
12590b57cec5SDimitry Andric     MachineInstr *BuiltMI =
12600b57cec5SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
12610b57cec5SDimitry Andric             .addFrameIndex(FrameIndex)
12620b57cec5SDimitry Andric             .addImm(0)
12630b57cec5SDimitry Andric             .addImm((int8_t)MI.getOperand(2).getImm());
12640b57cec5SDimitry Andric     transferDeadCC(&MI, BuiltMI);
12650b57cec5SDimitry Andric     return BuiltMI;
12660b57cec5SDimitry Andric   }
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric   if ((Opcode == SystemZ::SLFI && OpNum == 0 &&
12690b57cec5SDimitry Andric        isInt<8>((int32_t)-MI.getOperand(2).getImm())) ||
12700b57cec5SDimitry Andric       (Opcode == SystemZ::SLGFI && OpNum == 0 &&
12710b57cec5SDimitry Andric        isInt<8>((int64_t)-MI.getOperand(2).getImm()))) {
12720b57cec5SDimitry Andric     // SL(G)FI %reg, CONST -> AL(G)SI %mem, -CONST
12730b57cec5SDimitry Andric     Opcode = (Opcode == SystemZ::SLFI ? SystemZ::ALSI : SystemZ::ALGSI);
12740b57cec5SDimitry Andric     MachineInstr *BuiltMI =
12750b57cec5SDimitry Andric         BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))
12760b57cec5SDimitry Andric             .addFrameIndex(FrameIndex)
12770b57cec5SDimitry Andric             .addImm(0)
12780b57cec5SDimitry Andric             .addImm((int8_t)-MI.getOperand(2).getImm());
12790b57cec5SDimitry Andric     transferDeadCC(&MI, BuiltMI);
12800b57cec5SDimitry Andric     return BuiltMI;
12810b57cec5SDimitry Andric   }
12820b57cec5SDimitry Andric 
12835ffd83dbSDimitry Andric   unsigned MemImmOpc = 0;
12845ffd83dbSDimitry Andric   switch (Opcode) {
12855ffd83dbSDimitry Andric   case SystemZ::LHIMux:
12865ffd83dbSDimitry Andric   case SystemZ::LHI:    MemImmOpc = SystemZ::MVHI;  break;
12875ffd83dbSDimitry Andric   case SystemZ::LGHI:   MemImmOpc = SystemZ::MVGHI; break;
12885ffd83dbSDimitry Andric   case SystemZ::CHIMux:
12895ffd83dbSDimitry Andric   case SystemZ::CHI:    MemImmOpc = SystemZ::CHSI;  break;
12905ffd83dbSDimitry Andric   case SystemZ::CGHI:   MemImmOpc = SystemZ::CGHSI; break;
12915ffd83dbSDimitry Andric   case SystemZ::CLFIMux:
12925ffd83dbSDimitry Andric   case SystemZ::CLFI:
12935ffd83dbSDimitry Andric     if (isUInt<16>(MI.getOperand(1).getImm()))
12945ffd83dbSDimitry Andric       MemImmOpc = SystemZ::CLFHSI;
12955ffd83dbSDimitry Andric     break;
12965ffd83dbSDimitry Andric   case SystemZ::CLGFI:
12975ffd83dbSDimitry Andric     if (isUInt<16>(MI.getOperand(1).getImm()))
12985ffd83dbSDimitry Andric       MemImmOpc = SystemZ::CLGHSI;
12995ffd83dbSDimitry Andric     break;
13005ffd83dbSDimitry Andric   default: break;
13015ffd83dbSDimitry Andric   }
13025ffd83dbSDimitry Andric   if (MemImmOpc)
13035ffd83dbSDimitry Andric     return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
13045ffd83dbSDimitry Andric                    get(MemImmOpc))
13055ffd83dbSDimitry Andric                .addFrameIndex(FrameIndex)
13065ffd83dbSDimitry Andric                .addImm(0)
13075ffd83dbSDimitry Andric                .addImm(MI.getOperand(1).getImm());
13085ffd83dbSDimitry Andric 
13090b57cec5SDimitry Andric   if (Opcode == SystemZ::LGDR || Opcode == SystemZ::LDGR) {
13100b57cec5SDimitry Andric     bool Op0IsGPR = (Opcode == SystemZ::LGDR);
13110b57cec5SDimitry Andric     bool Op1IsGPR = (Opcode == SystemZ::LDGR);
13120b57cec5SDimitry Andric     // If we're spilling the destination of an LDGR or LGDR, store the
13130b57cec5SDimitry Andric     // source register instead.
13140b57cec5SDimitry Andric     if (OpNum == 0) {
13150b57cec5SDimitry Andric       unsigned StoreOpcode = Op1IsGPR ? SystemZ::STG : SystemZ::STD;
13160b57cec5SDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
13170b57cec5SDimitry Andric                      get(StoreOpcode))
13180b57cec5SDimitry Andric           .add(MI.getOperand(1))
13190b57cec5SDimitry Andric           .addFrameIndex(FrameIndex)
13200b57cec5SDimitry Andric           .addImm(0)
13210b57cec5SDimitry Andric           .addReg(0);
13220b57cec5SDimitry Andric     }
13230b57cec5SDimitry Andric     // If we're spilling the source of an LDGR or LGDR, load the
13240b57cec5SDimitry Andric     // destination register instead.
13250b57cec5SDimitry Andric     if (OpNum == 1) {
13260b57cec5SDimitry Andric       unsigned LoadOpcode = Op0IsGPR ? SystemZ::LG : SystemZ::LD;
13270b57cec5SDimitry Andric       return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
13280b57cec5SDimitry Andric                      get(LoadOpcode))
13290b57cec5SDimitry Andric         .add(MI.getOperand(0))
13300b57cec5SDimitry Andric         .addFrameIndex(FrameIndex)
13310b57cec5SDimitry Andric         .addImm(0)
13320b57cec5SDimitry Andric         .addReg(0);
13330b57cec5SDimitry Andric     }
13340b57cec5SDimitry Andric   }
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric   // Look for cases where the source of a simple store or the destination
13370b57cec5SDimitry Andric   // of a simple load is being spilled.  Try to use MVC instead.
13380b57cec5SDimitry Andric   //
13390b57cec5SDimitry Andric   // Although MVC is in practice a fast choice in these cases, it is still
13400b57cec5SDimitry Andric   // logically a bytewise copy.  This means that we cannot use it if the
13410b57cec5SDimitry Andric   // load or store is volatile.  We also wouldn't be able to use MVC if
13420b57cec5SDimitry Andric   // the two memories partially overlap, but that case cannot occur here,
13430b57cec5SDimitry Andric   // because we know that one of the memories is a full frame index.
13440b57cec5SDimitry Andric   //
13450b57cec5SDimitry Andric   // For performance reasons, we also want to avoid using MVC if the addresses
13460b57cec5SDimitry Andric   // might be equal.  We don't worry about that case here, because spill slot
13470b57cec5SDimitry Andric   // coloring happens later, and because we have special code to remove
13480b57cec5SDimitry Andric   // MVCs that turn out to be redundant.
13490b57cec5SDimitry Andric   if (OpNum == 0 && MI.hasOneMemOperand()) {
13500b57cec5SDimitry Andric     MachineMemOperand *MMO = *MI.memoperands_begin();
13510b57cec5SDimitry Andric     if (MMO->getSize() == Size && !MMO->isVolatile() && !MMO->isAtomic()) {
13520b57cec5SDimitry Andric       // Handle conversion of loads.
13530b57cec5SDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXLoad)) {
13540b57cec5SDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
13550b57cec5SDimitry Andric                        get(SystemZ::MVC))
13560b57cec5SDimitry Andric             .addFrameIndex(FrameIndex)
13570b57cec5SDimitry Andric             .addImm(0)
13580b57cec5SDimitry Andric             .addImm(Size)
13590b57cec5SDimitry Andric             .add(MI.getOperand(1))
13600b57cec5SDimitry Andric             .addImm(MI.getOperand(2).getImm())
13610b57cec5SDimitry Andric             .addMemOperand(MMO);
13620b57cec5SDimitry Andric       }
13630b57cec5SDimitry Andric       // Handle conversion of stores.
13640b57cec5SDimitry Andric       if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXStore)) {
13650b57cec5SDimitry Andric         return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),
13660b57cec5SDimitry Andric                        get(SystemZ::MVC))
13670b57cec5SDimitry Andric             .add(MI.getOperand(1))
13680b57cec5SDimitry Andric             .addImm(MI.getOperand(2).getImm())
13690b57cec5SDimitry Andric             .addImm(Size)
13700b57cec5SDimitry Andric             .addFrameIndex(FrameIndex)
13710b57cec5SDimitry Andric             .addImm(0)
13720b57cec5SDimitry Andric             .addMemOperand(MMO);
13730b57cec5SDimitry Andric       }
13740b57cec5SDimitry Andric     }
13750b57cec5SDimitry Andric   }
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric   // If the spilled operand is the final one or the instruction is
13785ffd83dbSDimitry Andric   // commutable, try to change <INSN>R into <INSN>.  Don't introduce a def of
13795ffd83dbSDimitry Andric   // CC if it is live and MI does not define it.
13800b57cec5SDimitry Andric   unsigned NumOps = MI.getNumExplicitOperands();
13810b57cec5SDimitry Andric   int MemOpcode = SystemZ::getMemOpcode(Opcode);
13825ffd83dbSDimitry Andric   if (MemOpcode == -1 ||
1383*0fca6ea1SDimitry Andric       (CCLiveAtMI && !MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&
13845ffd83dbSDimitry Andric        get(MemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)))
13855ffd83dbSDimitry Andric     return nullptr;
13865ffd83dbSDimitry Andric 
13875ffd83dbSDimitry Andric   // Check if all other vregs have a usable allocation in the case of vector
13885ffd83dbSDimitry Andric   // to FP conversion.
13895ffd83dbSDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
13905ffd83dbSDimitry Andric   for (unsigned I = 0, E = MCID.getNumOperands(); I != E; ++I) {
1391bdd1243dSDimitry Andric     const MCOperandInfo &MCOI = MCID.operands()[I];
13925ffd83dbSDimitry Andric     if (MCOI.OperandType != MCOI::OPERAND_REGISTER || I == OpNum)
13935ffd83dbSDimitry Andric       continue;
13945ffd83dbSDimitry Andric     const TargetRegisterClass *RC = TRI->getRegClass(MCOI.RegClass);
13955ffd83dbSDimitry Andric     if (RC == &SystemZ::VR32BitRegClass || RC == &SystemZ::VR64BitRegClass) {
13965ffd83dbSDimitry Andric       Register Reg = MI.getOperand(I).getReg();
1397bdd1243dSDimitry Andric       Register PhysReg = Reg.isVirtual()
1398e8d8bef9SDimitry Andric                              ? (VRM ? Register(VRM->getPhys(Reg)) : Register())
13995ffd83dbSDimitry Andric                              : Reg;
14005ffd83dbSDimitry Andric       if (!PhysReg ||
14015ffd83dbSDimitry Andric           !(SystemZ::FP32BitRegClass.contains(PhysReg) ||
14025ffd83dbSDimitry Andric             SystemZ::FP64BitRegClass.contains(PhysReg) ||
14035ffd83dbSDimitry Andric             SystemZ::VF128BitRegClass.contains(PhysReg)))
14045ffd83dbSDimitry Andric         return nullptr;
14055ffd83dbSDimitry Andric     }
14065ffd83dbSDimitry Andric   }
14075ffd83dbSDimitry Andric   // Fused multiply and add/sub need to have the same dst and accumulator reg.
14085ffd83dbSDimitry Andric   bool FusedFPOp = (Opcode == SystemZ::WFMADB || Opcode == SystemZ::WFMASB ||
14095ffd83dbSDimitry Andric                     Opcode == SystemZ::WFMSDB || Opcode == SystemZ::WFMSSB);
14105ffd83dbSDimitry Andric   if (FusedFPOp) {
14115ffd83dbSDimitry Andric     Register DstReg = VRM->getPhys(MI.getOperand(0).getReg());
14125ffd83dbSDimitry Andric     Register AccReg = VRM->getPhys(MI.getOperand(3).getReg());
14135ffd83dbSDimitry Andric     if (OpNum == 0 || OpNum == 3 || DstReg != AccReg)
14145ffd83dbSDimitry Andric       return nullptr;
14155ffd83dbSDimitry Andric   }
14165ffd83dbSDimitry Andric 
14175ffd83dbSDimitry Andric   // Try to swap compare operands if possible.
14185ffd83dbSDimitry Andric   bool NeedsCommute = false;
14195ffd83dbSDimitry Andric   if ((MI.getOpcode() == SystemZ::CR || MI.getOpcode() == SystemZ::CGR ||
14205ffd83dbSDimitry Andric        MI.getOpcode() == SystemZ::CLR || MI.getOpcode() == SystemZ::CLGR ||
14215ffd83dbSDimitry Andric        MI.getOpcode() == SystemZ::WFCDB || MI.getOpcode() == SystemZ::WFCSB ||
14225ffd83dbSDimitry Andric        MI.getOpcode() == SystemZ::WFKDB || MI.getOpcode() == SystemZ::WFKSB) &&
14235ffd83dbSDimitry Andric       OpNum == 0 && prepareCompareSwapOperands(MI))
14245ffd83dbSDimitry Andric     NeedsCommute = true;
14255ffd83dbSDimitry Andric 
14265ffd83dbSDimitry Andric   bool CCOperands = false;
14275ffd83dbSDimitry Andric   if (MI.getOpcode() == SystemZ::LOCRMux || MI.getOpcode() == SystemZ::LOCGR ||
14285ffd83dbSDimitry Andric       MI.getOpcode() == SystemZ::SELRMux || MI.getOpcode() == SystemZ::SELGR) {
14295ffd83dbSDimitry Andric     assert(MI.getNumOperands() == 6 && NumOps == 5 &&
14305ffd83dbSDimitry Andric            "LOCR/SELR instruction operands corrupt?");
14315ffd83dbSDimitry Andric     NumOps -= 2;
14325ffd83dbSDimitry Andric     CCOperands = true;
14335ffd83dbSDimitry Andric   }
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric   // See if this is a 3-address instruction that is convertible to 2-address
14360b57cec5SDimitry Andric   // and suitable for folding below.  Only try this with virtual registers
14370b57cec5SDimitry Andric   // and a provided VRM (during regalloc).
14385ffd83dbSDimitry Andric   if (NumOps == 3 && SystemZ::getTargetMemOpcode(MemOpcode) != -1) {
14390b57cec5SDimitry Andric     if (VRM == nullptr)
14405ffd83dbSDimitry Andric       return nullptr;
14410b57cec5SDimitry Andric     else {
14420b57cec5SDimitry Andric       Register DstReg = MI.getOperand(0).getReg();
14430b57cec5SDimitry Andric       Register DstPhys =
1444bdd1243dSDimitry Andric           (DstReg.isVirtual() ? Register(VRM->getPhys(DstReg)) : DstReg);
14450b57cec5SDimitry Andric       Register SrcReg = (OpNum == 2 ? MI.getOperand(1).getReg()
14460b57cec5SDimitry Andric                                     : ((OpNum == 1 && MI.isCommutable())
14470b57cec5SDimitry Andric                                            ? MI.getOperand(2).getReg()
14480b57cec5SDimitry Andric                                            : Register()));
14490b57cec5SDimitry Andric       if (DstPhys && !SystemZ::GRH32BitRegClass.contains(DstPhys) && SrcReg &&
1450bdd1243dSDimitry Andric           SrcReg.isVirtual() && DstPhys == VRM->getPhys(SrcReg))
14510b57cec5SDimitry Andric         NeedsCommute = (OpNum == 1);
14520b57cec5SDimitry Andric       else
14535ffd83dbSDimitry Andric         return nullptr;
14540b57cec5SDimitry Andric     }
14550b57cec5SDimitry Andric   }
14560b57cec5SDimitry Andric 
14575ffd83dbSDimitry Andric   if ((OpNum == NumOps - 1) || NeedsCommute || FusedFPOp) {
14580b57cec5SDimitry Andric     const MCInstrDesc &MemDesc = get(MemOpcode);
14590b57cec5SDimitry Andric     uint64_t AccessBytes = SystemZII::getAccessSize(MemDesc.TSFlags);
14600b57cec5SDimitry Andric     assert(AccessBytes != 0 && "Size of access should be known");
14610b57cec5SDimitry Andric     assert(AccessBytes <= Size && "Access outside the frame index");
14620b57cec5SDimitry Andric     uint64_t Offset = Size - AccessBytes;
14630b57cec5SDimitry Andric     MachineInstrBuilder MIB = BuildMI(*InsertPt->getParent(), InsertPt,
14640b57cec5SDimitry Andric                                       MI.getDebugLoc(), get(MemOpcode));
14655ffd83dbSDimitry Andric     if (MI.isCompare()) {
14665ffd83dbSDimitry Andric       assert(NumOps == 2 && "Expected 2 register operands for a compare.");
14675ffd83dbSDimitry Andric       MIB.add(MI.getOperand(NeedsCommute ? 1 : 0));
14685ffd83dbSDimitry Andric     }
14695ffd83dbSDimitry Andric     else if (FusedFPOp) {
14705ffd83dbSDimitry Andric       MIB.add(MI.getOperand(0));
14715ffd83dbSDimitry Andric       MIB.add(MI.getOperand(3));
14725ffd83dbSDimitry Andric       MIB.add(MI.getOperand(OpNum == 1 ? 2 : 1));
14735ffd83dbSDimitry Andric     }
14745ffd83dbSDimitry Andric     else {
14750b57cec5SDimitry Andric       MIB.add(MI.getOperand(0));
14760b57cec5SDimitry Andric       if (NeedsCommute)
14770b57cec5SDimitry Andric         MIB.add(MI.getOperand(2));
14780b57cec5SDimitry Andric       else
14790b57cec5SDimitry Andric         for (unsigned I = 1; I < OpNum; ++I)
14800b57cec5SDimitry Andric           MIB.add(MI.getOperand(I));
14815ffd83dbSDimitry Andric     }
14820b57cec5SDimitry Andric     MIB.addFrameIndex(FrameIndex).addImm(Offset);
14830b57cec5SDimitry Andric     if (MemDesc.TSFlags & SystemZII::HasIndex)
14840b57cec5SDimitry Andric       MIB.addReg(0);
14855ffd83dbSDimitry Andric     if (CCOperands) {
14865ffd83dbSDimitry Andric       unsigned CCValid = MI.getOperand(NumOps).getImm();
14875ffd83dbSDimitry Andric       unsigned CCMask = MI.getOperand(NumOps + 1).getImm();
14885ffd83dbSDimitry Andric       MIB.addImm(CCValid);
14895ffd83dbSDimitry Andric       MIB.addImm(NeedsCommute ? CCMask ^ CCValid : CCMask);
14905ffd83dbSDimitry Andric     }
1491*0fca6ea1SDimitry Andric     if (MIB->definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&
1492*0fca6ea1SDimitry Andric         (!MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) ||
1493*0fca6ea1SDimitry Andric          MI.registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))) {
14945ffd83dbSDimitry Andric       MIB->addRegisterDead(SystemZ::CC, TRI);
14955ffd83dbSDimitry Andric       if (CCLiveRange)
14965ffd83dbSDimitry Andric         CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());
14975ffd83dbSDimitry Andric     }
14985ffd83dbSDimitry Andric     // Constrain the register classes if converted from a vector opcode. The
14995ffd83dbSDimitry Andric     // allocated regs are in an FP reg-class per previous check above.
15005ffd83dbSDimitry Andric     for (const MachineOperand &MO : MIB->operands())
1501bdd1243dSDimitry Andric       if (MO.isReg() && MO.getReg().isVirtual()) {
150204eeddc0SDimitry Andric         Register Reg = MO.getReg();
15035ffd83dbSDimitry Andric         if (MRI.getRegClass(Reg) == &SystemZ::VR32BitRegClass)
15045ffd83dbSDimitry Andric           MRI.setRegClass(Reg, &SystemZ::FP32BitRegClass);
15055ffd83dbSDimitry Andric         else if (MRI.getRegClass(Reg) == &SystemZ::VR64BitRegClass)
15065ffd83dbSDimitry Andric           MRI.setRegClass(Reg, &SystemZ::FP64BitRegClass);
15075ffd83dbSDimitry Andric         else if (MRI.getRegClass(Reg) == &SystemZ::VR128BitRegClass)
15085ffd83dbSDimitry Andric           MRI.setRegClass(Reg, &SystemZ::VF128BitRegClass);
15095ffd83dbSDimitry Andric       }
15105ffd83dbSDimitry Andric 
15110b57cec5SDimitry Andric     transferDeadCC(&MI, MIB);
1512480093f4SDimitry Andric     transferMIFlag(&MI, MIB, MachineInstr::NoSWrap);
15135ffd83dbSDimitry Andric     transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);
15140b57cec5SDimitry Andric     return MIB;
15150b57cec5SDimitry Andric   }
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric   return nullptr;
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(
15210b57cec5SDimitry Andric     MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,
15220b57cec5SDimitry Andric     MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,
15230b57cec5SDimitry Andric     LiveIntervals *LIS) const {
1524*0fca6ea1SDimitry Andric   MachineRegisterInfo *MRI = &MF.getRegInfo();
1525*0fca6ea1SDimitry Andric   MachineBasicBlock *MBB = MI.getParent();
1526*0fca6ea1SDimitry Andric 
1527*0fca6ea1SDimitry Andric   // For reassociable FP operations, any loads have been purposefully left
1528*0fca6ea1SDimitry Andric   // unfolded so that MachineCombiner can do its work on reg/reg
1529*0fca6ea1SDimitry Andric   // opcodes. After that, as many loads as possible are now folded.
1530*0fca6ea1SDimitry Andric   // TODO: This may be beneficial with other opcodes as well as machine-sink
1531*0fca6ea1SDimitry Andric   // can move loads close to their user in a different MBB, which the isel
1532*0fca6ea1SDimitry Andric   // matcher did not see.
1533*0fca6ea1SDimitry Andric   unsigned LoadOpc = 0;
1534*0fca6ea1SDimitry Andric   unsigned RegMemOpcode = 0;
1535*0fca6ea1SDimitry Andric   const TargetRegisterClass *FPRC = nullptr;
1536*0fca6ea1SDimitry Andric   RegMemOpcode = MI.getOpcode() == SystemZ::WFADB   ? SystemZ::ADB
1537*0fca6ea1SDimitry Andric                  : MI.getOpcode() == SystemZ::WFSDB ? SystemZ::SDB
1538*0fca6ea1SDimitry Andric                  : MI.getOpcode() == SystemZ::WFMDB ? SystemZ::MDB
1539*0fca6ea1SDimitry Andric                                                     : 0;
1540*0fca6ea1SDimitry Andric   if (RegMemOpcode) {
1541*0fca6ea1SDimitry Andric     LoadOpc = SystemZ::VL64;
1542*0fca6ea1SDimitry Andric     FPRC = &SystemZ::FP64BitRegClass;
1543*0fca6ea1SDimitry Andric   } else {
1544*0fca6ea1SDimitry Andric     RegMemOpcode = MI.getOpcode() == SystemZ::WFASB   ? SystemZ::AEB
1545*0fca6ea1SDimitry Andric                    : MI.getOpcode() == SystemZ::WFSSB ? SystemZ::SEB
1546*0fca6ea1SDimitry Andric                    : MI.getOpcode() == SystemZ::WFMSB ? SystemZ::MEEB
1547*0fca6ea1SDimitry Andric                                                       : 0;
1548*0fca6ea1SDimitry Andric     if (RegMemOpcode) {
1549*0fca6ea1SDimitry Andric       LoadOpc = SystemZ::VL32;
1550*0fca6ea1SDimitry Andric       FPRC = &SystemZ::FP32BitRegClass;
1551*0fca6ea1SDimitry Andric     }
1552*0fca6ea1SDimitry Andric   }
1553*0fca6ea1SDimitry Andric   if (!RegMemOpcode || LoadMI.getOpcode() != LoadOpc)
15540b57cec5SDimitry Andric     return nullptr;
1555*0fca6ea1SDimitry Andric 
1556*0fca6ea1SDimitry Andric   // If RegMemOpcode clobbers CC, first make sure CC is not live at this point.
1557*0fca6ea1SDimitry Andric   if (get(RegMemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)) {
1558*0fca6ea1SDimitry Andric     assert(LoadMI.getParent() == MI.getParent() && "Assuming a local fold.");
1559*0fca6ea1SDimitry Andric     assert(LoadMI != InsertPt && "Assuming InsertPt not to be first in MBB.");
1560*0fca6ea1SDimitry Andric     for (MachineBasicBlock::iterator MII = std::prev(InsertPt);;
1561*0fca6ea1SDimitry Andric          --MII) {
1562*0fca6ea1SDimitry Andric       if (MII->definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {
1563*0fca6ea1SDimitry Andric         if (!MII->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))
1564*0fca6ea1SDimitry Andric           return nullptr;
1565*0fca6ea1SDimitry Andric         break;
1566*0fca6ea1SDimitry Andric       }
1567*0fca6ea1SDimitry Andric       if (MII == MBB->begin()) {
1568*0fca6ea1SDimitry Andric         if (MBB->isLiveIn(SystemZ::CC))
1569*0fca6ea1SDimitry Andric           return nullptr;
1570*0fca6ea1SDimitry Andric         break;
1571*0fca6ea1SDimitry Andric       }
1572*0fca6ea1SDimitry Andric     }
1573*0fca6ea1SDimitry Andric   }
1574*0fca6ea1SDimitry Andric 
1575*0fca6ea1SDimitry Andric   Register FoldAsLoadDefReg = LoadMI.getOperand(0).getReg();
1576*0fca6ea1SDimitry Andric   if (Ops.size() != 1 || FoldAsLoadDefReg != MI.getOperand(Ops[0]).getReg())
1577*0fca6ea1SDimitry Andric     return nullptr;
1578*0fca6ea1SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
1579*0fca6ea1SDimitry Andric   MachineOperand LHS = MI.getOperand(1);
1580*0fca6ea1SDimitry Andric   MachineOperand RHS = MI.getOperand(2);
1581*0fca6ea1SDimitry Andric   MachineOperand &RegMO = RHS.getReg() == FoldAsLoadDefReg ? LHS : RHS;
1582*0fca6ea1SDimitry Andric   if ((RegMemOpcode == SystemZ::SDB || RegMemOpcode == SystemZ::SEB) &&
1583*0fca6ea1SDimitry Andric       FoldAsLoadDefReg != RHS.getReg())
1584*0fca6ea1SDimitry Andric     return nullptr;
1585*0fca6ea1SDimitry Andric 
1586*0fca6ea1SDimitry Andric   MachineOperand &Base = LoadMI.getOperand(1);
1587*0fca6ea1SDimitry Andric   MachineOperand &Disp = LoadMI.getOperand(2);
1588*0fca6ea1SDimitry Andric   MachineOperand &Indx = LoadMI.getOperand(3);
1589*0fca6ea1SDimitry Andric   MachineInstrBuilder MIB =
1590*0fca6ea1SDimitry Andric       BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(RegMemOpcode), DstReg)
1591*0fca6ea1SDimitry Andric           .add(RegMO)
1592*0fca6ea1SDimitry Andric           .add(Base)
1593*0fca6ea1SDimitry Andric           .add(Disp)
1594*0fca6ea1SDimitry Andric           .add(Indx);
1595*0fca6ea1SDimitry Andric   MIB->addRegisterDead(SystemZ::CC, &RI);
1596*0fca6ea1SDimitry Andric   MRI->setRegClass(DstReg, FPRC);
1597*0fca6ea1SDimitry Andric   MRI->setRegClass(RegMO.getReg(), FPRC);
1598*0fca6ea1SDimitry Andric   transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);
1599*0fca6ea1SDimitry Andric 
1600*0fca6ea1SDimitry Andric   return MIB;
16010b57cec5SDimitry Andric }
16020b57cec5SDimitry Andric 
16030b57cec5SDimitry Andric bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
16040b57cec5SDimitry Andric   switch (MI.getOpcode()) {
16050b57cec5SDimitry Andric   case SystemZ::L128:
16060b57cec5SDimitry Andric     splitMove(MI, SystemZ::LG);
16070b57cec5SDimitry Andric     return true;
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric   case SystemZ::ST128:
16100b57cec5SDimitry Andric     splitMove(MI, SystemZ::STG);
16110b57cec5SDimitry Andric     return true;
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   case SystemZ::LX:
16140b57cec5SDimitry Andric     splitMove(MI, SystemZ::LD);
16150b57cec5SDimitry Andric     return true;
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric   case SystemZ::STX:
16180b57cec5SDimitry Andric     splitMove(MI, SystemZ::STD);
16190b57cec5SDimitry Andric     return true;
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric   case SystemZ::LBMux:
16220b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::LB, SystemZ::LBH);
16230b57cec5SDimitry Andric     return true;
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric   case SystemZ::LHMux:
16260b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::LH, SystemZ::LHH);
16270b57cec5SDimitry Andric     return true;
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   case SystemZ::LLCRMux:
16300b57cec5SDimitry Andric     expandZExtPseudo(MI, SystemZ::LLCR, 8);
16310b57cec5SDimitry Andric     return true;
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric   case SystemZ::LLHRMux:
16340b57cec5SDimitry Andric     expandZExtPseudo(MI, SystemZ::LLHR, 16);
16350b57cec5SDimitry Andric     return true;
16360b57cec5SDimitry Andric 
16370b57cec5SDimitry Andric   case SystemZ::LLCMux:
16380b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::LLC, SystemZ::LLCH);
16390b57cec5SDimitry Andric     return true;
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   case SystemZ::LLHMux:
16420b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::LLH, SystemZ::LLHH);
16430b57cec5SDimitry Andric     return true;
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   case SystemZ::LMux:
16460b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::L, SystemZ::LFH);
16470b57cec5SDimitry Andric     return true;
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric   case SystemZ::LOCMux:
16500b57cec5SDimitry Andric     expandLOCPseudo(MI, SystemZ::LOC, SystemZ::LOCFH);
16510b57cec5SDimitry Andric     return true;
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   case SystemZ::LOCHIMux:
16540b57cec5SDimitry Andric     expandLOCPseudo(MI, SystemZ::LOCHI, SystemZ::LOCHHI);
16550b57cec5SDimitry Andric     return true;
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric   case SystemZ::STCMux:
16580b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::STC, SystemZ::STCH);
16590b57cec5SDimitry Andric     return true;
16600b57cec5SDimitry Andric 
16610b57cec5SDimitry Andric   case SystemZ::STHMux:
16620b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::STH, SystemZ::STHH);
16630b57cec5SDimitry Andric     return true;
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   case SystemZ::STMux:
16660b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH);
16670b57cec5SDimitry Andric     return true;
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   case SystemZ::STOCMux:
16700b57cec5SDimitry Andric     expandLOCPseudo(MI, SystemZ::STOC, SystemZ::STOCFH);
16710b57cec5SDimitry Andric     return true;
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric   case SystemZ::LHIMux:
16740b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::LHI, SystemZ::IIHF, true);
16750b57cec5SDimitry Andric     return true;
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   case SystemZ::IIFMux:
16780b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false);
16790b57cec5SDimitry Andric     return true;
16800b57cec5SDimitry Andric 
16810b57cec5SDimitry Andric   case SystemZ::IILMux:
16820b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::IILL, SystemZ::IIHL, false);
16830b57cec5SDimitry Andric     return true;
16840b57cec5SDimitry Andric 
16850b57cec5SDimitry Andric   case SystemZ::IIHMux:
16860b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false);
16870b57cec5SDimitry Andric     return true;
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric   case SystemZ::NIFMux:
16900b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::NILF, SystemZ::NIHF, false);
16910b57cec5SDimitry Andric     return true;
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   case SystemZ::NILMux:
16940b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::NILL, SystemZ::NIHL, false);
16950b57cec5SDimitry Andric     return true;
16960b57cec5SDimitry Andric 
16970b57cec5SDimitry Andric   case SystemZ::NIHMux:
16980b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::NILH, SystemZ::NIHH, false);
16990b57cec5SDimitry Andric     return true;
17000b57cec5SDimitry Andric 
17010b57cec5SDimitry Andric   case SystemZ::OIFMux:
17020b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::OILF, SystemZ::OIHF, false);
17030b57cec5SDimitry Andric     return true;
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric   case SystemZ::OILMux:
17060b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::OILL, SystemZ::OIHL, false);
17070b57cec5SDimitry Andric     return true;
17080b57cec5SDimitry Andric 
17090b57cec5SDimitry Andric   case SystemZ::OIHMux:
17100b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::OILH, SystemZ::OIHH, false);
17110b57cec5SDimitry Andric     return true;
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric   case SystemZ::XIFMux:
17140b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::XILF, SystemZ::XIHF, false);
17150b57cec5SDimitry Andric     return true;
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric   case SystemZ::TMLMux:
17180b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::TMLL, SystemZ::TMHL, false);
17190b57cec5SDimitry Andric     return true;
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   case SystemZ::TMHMux:
17220b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::TMLH, SystemZ::TMHH, false);
17230b57cec5SDimitry Andric     return true;
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric   case SystemZ::AHIMux:
17260b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::AHI, SystemZ::AIH, false);
17270b57cec5SDimitry Andric     return true;
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   case SystemZ::AHIMuxK:
17300b57cec5SDimitry Andric     expandRIEPseudo(MI, SystemZ::AHI, SystemZ::AHIK, SystemZ::AIH);
17310b57cec5SDimitry Andric     return true;
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   case SystemZ::AFIMux:
17340b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false);
17350b57cec5SDimitry Andric     return true;
17360b57cec5SDimitry Andric 
17370b57cec5SDimitry Andric   case SystemZ::CHIMux:
17380b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::CHI, SystemZ::CIH, false);
17390b57cec5SDimitry Andric     return true;
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric   case SystemZ::CFIMux:
17420b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false);
17430b57cec5SDimitry Andric     return true;
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric   case SystemZ::CLFIMux:
17460b57cec5SDimitry Andric     expandRIPseudo(MI, SystemZ::CLFI, SystemZ::CLIH, false);
17470b57cec5SDimitry Andric     return true;
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   case SystemZ::CMux:
17500b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::C, SystemZ::CHF);
17510b57cec5SDimitry Andric     return true;
17520b57cec5SDimitry Andric 
17530b57cec5SDimitry Andric   case SystemZ::CLMux:
17540b57cec5SDimitry Andric     expandRXYPseudo(MI, SystemZ::CL, SystemZ::CLHF);
17550b57cec5SDimitry Andric     return true;
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric   case SystemZ::RISBMux: {
17588bcb0991SDimitry Andric     bool DestIsHigh = SystemZ::isHighReg(MI.getOperand(0).getReg());
17598bcb0991SDimitry Andric     bool SrcIsHigh = SystemZ::isHighReg(MI.getOperand(2).getReg());
17600b57cec5SDimitry Andric     if (SrcIsHigh == DestIsHigh)
17610b57cec5SDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHH : SystemZ::RISBLL));
17620b57cec5SDimitry Andric     else {
17630b57cec5SDimitry Andric       MI.setDesc(get(DestIsHigh ? SystemZ::RISBHL : SystemZ::RISBLH));
17640b57cec5SDimitry Andric       MI.getOperand(5).setImm(MI.getOperand(5).getImm() ^ 32);
17650b57cec5SDimitry Andric     }
17660b57cec5SDimitry Andric     return true;
17670b57cec5SDimitry Andric   }
17680b57cec5SDimitry Andric 
17690b57cec5SDimitry Andric   case SystemZ::ADJDYNALLOC:
17700b57cec5SDimitry Andric     splitAdjDynAlloc(MI);
17710b57cec5SDimitry Andric     return true;
17720b57cec5SDimitry Andric 
17730b57cec5SDimitry Andric   case TargetOpcode::LOAD_STACK_GUARD:
17740b57cec5SDimitry Andric     expandLoadStackGuard(&MI);
17750b57cec5SDimitry Andric     return true;
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric   default:
17780b57cec5SDimitry Andric     return false;
17790b57cec5SDimitry Andric   }
17800b57cec5SDimitry Andric }
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
17830b57cec5SDimitry Andric   if (MI.isInlineAsm()) {
17840b57cec5SDimitry Andric     const MachineFunction *MF = MI.getParent()->getParent();
17850b57cec5SDimitry Andric     const char *AsmStr = MI.getOperand(0).getSymbolName();
17860b57cec5SDimitry Andric     return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
17870b57cec5SDimitry Andric   }
1788349cc55cSDimitry Andric   else if (MI.getOpcode() == SystemZ::PATCHPOINT)
1789349cc55cSDimitry Andric     return PatchPointOpers(&MI).getNumPatchBytes();
1790349cc55cSDimitry Andric   else if (MI.getOpcode() == SystemZ::STACKMAP)
1791349cc55cSDimitry Andric     return MI.getOperand(1).getImm();
1792349cc55cSDimitry Andric   else if (MI.getOpcode() == SystemZ::FENTRY_CALL)
1793349cc55cSDimitry Andric     return 6;
1794349cc55cSDimitry Andric 
17950b57cec5SDimitry Andric   return MI.getDesc().getSize();
17960b57cec5SDimitry Andric }
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric SystemZII::Branch
17990b57cec5SDimitry Andric SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {
18000b57cec5SDimitry Andric   switch (MI.getOpcode()) {
18010b57cec5SDimitry Andric   case SystemZ::BR:
18020b57cec5SDimitry Andric   case SystemZ::BI:
18030b57cec5SDimitry Andric   case SystemZ::J:
18040b57cec5SDimitry Andric   case SystemZ::JG:
18050b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
18060b57cec5SDimitry Andric                              SystemZ::CCMASK_ANY, &MI.getOperand(0));
18070b57cec5SDimitry Andric 
18080b57cec5SDimitry Andric   case SystemZ::BRC:
18090b57cec5SDimitry Andric   case SystemZ::BRCL:
18100b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchNormal, MI.getOperand(0).getImm(),
18110b57cec5SDimitry Andric                              MI.getOperand(1).getImm(), &MI.getOperand(2));
18120b57cec5SDimitry Andric 
18130b57cec5SDimitry Andric   case SystemZ::BRCT:
18140b57cec5SDimitry Andric   case SystemZ::BRCTH:
18150b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCT, SystemZ::CCMASK_ICMP,
18160b57cec5SDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
18170b57cec5SDimitry Andric 
18180b57cec5SDimitry Andric   case SystemZ::BRCTG:
18190b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCTG, SystemZ::CCMASK_ICMP,
18200b57cec5SDimitry Andric                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
18210b57cec5SDimitry Andric 
18220b57cec5SDimitry Andric   case SystemZ::CIJ:
18230b57cec5SDimitry Andric   case SystemZ::CRJ:
18240b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchC, SystemZ::CCMASK_ICMP,
18250b57cec5SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
18260b57cec5SDimitry Andric 
18270b57cec5SDimitry Andric   case SystemZ::CLIJ:
18280b57cec5SDimitry Andric   case SystemZ::CLRJ:
18290b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCL, SystemZ::CCMASK_ICMP,
18300b57cec5SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric   case SystemZ::CGIJ:
18330b57cec5SDimitry Andric   case SystemZ::CGRJ:
18340b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCG, SystemZ::CCMASK_ICMP,
18350b57cec5SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
18360b57cec5SDimitry Andric 
18370b57cec5SDimitry Andric   case SystemZ::CLGIJ:
18380b57cec5SDimitry Andric   case SystemZ::CLGRJ:
18390b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP,
18400b57cec5SDimitry Andric                              MI.getOperand(2).getImm(), &MI.getOperand(3));
18410b57cec5SDimitry Andric 
18420b57cec5SDimitry Andric   case SystemZ::INLINEASM_BR:
18430b57cec5SDimitry Andric     // Don't try to analyze asm goto, so pass nullptr as branch target argument.
18440b57cec5SDimitry Andric     return SystemZII::Branch(SystemZII::AsmGoto, 0, 0, nullptr);
18450b57cec5SDimitry Andric 
18460b57cec5SDimitry Andric   default:
18470b57cec5SDimitry Andric     llvm_unreachable("Unrecognized branch opcode");
18480b57cec5SDimitry Andric   }
18490b57cec5SDimitry Andric }
18500b57cec5SDimitry Andric 
18510b57cec5SDimitry Andric void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
18520b57cec5SDimitry Andric                                            unsigned &LoadOpcode,
18530b57cec5SDimitry Andric                                            unsigned &StoreOpcode) const {
18540b57cec5SDimitry Andric   if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {
18550b57cec5SDimitry Andric     LoadOpcode = SystemZ::L;
18560b57cec5SDimitry Andric     StoreOpcode = SystemZ::ST;
18570b57cec5SDimitry Andric   } else if (RC == &SystemZ::GRH32BitRegClass) {
18580b57cec5SDimitry Andric     LoadOpcode = SystemZ::LFH;
18590b57cec5SDimitry Andric     StoreOpcode = SystemZ::STFH;
18600b57cec5SDimitry Andric   } else if (RC == &SystemZ::GRX32BitRegClass) {
18610b57cec5SDimitry Andric     LoadOpcode = SystemZ::LMux;
18620b57cec5SDimitry Andric     StoreOpcode = SystemZ::STMux;
18630b57cec5SDimitry Andric   } else if (RC == &SystemZ::GR64BitRegClass ||
18640b57cec5SDimitry Andric              RC == &SystemZ::ADDR64BitRegClass) {
18650b57cec5SDimitry Andric     LoadOpcode = SystemZ::LG;
18660b57cec5SDimitry Andric     StoreOpcode = SystemZ::STG;
18670b57cec5SDimitry Andric   } else if (RC == &SystemZ::GR128BitRegClass ||
18680b57cec5SDimitry Andric              RC == &SystemZ::ADDR128BitRegClass) {
18690b57cec5SDimitry Andric     LoadOpcode = SystemZ::L128;
18700b57cec5SDimitry Andric     StoreOpcode = SystemZ::ST128;
18710b57cec5SDimitry Andric   } else if (RC == &SystemZ::FP32BitRegClass) {
18720b57cec5SDimitry Andric     LoadOpcode = SystemZ::LE;
18730b57cec5SDimitry Andric     StoreOpcode = SystemZ::STE;
18740b57cec5SDimitry Andric   } else if (RC == &SystemZ::FP64BitRegClass) {
18750b57cec5SDimitry Andric     LoadOpcode = SystemZ::LD;
18760b57cec5SDimitry Andric     StoreOpcode = SystemZ::STD;
18770b57cec5SDimitry Andric   } else if (RC == &SystemZ::FP128BitRegClass) {
18780b57cec5SDimitry Andric     LoadOpcode = SystemZ::LX;
18790b57cec5SDimitry Andric     StoreOpcode = SystemZ::STX;
18800b57cec5SDimitry Andric   } else if (RC == &SystemZ::VR32BitRegClass) {
18810b57cec5SDimitry Andric     LoadOpcode = SystemZ::VL32;
18820b57cec5SDimitry Andric     StoreOpcode = SystemZ::VST32;
18830b57cec5SDimitry Andric   } else if (RC == &SystemZ::VR64BitRegClass) {
18840b57cec5SDimitry Andric     LoadOpcode = SystemZ::VL64;
18850b57cec5SDimitry Andric     StoreOpcode = SystemZ::VST64;
18860b57cec5SDimitry Andric   } else if (RC == &SystemZ::VF128BitRegClass ||
18870b57cec5SDimitry Andric              RC == &SystemZ::VR128BitRegClass) {
18880b57cec5SDimitry Andric     LoadOpcode = SystemZ::VL;
18890b57cec5SDimitry Andric     StoreOpcode = SystemZ::VST;
18900b57cec5SDimitry Andric   } else
18910b57cec5SDimitry Andric     llvm_unreachable("Unsupported regclass to load or store");
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
189581ad6265SDimitry Andric                                               int64_t Offset,
189681ad6265SDimitry Andric                                               const MachineInstr *MI) const {
18970b57cec5SDimitry Andric   const MCInstrDesc &MCID = get(Opcode);
18980b57cec5SDimitry Andric   int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);
18990b57cec5SDimitry Andric   if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {
19000b57cec5SDimitry Andric     // Get the instruction to use for unsigned 12-bit displacements.
19010b57cec5SDimitry Andric     int Disp12Opcode = SystemZ::getDisp12Opcode(Opcode);
19020b57cec5SDimitry Andric     if (Disp12Opcode >= 0)
19030b57cec5SDimitry Andric       return Disp12Opcode;
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric     // All address-related instructions can use unsigned 12-bit
19060b57cec5SDimitry Andric     // displacements.
19070b57cec5SDimitry Andric     return Opcode;
19080b57cec5SDimitry Andric   }
19090b57cec5SDimitry Andric   if (isInt<20>(Offset) && isInt<20>(Offset2)) {
19100b57cec5SDimitry Andric     // Get the instruction to use for signed 20-bit displacements.
19110b57cec5SDimitry Andric     int Disp20Opcode = SystemZ::getDisp20Opcode(Opcode);
19120b57cec5SDimitry Andric     if (Disp20Opcode >= 0)
19130b57cec5SDimitry Andric       return Disp20Opcode;
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric     // Check whether Opcode allows signed 20-bit displacements.
19160b57cec5SDimitry Andric     if (MCID.TSFlags & SystemZII::Has20BitOffset)
19170b57cec5SDimitry Andric       return Opcode;
191881ad6265SDimitry Andric 
191981ad6265SDimitry Andric     // If a VR32/VR64 reg ended up in an FP register, use the FP opcode.
192081ad6265SDimitry Andric     if (MI && MI->getOperand(0).isReg()) {
192181ad6265SDimitry Andric       Register Reg = MI->getOperand(0).getReg();
192281ad6265SDimitry Andric       if (Reg.isPhysical() && SystemZMC::getFirstReg(Reg) < 16) {
192381ad6265SDimitry Andric         switch (Opcode) {
192481ad6265SDimitry Andric         case SystemZ::VL32:
192581ad6265SDimitry Andric           return SystemZ::LEY;
192681ad6265SDimitry Andric         case SystemZ::VST32:
192781ad6265SDimitry Andric           return SystemZ::STEY;
192881ad6265SDimitry Andric         case SystemZ::VL64:
192981ad6265SDimitry Andric           return SystemZ::LDY;
193081ad6265SDimitry Andric         case SystemZ::VST64:
193181ad6265SDimitry Andric           return SystemZ::STDY;
193281ad6265SDimitry Andric         default: break;
193381ad6265SDimitry Andric         }
193481ad6265SDimitry Andric       }
193581ad6265SDimitry Andric     }
19360b57cec5SDimitry Andric   }
19370b57cec5SDimitry Andric   return 0;
19380b57cec5SDimitry Andric }
19390b57cec5SDimitry Andric 
19401fd87a68SDimitry Andric bool SystemZInstrInfo::hasDisplacementPairInsn(unsigned Opcode) const {
19411fd87a68SDimitry Andric   const MCInstrDesc &MCID = get(Opcode);
19421fd87a68SDimitry Andric   if (MCID.TSFlags & SystemZII::Has20BitOffset)
19431fd87a68SDimitry Andric     return SystemZ::getDisp12Opcode(Opcode) >= 0;
19441fd87a68SDimitry Andric   return SystemZ::getDisp20Opcode(Opcode) >= 0;
19451fd87a68SDimitry Andric }
19461fd87a68SDimitry Andric 
19470b57cec5SDimitry Andric unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
19480b57cec5SDimitry Andric   switch (Opcode) {
19490b57cec5SDimitry Andric   case SystemZ::L:      return SystemZ::LT;
19500b57cec5SDimitry Andric   case SystemZ::LY:     return SystemZ::LT;
19510b57cec5SDimitry Andric   case SystemZ::LG:     return SystemZ::LTG;
19520b57cec5SDimitry Andric   case SystemZ::LGF:    return SystemZ::LTGF;
19530b57cec5SDimitry Andric   case SystemZ::LR:     return SystemZ::LTR;
19540b57cec5SDimitry Andric   case SystemZ::LGFR:   return SystemZ::LTGFR;
19550b57cec5SDimitry Andric   case SystemZ::LGR:    return SystemZ::LTGR;
19560b57cec5SDimitry Andric   case SystemZ::LCDFR:  return SystemZ::LCDBR;
19570b57cec5SDimitry Andric   case SystemZ::LPDFR:  return SystemZ::LPDBR;
19580b57cec5SDimitry Andric   case SystemZ::LNDFR:  return SystemZ::LNDBR;
19590b57cec5SDimitry Andric   case SystemZ::LCDFR_32:  return SystemZ::LCEBR;
19600b57cec5SDimitry Andric   case SystemZ::LPDFR_32:  return SystemZ::LPEBR;
19610b57cec5SDimitry Andric   case SystemZ::LNDFR_32:  return SystemZ::LNEBR;
19620b57cec5SDimitry Andric   // On zEC12 we prefer to use RISBGN.  But if there is a chance to
19630b57cec5SDimitry Andric   // actually use the condition code, we may turn it back into RISGB.
19640b57cec5SDimitry Andric   // Note that RISBG is not really a "load-and-test" instruction,
19650b57cec5SDimitry Andric   // but sets the same condition code values, so is OK to use here.
19660b57cec5SDimitry Andric   case SystemZ::RISBGN: return SystemZ::RISBG;
19670b57cec5SDimitry Andric   default:              return 0;
19680b57cec5SDimitry Andric   }
19690b57cec5SDimitry Andric }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
19720b57cec5SDimitry Andric                                    unsigned &Start, unsigned &End) const {
19730b57cec5SDimitry Andric   // Reject trivial all-zero masks.
19740b57cec5SDimitry Andric   Mask &= allOnes(BitSize);
19750b57cec5SDimitry Andric   if (Mask == 0)
19760b57cec5SDimitry Andric     return false;
19770b57cec5SDimitry Andric 
19780b57cec5SDimitry Andric   // Handle the 1+0+ or 0+1+0* cases.  Start then specifies the index of
19790b57cec5SDimitry Andric   // the msb and End specifies the index of the lsb.
19800b57cec5SDimitry Andric   unsigned LSB, Length;
1981bdd1243dSDimitry Andric   if (isShiftedMask_64(Mask, LSB, Length)) {
19820b57cec5SDimitry Andric     Start = 63 - (LSB + Length - 1);
19830b57cec5SDimitry Andric     End = 63 - LSB;
19840b57cec5SDimitry Andric     return true;
19850b57cec5SDimitry Andric   }
19860b57cec5SDimitry Andric 
19870b57cec5SDimitry Andric   // Handle the wrap-around 1+0+1+ cases.  Start then specifies the msb
19880b57cec5SDimitry Andric   // of the low 1s and End specifies the lsb of the high 1s.
1989bdd1243dSDimitry Andric   if (isShiftedMask_64(Mask ^ allOnes(BitSize), LSB, Length)) {
19900b57cec5SDimitry Andric     assert(LSB > 0 && "Bottom bit must be set");
19910b57cec5SDimitry Andric     assert(LSB + Length < BitSize && "Top bit must be set");
19920b57cec5SDimitry Andric     Start = 63 - (LSB - 1);
19930b57cec5SDimitry Andric     End = 63 - (LSB + Length);
19940b57cec5SDimitry Andric     return true;
19950b57cec5SDimitry Andric   }
19960b57cec5SDimitry Andric 
19970b57cec5SDimitry Andric   return false;
19980b57cec5SDimitry Andric }
19990b57cec5SDimitry Andric 
20000b57cec5SDimitry Andric unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
20010b57cec5SDimitry Andric                                            SystemZII::FusedCompareType Type,
20020b57cec5SDimitry Andric                                            const MachineInstr *MI) const {
20030b57cec5SDimitry Andric   switch (Opcode) {
20040b57cec5SDimitry Andric   case SystemZ::CHI:
20050b57cec5SDimitry Andric   case SystemZ::CGHI:
20060b57cec5SDimitry Andric     if (!(MI && isInt<8>(MI->getOperand(1).getImm())))
20070b57cec5SDimitry Andric       return 0;
20080b57cec5SDimitry Andric     break;
20090b57cec5SDimitry Andric   case SystemZ::CLFI:
20100b57cec5SDimitry Andric   case SystemZ::CLGFI:
20110b57cec5SDimitry Andric     if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
20120b57cec5SDimitry Andric       return 0;
20130b57cec5SDimitry Andric     break;
20140b57cec5SDimitry Andric   case SystemZ::CL:
20150b57cec5SDimitry Andric   case SystemZ::CLG:
20160b57cec5SDimitry Andric     if (!STI.hasMiscellaneousExtensions())
20170b57cec5SDimitry Andric       return 0;
20180b57cec5SDimitry Andric     if (!(MI && MI->getOperand(3).getReg() == 0))
20190b57cec5SDimitry Andric       return 0;
20200b57cec5SDimitry Andric     break;
20210b57cec5SDimitry Andric   }
20220b57cec5SDimitry Andric   switch (Type) {
20230b57cec5SDimitry Andric   case SystemZII::CompareAndBranch:
20240b57cec5SDimitry Andric     switch (Opcode) {
20250b57cec5SDimitry Andric     case SystemZ::CR:
20260b57cec5SDimitry Andric       return SystemZ::CRJ;
20270b57cec5SDimitry Andric     case SystemZ::CGR:
20280b57cec5SDimitry Andric       return SystemZ::CGRJ;
20290b57cec5SDimitry Andric     case SystemZ::CHI:
20300b57cec5SDimitry Andric       return SystemZ::CIJ;
20310b57cec5SDimitry Andric     case SystemZ::CGHI:
20320b57cec5SDimitry Andric       return SystemZ::CGIJ;
20330b57cec5SDimitry Andric     case SystemZ::CLR:
20340b57cec5SDimitry Andric       return SystemZ::CLRJ;
20350b57cec5SDimitry Andric     case SystemZ::CLGR:
20360b57cec5SDimitry Andric       return SystemZ::CLGRJ;
20370b57cec5SDimitry Andric     case SystemZ::CLFI:
20380b57cec5SDimitry Andric       return SystemZ::CLIJ;
20390b57cec5SDimitry Andric     case SystemZ::CLGFI:
20400b57cec5SDimitry Andric       return SystemZ::CLGIJ;
20410b57cec5SDimitry Andric     default:
20420b57cec5SDimitry Andric       return 0;
20430b57cec5SDimitry Andric     }
20440b57cec5SDimitry Andric   case SystemZII::CompareAndReturn:
20450b57cec5SDimitry Andric     switch (Opcode) {
20460b57cec5SDimitry Andric     case SystemZ::CR:
20470b57cec5SDimitry Andric       return SystemZ::CRBReturn;
20480b57cec5SDimitry Andric     case SystemZ::CGR:
20490b57cec5SDimitry Andric       return SystemZ::CGRBReturn;
20500b57cec5SDimitry Andric     case SystemZ::CHI:
20510b57cec5SDimitry Andric       return SystemZ::CIBReturn;
20520b57cec5SDimitry Andric     case SystemZ::CGHI:
20530b57cec5SDimitry Andric       return SystemZ::CGIBReturn;
20540b57cec5SDimitry Andric     case SystemZ::CLR:
20550b57cec5SDimitry Andric       return SystemZ::CLRBReturn;
20560b57cec5SDimitry Andric     case SystemZ::CLGR:
20570b57cec5SDimitry Andric       return SystemZ::CLGRBReturn;
20580b57cec5SDimitry Andric     case SystemZ::CLFI:
20590b57cec5SDimitry Andric       return SystemZ::CLIBReturn;
20600b57cec5SDimitry Andric     case SystemZ::CLGFI:
20610b57cec5SDimitry Andric       return SystemZ::CLGIBReturn;
20620b57cec5SDimitry Andric     default:
20630b57cec5SDimitry Andric       return 0;
20640b57cec5SDimitry Andric     }
20650b57cec5SDimitry Andric   case SystemZII::CompareAndSibcall:
20660b57cec5SDimitry Andric     switch (Opcode) {
20670b57cec5SDimitry Andric     case SystemZ::CR:
20680b57cec5SDimitry Andric       return SystemZ::CRBCall;
20690b57cec5SDimitry Andric     case SystemZ::CGR:
20700b57cec5SDimitry Andric       return SystemZ::CGRBCall;
20710b57cec5SDimitry Andric     case SystemZ::CHI:
20720b57cec5SDimitry Andric       return SystemZ::CIBCall;
20730b57cec5SDimitry Andric     case SystemZ::CGHI:
20740b57cec5SDimitry Andric       return SystemZ::CGIBCall;
20750b57cec5SDimitry Andric     case SystemZ::CLR:
20760b57cec5SDimitry Andric       return SystemZ::CLRBCall;
20770b57cec5SDimitry Andric     case SystemZ::CLGR:
20780b57cec5SDimitry Andric       return SystemZ::CLGRBCall;
20790b57cec5SDimitry Andric     case SystemZ::CLFI:
20800b57cec5SDimitry Andric       return SystemZ::CLIBCall;
20810b57cec5SDimitry Andric     case SystemZ::CLGFI:
20820b57cec5SDimitry Andric       return SystemZ::CLGIBCall;
20830b57cec5SDimitry Andric     default:
20840b57cec5SDimitry Andric       return 0;
20850b57cec5SDimitry Andric     }
20860b57cec5SDimitry Andric   case SystemZII::CompareAndTrap:
20870b57cec5SDimitry Andric     switch (Opcode) {
20880b57cec5SDimitry Andric     case SystemZ::CR:
20890b57cec5SDimitry Andric       return SystemZ::CRT;
20900b57cec5SDimitry Andric     case SystemZ::CGR:
20910b57cec5SDimitry Andric       return SystemZ::CGRT;
20920b57cec5SDimitry Andric     case SystemZ::CHI:
20930b57cec5SDimitry Andric       return SystemZ::CIT;
20940b57cec5SDimitry Andric     case SystemZ::CGHI:
20950b57cec5SDimitry Andric       return SystemZ::CGIT;
20960b57cec5SDimitry Andric     case SystemZ::CLR:
20970b57cec5SDimitry Andric       return SystemZ::CLRT;
20980b57cec5SDimitry Andric     case SystemZ::CLGR:
20990b57cec5SDimitry Andric       return SystemZ::CLGRT;
21000b57cec5SDimitry Andric     case SystemZ::CLFI:
21010b57cec5SDimitry Andric       return SystemZ::CLFIT;
21020b57cec5SDimitry Andric     case SystemZ::CLGFI:
21030b57cec5SDimitry Andric       return SystemZ::CLGIT;
21040b57cec5SDimitry Andric     case SystemZ::CL:
21050b57cec5SDimitry Andric       return SystemZ::CLT;
21060b57cec5SDimitry Andric     case SystemZ::CLG:
21070b57cec5SDimitry Andric       return SystemZ::CLGT;
21080b57cec5SDimitry Andric     default:
21090b57cec5SDimitry Andric       return 0;
21100b57cec5SDimitry Andric     }
21110b57cec5SDimitry Andric   }
21120b57cec5SDimitry Andric   return 0;
21130b57cec5SDimitry Andric }
21140b57cec5SDimitry Andric 
21155ffd83dbSDimitry Andric bool SystemZInstrInfo::
21165ffd83dbSDimitry Andric prepareCompareSwapOperands(MachineBasicBlock::iterator const MBBI) const {
21175ffd83dbSDimitry Andric   assert(MBBI->isCompare() && MBBI->getOperand(0).isReg() &&
21185ffd83dbSDimitry Andric          MBBI->getOperand(1).isReg() && !MBBI->mayLoad() &&
21195ffd83dbSDimitry Andric          "Not a compare reg/reg.");
21205ffd83dbSDimitry Andric 
21215ffd83dbSDimitry Andric   MachineBasicBlock *MBB = MBBI->getParent();
21225ffd83dbSDimitry Andric   bool CCLive = true;
21235ffd83dbSDimitry Andric   SmallVector<MachineInstr *, 4> CCUsers;
2124bdd1243dSDimitry Andric   for (MachineInstr &MI : llvm::make_range(std::next(MBBI), MBB->end())) {
2125*0fca6ea1SDimitry Andric     if (MI.readsRegister(SystemZ::CC, /*TRI=*/nullptr)) {
2126bdd1243dSDimitry Andric       unsigned Flags = MI.getDesc().TSFlags;
21275ffd83dbSDimitry Andric       if ((Flags & SystemZII::CCMaskFirst) || (Flags & SystemZII::CCMaskLast))
2128bdd1243dSDimitry Andric         CCUsers.push_back(&MI);
21295ffd83dbSDimitry Andric       else
21305ffd83dbSDimitry Andric         return false;
21315ffd83dbSDimitry Andric     }
2132*0fca6ea1SDimitry Andric     if (MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {
21335ffd83dbSDimitry Andric       CCLive = false;
21345ffd83dbSDimitry Andric       break;
21355ffd83dbSDimitry Andric     }
21365ffd83dbSDimitry Andric   }
21375ffd83dbSDimitry Andric   if (CCLive) {
2138*0fca6ea1SDimitry Andric     LiveRegUnits LiveRegs(*MBB->getParent()->getSubtarget().getRegisterInfo());
21395ffd83dbSDimitry Andric     LiveRegs.addLiveOuts(*MBB);
2140*0fca6ea1SDimitry Andric     if (!LiveRegs.available(SystemZ::CC))
21415ffd83dbSDimitry Andric       return false;
21425ffd83dbSDimitry Andric   }
21435ffd83dbSDimitry Andric 
21445ffd83dbSDimitry Andric   // Update all CC users.
21455ffd83dbSDimitry Andric   for (unsigned Idx = 0; Idx < CCUsers.size(); ++Idx) {
21465ffd83dbSDimitry Andric     unsigned Flags = CCUsers[Idx]->getDesc().TSFlags;
21475ffd83dbSDimitry Andric     unsigned FirstOpNum = ((Flags & SystemZII::CCMaskFirst) ?
21485ffd83dbSDimitry Andric                            0 : CCUsers[Idx]->getNumExplicitOperands() - 2);
21495ffd83dbSDimitry Andric     MachineOperand &CCMaskMO = CCUsers[Idx]->getOperand(FirstOpNum + 1);
21505ffd83dbSDimitry Andric     unsigned NewCCMask = SystemZ::reverseCCMask(CCMaskMO.getImm());
21515ffd83dbSDimitry Andric     CCMaskMO.setImm(NewCCMask);
21525ffd83dbSDimitry Andric   }
21535ffd83dbSDimitry Andric 
21545ffd83dbSDimitry Andric   return true;
21555ffd83dbSDimitry Andric }
21565ffd83dbSDimitry Andric 
21575ffd83dbSDimitry Andric unsigned SystemZ::reverseCCMask(unsigned CCMask) {
21585ffd83dbSDimitry Andric   return ((CCMask & SystemZ::CCMASK_CMP_EQ) |
2159*0fca6ea1SDimitry Andric           ((CCMask & SystemZ::CCMASK_CMP_GT) ? SystemZ::CCMASK_CMP_LT : 0) |
2160*0fca6ea1SDimitry Andric           ((CCMask & SystemZ::CCMASK_CMP_LT) ? SystemZ::CCMASK_CMP_GT : 0) |
21615ffd83dbSDimitry Andric           (CCMask & SystemZ::CCMASK_CMP_UO));
21625ffd83dbSDimitry Andric }
21635ffd83dbSDimitry Andric 
21645ffd83dbSDimitry Andric MachineBasicBlock *SystemZ::emitBlockAfter(MachineBasicBlock *MBB) {
21655ffd83dbSDimitry Andric   MachineFunction &MF = *MBB->getParent();
21665ffd83dbSDimitry Andric   MachineBasicBlock *NewMBB = MF.CreateMachineBasicBlock(MBB->getBasicBlock());
21675ffd83dbSDimitry Andric   MF.insert(std::next(MachineFunction::iterator(MBB)), NewMBB);
21685ffd83dbSDimitry Andric   return NewMBB;
21695ffd83dbSDimitry Andric }
21705ffd83dbSDimitry Andric 
21715ffd83dbSDimitry Andric MachineBasicBlock *SystemZ::splitBlockAfter(MachineBasicBlock::iterator MI,
21725ffd83dbSDimitry Andric                                             MachineBasicBlock *MBB) {
21735ffd83dbSDimitry Andric   MachineBasicBlock *NewMBB = emitBlockAfter(MBB);
21745ffd83dbSDimitry Andric   NewMBB->splice(NewMBB->begin(), MBB,
21755ffd83dbSDimitry Andric                  std::next(MachineBasicBlock::iterator(MI)), MBB->end());
21765ffd83dbSDimitry Andric   NewMBB->transferSuccessorsAndUpdatePHIs(MBB);
21775ffd83dbSDimitry Andric   return NewMBB;
21785ffd83dbSDimitry Andric }
21795ffd83dbSDimitry Andric 
21805ffd83dbSDimitry Andric MachineBasicBlock *SystemZ::splitBlockBefore(MachineBasicBlock::iterator MI,
21815ffd83dbSDimitry Andric                                              MachineBasicBlock *MBB) {
21825ffd83dbSDimitry Andric   MachineBasicBlock *NewMBB = emitBlockAfter(MBB);
21835ffd83dbSDimitry Andric   NewMBB->splice(NewMBB->begin(), MBB, MI, MBB->end());
21845ffd83dbSDimitry Andric   NewMBB->transferSuccessorsAndUpdatePHIs(MBB);
21855ffd83dbSDimitry Andric   return NewMBB;
21865ffd83dbSDimitry Andric }
21875ffd83dbSDimitry Andric 
21880b57cec5SDimitry Andric unsigned SystemZInstrInfo::getLoadAndTrap(unsigned Opcode) const {
21890b57cec5SDimitry Andric   if (!STI.hasLoadAndTrap())
21900b57cec5SDimitry Andric     return 0;
21910b57cec5SDimitry Andric   switch (Opcode) {
21920b57cec5SDimitry Andric   case SystemZ::L:
21930b57cec5SDimitry Andric   case SystemZ::LY:
21940b57cec5SDimitry Andric     return SystemZ::LAT;
21950b57cec5SDimitry Andric   case SystemZ::LG:
21960b57cec5SDimitry Andric     return SystemZ::LGAT;
21970b57cec5SDimitry Andric   case SystemZ::LFH:
21980b57cec5SDimitry Andric     return SystemZ::LFHAT;
21990b57cec5SDimitry Andric   case SystemZ::LLGF:
22000b57cec5SDimitry Andric     return SystemZ::LLGFAT;
22010b57cec5SDimitry Andric   case SystemZ::LLGT:
22020b57cec5SDimitry Andric     return SystemZ::LLGTAT;
22030b57cec5SDimitry Andric   }
22040b57cec5SDimitry Andric   return 0;
22050b57cec5SDimitry Andric }
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
22080b57cec5SDimitry Andric                                      MachineBasicBlock::iterator MBBI,
22090b57cec5SDimitry Andric                                      unsigned Reg, uint64_t Value) const {
22100b57cec5SDimitry Andric   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
2211349cc55cSDimitry Andric   unsigned Opcode = 0;
22120b57cec5SDimitry Andric   if (isInt<16>(Value))
22130b57cec5SDimitry Andric     Opcode = SystemZ::LGHI;
22140b57cec5SDimitry Andric   else if (SystemZ::isImmLL(Value))
22150b57cec5SDimitry Andric     Opcode = SystemZ::LLILL;
22160b57cec5SDimitry Andric   else if (SystemZ::isImmLH(Value)) {
22170b57cec5SDimitry Andric     Opcode = SystemZ::LLILH;
22180b57cec5SDimitry Andric     Value >>= 16;
22190b57cec5SDimitry Andric   }
2220349cc55cSDimitry Andric   else if (isInt<32>(Value))
2221349cc55cSDimitry Andric     Opcode = SystemZ::LGFI;
2222349cc55cSDimitry Andric   if (Opcode) {
22230b57cec5SDimitry Andric     BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);
2224349cc55cSDimitry Andric     return;
2225349cc55cSDimitry Andric   }
2226349cc55cSDimitry Andric 
2227349cc55cSDimitry Andric   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
2228349cc55cSDimitry Andric   assert (MRI.isSSA() &&  "Huge values only handled before reg-alloc .");
2229349cc55cSDimitry Andric   Register Reg0 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);
2230349cc55cSDimitry Andric   Register Reg1 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);
2231349cc55cSDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IMPLICIT_DEF), Reg0);
2232349cc55cSDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IIHF64), Reg1)
2233349cc55cSDimitry Andric     .addReg(Reg0).addImm(Value >> 32);
2234349cc55cSDimitry Andric   BuildMI(MBB, MBBI, DL, get(SystemZ::IILF64), Reg)
2235349cc55cSDimitry Andric     .addReg(Reg1).addImm(Value & ((uint64_t(1) << 32) - 1));
22360b57cec5SDimitry Andric }
22370b57cec5SDimitry Andric 
2238480093f4SDimitry Andric bool SystemZInstrInfo::verifyInstruction(const MachineInstr &MI,
2239480093f4SDimitry Andric                                          StringRef &ErrInfo) const {
2240480093f4SDimitry Andric   const MCInstrDesc &MCID = MI.getDesc();
2241480093f4SDimitry Andric   for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
2242480093f4SDimitry Andric     if (I >= MCID.getNumOperands())
2243480093f4SDimitry Andric       break;
2244480093f4SDimitry Andric     const MachineOperand &Op = MI.getOperand(I);
2245bdd1243dSDimitry Andric     const MCOperandInfo &MCOI = MCID.operands()[I];
2246480093f4SDimitry Andric     // Addressing modes have register and immediate operands. Op should be a
2247480093f4SDimitry Andric     // register (or frame index) operand if MCOI.RegClass contains a valid
2248480093f4SDimitry Andric     // register class, or an immediate otherwise.
2249480093f4SDimitry Andric     if (MCOI.OperandType == MCOI::OPERAND_MEMORY &&
2250480093f4SDimitry Andric         ((MCOI.RegClass != -1 && !Op.isReg() && !Op.isFI()) ||
2251480093f4SDimitry Andric          (MCOI.RegClass == -1 && !Op.isImm()))) {
2252480093f4SDimitry Andric       ErrInfo = "Addressing mode operands corrupt!";
2253480093f4SDimitry Andric       return false;
2254480093f4SDimitry Andric     }
2255480093f4SDimitry Andric   }
2256480093f4SDimitry Andric 
2257480093f4SDimitry Andric   return true;
2258480093f4SDimitry Andric }
2259480093f4SDimitry Andric 
22600b57cec5SDimitry Andric bool SystemZInstrInfo::
22610b57cec5SDimitry Andric areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
22628bcb0991SDimitry Andric                                 const MachineInstr &MIb) const {
22630b57cec5SDimitry Andric 
22640b57cec5SDimitry Andric   if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand())
22650b57cec5SDimitry Andric     return false;
22660b57cec5SDimitry Andric 
22670b57cec5SDimitry Andric   // If mem-operands show that the same address Value is used by both
22680b57cec5SDimitry Andric   // instructions, check for non-overlapping offsets and widths. Not
22690b57cec5SDimitry Andric   // sure if a register based analysis would be an improvement...
22700b57cec5SDimitry Andric 
22710b57cec5SDimitry Andric   MachineMemOperand *MMOa = *MIa.memoperands_begin();
22720b57cec5SDimitry Andric   MachineMemOperand *MMOb = *MIb.memoperands_begin();
22730b57cec5SDimitry Andric   const Value *VALa = MMOa->getValue();
22740b57cec5SDimitry Andric   const Value *VALb = MMOb->getValue();
22750b57cec5SDimitry Andric   bool SameVal = (VALa && VALb && (VALa == VALb));
22760b57cec5SDimitry Andric   if (!SameVal) {
22770b57cec5SDimitry Andric     const PseudoSourceValue *PSVa = MMOa->getPseudoValue();
22780b57cec5SDimitry Andric     const PseudoSourceValue *PSVb = MMOb->getPseudoValue();
22790b57cec5SDimitry Andric     if (PSVa && PSVb && (PSVa == PSVb))
22800b57cec5SDimitry Andric       SameVal = true;
22810b57cec5SDimitry Andric   }
22820b57cec5SDimitry Andric   if (SameVal) {
22830b57cec5SDimitry Andric     int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset();
2284*0fca6ea1SDimitry Andric     LocationSize WidthA = MMOa->getSize(), WidthB = MMOb->getSize();
22850b57cec5SDimitry Andric     int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
22860b57cec5SDimitry Andric     int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
2287*0fca6ea1SDimitry Andric     LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
2288*0fca6ea1SDimitry Andric     if (LowWidth.hasValue() &&
2289*0fca6ea1SDimitry Andric         LowOffset + (int)LowWidth.getValue() <= HighOffset)
22900b57cec5SDimitry Andric       return true;
22910b57cec5SDimitry Andric   }
22920b57cec5SDimitry Andric 
22930b57cec5SDimitry Andric   return false;
22940b57cec5SDimitry Andric }
2295*0fca6ea1SDimitry Andric 
2296*0fca6ea1SDimitry Andric bool SystemZInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,
2297*0fca6ea1SDimitry Andric                                                const Register Reg,
2298*0fca6ea1SDimitry Andric                                                int64_t &ImmVal) const {
2299*0fca6ea1SDimitry Andric 
2300*0fca6ea1SDimitry Andric   if (MI.getOpcode() == SystemZ::VGBM && Reg == MI.getOperand(0).getReg()) {
2301*0fca6ea1SDimitry Andric     ImmVal = MI.getOperand(1).getImm();
2302*0fca6ea1SDimitry Andric     // TODO: Handle non-0 values
2303*0fca6ea1SDimitry Andric     return ImmVal == 0;
2304*0fca6ea1SDimitry Andric   }
2305*0fca6ea1SDimitry Andric 
2306*0fca6ea1SDimitry Andric   return false;
2307*0fca6ea1SDimitry Andric }
2308