1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 12:02:58 +02:00
llvm-mirror/lib/Target/Hexagon/HexagonRegisterInfo.cpp
Chandler Carruth ae65e281f3 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

347 lines
12 KiB
C++

//===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains the Hexagon implementation of the TargetRegisterInfo
// class.
//
//===----------------------------------------------------------------------===//
#include "HexagonRegisterInfo.h"
#include "Hexagon.h"
#include "HexagonMachineFunctionInfo.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#define GET_REGINFO_TARGET_DESC
#include "HexagonGenRegisterInfo.inc"
using namespace llvm;
HexagonRegisterInfo::HexagonRegisterInfo(unsigned HwMode)
: HexagonGenRegisterInfo(Hexagon::R31, 0/*DwarfFlavor*/, 0/*EHFlavor*/,
0/*PC*/, HwMode) {}
bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(unsigned R) const {
return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 ||
R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1;
}
const MCPhysReg *
HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF,
const TargetRegisterClass *RC) const {
using namespace Hexagon;
static const MCPhysReg Int32[] = {
R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, 0
};
static const MCPhysReg Int64[] = {
D0, D1, D2, D3, D4, D5, D6, D7, 0
};
static const MCPhysReg Pred[] = {
P0, P1, P2, P3, 0
};
static const MCPhysReg VecSgl[] = {
V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13,
V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27,
V28, V29, V30, V31, 0
};
static const MCPhysReg VecDbl[] = {
W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, 0
};
switch (RC->getID()) {
case IntRegsRegClassID:
return Int32;
case DoubleRegsRegClassID:
return Int64;
case PredRegsRegClassID:
return Pred;
case HvxVRRegClassID:
return VecSgl;
case HvxWRRegClassID:
return VecDbl;
default:
break;
}
static const MCPhysReg Empty[] = { 0 };
#ifndef NDEBUG
dbgs() << "Register class: " << getRegClassName(RC) << "\n";
#endif
llvm_unreachable("Unexpected register class");
return Empty;
}
const MCPhysReg *
HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
static const MCPhysReg CalleeSavedRegsV3[] = {
Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23,
Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
};
// Functions that contain a call to __builtin_eh_return also save the first 4
// parameter registers.
static const MCPhysReg CalleeSavedRegsV3EHReturn[] = {
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3,
Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23,
Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
};
bool HasEHReturn = MF->getInfo<HexagonMachineFunctionInfo>()->hasEHReturn();
return HasEHReturn ? CalleeSavedRegsV3EHReturn : CalleeSavedRegsV3;
}
const uint32_t *HexagonRegisterInfo::getCallPreservedMask(
const MachineFunction &MF, CallingConv::ID) const {
return HexagonCSR_RegMask;
}
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
const {
BitVector Reserved(getNumRegs());
Reserved.set(Hexagon::R29);
Reserved.set(Hexagon::R30);
Reserved.set(Hexagon::R31);
Reserved.set(Hexagon::VTMP);
// Guest registers.
Reserved.set(Hexagon::GELR); // G0
Reserved.set(Hexagon::GSR); // G1
Reserved.set(Hexagon::GOSP); // G2
Reserved.set(Hexagon::G3); // G3
// Control registers.
Reserved.set(Hexagon::SA0); // C0
Reserved.set(Hexagon::LC0); // C1
Reserved.set(Hexagon::SA1); // C2
Reserved.set(Hexagon::LC1); // C3
Reserved.set(Hexagon::P3_0); // C4
Reserved.set(Hexagon::USR); // C8
Reserved.set(Hexagon::PC); // C9
Reserved.set(Hexagon::UGP); // C10
Reserved.set(Hexagon::GP); // C11
Reserved.set(Hexagon::CS0); // C12
Reserved.set(Hexagon::CS1); // C13
Reserved.set(Hexagon::UPCYCLELO); // C14
Reserved.set(Hexagon::UPCYCLEHI); // C15
Reserved.set(Hexagon::FRAMELIMIT); // C16
Reserved.set(Hexagon::FRAMEKEY); // C17
Reserved.set(Hexagon::PKTCOUNTLO); // C18
Reserved.set(Hexagon::PKTCOUNTHI); // C19
Reserved.set(Hexagon::UTIMERLO); // C30
Reserved.set(Hexagon::UTIMERHI); // C31
// Out of the control registers, only C8 is explicitly defined in
// HexagonRegisterInfo.td. If others are defined, make sure to add
// them here as well.
Reserved.set(Hexagon::C8);
Reserved.set(Hexagon::USR_OVF);
if (MF.getSubtarget<HexagonSubtarget>().hasReservedR19())
Reserved.set(Hexagon::R19);
for (int x = Reserved.find_first(); x >= 0; x = Reserved.find_next(x))
markSuperRegs(Reserved, x);
return Reserved;
}
void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOp,
RegScavenger *RS) const {
//
// Hexagon_TODO: Do we need to enforce this for Hexagon?
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
MachineBasicBlock &MB = *MI.getParent();
MachineFunction &MF = *MB.getParent();
auto &HST = MF.getSubtarget<HexagonSubtarget>();
auto &HII = *HST.getInstrInfo();
auto &HFI = *HST.getFrameLowering();
unsigned BP = 0;
int FI = MI.getOperand(FIOp).getIndex();
// Select the base pointer (BP) and calculate the actual offset from BP
// to the beginning of the object at index FI.
int Offset = HFI.getFrameIndexReference(MF, FI, BP);
// Add the offset from the instruction.
int RealOffset = Offset + MI.getOperand(FIOp+1).getImm();
bool IsKill = false;
unsigned Opc = MI.getOpcode();
switch (Opc) {
case Hexagon::PS_fia:
MI.setDesc(HII.get(Hexagon::A2_addi));
MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
MI.RemoveOperand(FIOp+1);
return;
case Hexagon::PS_fi:
// Set up the instruction for updating below.
MI.setDesc(HII.get(Hexagon::A2_addi));
break;
}
if (!HII.isValidOffset(Opc, RealOffset, this)) {
// If the offset is not valid, calculate the address in a temporary
// register and use it with offset 0.
auto &MRI = MF.getRegInfo();
unsigned TmpR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);
const DebugLoc &DL = MI.getDebugLoc();
BuildMI(MB, II, DL, HII.get(Hexagon::A2_addi), TmpR)
.addReg(BP)
.addImm(RealOffset);
BP = TmpR;
RealOffset = 0;
IsKill = true;
}
MI.getOperand(FIOp).ChangeToRegister(BP, false, false, IsKill);
MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
}
bool HexagonRegisterInfo::shouldCoalesce(MachineInstr *MI,
const TargetRegisterClass *SrcRC, unsigned SubReg,
const TargetRegisterClass *DstRC, unsigned DstSubReg,
const TargetRegisterClass *NewRC, LiveIntervals &LIS) const {
// Coalescing will extend the live interval of the destination register.
// If the destination register is a vector pair, avoid introducing function
// calls into the interval, since it could result in a spilling of a pair
// instead of a single vector.
MachineFunction &MF = *MI->getParent()->getParent();
const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
if (!HST.useHVXOps() || NewRC->getID() != Hexagon::HvxWRRegClass.getID())
return true;
bool SmallSrc = SrcRC->getID() == Hexagon::HvxVRRegClass.getID();
bool SmallDst = DstRC->getID() == Hexagon::HvxVRRegClass.getID();
if (!SmallSrc && !SmallDst)
return true;
unsigned DstReg = MI->getOperand(0).getReg();
unsigned SrcReg = MI->getOperand(1).getReg();
const SlotIndexes &Indexes = *LIS.getSlotIndexes();
auto HasCall = [&Indexes] (const LiveInterval::Segment &S) {
for (SlotIndex I = S.start.getBaseIndex(), E = S.end.getBaseIndex();
I != E; I = I.getNextIndex()) {
if (const MachineInstr *MI = Indexes.getInstructionFromIndex(I))
if (MI->isCall())
return true;
}
return false;
};
if (SmallSrc == SmallDst) {
// Both must be true, because the case for both being false was
// checked earlier. Both registers will be coalesced into a register
// of a wider class (HvxWR), and we don't want its live range to
// span over calls.
return !any_of(LIS.getInterval(DstReg), HasCall) &&
!any_of(LIS.getInterval(SrcReg), HasCall);
}
// If one register is large (HvxWR) and the other is small (HvxVR), then
// coalescing is ok if the large is already live across a function call,
// or if the small one is not.
unsigned SmallReg = SmallSrc ? SrcReg : DstReg;
unsigned LargeReg = SmallSrc ? DstReg : SrcReg;
return any_of(LIS.getInterval(LargeReg), HasCall) ||
!any_of(LIS.getInterval(SmallReg), HasCall);
}
unsigned HexagonRegisterInfo::getRARegister() const {
return Hexagon::R31;
}
unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
&MF) const {
const HexagonFrameLowering *TFI = getFrameLowering(MF);
if (TFI->hasFP(MF))
return getFrameRegister();
return getStackRegister();
}
unsigned HexagonRegisterInfo::getFrameRegister() const {
return Hexagon::R30;
}
unsigned HexagonRegisterInfo::getStackRegister() const {
return Hexagon::R29;
}
unsigned HexagonRegisterInfo::getHexagonSubRegIndex(
const TargetRegisterClass &RC, unsigned GenIdx) const {
assert(GenIdx == Hexagon::ps_sub_lo || GenIdx == Hexagon::ps_sub_hi);
static const unsigned ISub[] = { Hexagon::isub_lo, Hexagon::isub_hi };
static const unsigned VSub[] = { Hexagon::vsub_lo, Hexagon::vsub_hi };
static const unsigned WSub[] = { Hexagon::wsub_lo, Hexagon::wsub_hi };
switch (RC.getID()) {
case Hexagon::CtrRegs64RegClassID:
case Hexagon::DoubleRegsRegClassID:
return ISub[GenIdx];
case Hexagon::HvxWRRegClassID:
return VSub[GenIdx];
case Hexagon::HvxVQRRegClassID:
return WSub[GenIdx];
}
if (const TargetRegisterClass *SuperRC = *RC.getSuperClasses())
return getHexagonSubRegIndex(*SuperRC, GenIdx);
llvm_unreachable("Invalid register class");
}
bool HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF)
const {
return MF.getSubtarget<HexagonSubtarget>().getFrameLowering()->hasFP(MF);
}
const TargetRegisterClass *
HexagonRegisterInfo::getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const {
return &Hexagon::IntRegsRegClass;
}
unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
return Hexagon::R6;
}