452 lines · cpp
1//===-- SystemZRegisterInfo.cpp - SystemZ register information ------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SystemZRegisterInfo.h"10#include "SystemZInstrInfo.h"11#include "SystemZSubtarget.h"12#include "llvm/ADT/SmallSet.h"13#include "llvm/CodeGen/LiveIntervals.h"14#include "llvm/CodeGen/MachineInstrBuilder.h"15#include "llvm/CodeGen/MachineRegisterInfo.h"16#include "llvm/CodeGen/TargetFrameLowering.h"17#include "llvm/CodeGen/VirtRegMap.h"18#include "llvm/IR/DebugInfoMetadata.h"19 20using namespace llvm;21 22#define GET_REGINFO_TARGET_DESC23#include "SystemZGenRegisterInfo.inc"24 25// Given that MO is a GRX32 operand, return either GR32 or GRH32 if MO26// somehow belongs in it. Otherwise, return GRX32.27static const TargetRegisterClass *getRC32(MachineOperand &MO,28 const VirtRegMap *VRM,29 const MachineRegisterInfo *MRI) {30 const TargetRegisterClass *RC = MRI->getRegClass(MO.getReg());31 32 if (SystemZ::GR32BitRegClass.hasSubClassEq(RC) ||33 MO.getSubReg() == SystemZ::subreg_ll32 ||34 MO.getSubReg() == SystemZ::subreg_l32)35 return &SystemZ::GR32BitRegClass;36 if (SystemZ::GRH32BitRegClass.hasSubClassEq(RC) ||37 MO.getSubReg() == SystemZ::subreg_lh32 ||38 MO.getSubReg() == SystemZ::subreg_h32)39 return &SystemZ::GRH32BitRegClass;40 41 if (VRM && VRM->hasPhys(MO.getReg())) {42 Register PhysReg = VRM->getPhys(MO.getReg());43 if (SystemZ::GR32BitRegClass.contains(PhysReg))44 return &SystemZ::GR32BitRegClass;45 assert (SystemZ::GRH32BitRegClass.contains(PhysReg) &&46 "Phys reg not in GR32 or GRH32?");47 return &SystemZ::GRH32BitRegClass;48 }49 50 assert (RC == &SystemZ::GRX32BitRegClass);51 return RC;52}53 54// Pass the registers of RC as hints while making sure that if any of these55// registers are copy hints (and therefore already in Hints), hint them56// first.57static void addHints(ArrayRef<MCPhysReg> Order,58 SmallVectorImpl<MCPhysReg> &Hints,59 const TargetRegisterClass *RC,60 const MachineRegisterInfo *MRI) {61 SmallSet<unsigned, 4> CopyHints(llvm::from_range, Hints);62 Hints.clear();63 for (MCPhysReg Reg : Order)64 if (CopyHints.count(Reg) &&65 RC->contains(Reg) && !MRI->isReserved(Reg))66 Hints.push_back(Reg);67 for (MCPhysReg Reg : Order)68 if (!CopyHints.count(Reg) &&69 RC->contains(Reg) && !MRI->isReserved(Reg))70 Hints.push_back(Reg);71}72 73bool SystemZRegisterInfo::getRegAllocationHints(74 Register VirtReg, ArrayRef<MCPhysReg> Order,75 SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF,76 const VirtRegMap *VRM, const LiveRegMatrix *Matrix) const {77 const MachineRegisterInfo *MRI = &MF.getRegInfo();78 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();79 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();80 81 bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(82 VirtReg, Order, Hints, MF, VRM, Matrix);83 84 if (VRM != nullptr) {85 // Add any two address hints after any copy hints.86 SmallSet<unsigned, 4> TwoAddrHints;87 for (auto &Use : MRI->reg_nodbg_instructions(VirtReg))88 if (SystemZ::getTwoOperandOpcode(Use.getOpcode()) != -1) {89 const MachineOperand *VRRegMO = nullptr;90 const MachineOperand *OtherMO = nullptr;91 const MachineOperand *CommuMO = nullptr;92 if (VirtReg == Use.getOperand(0).getReg()) {93 VRRegMO = &Use.getOperand(0);94 OtherMO = &Use.getOperand(1);95 if (Use.isCommutable())96 CommuMO = &Use.getOperand(2);97 } else if (VirtReg == Use.getOperand(1).getReg()) {98 VRRegMO = &Use.getOperand(1);99 OtherMO = &Use.getOperand(0);100 } else if (VirtReg == Use.getOperand(2).getReg() &&101 Use.isCommutable()) {102 VRRegMO = &Use.getOperand(2);103 OtherMO = &Use.getOperand(0);104 } else105 continue;106 107 auto tryAddHint = [&](const MachineOperand *MO) -> void {108 Register Reg = MO->getReg();109 Register PhysReg =110 Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg));111 if (PhysReg) {112 if (MO->getSubReg())113 PhysReg = getSubReg(PhysReg, MO->getSubReg());114 if (VRRegMO->getSubReg())115 PhysReg = getMatchingSuperReg(PhysReg, VRRegMO->getSubReg(),116 MRI->getRegClass(VirtReg));117 if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg))118 TwoAddrHints.insert(PhysReg);119 }120 };121 tryAddHint(OtherMO);122 if (CommuMO)123 tryAddHint(CommuMO);124 }125 for (MCPhysReg OrderReg : Order)126 if (TwoAddrHints.count(OrderReg))127 Hints.push_back(OrderReg);128 }129 130 if (MRI->getRegClass(VirtReg) == &SystemZ::GRX32BitRegClass) {131 SmallVector<Register, 8> Worklist;132 SmallSet<Register, 4> DoneRegs;133 Worklist.push_back(VirtReg);134 while (Worklist.size()) {135 Register Reg = Worklist.pop_back_val();136 if (!DoneRegs.insert(Reg).second)137 continue;138 139 for (auto &Use : MRI->reg_instructions(Reg)) {140 // For LOCRMux, see if the other operand is already a high or low141 // register, and in that case give the corresponding hints for142 // VirtReg. LOCR instructions need both operands in either high or143 // low parts. Same handling for SELRMux.144 if (Use.getOpcode() == SystemZ::LOCRMux ||145 Use.getOpcode() == SystemZ::SELRMux) {146 MachineOperand &TrueMO = Use.getOperand(1);147 MachineOperand &FalseMO = Use.getOperand(2);148 const TargetRegisterClass *RC =149 TRI->getCommonSubClass(getRC32(FalseMO, VRM, MRI),150 getRC32(TrueMO, VRM, MRI));151 if (Use.getOpcode() == SystemZ::SELRMux)152 RC = TRI->getCommonSubClass(RC,153 getRC32(Use.getOperand(0), VRM, MRI));154 if (RC && RC != &SystemZ::GRX32BitRegClass) {155 addHints(Order, Hints, RC, MRI);156 // Return true to make these hints the only regs available to157 // RA. This may mean extra spilling but since the alternative is158 // a jump sequence expansion of the LOCRMux, it is preferred.159 return true;160 }161 162 // Add the other operand of the LOCRMux to the worklist.163 Register OtherReg =164 (TrueMO.getReg() == Reg ? FalseMO.getReg() : TrueMO.getReg());165 if (MRI->getRegClass(OtherReg) == &SystemZ::GRX32BitRegClass)166 Worklist.push_back(OtherReg);167 } // end LOCRMux168 else if (Use.getOpcode() == SystemZ::CHIMux ||169 Use.getOpcode() == SystemZ::CFIMux) {170 if (Use.getOperand(1).getImm() == 0) {171 bool OnlyLMuxes = true;172 for (MachineInstr &DefMI : MRI->def_instructions(VirtReg))173 if (DefMI.getOpcode() != SystemZ::LMux)174 OnlyLMuxes = false;175 if (OnlyLMuxes) {176 addHints(Order, Hints, &SystemZ::GR32BitRegClass, MRI);177 // Return false to make these hints preferred but not obligatory.178 return false;179 }180 }181 } // end CHIMux / CFIMux182 }183 }184 }185 186 return BaseImplRetVal;187}188 189const MCPhysReg *190SystemZXPLINK64Registers::getCalleeSavedRegs(const MachineFunction *MF) const {191 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();192 return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_SaveList193 : CSR_SystemZ_XPLINK64_SaveList;194}195 196const MCPhysReg *197SystemZELFRegisters::getCalleeSavedRegs(const MachineFunction *MF) const {198 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();199 if (MF->getFunction().getCallingConv() == CallingConv::GHC)200 return CSR_SystemZ_NoRegs_SaveList;201 if (MF->getFunction().getCallingConv() == CallingConv::AnyReg)202 return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_SaveList203 : CSR_SystemZ_AllRegs_SaveList;204 if (MF->getSubtarget().getTargetLowering()->supportSwiftError() &&205 MF->getFunction().getAttributes().hasAttrSomewhere(206 Attribute::SwiftError))207 return CSR_SystemZ_SwiftError_SaveList;208 return CSR_SystemZ_ELF_SaveList;209}210 211const uint32_t *212SystemZXPLINK64Registers::getCallPreservedMask(const MachineFunction &MF,213 CallingConv::ID CC) const {214 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();215 return Subtarget.hasVector() ? CSR_SystemZ_XPLINK64_Vector_RegMask216 : CSR_SystemZ_XPLINK64_RegMask;217}218 219const uint32_t *220SystemZELFRegisters::getCallPreservedMask(const MachineFunction &MF,221 CallingConv::ID CC) const {222 const SystemZSubtarget &Subtarget = MF.getSubtarget<SystemZSubtarget>();223 if (CC == CallingConv::GHC)224 return CSR_SystemZ_NoRegs_RegMask;225 if (CC == CallingConv::AnyReg)226 return Subtarget.hasVector()? CSR_SystemZ_AllRegs_Vector_RegMask227 : CSR_SystemZ_AllRegs_RegMask;228 if (MF.getSubtarget().getTargetLowering()->supportSwiftError() &&229 MF.getFunction().getAttributes().hasAttrSomewhere(230 Attribute::SwiftError))231 return CSR_SystemZ_SwiftError_RegMask;232 return CSR_SystemZ_ELF_RegMask;233}234 235SystemZRegisterInfo::SystemZRegisterInfo(unsigned int RA, unsigned int HwMode)236 : SystemZGenRegisterInfo(RA, /*DwarfFlavour=*/0, /*EHFlavour=*/0, /*PC=*/0,237 HwMode) {}238 239const MCPhysReg *240SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {241 242 const SystemZSubtarget *Subtarget = &MF->getSubtarget<SystemZSubtarget>();243 SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();244 245 return Regs->getCalleeSavedRegs(MF);246}247 248const uint32_t *249SystemZRegisterInfo::getCallPreservedMask(const MachineFunction &MF,250 CallingConv::ID CC) const {251 252 const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();253 SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();254 return Regs->getCallPreservedMask(MF, CC);255}256 257const uint32_t *SystemZRegisterInfo::getNoPreservedMask() const {258 return CSR_SystemZ_NoRegs_RegMask;259}260 261BitVector262SystemZRegisterInfo::getReservedRegs(const MachineFunction &MF) const {263 BitVector Reserved(getNumRegs());264 const SystemZFrameLowering *TFI = getFrameLowering(MF);265 const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();266 SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();267 if (TFI->hasFP(MF))268 // The frame pointer. Reserve all aliases.269 for (MCRegAliasIterator AI(Regs->getFramePointerRegister(), this, true);270 AI.isValid(); ++AI)271 Reserved.set(*AI);272 273 // Reserve all aliases for the stack pointer.274 for (MCRegAliasIterator AI(Regs->getStackPointerRegister(), this, true);275 AI.isValid(); ++AI)276 Reserved.set(*AI);277 278 // A0 and A1 hold the thread pointer.279 Reserved.set(SystemZ::A0);280 Reserved.set(SystemZ::A1);281 282 // FPC is the floating-point control register.283 Reserved.set(SystemZ::FPC);284 285 return Reserved;286}287 288bool289SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,290 int SPAdj, unsigned FIOperandNum,291 RegScavenger *RS) const {292 assert(SPAdj == 0 && "Outgoing arguments should be part of the frame");293 294 MachineBasicBlock &MBB = *MI->getParent();295 MachineFunction &MF = *MBB.getParent();296 auto *TII = MF.getSubtarget<SystemZSubtarget>().getInstrInfo();297 const SystemZFrameLowering *TFI = getFrameLowering(MF);298 DebugLoc DL = MI->getDebugLoc();299 300 // Decompose the frame index into a base and offset.301 int FrameIndex = MI->getOperand(FIOperandNum).getIndex();302 Register BasePtr;303 int64_t Offset =304 (TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed() +305 MI->getOperand(FIOperandNum + 1).getImm());306 307 // Special handling of dbg_value instructions.308 if (MI->isDebugValue()) {309 MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, /*isDef*/ false);310 if (MI->isNonListDebugValue()) {311 MI->getDebugOffset().ChangeToImmediate(Offset);312 } else {313 unsigned OpIdx = MI->getDebugOperandIndex(&MI->getOperand(FIOperandNum));314 SmallVector<uint64_t, 3> Ops;315 DIExpression::appendOffset(316 Ops, TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed());317 MI->getDebugExpressionOp().setMetadata(318 DIExpression::appendOpsToArg(MI->getDebugExpression(), Ops, OpIdx));319 }320 return false;321 }322 323 // See if the offset is in range, or if an equivalent instruction that324 // accepts the offset exists.325 unsigned Opcode = MI->getOpcode();326 unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI);327 if (OpcodeForOffset) {328 if (OpcodeForOffset == SystemZ::LE &&329 MF.getSubtarget<SystemZSubtarget>().hasVector()) {330 // If LE is ok for offset, use LDE instead on z13.331 OpcodeForOffset = SystemZ::LDE32;332 }333 MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);334 }335 else {336 // Create an anchor point that is in range. Start at 0xffff so that337 // can use LLILH to load the immediate.338 int64_t OldOffset = Offset;339 int64_t Mask = 0xffff;340 do {341 Offset = OldOffset & Mask;342 OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);343 Mask >>= 1;344 assert(Mask && "One offset must be OK");345 } while (!OpcodeForOffset);346 347 Register ScratchReg =348 MF.getRegInfo().createVirtualRegister(&SystemZ::ADDR64BitRegClass);349 int64_t HighOffset = OldOffset - Offset;350 351 if (MI->getDesc().TSFlags & SystemZII::HasIndex352 && MI->getOperand(FIOperandNum + 2).getReg() == 0) {353 // Load the offset into the scratch register and use it as an index.354 // The scratch register then dies here.355 TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);356 MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false);357 MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg,358 false, false, true);359 } else {360 // Load the anchor address into a scratch register.361 unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset);362 if (LAOpcode)363 BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg)364 .addReg(BasePtr).addImm(HighOffset).addReg(0);365 else {366 // Load the high offset into the scratch register and use it as367 // an index.368 TII->loadImmediate(MBB, MI, ScratchReg, HighOffset);369 BuildMI(MBB, MI, DL, TII->get(SystemZ::LA), ScratchReg)370 .addReg(BasePtr, RegState::Kill).addImm(0).addReg(ScratchReg);371 }372 373 // Use the scratch register as the base. It then dies here.374 MI->getOperand(FIOperandNum).ChangeToRegister(ScratchReg,375 false, false, true);376 }377 }378 MI->setDesc(TII->get(OpcodeForOffset));379 MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);380 return false;381}382 383bool SystemZRegisterInfo::shouldCoalesce(MachineInstr *MI,384 const TargetRegisterClass *SrcRC,385 unsigned SubReg,386 const TargetRegisterClass *DstRC,387 unsigned DstSubReg,388 const TargetRegisterClass *NewRC,389 LiveIntervals &LIS) const {390 assert (MI->isCopy() && "Only expecting COPY instructions");391 392 // Coalesce anything which is not a COPY involving a subreg to/from GR128.393 if (!(NewRC->hasSuperClassEq(&SystemZ::GR128BitRegClass) &&394 (getRegSizeInBits(*SrcRC) <= 64 || getRegSizeInBits(*DstRC) <= 64) &&395 !MI->getOperand(1).isUndef()))396 return true;397 398 // Allow coalescing of a GR128 subreg COPY only if the subreg liverange is399 // local to one MBB with not too many interferring physreg clobbers. Otherwise400 // regalloc may run out of registers.401 unsigned SubregOpIdx = getRegSizeInBits(*SrcRC) == 128 ? 0 : 1;402 LiveInterval &LI = LIS.getInterval(MI->getOperand(SubregOpIdx).getReg());403 404 // Check that the subreg is local to MBB.405 MachineBasicBlock *MBB = MI->getParent();406 MachineInstr *FirstMI = LIS.getInstructionFromIndex(LI.beginIndex());407 MachineInstr *LastMI = LIS.getInstructionFromIndex(LI.endIndex());408 if (!FirstMI || FirstMI->getParent() != MBB ||409 !LastMI || LastMI->getParent() != MBB)410 return false;411 412 // Check if coalescing seems safe by finding the set of clobbered physreg413 // pairs in the region.414 BitVector PhysClobbered(getNumRegs());415 for (MachineBasicBlock::iterator MII = FirstMI,416 MEE = std::next(LastMI->getIterator());417 MII != MEE; ++MII)418 for (const MachineOperand &MO : MII->operands())419 if (MO.isReg() && MO.getReg().isPhysical()) {420 for (MCPhysReg SI : superregs_inclusive(MO.getReg()))421 if (NewRC->contains(SI)) {422 PhysClobbered.set(SI);423 break;424 }425 }426 427 // Demand an arbitrary margin of free regs.428 unsigned const DemandedFreeGR128 = 3;429 if (PhysClobbered.count() > (NewRC->getNumRegs() - DemandedFreeGR128))430 return false;431 432 return true;433}434 435Register436SystemZRegisterInfo::getFrameRegister(const MachineFunction &MF) const {437 const SystemZFrameLowering *TFI = getFrameLowering(MF);438 const SystemZSubtarget *Subtarget = &MF.getSubtarget<SystemZSubtarget>();439 SystemZCallingConventionRegisters *Regs = Subtarget->getSpecialRegisters();440 441 return TFI->hasFP(MF) ? Regs->getFramePointerRegister()442 : Regs->getStackPointerRegister();443}444 445const TargetRegisterClass *446SystemZRegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {447 if (RC == &SystemZ::CCRRegClass)448 return &SystemZ::GR32BitRegClass;449 return RC;450}451 452