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