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