Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
35266 views
//===-- SystemZInstrInfo.cpp - SystemZ instruction information ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains the SystemZ implementation of the TargetInstrInfo class.9//10//===----------------------------------------------------------------------===//1112#include "SystemZInstrInfo.h"13#include "MCTargetDesc/SystemZMCTargetDesc.h"14#include "SystemZ.h"15#include "SystemZInstrBuilder.h"16#include "SystemZSubtarget.h"17#include "llvm/ADT/Statistic.h"18#include "llvm/CodeGen/LiveInterval.h"19#include "llvm/CodeGen/LiveIntervals.h"20#include "llvm/CodeGen/LiveRegUnits.h"21#include "llvm/CodeGen/LiveVariables.h"22#include "llvm/CodeGen/MachineBasicBlock.h"23#include "llvm/CodeGen/MachineFrameInfo.h"24#include "llvm/CodeGen/MachineFunction.h"25#include "llvm/CodeGen/MachineInstr.h"26#include "llvm/CodeGen/MachineMemOperand.h"27#include "llvm/CodeGen/MachineOperand.h"28#include "llvm/CodeGen/MachineRegisterInfo.h"29#include "llvm/CodeGen/SlotIndexes.h"30#include "llvm/CodeGen/StackMaps.h"31#include "llvm/CodeGen/TargetInstrInfo.h"32#include "llvm/CodeGen/TargetSubtargetInfo.h"33#include "llvm/CodeGen/VirtRegMap.h"34#include "llvm/MC/MCInstrDesc.h"35#include "llvm/MC/MCRegisterInfo.h"36#include "llvm/Support/BranchProbability.h"37#include "llvm/Support/ErrorHandling.h"38#include "llvm/Support/MathExtras.h"39#include "llvm/Target/TargetMachine.h"40#include <cassert>41#include <cstdint>42#include <iterator>4344using namespace llvm;4546#define GET_INSTRINFO_CTOR_DTOR47#define GET_INSTRMAP_INFO48#include "SystemZGenInstrInfo.inc"4950#define DEBUG_TYPE "systemz-II"5152// Return a mask with Count low bits set.53static uint64_t allOnes(unsigned int Count) {54return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;55}5657// Pin the vtable to this file.58void SystemZInstrInfo::anchor() {}5960SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti)61: SystemZGenInstrInfo(-1, -1),62RI(sti.getSpecialRegisters()->getReturnFunctionAddressRegister()),63STI(sti) {}6465// MI is a 128-bit load or store. Split it into two 64-bit loads or stores,66// each having the opcode given by NewOpcode.67void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI,68unsigned NewOpcode) const {69MachineBasicBlock *MBB = MI->getParent();70MachineFunction &MF = *MBB->getParent();7172// Get two load or store instructions. Use the original instruction for73// one of them and create a clone for the other.74MachineInstr *HighPartMI = MF.CloneMachineInstr(&*MI);75MachineInstr *LowPartMI = &*MI;76MBB->insert(LowPartMI, HighPartMI);7778// Set up the two 64-bit registers and remember super reg and its flags.79MachineOperand &HighRegOp = HighPartMI->getOperand(0);80MachineOperand &LowRegOp = LowPartMI->getOperand(0);81Register Reg128 = LowRegOp.getReg();82unsigned Reg128Killed = getKillRegState(LowRegOp.isKill());83unsigned Reg128Undef = getUndefRegState(LowRegOp.isUndef());84HighRegOp.setReg(RI.getSubReg(HighRegOp.getReg(), SystemZ::subreg_h64));85LowRegOp.setReg(RI.getSubReg(LowRegOp.getReg(), SystemZ::subreg_l64));8687// The address in the first (high) instruction is already correct.88// Adjust the offset in the second (low) instruction.89MachineOperand &HighOffsetOp = HighPartMI->getOperand(2);90MachineOperand &LowOffsetOp = LowPartMI->getOperand(2);91LowOffsetOp.setImm(LowOffsetOp.getImm() + 8);9293// Set the opcodes.94unsigned HighOpcode = getOpcodeForOffset(NewOpcode, HighOffsetOp.getImm());95unsigned LowOpcode = getOpcodeForOffset(NewOpcode, LowOffsetOp.getImm());96assert(HighOpcode && LowOpcode && "Both offsets should be in range");97HighPartMI->setDesc(get(HighOpcode));98LowPartMI->setDesc(get(LowOpcode));99100MachineInstr *FirstMI = HighPartMI;101if (MI->mayStore()) {102FirstMI->getOperand(0).setIsKill(false);103// Add implicit uses of the super register in case one of the subregs is104// undefined. We could track liveness and skip storing an undefined105// subreg, but this is hopefully rare (discovered with llvm-stress).106// If Reg128 was killed, set kill flag on MI.107unsigned Reg128UndefImpl = (Reg128Undef | RegState::Implicit);108MachineInstrBuilder(MF, HighPartMI).addReg(Reg128, Reg128UndefImpl);109MachineInstrBuilder(MF, LowPartMI).addReg(Reg128, (Reg128UndefImpl | Reg128Killed));110} else {111// If HighPartMI clobbers any of the address registers, it needs to come112// after LowPartMI.113auto overlapsAddressReg = [&](Register Reg) -> bool {114return RI.regsOverlap(Reg, MI->getOperand(1).getReg()) ||115RI.regsOverlap(Reg, MI->getOperand(3).getReg());116};117if (overlapsAddressReg(HighRegOp.getReg())) {118assert(!overlapsAddressReg(LowRegOp.getReg()) &&119"Both loads clobber address!");120MBB->splice(HighPartMI, MBB, LowPartMI);121FirstMI = LowPartMI;122}123}124125// Clear the kill flags on the address registers in the first instruction.126FirstMI->getOperand(1).setIsKill(false);127FirstMI->getOperand(3).setIsKill(false);128}129130// Split ADJDYNALLOC instruction MI.131void SystemZInstrInfo::splitAdjDynAlloc(MachineBasicBlock::iterator MI) const {132MachineBasicBlock *MBB = MI->getParent();133MachineFunction &MF = *MBB->getParent();134MachineFrameInfo &MFFrame = MF.getFrameInfo();135MachineOperand &OffsetMO = MI->getOperand(2);136SystemZCallingConventionRegisters *Regs = STI.getSpecialRegisters();137138uint64_t Offset = (MFFrame.getMaxCallFrameSize() +139Regs->getCallFrameSize() +140Regs->getStackPointerBias() +141OffsetMO.getImm());142unsigned NewOpcode = getOpcodeForOffset(SystemZ::LA, Offset);143assert(NewOpcode && "No support for huge argument lists yet");144MI->setDesc(get(NewOpcode));145OffsetMO.setImm(Offset);146}147148// MI is an RI-style pseudo instruction. Replace it with LowOpcode149// if the first operand is a low GR32 and HighOpcode if the first operand150// is a high GR32. ConvertHigh is true if LowOpcode takes a signed operand151// and HighOpcode takes an unsigned 32-bit operand. In those cases,152// MI has the same kind of operand as LowOpcode, so needs to be converted153// if HighOpcode is used.154void SystemZInstrInfo::expandRIPseudo(MachineInstr &MI, unsigned LowOpcode,155unsigned HighOpcode,156bool ConvertHigh) const {157Register Reg = MI.getOperand(0).getReg();158bool IsHigh = SystemZ::isHighReg(Reg);159MI.setDesc(get(IsHigh ? HighOpcode : LowOpcode));160if (IsHigh && ConvertHigh)161MI.getOperand(1).setImm(uint32_t(MI.getOperand(1).getImm()));162}163164// MI is a three-operand RIE-style pseudo instruction. Replace it with165// LowOpcodeK if the registers are both low GR32s, otherwise use a move166// followed by HighOpcode or LowOpcode, depending on whether the target167// is a high or low GR32.168void SystemZInstrInfo::expandRIEPseudo(MachineInstr &MI, unsigned LowOpcode,169unsigned LowOpcodeK,170unsigned HighOpcode) const {171Register DestReg = MI.getOperand(0).getReg();172Register SrcReg = MI.getOperand(1).getReg();173bool DestIsHigh = SystemZ::isHighReg(DestReg);174bool SrcIsHigh = SystemZ::isHighReg(SrcReg);175if (!DestIsHigh && !SrcIsHigh)176MI.setDesc(get(LowOpcodeK));177else {178if (DestReg != SrcReg) {179emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(), DestReg, SrcReg,180SystemZ::LR, 32, MI.getOperand(1).isKill(),181MI.getOperand(1).isUndef());182MI.getOperand(1).setReg(DestReg);183}184MI.setDesc(get(DestIsHigh ? HighOpcode : LowOpcode));185MI.tieOperands(0, 1);186}187}188189// MI is an RXY-style pseudo instruction. Replace it with LowOpcode190// if the first operand is a low GR32 and HighOpcode if the first operand191// is a high GR32.192void SystemZInstrInfo::expandRXYPseudo(MachineInstr &MI, unsigned LowOpcode,193unsigned HighOpcode) const {194Register Reg = MI.getOperand(0).getReg();195unsigned Opcode = getOpcodeForOffset(196SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode,197MI.getOperand(2).getImm());198MI.setDesc(get(Opcode));199}200201// MI is a load-on-condition pseudo instruction with a single register202// (source or destination) operand. Replace it with LowOpcode if the203// register is a low GR32 and HighOpcode if the register is a high GR32.204void SystemZInstrInfo::expandLOCPseudo(MachineInstr &MI, unsigned LowOpcode,205unsigned HighOpcode) const {206Register Reg = MI.getOperand(0).getReg();207unsigned Opcode = SystemZ::isHighReg(Reg) ? HighOpcode : LowOpcode;208MI.setDesc(get(Opcode));209}210211// MI is an RR-style pseudo instruction that zero-extends the low Size bits212// of one GRX32 into another. Replace it with LowOpcode if both operands213// are low registers, otherwise use RISB[LH]G.214void SystemZInstrInfo::expandZExtPseudo(MachineInstr &MI, unsigned LowOpcode,215unsigned Size) const {216MachineInstrBuilder MIB =217emitGRX32Move(*MI.getParent(), MI, MI.getDebugLoc(),218MI.getOperand(0).getReg(), MI.getOperand(1).getReg(), LowOpcode,219Size, MI.getOperand(1).isKill(), MI.getOperand(1).isUndef());220221// Keep the remaining operands as-is.222for (const MachineOperand &MO : llvm::drop_begin(MI.operands(), 2))223MIB.add(MO);224225MI.eraseFromParent();226}227228void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const {229MachineBasicBlock *MBB = MI->getParent();230MachineFunction &MF = *MBB->getParent();231const Register Reg64 = MI->getOperand(0).getReg();232const Register Reg32 = RI.getSubReg(Reg64, SystemZ::subreg_l32);233234// EAR can only load the low subregister so us a shift for %a0 to produce235// the GR containing %a0 and %a1.236237// ear <reg>, %a0238BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)239.addReg(SystemZ::A0)240.addReg(Reg64, RegState::ImplicitDefine);241242// sllg <reg>, <reg>, 32243BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::SLLG), Reg64)244.addReg(Reg64)245.addReg(0)246.addImm(32);247248// ear <reg>, %a1249BuildMI(*MBB, MI, MI->getDebugLoc(), get(SystemZ::EAR), Reg32)250.addReg(SystemZ::A1);251252// lg <reg>, 40(<reg>)253MI->setDesc(get(SystemZ::LG));254MachineInstrBuilder(MF, MI).addReg(Reg64).addImm(40).addReg(0);255}256257// Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR258// DestReg before MBBI in MBB. Use LowLowOpcode when both DestReg and SrcReg259// are low registers, otherwise use RISB[LH]G. Size is the number of bits260// taken from the low end of SrcReg (8 for LLCR, 16 for LLHR and 32 for LR).261// KillSrc is true if this move is the last use of SrcReg.262MachineInstrBuilder263SystemZInstrInfo::emitGRX32Move(MachineBasicBlock &MBB,264MachineBasicBlock::iterator MBBI,265const DebugLoc &DL, unsigned DestReg,266unsigned SrcReg, unsigned LowLowOpcode,267unsigned Size, bool KillSrc,268bool UndefSrc) const {269unsigned Opcode;270bool DestIsHigh = SystemZ::isHighReg(DestReg);271bool SrcIsHigh = SystemZ::isHighReg(SrcReg);272if (DestIsHigh && SrcIsHigh)273Opcode = SystemZ::RISBHH;274else if (DestIsHigh && !SrcIsHigh)275Opcode = SystemZ::RISBHL;276else if (!DestIsHigh && SrcIsHigh)277Opcode = SystemZ::RISBLH;278else {279return BuildMI(MBB, MBBI, DL, get(LowLowOpcode), DestReg)280.addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc));281}282unsigned Rotate = (DestIsHigh != SrcIsHigh ? 32 : 0);283return BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)284.addReg(DestReg, RegState::Undef)285.addReg(SrcReg, getKillRegState(KillSrc) | getUndefRegState(UndefSrc))286.addImm(32 - Size).addImm(128 + 31).addImm(Rotate);287}288289MachineInstr *SystemZInstrInfo::commuteInstructionImpl(MachineInstr &MI,290bool NewMI,291unsigned OpIdx1,292unsigned OpIdx2) const {293auto cloneIfNew = [NewMI](MachineInstr &MI) -> MachineInstr & {294if (NewMI)295return *MI.getParent()->getParent()->CloneMachineInstr(&MI);296return MI;297};298299switch (MI.getOpcode()) {300case SystemZ::SELRMux:301case SystemZ::SELFHR:302case SystemZ::SELR:303case SystemZ::SELGR:304case SystemZ::LOCRMux:305case SystemZ::LOCFHR:306case SystemZ::LOCR:307case SystemZ::LOCGR: {308auto &WorkingMI = cloneIfNew(MI);309// Invert condition.310unsigned CCValid = WorkingMI.getOperand(3).getImm();311unsigned CCMask = WorkingMI.getOperand(4).getImm();312WorkingMI.getOperand(4).setImm(CCMask ^ CCValid);313return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,314OpIdx1, OpIdx2);315}316default:317return TargetInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);318}319}320321// If MI is a simple load or store for a frame object, return the register322// it loads or stores and set FrameIndex to the index of the frame object.323// Return 0 otherwise.324//325// Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.326static int isSimpleMove(const MachineInstr &MI, int &FrameIndex,327unsigned Flag) {328const MCInstrDesc &MCID = MI.getDesc();329if ((MCID.TSFlags & Flag) && MI.getOperand(1).isFI() &&330MI.getOperand(2).getImm() == 0 && MI.getOperand(3).getReg() == 0) {331FrameIndex = MI.getOperand(1).getIndex();332return MI.getOperand(0).getReg();333}334return 0;335}336337Register SystemZInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,338int &FrameIndex) const {339return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXLoad);340}341342Register SystemZInstrInfo::isStoreToStackSlot(const MachineInstr &MI,343int &FrameIndex) const {344return isSimpleMove(MI, FrameIndex, SystemZII::SimpleBDXStore);345}346347bool SystemZInstrInfo::isStackSlotCopy(const MachineInstr &MI,348int &DestFrameIndex,349int &SrcFrameIndex) const {350// Check for MVC 0(Length,FI1),0(FI2)351const MachineFrameInfo &MFI = MI.getParent()->getParent()->getFrameInfo();352if (MI.getOpcode() != SystemZ::MVC || !MI.getOperand(0).isFI() ||353MI.getOperand(1).getImm() != 0 || !MI.getOperand(3).isFI() ||354MI.getOperand(4).getImm() != 0)355return false;356357// Check that Length covers the full slots.358int64_t Length = MI.getOperand(2).getImm();359unsigned FI1 = MI.getOperand(0).getIndex();360unsigned FI2 = MI.getOperand(3).getIndex();361if (MFI.getObjectSize(FI1) != Length ||362MFI.getObjectSize(FI2) != Length)363return false;364365DestFrameIndex = FI1;366SrcFrameIndex = FI2;367return true;368}369370bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB,371MachineBasicBlock *&TBB,372MachineBasicBlock *&FBB,373SmallVectorImpl<MachineOperand> &Cond,374bool AllowModify) const {375// Most of the code and comments here are boilerplate.376377// Start from the bottom of the block and work up, examining the378// terminator instructions.379MachineBasicBlock::iterator I = MBB.end();380while (I != MBB.begin()) {381--I;382if (I->isDebugInstr())383continue;384385// Working from the bottom, when we see a non-terminator instruction, we're386// done.387if (!isUnpredicatedTerminator(*I))388break;389390// A terminator that isn't a branch can't easily be handled by this391// analysis.392if (!I->isBranch())393return true;394395// Can't handle indirect branches.396SystemZII::Branch Branch(getBranchInfo(*I));397if (!Branch.hasMBBTarget())398return true;399400// Punt on compound branches.401if (Branch.Type != SystemZII::BranchNormal)402return true;403404if (Branch.CCMask == SystemZ::CCMASK_ANY) {405// Handle unconditional branches.406if (!AllowModify) {407TBB = Branch.getMBBTarget();408continue;409}410411// If the block has any instructions after a JMP, delete them.412MBB.erase(std::next(I), MBB.end());413414Cond.clear();415FBB = nullptr;416417// Delete the JMP if it's equivalent to a fall-through.418if (MBB.isLayoutSuccessor(Branch.getMBBTarget())) {419TBB = nullptr;420I->eraseFromParent();421I = MBB.end();422continue;423}424425// TBB is used to indicate the unconditinal destination.426TBB = Branch.getMBBTarget();427continue;428}429430// Working from the bottom, handle the first conditional branch.431if (Cond.empty()) {432// FIXME: add X86-style branch swap433FBB = TBB;434TBB = Branch.getMBBTarget();435Cond.push_back(MachineOperand::CreateImm(Branch.CCValid));436Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));437continue;438}439440// Handle subsequent conditional branches.441assert(Cond.size() == 2 && TBB && "Should have seen a conditional branch");442443// Only handle the case where all conditional branches branch to the same444// destination.445if (TBB != Branch.getMBBTarget())446return true;447448// If the conditions are the same, we can leave them alone.449unsigned OldCCValid = Cond[0].getImm();450unsigned OldCCMask = Cond[1].getImm();451if (OldCCValid == Branch.CCValid && OldCCMask == Branch.CCMask)452continue;453454// FIXME: Try combining conditions like X86 does. Should be easy on Z!455return false;456}457458return false;459}460461unsigned SystemZInstrInfo::removeBranch(MachineBasicBlock &MBB,462int *BytesRemoved) const {463assert(!BytesRemoved && "code size not handled");464465// Most of the code and comments here are boilerplate.466MachineBasicBlock::iterator I = MBB.end();467unsigned Count = 0;468469while (I != MBB.begin()) {470--I;471if (I->isDebugInstr())472continue;473if (!I->isBranch())474break;475if (!getBranchInfo(*I).hasMBBTarget())476break;477// Remove the branch.478I->eraseFromParent();479I = MBB.end();480++Count;481}482483return Count;484}485486bool SystemZInstrInfo::487reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {488assert(Cond.size() == 2 && "Invalid condition");489Cond[1].setImm(Cond[1].getImm() ^ Cond[0].getImm());490return false;491}492493unsigned SystemZInstrInfo::insertBranch(MachineBasicBlock &MBB,494MachineBasicBlock *TBB,495MachineBasicBlock *FBB,496ArrayRef<MachineOperand> Cond,497const DebugLoc &DL,498int *BytesAdded) const {499// In this function we output 32-bit branches, which should always500// have enough range. They can be shortened and relaxed by later code501// in the pipeline, if desired.502503// Shouldn't be a fall through.504assert(TBB && "insertBranch must not be told to insert a fallthrough");505assert((Cond.size() == 2 || Cond.size() == 0) &&506"SystemZ branch conditions have one component!");507assert(!BytesAdded && "code size not handled");508509if (Cond.empty()) {510// Unconditional branch?511assert(!FBB && "Unconditional branch with multiple successors!");512BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(TBB);513return 1;514}515516// Conditional branch.517unsigned Count = 0;518unsigned CCValid = Cond[0].getImm();519unsigned CCMask = Cond[1].getImm();520BuildMI(&MBB, DL, get(SystemZ::BRC))521.addImm(CCValid).addImm(CCMask).addMBB(TBB);522++Count;523524if (FBB) {525// Two-way Conditional branch. Insert the second branch.526BuildMI(&MBB, DL, get(SystemZ::J)).addMBB(FBB);527++Count;528}529return Count;530}531532bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,533Register &SrcReg2, int64_t &Mask,534int64_t &Value) const {535assert(MI.isCompare() && "Caller should have checked for a comparison");536537if (MI.getNumExplicitOperands() == 2 && MI.getOperand(0).isReg() &&538MI.getOperand(1).isImm()) {539SrcReg = MI.getOperand(0).getReg();540SrcReg2 = 0;541Value = MI.getOperand(1).getImm();542Mask = ~0;543return true;544}545546return false;547}548549bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,550ArrayRef<MachineOperand> Pred,551Register DstReg, Register TrueReg,552Register FalseReg, int &CondCycles,553int &TrueCycles,554int &FalseCycles) const {555// Not all subtargets have LOCR instructions.556if (!STI.hasLoadStoreOnCond())557return false;558if (Pred.size() != 2)559return false;560561// Check register classes.562const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();563const TargetRegisterClass *RC =564RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));565if (!RC)566return false;567568// We have LOCR instructions for 32 and 64 bit general purpose registers.569if ((STI.hasLoadStoreOnCond2() &&570SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) ||571SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||572SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {573CondCycles = 2;574TrueCycles = 2;575FalseCycles = 2;576return true;577}578579// Can't do anything else.580return false;581}582583void SystemZInstrInfo::insertSelect(MachineBasicBlock &MBB,584MachineBasicBlock::iterator I,585const DebugLoc &DL, Register DstReg,586ArrayRef<MachineOperand> Pred,587Register TrueReg,588Register FalseReg) const {589MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();590const TargetRegisterClass *RC = MRI.getRegClass(DstReg);591592assert(Pred.size() == 2 && "Invalid condition");593unsigned CCValid = Pred[0].getImm();594unsigned CCMask = Pred[1].getImm();595596unsigned Opc;597if (SystemZ::GRX32BitRegClass.hasSubClassEq(RC)) {598if (STI.hasMiscellaneousExtensions3())599Opc = SystemZ::SELRMux;600else if (STI.hasLoadStoreOnCond2())601Opc = SystemZ::LOCRMux;602else {603Opc = SystemZ::LOCR;604MRI.constrainRegClass(DstReg, &SystemZ::GR32BitRegClass);605Register TReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);606Register FReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);607BuildMI(MBB, I, DL, get(TargetOpcode::COPY), TReg).addReg(TrueReg);608BuildMI(MBB, I, DL, get(TargetOpcode::COPY), FReg).addReg(FalseReg);609TrueReg = TReg;610FalseReg = FReg;611}612} else if (SystemZ::GR64BitRegClass.hasSubClassEq(RC)) {613if (STI.hasMiscellaneousExtensions3())614Opc = SystemZ::SELGR;615else616Opc = SystemZ::LOCGR;617} else618llvm_unreachable("Invalid register class");619620BuildMI(MBB, I, DL, get(Opc), DstReg)621.addReg(FalseReg).addReg(TrueReg)622.addImm(CCValid).addImm(CCMask);623}624625MachineInstr *SystemZInstrInfo::optimizeLoadInstr(MachineInstr &MI,626const MachineRegisterInfo *MRI,627Register &FoldAsLoadDefReg,628MachineInstr *&DefMI) const {629// Check whether we can move the DefMI load, and that it only has one use.630DefMI = MRI->getVRegDef(FoldAsLoadDefReg);631assert(DefMI);632bool SawStore = false;633if (!DefMI->isSafeToMove(nullptr, SawStore) ||634!MRI->hasOneNonDBGUse(FoldAsLoadDefReg))635return nullptr;636637int UseOpIdx =638MI.findRegisterUseOperandIdx(FoldAsLoadDefReg, /*TRI=*/nullptr);639assert(UseOpIdx != -1 && "Expected FoldAsLoadDefReg to be used by MI.");640641// Check whether we can fold the load.642if (MachineInstr *FoldMI =643foldMemoryOperand(MI, {((unsigned)UseOpIdx)}, *DefMI)) {644FoldAsLoadDefReg = 0;645return FoldMI;646}647648return nullptr;649}650651bool SystemZInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,652Register Reg,653MachineRegisterInfo *MRI) const {654unsigned DefOpc = DefMI.getOpcode();655656if (DefOpc == SystemZ::VGBM) {657int64_t ImmVal = DefMI.getOperand(1).getImm();658if (ImmVal != 0) // TODO: Handle other values659return false;660661// Fold gr128 = COPY (vr128 VGBM imm)662//663// %tmp:gr64 = LGHI 0664// to gr128 = REG_SEQUENCE %tmp, %tmp665assert(DefMI.getOperand(0).getReg() == Reg);666667if (!UseMI.isCopy())668return false;669670Register CopyDstReg = UseMI.getOperand(0).getReg();671if (CopyDstReg.isVirtual() &&672MRI->getRegClass(CopyDstReg) == &SystemZ::GR128BitRegClass &&673MRI->hasOneNonDBGUse(Reg)) {674// TODO: Handle physical registers675// TODO: Handle gr64 uses with subregister indexes676// TODO: Should this multi-use cases?677Register TmpReg = MRI->createVirtualRegister(&SystemZ::GR64BitRegClass);678MachineBasicBlock &MBB = *UseMI.getParent();679680loadImmediate(MBB, UseMI.getIterator(), TmpReg, ImmVal);681682UseMI.setDesc(get(SystemZ::REG_SEQUENCE));683UseMI.getOperand(1).setReg(TmpReg);684MachineInstrBuilder(*MBB.getParent(), &UseMI)685.addImm(SystemZ::subreg_h64)686.addReg(TmpReg)687.addImm(SystemZ::subreg_l64);688689if (MRI->use_nodbg_empty(Reg))690DefMI.eraseFromParent();691return true;692}693694return false;695}696697if (DefOpc != SystemZ::LHIMux && DefOpc != SystemZ::LHI &&698DefOpc != SystemZ::LGHI)699return false;700if (DefMI.getOperand(0).getReg() != Reg)701return false;702int32_t ImmVal = (int32_t)DefMI.getOperand(1).getImm();703704unsigned UseOpc = UseMI.getOpcode();705unsigned NewUseOpc;706unsigned UseIdx;707int CommuteIdx = -1;708bool TieOps = false;709switch (UseOpc) {710case SystemZ::SELRMux:711TieOps = true;712[[fallthrough]];713case SystemZ::LOCRMux:714if (!STI.hasLoadStoreOnCond2())715return false;716NewUseOpc = SystemZ::LOCHIMux;717if (UseMI.getOperand(2).getReg() == Reg)718UseIdx = 2;719else if (UseMI.getOperand(1).getReg() == Reg)720UseIdx = 2, CommuteIdx = 1;721else722return false;723break;724case SystemZ::SELGR:725TieOps = true;726[[fallthrough]];727case SystemZ::LOCGR:728if (!STI.hasLoadStoreOnCond2())729return false;730NewUseOpc = SystemZ::LOCGHI;731if (UseMI.getOperand(2).getReg() == Reg)732UseIdx = 2;733else if (UseMI.getOperand(1).getReg() == Reg)734UseIdx = 2, CommuteIdx = 1;735else736return false;737break;738default:739return false;740}741742if (CommuteIdx != -1)743if (!commuteInstruction(UseMI, false, CommuteIdx, UseIdx))744return false;745746bool DeleteDef = MRI->hasOneNonDBGUse(Reg);747UseMI.setDesc(get(NewUseOpc));748if (TieOps)749UseMI.tieOperands(0, 1);750UseMI.getOperand(UseIdx).ChangeToImmediate(ImmVal);751if (DeleteDef)752DefMI.eraseFromParent();753754return true;755}756757bool SystemZInstrInfo::isPredicable(const MachineInstr &MI) const {758unsigned Opcode = MI.getOpcode();759if (Opcode == SystemZ::Return ||760Opcode == SystemZ::Return_XPLINK ||761Opcode == SystemZ::Trap ||762Opcode == SystemZ::CallJG ||763Opcode == SystemZ::CallBR)764return true;765return false;766}767768bool SystemZInstrInfo::769isProfitableToIfCvt(MachineBasicBlock &MBB,770unsigned NumCycles, unsigned ExtraPredCycles,771BranchProbability Probability) const {772// Avoid using conditional returns at the end of a loop (since then773// we'd need to emit an unconditional branch to the beginning anyway,774// making the loop body longer). This doesn't apply for low-probability775// loops (eg. compare-and-swap retry), so just decide based on branch776// probability instead of looping structure.777// However, since Compare and Trap instructions cost the same as a regular778// Compare instruction, we should allow the if conversion to convert this779// into a Conditional Compare regardless of the branch probability.780if (MBB.getLastNonDebugInstr()->getOpcode() != SystemZ::Trap &&781MBB.succ_empty() && Probability < BranchProbability(1, 8))782return false;783// For now only convert single instructions.784return NumCycles == 1;785}786787bool SystemZInstrInfo::788isProfitableToIfCvt(MachineBasicBlock &TMBB,789unsigned NumCyclesT, unsigned ExtraPredCyclesT,790MachineBasicBlock &FMBB,791unsigned NumCyclesF, unsigned ExtraPredCyclesF,792BranchProbability Probability) const {793// For now avoid converting mutually-exclusive cases.794return false;795}796797bool SystemZInstrInfo::798isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,799BranchProbability Probability) const {800// For now only duplicate single instructions.801return NumCycles == 1;802}803804bool SystemZInstrInfo::PredicateInstruction(805MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {806assert(Pred.size() == 2 && "Invalid condition");807unsigned CCValid = Pred[0].getImm();808unsigned CCMask = Pred[1].getImm();809assert(CCMask > 0 && CCMask < 15 && "Invalid predicate");810unsigned Opcode = MI.getOpcode();811if (Opcode == SystemZ::Trap) {812MI.setDesc(get(SystemZ::CondTrap));813MachineInstrBuilder(*MI.getParent()->getParent(), MI)814.addImm(CCValid).addImm(CCMask)815.addReg(SystemZ::CC, RegState::Implicit);816return true;817}818if (Opcode == SystemZ::Return || Opcode == SystemZ::Return_XPLINK) {819MI.setDesc(get(Opcode == SystemZ::Return ? SystemZ::CondReturn820: SystemZ::CondReturn_XPLINK));821MachineInstrBuilder(*MI.getParent()->getParent(), MI)822.addImm(CCValid)823.addImm(CCMask)824.addReg(SystemZ::CC, RegState::Implicit);825return true;826}827if (Opcode == SystemZ::CallJG) {828MachineOperand FirstOp = MI.getOperand(0);829const uint32_t *RegMask = MI.getOperand(1).getRegMask();830MI.removeOperand(1);831MI.removeOperand(0);832MI.setDesc(get(SystemZ::CallBRCL));833MachineInstrBuilder(*MI.getParent()->getParent(), MI)834.addImm(CCValid)835.addImm(CCMask)836.add(FirstOp)837.addRegMask(RegMask)838.addReg(SystemZ::CC, RegState::Implicit);839return true;840}841if (Opcode == SystemZ::CallBR) {842MachineOperand Target = MI.getOperand(0);843const uint32_t *RegMask = MI.getOperand(1).getRegMask();844MI.removeOperand(1);845MI.removeOperand(0);846MI.setDesc(get(SystemZ::CallBCR));847MachineInstrBuilder(*MI.getParent()->getParent(), MI)848.addImm(CCValid).addImm(CCMask)849.add(Target)850.addRegMask(RegMask)851.addReg(SystemZ::CC, RegState::Implicit);852return true;853}854return false;855}856857void SystemZInstrInfo::copyPhysReg(MachineBasicBlock &MBB,858MachineBasicBlock::iterator MBBI,859const DebugLoc &DL, MCRegister DestReg,860MCRegister SrcReg, bool KillSrc) const {861// Split 128-bit GPR moves into two 64-bit moves. Add implicit uses of the862// super register in case one of the subregs is undefined.863// This handles ADDR128 too.864if (SystemZ::GR128BitRegClass.contains(DestReg, SrcReg)) {865copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_h64),866RI.getSubReg(SrcReg, SystemZ::subreg_h64), KillSrc);867MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))868.addReg(SrcReg, RegState::Implicit);869copyPhysReg(MBB, MBBI, DL, RI.getSubReg(DestReg, SystemZ::subreg_l64),870RI.getSubReg(SrcReg, SystemZ::subreg_l64), KillSrc);871MachineInstrBuilder(*MBB.getParent(), std::prev(MBBI))872.addReg(SrcReg, (getKillRegState(KillSrc) | RegState::Implicit));873return;874}875876if (SystemZ::GRX32BitRegClass.contains(DestReg, SrcReg)) {877emitGRX32Move(MBB, MBBI, DL, DestReg, SrcReg, SystemZ::LR, 32, KillSrc,878false);879return;880}881882// Move 128-bit floating-point values between VR128 and FP128.883if (SystemZ::VR128BitRegClass.contains(DestReg) &&884SystemZ::FP128BitRegClass.contains(SrcReg)) {885MCRegister SrcRegHi =886RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64),887SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);888MCRegister SrcRegLo =889RI.getMatchingSuperReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64),890SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);891892BuildMI(MBB, MBBI, DL, get(SystemZ::VMRHG), DestReg)893.addReg(SrcRegHi, getKillRegState(KillSrc))894.addReg(SrcRegLo, getKillRegState(KillSrc));895return;896}897if (SystemZ::FP128BitRegClass.contains(DestReg) &&898SystemZ::VR128BitRegClass.contains(SrcReg)) {899MCRegister DestRegHi =900RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_h64),901SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);902MCRegister DestRegLo =903RI.getMatchingSuperReg(RI.getSubReg(DestReg, SystemZ::subreg_l64),904SystemZ::subreg_h64, &SystemZ::VR128BitRegClass);905906if (DestRegHi != SrcReg)907copyPhysReg(MBB, MBBI, DL, DestRegHi, SrcReg, false);908BuildMI(MBB, MBBI, DL, get(SystemZ::VREPG), DestRegLo)909.addReg(SrcReg, getKillRegState(KillSrc)).addImm(1);910return;911}912913if (SystemZ::FP128BitRegClass.contains(DestReg) &&914SystemZ::GR128BitRegClass.contains(SrcReg)) {915MCRegister DestRegHi = RI.getSubReg(DestReg, SystemZ::subreg_h64);916MCRegister DestRegLo = RI.getSubReg(DestReg, SystemZ::subreg_l64);917MCRegister SrcRegHi = RI.getSubReg(SrcReg, SystemZ::subreg_h64);918MCRegister SrcRegLo = RI.getSubReg(SrcReg, SystemZ::subreg_l64);919920BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegHi)921.addReg(SrcRegHi)922.addReg(DestReg, RegState::ImplicitDefine);923924BuildMI(MBB, MBBI, DL, get(SystemZ::LDGR), DestRegLo)925.addReg(SrcRegLo, getKillRegState(KillSrc));926return;927}928929// Move CC value from a GR32.930if (DestReg == SystemZ::CC) {931unsigned Opcode =932SystemZ::GR32BitRegClass.contains(SrcReg) ? SystemZ::TMLH : SystemZ::TMHH;933BuildMI(MBB, MBBI, DL, get(Opcode))934.addReg(SrcReg, getKillRegState(KillSrc))935.addImm(3 << (SystemZ::IPM_CC - 16));936return;937}938939if (SystemZ::GR128BitRegClass.contains(DestReg) &&940SystemZ::VR128BitRegClass.contains(SrcReg)) {941MCRegister DestH64 = RI.getSubReg(DestReg, SystemZ::subreg_h64);942MCRegister DestL64 = RI.getSubReg(DestReg, SystemZ::subreg_l64);943944BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestH64)945.addReg(SrcReg)946.addReg(SystemZ::NoRegister)947.addImm(0)948.addDef(DestReg, RegState::Implicit);949BuildMI(MBB, MBBI, DL, get(SystemZ::VLGVG), DestL64)950.addReg(SrcReg, getKillRegState(KillSrc))951.addReg(SystemZ::NoRegister)952.addImm(1);953return;954}955956if (SystemZ::VR128BitRegClass.contains(DestReg) &&957SystemZ::GR128BitRegClass.contains(SrcReg)) {958BuildMI(MBB, MBBI, DL, get(SystemZ::VLVGP), DestReg)959.addReg(RI.getSubReg(SrcReg, SystemZ::subreg_h64))960.addReg(RI.getSubReg(SrcReg, SystemZ::subreg_l64));961return;962}963964// Everything else needs only one instruction.965unsigned Opcode;966if (SystemZ::GR64BitRegClass.contains(DestReg, SrcReg))967Opcode = SystemZ::LGR;968else if (SystemZ::FP32BitRegClass.contains(DestReg, SrcReg))969// For z13 we prefer LDR over LER to avoid partial register dependencies.970Opcode = STI.hasVector() ? SystemZ::LDR32 : SystemZ::LER;971else if (SystemZ::FP64BitRegClass.contains(DestReg, SrcReg))972Opcode = SystemZ::LDR;973else if (SystemZ::FP128BitRegClass.contains(DestReg, SrcReg))974Opcode = SystemZ::LXR;975else if (SystemZ::VR32BitRegClass.contains(DestReg, SrcReg))976Opcode = SystemZ::VLR32;977else if (SystemZ::VR64BitRegClass.contains(DestReg, SrcReg))978Opcode = SystemZ::VLR64;979else if (SystemZ::VR128BitRegClass.contains(DestReg, SrcReg))980Opcode = SystemZ::VLR;981else if (SystemZ::AR32BitRegClass.contains(DestReg, SrcReg))982Opcode = SystemZ::CPYA;983else984llvm_unreachable("Impossible reg-to-reg copy");985986BuildMI(MBB, MBBI, DL, get(Opcode), DestReg)987.addReg(SrcReg, getKillRegState(KillSrc));988}989990void SystemZInstrInfo::storeRegToStackSlot(991MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,992bool isKill, int FrameIdx, const TargetRegisterClass *RC,993const TargetRegisterInfo *TRI, Register VReg) const {994DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();995996// Callers may expect a single instruction, so keep 128-bit moves997// together for now and lower them after register allocation.998unsigned LoadOpcode, StoreOpcode;999getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);1000addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))1001.addReg(SrcReg, getKillRegState(isKill)),1002FrameIdx);1003}10041005void SystemZInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,1006MachineBasicBlock::iterator MBBI,1007Register DestReg, int FrameIdx,1008const TargetRegisterClass *RC,1009const TargetRegisterInfo *TRI,1010Register VReg) const {1011DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();10121013// Callers may expect a single instruction, so keep 128-bit moves1014// together for now and lower them after register allocation.1015unsigned LoadOpcode, StoreOpcode;1016getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode);1017addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg),1018FrameIdx);1019}10201021// Return true if MI is a simple load or store with a 12-bit displacement1022// and no index. Flag is SimpleBDXLoad for loads and SimpleBDXStore for stores.1023static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) {1024const MCInstrDesc &MCID = MI->getDesc();1025return ((MCID.TSFlags & Flag) &&1026isUInt<12>(MI->getOperand(2).getImm()) &&1027MI->getOperand(3).getReg() == 0);1028}10291030namespace {10311032struct LogicOp {1033LogicOp() = default;1034LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize)1035: RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {}10361037explicit operator bool() const { return RegSize; }10381039unsigned RegSize = 0;1040unsigned ImmLSB = 0;1041unsigned ImmSize = 0;1042};10431044} // end anonymous namespace10451046static LogicOp interpretAndImmediate(unsigned Opcode) {1047switch (Opcode) {1048case SystemZ::NILMux: return LogicOp(32, 0, 16);1049case SystemZ::NIHMux: return LogicOp(32, 16, 16);1050case SystemZ::NILL64: return LogicOp(64, 0, 16);1051case SystemZ::NILH64: return LogicOp(64, 16, 16);1052case SystemZ::NIHL64: return LogicOp(64, 32, 16);1053case SystemZ::NIHH64: return LogicOp(64, 48, 16);1054case SystemZ::NIFMux: return LogicOp(32, 0, 32);1055case SystemZ::NILF64: return LogicOp(64, 0, 32);1056case SystemZ::NIHF64: return LogicOp(64, 32, 32);1057default: return LogicOp();1058}1059}10601061static void transferDeadCC(MachineInstr *OldMI, MachineInstr *NewMI) {1062if (OldMI->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr)) {1063MachineOperand *CCDef =1064NewMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr);1065if (CCDef != nullptr)1066CCDef->setIsDead(true);1067}1068}10691070static void transferMIFlag(MachineInstr *OldMI, MachineInstr *NewMI,1071MachineInstr::MIFlag Flag) {1072if (OldMI->getFlag(Flag))1073NewMI->setFlag(Flag);1074}10751076MachineInstr *1077SystemZInstrInfo::convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,1078LiveIntervals *LIS) const {1079MachineBasicBlock *MBB = MI.getParent();10801081// Try to convert an AND into an RISBG-type instruction.1082// TODO: It might be beneficial to select RISBG and shorten to AND instead.1083if (LogicOp And = interpretAndImmediate(MI.getOpcode())) {1084uint64_t Imm = MI.getOperand(2).getImm() << And.ImmLSB;1085// AND IMMEDIATE leaves the other bits of the register unchanged.1086Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB);1087unsigned Start, End;1088if (isRxSBGMask(Imm, And.RegSize, Start, End)) {1089unsigned NewOpcode;1090if (And.RegSize == 64) {1091NewOpcode = SystemZ::RISBG;1092// Prefer RISBGN if available, since it does not clobber CC.1093if (STI.hasMiscellaneousExtensions())1094NewOpcode = SystemZ::RISBGN;1095} else {1096NewOpcode = SystemZ::RISBMux;1097Start &= 31;1098End &= 31;1099}1100MachineOperand &Dest = MI.getOperand(0);1101MachineOperand &Src = MI.getOperand(1);1102MachineInstrBuilder MIB =1103BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpcode))1104.add(Dest)1105.addReg(0)1106.addReg(Src.getReg(), getKillRegState(Src.isKill()),1107Src.getSubReg())1108.addImm(Start)1109.addImm(End + 128)1110.addImm(0);1111if (LV) {1112unsigned NumOps = MI.getNumOperands();1113for (unsigned I = 1; I < NumOps; ++I) {1114MachineOperand &Op = MI.getOperand(I);1115if (Op.isReg() && Op.isKill())1116LV->replaceKillInstruction(Op.getReg(), MI, *MIB);1117}1118}1119if (LIS)1120LIS->ReplaceMachineInstrInMaps(MI, *MIB);1121transferDeadCC(&MI, MIB);1122return MIB;1123}1124}1125return nullptr;1126}11271128bool SystemZInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,1129bool Invert) const {1130unsigned Opc = Inst.getOpcode();1131if (Invert) {1132auto InverseOpcode = getInverseOpcode(Opc);1133if (!InverseOpcode)1134return false;1135Opc = *InverseOpcode;1136}11371138switch (Opc) {1139default:1140break;1141// Adds and multiplications.1142case SystemZ::WFADB:1143case SystemZ::WFASB:1144case SystemZ::WFAXB:1145case SystemZ::VFADB:1146case SystemZ::VFASB:1147case SystemZ::WFMDB:1148case SystemZ::WFMSB:1149case SystemZ::WFMXB:1150case SystemZ::VFMDB:1151case SystemZ::VFMSB:1152return (Inst.getFlag(MachineInstr::MIFlag::FmReassoc) &&1153Inst.getFlag(MachineInstr::MIFlag::FmNsz));1154}11551156return false;1157}11581159std::optional<unsigned>1160SystemZInstrInfo::getInverseOpcode(unsigned Opcode) const {1161// fadd => fsub1162switch (Opcode) {1163case SystemZ::WFADB:1164return SystemZ::WFSDB;1165case SystemZ::WFASB:1166return SystemZ::WFSSB;1167case SystemZ::WFAXB:1168return SystemZ::WFSXB;1169case SystemZ::VFADB:1170return SystemZ::VFSDB;1171case SystemZ::VFASB:1172return SystemZ::VFSSB;1173// fsub => fadd1174case SystemZ::WFSDB:1175return SystemZ::WFADB;1176case SystemZ::WFSSB:1177return SystemZ::WFASB;1178case SystemZ::WFSXB:1179return SystemZ::WFAXB;1180case SystemZ::VFSDB:1181return SystemZ::VFADB;1182case SystemZ::VFSSB:1183return SystemZ::VFASB;1184default:1185return std::nullopt;1186}1187}11881189MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(1190MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,1191MachineBasicBlock::iterator InsertPt, int FrameIndex,1192LiveIntervals *LIS, VirtRegMap *VRM) const {1193const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();1194MachineRegisterInfo &MRI = MF.getRegInfo();1195const MachineFrameInfo &MFI = MF.getFrameInfo();1196unsigned Size = MFI.getObjectSize(FrameIndex);1197unsigned Opcode = MI.getOpcode();11981199// Check CC liveness if new instruction introduces a dead def of CC.1200SlotIndex MISlot = SlotIndex();1201LiveRange *CCLiveRange = nullptr;1202bool CCLiveAtMI = true;1203if (LIS) {1204MISlot = LIS->getSlotIndexes()->getInstructionIndex(MI).getRegSlot();1205auto CCUnits = TRI->regunits(MCRegister::from(SystemZ::CC));1206assert(range_size(CCUnits) == 1 && "CC only has one reg unit.");1207CCLiveRange = &LIS->getRegUnit(*CCUnits.begin());1208CCLiveAtMI = CCLiveRange->liveAt(MISlot);1209}12101211if (Ops.size() == 2 && Ops[0] == 0 && Ops[1] == 1) {1212if (!CCLiveAtMI && (Opcode == SystemZ::LA || Opcode == SystemZ::LAY) &&1213isInt<8>(MI.getOperand(2).getImm()) && !MI.getOperand(3).getReg()) {1214// LA(Y) %reg, CONST(%reg) -> AGSI %mem, CONST1215MachineInstr *BuiltMI = BuildMI(*InsertPt->getParent(), InsertPt,1216MI.getDebugLoc(), get(SystemZ::AGSI))1217.addFrameIndex(FrameIndex)1218.addImm(0)1219.addImm(MI.getOperand(2).getImm());1220BuiltMI->findRegisterDefOperand(SystemZ::CC, /*TRI=*/nullptr)1221->setIsDead(true);1222CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());1223return BuiltMI;1224}1225return nullptr;1226}12271228// All other cases require a single operand.1229if (Ops.size() != 1)1230return nullptr;12311232unsigned OpNum = Ops[0];1233assert(Size * 8 ==1234TRI->getRegSizeInBits(*MF.getRegInfo()1235.getRegClass(MI.getOperand(OpNum).getReg())) &&1236"Invalid size combination");12371238if ((Opcode == SystemZ::AHI || Opcode == SystemZ::AGHI) && OpNum == 0 &&1239isInt<8>(MI.getOperand(2).getImm())) {1240// A(G)HI %reg, CONST -> A(G)SI %mem, CONST1241Opcode = (Opcode == SystemZ::AHI ? SystemZ::ASI : SystemZ::AGSI);1242MachineInstr *BuiltMI =1243BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))1244.addFrameIndex(FrameIndex)1245.addImm(0)1246.addImm(MI.getOperand(2).getImm());1247transferDeadCC(&MI, BuiltMI);1248transferMIFlag(&MI, BuiltMI, MachineInstr::NoSWrap);1249return BuiltMI;1250}12511252if ((Opcode == SystemZ::ALFI && OpNum == 0 &&1253isInt<8>((int32_t)MI.getOperand(2).getImm())) ||1254(Opcode == SystemZ::ALGFI && OpNum == 0 &&1255isInt<8>((int64_t)MI.getOperand(2).getImm()))) {1256// AL(G)FI %reg, CONST -> AL(G)SI %mem, CONST1257Opcode = (Opcode == SystemZ::ALFI ? SystemZ::ALSI : SystemZ::ALGSI);1258MachineInstr *BuiltMI =1259BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))1260.addFrameIndex(FrameIndex)1261.addImm(0)1262.addImm((int8_t)MI.getOperand(2).getImm());1263transferDeadCC(&MI, BuiltMI);1264return BuiltMI;1265}12661267if ((Opcode == SystemZ::SLFI && OpNum == 0 &&1268isInt<8>((int32_t)-MI.getOperand(2).getImm())) ||1269(Opcode == SystemZ::SLGFI && OpNum == 0 &&1270isInt<8>((int64_t)-MI.getOperand(2).getImm()))) {1271// SL(G)FI %reg, CONST -> AL(G)SI %mem, -CONST1272Opcode = (Opcode == SystemZ::SLFI ? SystemZ::ALSI : SystemZ::ALGSI);1273MachineInstr *BuiltMI =1274BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(), get(Opcode))1275.addFrameIndex(FrameIndex)1276.addImm(0)1277.addImm((int8_t)-MI.getOperand(2).getImm());1278transferDeadCC(&MI, BuiltMI);1279return BuiltMI;1280}12811282unsigned MemImmOpc = 0;1283switch (Opcode) {1284case SystemZ::LHIMux:1285case SystemZ::LHI: MemImmOpc = SystemZ::MVHI; break;1286case SystemZ::LGHI: MemImmOpc = SystemZ::MVGHI; break;1287case SystemZ::CHIMux:1288case SystemZ::CHI: MemImmOpc = SystemZ::CHSI; break;1289case SystemZ::CGHI: MemImmOpc = SystemZ::CGHSI; break;1290case SystemZ::CLFIMux:1291case SystemZ::CLFI:1292if (isUInt<16>(MI.getOperand(1).getImm()))1293MemImmOpc = SystemZ::CLFHSI;1294break;1295case SystemZ::CLGFI:1296if (isUInt<16>(MI.getOperand(1).getImm()))1297MemImmOpc = SystemZ::CLGHSI;1298break;1299default: break;1300}1301if (MemImmOpc)1302return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),1303get(MemImmOpc))1304.addFrameIndex(FrameIndex)1305.addImm(0)1306.addImm(MI.getOperand(1).getImm());13071308if (Opcode == SystemZ::LGDR || Opcode == SystemZ::LDGR) {1309bool Op0IsGPR = (Opcode == SystemZ::LGDR);1310bool Op1IsGPR = (Opcode == SystemZ::LDGR);1311// If we're spilling the destination of an LDGR or LGDR, store the1312// source register instead.1313if (OpNum == 0) {1314unsigned StoreOpcode = Op1IsGPR ? SystemZ::STG : SystemZ::STD;1315return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),1316get(StoreOpcode))1317.add(MI.getOperand(1))1318.addFrameIndex(FrameIndex)1319.addImm(0)1320.addReg(0);1321}1322// If we're spilling the source of an LDGR or LGDR, load the1323// destination register instead.1324if (OpNum == 1) {1325unsigned LoadOpcode = Op0IsGPR ? SystemZ::LG : SystemZ::LD;1326return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),1327get(LoadOpcode))1328.add(MI.getOperand(0))1329.addFrameIndex(FrameIndex)1330.addImm(0)1331.addReg(0);1332}1333}13341335// Look for cases where the source of a simple store or the destination1336// of a simple load is being spilled. Try to use MVC instead.1337//1338// Although MVC is in practice a fast choice in these cases, it is still1339// logically a bytewise copy. This means that we cannot use it if the1340// load or store is volatile. We also wouldn't be able to use MVC if1341// the two memories partially overlap, but that case cannot occur here,1342// because we know that one of the memories is a full frame index.1343//1344// For performance reasons, we also want to avoid using MVC if the addresses1345// might be equal. We don't worry about that case here, because spill slot1346// coloring happens later, and because we have special code to remove1347// MVCs that turn out to be redundant.1348if (OpNum == 0 && MI.hasOneMemOperand()) {1349MachineMemOperand *MMO = *MI.memoperands_begin();1350if (MMO->getSize() == Size && !MMO->isVolatile() && !MMO->isAtomic()) {1351// Handle conversion of loads.1352if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXLoad)) {1353return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),1354get(SystemZ::MVC))1355.addFrameIndex(FrameIndex)1356.addImm(0)1357.addImm(Size)1358.add(MI.getOperand(1))1359.addImm(MI.getOperand(2).getImm())1360.addMemOperand(MMO);1361}1362// Handle conversion of stores.1363if (isSimpleBD12Move(&MI, SystemZII::SimpleBDXStore)) {1364return BuildMI(*InsertPt->getParent(), InsertPt, MI.getDebugLoc(),1365get(SystemZ::MVC))1366.add(MI.getOperand(1))1367.addImm(MI.getOperand(2).getImm())1368.addImm(Size)1369.addFrameIndex(FrameIndex)1370.addImm(0)1371.addMemOperand(MMO);1372}1373}1374}13751376// If the spilled operand is the final one or the instruction is1377// commutable, try to change <INSN>R into <INSN>. Don't introduce a def of1378// CC if it is live and MI does not define it.1379unsigned NumOps = MI.getNumExplicitOperands();1380int MemOpcode = SystemZ::getMemOpcode(Opcode);1381if (MemOpcode == -1 ||1382(CCLiveAtMI && !MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&1383get(MemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)))1384return nullptr;13851386// Check if all other vregs have a usable allocation in the case of vector1387// to FP conversion.1388const MCInstrDesc &MCID = MI.getDesc();1389for (unsigned I = 0, E = MCID.getNumOperands(); I != E; ++I) {1390const MCOperandInfo &MCOI = MCID.operands()[I];1391if (MCOI.OperandType != MCOI::OPERAND_REGISTER || I == OpNum)1392continue;1393const TargetRegisterClass *RC = TRI->getRegClass(MCOI.RegClass);1394if (RC == &SystemZ::VR32BitRegClass || RC == &SystemZ::VR64BitRegClass) {1395Register Reg = MI.getOperand(I).getReg();1396Register PhysReg = Reg.isVirtual()1397? (VRM ? Register(VRM->getPhys(Reg)) : Register())1398: Reg;1399if (!PhysReg ||1400!(SystemZ::FP32BitRegClass.contains(PhysReg) ||1401SystemZ::FP64BitRegClass.contains(PhysReg) ||1402SystemZ::VF128BitRegClass.contains(PhysReg)))1403return nullptr;1404}1405}1406// Fused multiply and add/sub need to have the same dst and accumulator reg.1407bool FusedFPOp = (Opcode == SystemZ::WFMADB || Opcode == SystemZ::WFMASB ||1408Opcode == SystemZ::WFMSDB || Opcode == SystemZ::WFMSSB);1409if (FusedFPOp) {1410Register DstReg = VRM->getPhys(MI.getOperand(0).getReg());1411Register AccReg = VRM->getPhys(MI.getOperand(3).getReg());1412if (OpNum == 0 || OpNum == 3 || DstReg != AccReg)1413return nullptr;1414}14151416// Try to swap compare operands if possible.1417bool NeedsCommute = false;1418if ((MI.getOpcode() == SystemZ::CR || MI.getOpcode() == SystemZ::CGR ||1419MI.getOpcode() == SystemZ::CLR || MI.getOpcode() == SystemZ::CLGR ||1420MI.getOpcode() == SystemZ::WFCDB || MI.getOpcode() == SystemZ::WFCSB ||1421MI.getOpcode() == SystemZ::WFKDB || MI.getOpcode() == SystemZ::WFKSB) &&1422OpNum == 0 && prepareCompareSwapOperands(MI))1423NeedsCommute = true;14241425bool CCOperands = false;1426if (MI.getOpcode() == SystemZ::LOCRMux || MI.getOpcode() == SystemZ::LOCGR ||1427MI.getOpcode() == SystemZ::SELRMux || MI.getOpcode() == SystemZ::SELGR) {1428assert(MI.getNumOperands() == 6 && NumOps == 5 &&1429"LOCR/SELR instruction operands corrupt?");1430NumOps -= 2;1431CCOperands = true;1432}14331434// See if this is a 3-address instruction that is convertible to 2-address1435// and suitable for folding below. Only try this with virtual registers1436// and a provided VRM (during regalloc).1437if (NumOps == 3 && SystemZ::getTargetMemOpcode(MemOpcode) != -1) {1438if (VRM == nullptr)1439return nullptr;1440else {1441Register DstReg = MI.getOperand(0).getReg();1442Register DstPhys =1443(DstReg.isVirtual() ? Register(VRM->getPhys(DstReg)) : DstReg);1444Register SrcReg = (OpNum == 2 ? MI.getOperand(1).getReg()1445: ((OpNum == 1 && MI.isCommutable())1446? MI.getOperand(2).getReg()1447: Register()));1448if (DstPhys && !SystemZ::GRH32BitRegClass.contains(DstPhys) && SrcReg &&1449SrcReg.isVirtual() && DstPhys == VRM->getPhys(SrcReg))1450NeedsCommute = (OpNum == 1);1451else1452return nullptr;1453}1454}14551456if ((OpNum == NumOps - 1) || NeedsCommute || FusedFPOp) {1457const MCInstrDesc &MemDesc = get(MemOpcode);1458uint64_t AccessBytes = SystemZII::getAccessSize(MemDesc.TSFlags);1459assert(AccessBytes != 0 && "Size of access should be known");1460assert(AccessBytes <= Size && "Access outside the frame index");1461uint64_t Offset = Size - AccessBytes;1462MachineInstrBuilder MIB = BuildMI(*InsertPt->getParent(), InsertPt,1463MI.getDebugLoc(), get(MemOpcode));1464if (MI.isCompare()) {1465assert(NumOps == 2 && "Expected 2 register operands for a compare.");1466MIB.add(MI.getOperand(NeedsCommute ? 1 : 0));1467}1468else if (FusedFPOp) {1469MIB.add(MI.getOperand(0));1470MIB.add(MI.getOperand(3));1471MIB.add(MI.getOperand(OpNum == 1 ? 2 : 1));1472}1473else {1474MIB.add(MI.getOperand(0));1475if (NeedsCommute)1476MIB.add(MI.getOperand(2));1477else1478for (unsigned I = 1; I < OpNum; ++I)1479MIB.add(MI.getOperand(I));1480}1481MIB.addFrameIndex(FrameIndex).addImm(Offset);1482if (MemDesc.TSFlags & SystemZII::HasIndex)1483MIB.addReg(0);1484if (CCOperands) {1485unsigned CCValid = MI.getOperand(NumOps).getImm();1486unsigned CCMask = MI.getOperand(NumOps + 1).getImm();1487MIB.addImm(CCValid);1488MIB.addImm(NeedsCommute ? CCMask ^ CCValid : CCMask);1489}1490if (MIB->definesRegister(SystemZ::CC, /*TRI=*/nullptr) &&1491(!MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr) ||1492MI.registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))) {1493MIB->addRegisterDead(SystemZ::CC, TRI);1494if (CCLiveRange)1495CCLiveRange->createDeadDef(MISlot, LIS->getVNInfoAllocator());1496}1497// Constrain the register classes if converted from a vector opcode. The1498// allocated regs are in an FP reg-class per previous check above.1499for (const MachineOperand &MO : MIB->operands())1500if (MO.isReg() && MO.getReg().isVirtual()) {1501Register Reg = MO.getReg();1502if (MRI.getRegClass(Reg) == &SystemZ::VR32BitRegClass)1503MRI.setRegClass(Reg, &SystemZ::FP32BitRegClass);1504else if (MRI.getRegClass(Reg) == &SystemZ::VR64BitRegClass)1505MRI.setRegClass(Reg, &SystemZ::FP64BitRegClass);1506else if (MRI.getRegClass(Reg) == &SystemZ::VR128BitRegClass)1507MRI.setRegClass(Reg, &SystemZ::VF128BitRegClass);1508}15091510transferDeadCC(&MI, MIB);1511transferMIFlag(&MI, MIB, MachineInstr::NoSWrap);1512transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);1513return MIB;1514}15151516return nullptr;1517}15181519MachineInstr *SystemZInstrInfo::foldMemoryOperandImpl(1520MachineFunction &MF, MachineInstr &MI, ArrayRef<unsigned> Ops,1521MachineBasicBlock::iterator InsertPt, MachineInstr &LoadMI,1522LiveIntervals *LIS) const {1523MachineRegisterInfo *MRI = &MF.getRegInfo();1524MachineBasicBlock *MBB = MI.getParent();15251526// For reassociable FP operations, any loads have been purposefully left1527// unfolded so that MachineCombiner can do its work on reg/reg1528// opcodes. After that, as many loads as possible are now folded.1529// TODO: This may be beneficial with other opcodes as well as machine-sink1530// can move loads close to their user in a different MBB, which the isel1531// matcher did not see.1532unsigned LoadOpc = 0;1533unsigned RegMemOpcode = 0;1534const TargetRegisterClass *FPRC = nullptr;1535RegMemOpcode = MI.getOpcode() == SystemZ::WFADB ? SystemZ::ADB1536: MI.getOpcode() == SystemZ::WFSDB ? SystemZ::SDB1537: MI.getOpcode() == SystemZ::WFMDB ? SystemZ::MDB1538: 0;1539if (RegMemOpcode) {1540LoadOpc = SystemZ::VL64;1541FPRC = &SystemZ::FP64BitRegClass;1542} else {1543RegMemOpcode = MI.getOpcode() == SystemZ::WFASB ? SystemZ::AEB1544: MI.getOpcode() == SystemZ::WFSSB ? SystemZ::SEB1545: MI.getOpcode() == SystemZ::WFMSB ? SystemZ::MEEB1546: 0;1547if (RegMemOpcode) {1548LoadOpc = SystemZ::VL32;1549FPRC = &SystemZ::FP32BitRegClass;1550}1551}1552if (!RegMemOpcode || LoadMI.getOpcode() != LoadOpc)1553return nullptr;15541555// If RegMemOpcode clobbers CC, first make sure CC is not live at this point.1556if (get(RegMemOpcode).hasImplicitDefOfPhysReg(SystemZ::CC)) {1557assert(LoadMI.getParent() == MI.getParent() && "Assuming a local fold.");1558assert(LoadMI != InsertPt && "Assuming InsertPt not to be first in MBB.");1559for (MachineBasicBlock::iterator MII = std::prev(InsertPt);;1560--MII) {1561if (MII->definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {1562if (!MII->registerDefIsDead(SystemZ::CC, /*TRI=*/nullptr))1563return nullptr;1564break;1565}1566if (MII == MBB->begin()) {1567if (MBB->isLiveIn(SystemZ::CC))1568return nullptr;1569break;1570}1571}1572}15731574Register FoldAsLoadDefReg = LoadMI.getOperand(0).getReg();1575if (Ops.size() != 1 || FoldAsLoadDefReg != MI.getOperand(Ops[0]).getReg())1576return nullptr;1577Register DstReg = MI.getOperand(0).getReg();1578MachineOperand LHS = MI.getOperand(1);1579MachineOperand RHS = MI.getOperand(2);1580MachineOperand &RegMO = RHS.getReg() == FoldAsLoadDefReg ? LHS : RHS;1581if ((RegMemOpcode == SystemZ::SDB || RegMemOpcode == SystemZ::SEB) &&1582FoldAsLoadDefReg != RHS.getReg())1583return nullptr;15841585MachineOperand &Base = LoadMI.getOperand(1);1586MachineOperand &Disp = LoadMI.getOperand(2);1587MachineOperand &Indx = LoadMI.getOperand(3);1588MachineInstrBuilder MIB =1589BuildMI(*MI.getParent(), InsertPt, MI.getDebugLoc(), get(RegMemOpcode), DstReg)1590.add(RegMO)1591.add(Base)1592.add(Disp)1593.add(Indx);1594MIB->addRegisterDead(SystemZ::CC, &RI);1595MRI->setRegClass(DstReg, FPRC);1596MRI->setRegClass(RegMO.getReg(), FPRC);1597transferMIFlag(&MI, MIB, MachineInstr::NoFPExcept);15981599return MIB;1600}16011602bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {1603switch (MI.getOpcode()) {1604case SystemZ::L128:1605splitMove(MI, SystemZ::LG);1606return true;16071608case SystemZ::ST128:1609splitMove(MI, SystemZ::STG);1610return true;16111612case SystemZ::LX:1613splitMove(MI, SystemZ::LD);1614return true;16151616case SystemZ::STX:1617splitMove(MI, SystemZ::STD);1618return true;16191620case SystemZ::LBMux:1621expandRXYPseudo(MI, SystemZ::LB, SystemZ::LBH);1622return true;16231624case SystemZ::LHMux:1625expandRXYPseudo(MI, SystemZ::LH, SystemZ::LHH);1626return true;16271628case SystemZ::LLCRMux:1629expandZExtPseudo(MI, SystemZ::LLCR, 8);1630return true;16311632case SystemZ::LLHRMux:1633expandZExtPseudo(MI, SystemZ::LLHR, 16);1634return true;16351636case SystemZ::LLCMux:1637expandRXYPseudo(MI, SystemZ::LLC, SystemZ::LLCH);1638return true;16391640case SystemZ::LLHMux:1641expandRXYPseudo(MI, SystemZ::LLH, SystemZ::LLHH);1642return true;16431644case SystemZ::LMux:1645expandRXYPseudo(MI, SystemZ::L, SystemZ::LFH);1646return true;16471648case SystemZ::LOCMux:1649expandLOCPseudo(MI, SystemZ::LOC, SystemZ::LOCFH);1650return true;16511652case SystemZ::LOCHIMux:1653expandLOCPseudo(MI, SystemZ::LOCHI, SystemZ::LOCHHI);1654return true;16551656case SystemZ::STCMux:1657expandRXYPseudo(MI, SystemZ::STC, SystemZ::STCH);1658return true;16591660case SystemZ::STHMux:1661expandRXYPseudo(MI, SystemZ::STH, SystemZ::STHH);1662return true;16631664case SystemZ::STMux:1665expandRXYPseudo(MI, SystemZ::ST, SystemZ::STFH);1666return true;16671668case SystemZ::STOCMux:1669expandLOCPseudo(MI, SystemZ::STOC, SystemZ::STOCFH);1670return true;16711672case SystemZ::LHIMux:1673expandRIPseudo(MI, SystemZ::LHI, SystemZ::IIHF, true);1674return true;16751676case SystemZ::IIFMux:1677expandRIPseudo(MI, SystemZ::IILF, SystemZ::IIHF, false);1678return true;16791680case SystemZ::IILMux:1681expandRIPseudo(MI, SystemZ::IILL, SystemZ::IIHL, false);1682return true;16831684case SystemZ::IIHMux:1685expandRIPseudo(MI, SystemZ::IILH, SystemZ::IIHH, false);1686return true;16871688case SystemZ::NIFMux:1689expandRIPseudo(MI, SystemZ::NILF, SystemZ::NIHF, false);1690return true;16911692case SystemZ::NILMux:1693expandRIPseudo(MI, SystemZ::NILL, SystemZ::NIHL, false);1694return true;16951696case SystemZ::NIHMux:1697expandRIPseudo(MI, SystemZ::NILH, SystemZ::NIHH, false);1698return true;16991700case SystemZ::OIFMux:1701expandRIPseudo(MI, SystemZ::OILF, SystemZ::OIHF, false);1702return true;17031704case SystemZ::OILMux:1705expandRIPseudo(MI, SystemZ::OILL, SystemZ::OIHL, false);1706return true;17071708case SystemZ::OIHMux:1709expandRIPseudo(MI, SystemZ::OILH, SystemZ::OIHH, false);1710return true;17111712case SystemZ::XIFMux:1713expandRIPseudo(MI, SystemZ::XILF, SystemZ::XIHF, false);1714return true;17151716case SystemZ::TMLMux:1717expandRIPseudo(MI, SystemZ::TMLL, SystemZ::TMHL, false);1718return true;17191720case SystemZ::TMHMux:1721expandRIPseudo(MI, SystemZ::TMLH, SystemZ::TMHH, false);1722return true;17231724case SystemZ::AHIMux:1725expandRIPseudo(MI, SystemZ::AHI, SystemZ::AIH, false);1726return true;17271728case SystemZ::AHIMuxK:1729expandRIEPseudo(MI, SystemZ::AHI, SystemZ::AHIK, SystemZ::AIH);1730return true;17311732case SystemZ::AFIMux:1733expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false);1734return true;17351736case SystemZ::CHIMux:1737expandRIPseudo(MI, SystemZ::CHI, SystemZ::CIH, false);1738return true;17391740case SystemZ::CFIMux:1741expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false);1742return true;17431744case SystemZ::CLFIMux:1745expandRIPseudo(MI, SystemZ::CLFI, SystemZ::CLIH, false);1746return true;17471748case SystemZ::CMux:1749expandRXYPseudo(MI, SystemZ::C, SystemZ::CHF);1750return true;17511752case SystemZ::CLMux:1753expandRXYPseudo(MI, SystemZ::CL, SystemZ::CLHF);1754return true;17551756case SystemZ::RISBMux: {1757bool DestIsHigh = SystemZ::isHighReg(MI.getOperand(0).getReg());1758bool SrcIsHigh = SystemZ::isHighReg(MI.getOperand(2).getReg());1759if (SrcIsHigh == DestIsHigh)1760MI.setDesc(get(DestIsHigh ? SystemZ::RISBHH : SystemZ::RISBLL));1761else {1762MI.setDesc(get(DestIsHigh ? SystemZ::RISBHL : SystemZ::RISBLH));1763MI.getOperand(5).setImm(MI.getOperand(5).getImm() ^ 32);1764}1765return true;1766}17671768case SystemZ::ADJDYNALLOC:1769splitAdjDynAlloc(MI);1770return true;17711772case TargetOpcode::LOAD_STACK_GUARD:1773expandLoadStackGuard(&MI);1774return true;17751776default:1777return false;1778}1779}17801781unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {1782if (MI.isInlineAsm()) {1783const MachineFunction *MF = MI.getParent()->getParent();1784const char *AsmStr = MI.getOperand(0).getSymbolName();1785return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());1786}1787else if (MI.getOpcode() == SystemZ::PATCHPOINT)1788return PatchPointOpers(&MI).getNumPatchBytes();1789else if (MI.getOpcode() == SystemZ::STACKMAP)1790return MI.getOperand(1).getImm();1791else if (MI.getOpcode() == SystemZ::FENTRY_CALL)1792return 6;17931794return MI.getDesc().getSize();1795}17961797SystemZII::Branch1798SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {1799switch (MI.getOpcode()) {1800case SystemZ::BR:1801case SystemZ::BI:1802case SystemZ::J:1803case SystemZ::JG:1804return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,1805SystemZ::CCMASK_ANY, &MI.getOperand(0));18061807case SystemZ::BRC:1808case SystemZ::BRCL:1809return SystemZII::Branch(SystemZII::BranchNormal, MI.getOperand(0).getImm(),1810MI.getOperand(1).getImm(), &MI.getOperand(2));18111812case SystemZ::BRCT:1813case SystemZ::BRCTH:1814return SystemZII::Branch(SystemZII::BranchCT, SystemZ::CCMASK_ICMP,1815SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));18161817case SystemZ::BRCTG:1818return SystemZII::Branch(SystemZII::BranchCTG, SystemZ::CCMASK_ICMP,1819SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));18201821case SystemZ::CIJ:1822case SystemZ::CRJ:1823return SystemZII::Branch(SystemZII::BranchC, SystemZ::CCMASK_ICMP,1824MI.getOperand(2).getImm(), &MI.getOperand(3));18251826case SystemZ::CLIJ:1827case SystemZ::CLRJ:1828return SystemZII::Branch(SystemZII::BranchCL, SystemZ::CCMASK_ICMP,1829MI.getOperand(2).getImm(), &MI.getOperand(3));18301831case SystemZ::CGIJ:1832case SystemZ::CGRJ:1833return SystemZII::Branch(SystemZII::BranchCG, SystemZ::CCMASK_ICMP,1834MI.getOperand(2).getImm(), &MI.getOperand(3));18351836case SystemZ::CLGIJ:1837case SystemZ::CLGRJ:1838return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP,1839MI.getOperand(2).getImm(), &MI.getOperand(3));18401841case SystemZ::INLINEASM_BR:1842// Don't try to analyze asm goto, so pass nullptr as branch target argument.1843return SystemZII::Branch(SystemZII::AsmGoto, 0, 0, nullptr);18441845default:1846llvm_unreachable("Unrecognized branch opcode");1847}1848}18491850void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,1851unsigned &LoadOpcode,1852unsigned &StoreOpcode) const {1853if (RC == &SystemZ::GR32BitRegClass || RC == &SystemZ::ADDR32BitRegClass) {1854LoadOpcode = SystemZ::L;1855StoreOpcode = SystemZ::ST;1856} else if (RC == &SystemZ::GRH32BitRegClass) {1857LoadOpcode = SystemZ::LFH;1858StoreOpcode = SystemZ::STFH;1859} else if (RC == &SystemZ::GRX32BitRegClass) {1860LoadOpcode = SystemZ::LMux;1861StoreOpcode = SystemZ::STMux;1862} else if (RC == &SystemZ::GR64BitRegClass ||1863RC == &SystemZ::ADDR64BitRegClass) {1864LoadOpcode = SystemZ::LG;1865StoreOpcode = SystemZ::STG;1866} else if (RC == &SystemZ::GR128BitRegClass ||1867RC == &SystemZ::ADDR128BitRegClass) {1868LoadOpcode = SystemZ::L128;1869StoreOpcode = SystemZ::ST128;1870} else if (RC == &SystemZ::FP32BitRegClass) {1871LoadOpcode = SystemZ::LE;1872StoreOpcode = SystemZ::STE;1873} else if (RC == &SystemZ::FP64BitRegClass) {1874LoadOpcode = SystemZ::LD;1875StoreOpcode = SystemZ::STD;1876} else if (RC == &SystemZ::FP128BitRegClass) {1877LoadOpcode = SystemZ::LX;1878StoreOpcode = SystemZ::STX;1879} else if (RC == &SystemZ::VR32BitRegClass) {1880LoadOpcode = SystemZ::VL32;1881StoreOpcode = SystemZ::VST32;1882} else if (RC == &SystemZ::VR64BitRegClass) {1883LoadOpcode = SystemZ::VL64;1884StoreOpcode = SystemZ::VST64;1885} else if (RC == &SystemZ::VF128BitRegClass ||1886RC == &SystemZ::VR128BitRegClass) {1887LoadOpcode = SystemZ::VL;1888StoreOpcode = SystemZ::VST;1889} else1890llvm_unreachable("Unsupported regclass to load or store");1891}18921893unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,1894int64_t Offset,1895const MachineInstr *MI) const {1896const MCInstrDesc &MCID = get(Opcode);1897int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);1898if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {1899// Get the instruction to use for unsigned 12-bit displacements.1900int Disp12Opcode = SystemZ::getDisp12Opcode(Opcode);1901if (Disp12Opcode >= 0)1902return Disp12Opcode;19031904// All address-related instructions can use unsigned 12-bit1905// displacements.1906return Opcode;1907}1908if (isInt<20>(Offset) && isInt<20>(Offset2)) {1909// Get the instruction to use for signed 20-bit displacements.1910int Disp20Opcode = SystemZ::getDisp20Opcode(Opcode);1911if (Disp20Opcode >= 0)1912return Disp20Opcode;19131914// Check whether Opcode allows signed 20-bit displacements.1915if (MCID.TSFlags & SystemZII::Has20BitOffset)1916return Opcode;19171918// If a VR32/VR64 reg ended up in an FP register, use the FP opcode.1919if (MI && MI->getOperand(0).isReg()) {1920Register Reg = MI->getOperand(0).getReg();1921if (Reg.isPhysical() && SystemZMC::getFirstReg(Reg) < 16) {1922switch (Opcode) {1923case SystemZ::VL32:1924return SystemZ::LEY;1925case SystemZ::VST32:1926return SystemZ::STEY;1927case SystemZ::VL64:1928return SystemZ::LDY;1929case SystemZ::VST64:1930return SystemZ::STDY;1931default: break;1932}1933}1934}1935}1936return 0;1937}19381939bool SystemZInstrInfo::hasDisplacementPairInsn(unsigned Opcode) const {1940const MCInstrDesc &MCID = get(Opcode);1941if (MCID.TSFlags & SystemZII::Has20BitOffset)1942return SystemZ::getDisp12Opcode(Opcode) >= 0;1943return SystemZ::getDisp20Opcode(Opcode) >= 0;1944}19451946unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {1947switch (Opcode) {1948case SystemZ::L: return SystemZ::LT;1949case SystemZ::LY: return SystemZ::LT;1950case SystemZ::LG: return SystemZ::LTG;1951case SystemZ::LGF: return SystemZ::LTGF;1952case SystemZ::LR: return SystemZ::LTR;1953case SystemZ::LGFR: return SystemZ::LTGFR;1954case SystemZ::LGR: return SystemZ::LTGR;1955case SystemZ::LCDFR: return SystemZ::LCDBR;1956case SystemZ::LPDFR: return SystemZ::LPDBR;1957case SystemZ::LNDFR: return SystemZ::LNDBR;1958case SystemZ::LCDFR_32: return SystemZ::LCEBR;1959case SystemZ::LPDFR_32: return SystemZ::LPEBR;1960case SystemZ::LNDFR_32: return SystemZ::LNEBR;1961// On zEC12 we prefer to use RISBGN. But if there is a chance to1962// actually use the condition code, we may turn it back into RISGB.1963// Note that RISBG is not really a "load-and-test" instruction,1964// but sets the same condition code values, so is OK to use here.1965case SystemZ::RISBGN: return SystemZ::RISBG;1966default: return 0;1967}1968}19691970bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,1971unsigned &Start, unsigned &End) const {1972// Reject trivial all-zero masks.1973Mask &= allOnes(BitSize);1974if (Mask == 0)1975return false;19761977// Handle the 1+0+ or 0+1+0* cases. Start then specifies the index of1978// the msb and End specifies the index of the lsb.1979unsigned LSB, Length;1980if (isShiftedMask_64(Mask, LSB, Length)) {1981Start = 63 - (LSB + Length - 1);1982End = 63 - LSB;1983return true;1984}19851986// Handle the wrap-around 1+0+1+ cases. Start then specifies the msb1987// of the low 1s and End specifies the lsb of the high 1s.1988if (isShiftedMask_64(Mask ^ allOnes(BitSize), LSB, Length)) {1989assert(LSB > 0 && "Bottom bit must be set");1990assert(LSB + Length < BitSize && "Top bit must be set");1991Start = 63 - (LSB - 1);1992End = 63 - (LSB + Length);1993return true;1994}19951996return false;1997}19981999unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,2000SystemZII::FusedCompareType Type,2001const MachineInstr *MI) const {2002switch (Opcode) {2003case SystemZ::CHI:2004case SystemZ::CGHI:2005if (!(MI && isInt<8>(MI->getOperand(1).getImm())))2006return 0;2007break;2008case SystemZ::CLFI:2009case SystemZ::CLGFI:2010if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))2011return 0;2012break;2013case SystemZ::CL:2014case SystemZ::CLG:2015if (!STI.hasMiscellaneousExtensions())2016return 0;2017if (!(MI && MI->getOperand(3).getReg() == 0))2018return 0;2019break;2020}2021switch (Type) {2022case SystemZII::CompareAndBranch:2023switch (Opcode) {2024case SystemZ::CR:2025return SystemZ::CRJ;2026case SystemZ::CGR:2027return SystemZ::CGRJ;2028case SystemZ::CHI:2029return SystemZ::CIJ;2030case SystemZ::CGHI:2031return SystemZ::CGIJ;2032case SystemZ::CLR:2033return SystemZ::CLRJ;2034case SystemZ::CLGR:2035return SystemZ::CLGRJ;2036case SystemZ::CLFI:2037return SystemZ::CLIJ;2038case SystemZ::CLGFI:2039return SystemZ::CLGIJ;2040default:2041return 0;2042}2043case SystemZII::CompareAndReturn:2044switch (Opcode) {2045case SystemZ::CR:2046return SystemZ::CRBReturn;2047case SystemZ::CGR:2048return SystemZ::CGRBReturn;2049case SystemZ::CHI:2050return SystemZ::CIBReturn;2051case SystemZ::CGHI:2052return SystemZ::CGIBReturn;2053case SystemZ::CLR:2054return SystemZ::CLRBReturn;2055case SystemZ::CLGR:2056return SystemZ::CLGRBReturn;2057case SystemZ::CLFI:2058return SystemZ::CLIBReturn;2059case SystemZ::CLGFI:2060return SystemZ::CLGIBReturn;2061default:2062return 0;2063}2064case SystemZII::CompareAndSibcall:2065switch (Opcode) {2066case SystemZ::CR:2067return SystemZ::CRBCall;2068case SystemZ::CGR:2069return SystemZ::CGRBCall;2070case SystemZ::CHI:2071return SystemZ::CIBCall;2072case SystemZ::CGHI:2073return SystemZ::CGIBCall;2074case SystemZ::CLR:2075return SystemZ::CLRBCall;2076case SystemZ::CLGR:2077return SystemZ::CLGRBCall;2078case SystemZ::CLFI:2079return SystemZ::CLIBCall;2080case SystemZ::CLGFI:2081return SystemZ::CLGIBCall;2082default:2083return 0;2084}2085case SystemZII::CompareAndTrap:2086switch (Opcode) {2087case SystemZ::CR:2088return SystemZ::CRT;2089case SystemZ::CGR:2090return SystemZ::CGRT;2091case SystemZ::CHI:2092return SystemZ::CIT;2093case SystemZ::CGHI:2094return SystemZ::CGIT;2095case SystemZ::CLR:2096return SystemZ::CLRT;2097case SystemZ::CLGR:2098return SystemZ::CLGRT;2099case SystemZ::CLFI:2100return SystemZ::CLFIT;2101case SystemZ::CLGFI:2102return SystemZ::CLGIT;2103case SystemZ::CL:2104return SystemZ::CLT;2105case SystemZ::CLG:2106return SystemZ::CLGT;2107default:2108return 0;2109}2110}2111return 0;2112}21132114bool SystemZInstrInfo::2115prepareCompareSwapOperands(MachineBasicBlock::iterator const MBBI) const {2116assert(MBBI->isCompare() && MBBI->getOperand(0).isReg() &&2117MBBI->getOperand(1).isReg() && !MBBI->mayLoad() &&2118"Not a compare reg/reg.");21192120MachineBasicBlock *MBB = MBBI->getParent();2121bool CCLive = true;2122SmallVector<MachineInstr *, 4> CCUsers;2123for (MachineInstr &MI : llvm::make_range(std::next(MBBI), MBB->end())) {2124if (MI.readsRegister(SystemZ::CC, /*TRI=*/nullptr)) {2125unsigned Flags = MI.getDesc().TSFlags;2126if ((Flags & SystemZII::CCMaskFirst) || (Flags & SystemZII::CCMaskLast))2127CCUsers.push_back(&MI);2128else2129return false;2130}2131if (MI.definesRegister(SystemZ::CC, /*TRI=*/nullptr)) {2132CCLive = false;2133break;2134}2135}2136if (CCLive) {2137LiveRegUnits LiveRegs(*MBB->getParent()->getSubtarget().getRegisterInfo());2138LiveRegs.addLiveOuts(*MBB);2139if (!LiveRegs.available(SystemZ::CC))2140return false;2141}21422143// Update all CC users.2144for (unsigned Idx = 0; Idx < CCUsers.size(); ++Idx) {2145unsigned Flags = CCUsers[Idx]->getDesc().TSFlags;2146unsigned FirstOpNum = ((Flags & SystemZII::CCMaskFirst) ?21470 : CCUsers[Idx]->getNumExplicitOperands() - 2);2148MachineOperand &CCMaskMO = CCUsers[Idx]->getOperand(FirstOpNum + 1);2149unsigned NewCCMask = SystemZ::reverseCCMask(CCMaskMO.getImm());2150CCMaskMO.setImm(NewCCMask);2151}21522153return true;2154}21552156unsigned SystemZ::reverseCCMask(unsigned CCMask) {2157return ((CCMask & SystemZ::CCMASK_CMP_EQ) |2158((CCMask & SystemZ::CCMASK_CMP_GT) ? SystemZ::CCMASK_CMP_LT : 0) |2159((CCMask & SystemZ::CCMASK_CMP_LT) ? SystemZ::CCMASK_CMP_GT : 0) |2160(CCMask & SystemZ::CCMASK_CMP_UO));2161}21622163MachineBasicBlock *SystemZ::emitBlockAfter(MachineBasicBlock *MBB) {2164MachineFunction &MF = *MBB->getParent();2165MachineBasicBlock *NewMBB = MF.CreateMachineBasicBlock(MBB->getBasicBlock());2166MF.insert(std::next(MachineFunction::iterator(MBB)), NewMBB);2167return NewMBB;2168}21692170MachineBasicBlock *SystemZ::splitBlockAfter(MachineBasicBlock::iterator MI,2171MachineBasicBlock *MBB) {2172MachineBasicBlock *NewMBB = emitBlockAfter(MBB);2173NewMBB->splice(NewMBB->begin(), MBB,2174std::next(MachineBasicBlock::iterator(MI)), MBB->end());2175NewMBB->transferSuccessorsAndUpdatePHIs(MBB);2176return NewMBB;2177}21782179MachineBasicBlock *SystemZ::splitBlockBefore(MachineBasicBlock::iterator MI,2180MachineBasicBlock *MBB) {2181MachineBasicBlock *NewMBB = emitBlockAfter(MBB);2182NewMBB->splice(NewMBB->begin(), MBB, MI, MBB->end());2183NewMBB->transferSuccessorsAndUpdatePHIs(MBB);2184return NewMBB;2185}21862187unsigned SystemZInstrInfo::getLoadAndTrap(unsigned Opcode) const {2188if (!STI.hasLoadAndTrap())2189return 0;2190switch (Opcode) {2191case SystemZ::L:2192case SystemZ::LY:2193return SystemZ::LAT;2194case SystemZ::LG:2195return SystemZ::LGAT;2196case SystemZ::LFH:2197return SystemZ::LFHAT;2198case SystemZ::LLGF:2199return SystemZ::LLGFAT;2200case SystemZ::LLGT:2201return SystemZ::LLGTAT;2202}2203return 0;2204}22052206void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,2207MachineBasicBlock::iterator MBBI,2208unsigned Reg, uint64_t Value) const {2209DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();2210unsigned Opcode = 0;2211if (isInt<16>(Value))2212Opcode = SystemZ::LGHI;2213else if (SystemZ::isImmLL(Value))2214Opcode = SystemZ::LLILL;2215else if (SystemZ::isImmLH(Value)) {2216Opcode = SystemZ::LLILH;2217Value >>= 16;2218}2219else if (isInt<32>(Value))2220Opcode = SystemZ::LGFI;2221if (Opcode) {2222BuildMI(MBB, MBBI, DL, get(Opcode), Reg).addImm(Value);2223return;2224}22252226MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();2227assert (MRI.isSSA() && "Huge values only handled before reg-alloc .");2228Register Reg0 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);2229Register Reg1 = MRI.createVirtualRegister(&SystemZ::GR64BitRegClass);2230BuildMI(MBB, MBBI, DL, get(SystemZ::IMPLICIT_DEF), Reg0);2231BuildMI(MBB, MBBI, DL, get(SystemZ::IIHF64), Reg1)2232.addReg(Reg0).addImm(Value >> 32);2233BuildMI(MBB, MBBI, DL, get(SystemZ::IILF64), Reg)2234.addReg(Reg1).addImm(Value & ((uint64_t(1) << 32) - 1));2235}22362237bool SystemZInstrInfo::verifyInstruction(const MachineInstr &MI,2238StringRef &ErrInfo) const {2239const MCInstrDesc &MCID = MI.getDesc();2240for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {2241if (I >= MCID.getNumOperands())2242break;2243const MachineOperand &Op = MI.getOperand(I);2244const MCOperandInfo &MCOI = MCID.operands()[I];2245// Addressing modes have register and immediate operands. Op should be a2246// register (or frame index) operand if MCOI.RegClass contains a valid2247// register class, or an immediate otherwise.2248if (MCOI.OperandType == MCOI::OPERAND_MEMORY &&2249((MCOI.RegClass != -1 && !Op.isReg() && !Op.isFI()) ||2250(MCOI.RegClass == -1 && !Op.isImm()))) {2251ErrInfo = "Addressing mode operands corrupt!";2252return false;2253}2254}22552256return true;2257}22582259bool SystemZInstrInfo::2260areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,2261const MachineInstr &MIb) const {22622263if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand())2264return false;22652266// If mem-operands show that the same address Value is used by both2267// instructions, check for non-overlapping offsets and widths. Not2268// sure if a register based analysis would be an improvement...22692270MachineMemOperand *MMOa = *MIa.memoperands_begin();2271MachineMemOperand *MMOb = *MIb.memoperands_begin();2272const Value *VALa = MMOa->getValue();2273const Value *VALb = MMOb->getValue();2274bool SameVal = (VALa && VALb && (VALa == VALb));2275if (!SameVal) {2276const PseudoSourceValue *PSVa = MMOa->getPseudoValue();2277const PseudoSourceValue *PSVb = MMOb->getPseudoValue();2278if (PSVa && PSVb && (PSVa == PSVb))2279SameVal = true;2280}2281if (SameVal) {2282int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset();2283LocationSize WidthA = MMOa->getSize(), WidthB = MMOb->getSize();2284int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;2285int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;2286LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;2287if (LowWidth.hasValue() &&2288LowOffset + (int)LowWidth.getValue() <= HighOffset)2289return true;2290}22912292return false;2293}22942295bool SystemZInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,2296const Register Reg,2297int64_t &ImmVal) const {22982299if (MI.getOpcode() == SystemZ::VGBM && Reg == MI.getOperand(0).getReg()) {2300ImmVal = MI.getOperand(1).getImm();2301// TODO: Handle non-0 values2302return ImmVal == 0;2303}23042305return false;2306}230723082309