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