llvm-6502/lib/Target/Hexagon/HexagonRegisterInfo.cpp
Chandler Carruth 37097623bb This reverts a long string of commits to the Hexagon backend. These
commits have had several major issues pointed out in review, and those
issues are not being addressed in a timely fashion. Furthermore, this
was all committed leading up to the v3.1 branch, and we don't need piles
of code with outstanding issues in the branch.

It is possible that not all of these commits were necessary to revert to
get us back to a green state, but I'm going to let the Hexagon
maintainer sort that out. They can recommit, in order, after addressing
the feedback.

Reverted commits, with some notes:

Primary commit r154616: HexagonPacketizer
  - There are lots of review comments here. This is the primary reason
    for reverting. In particular, it introduced large amount of warnings
    due to a bad construct in tablegen.
  - Follow-up commits that should be folded back into this when
    reposting:
    - r154622: CMake fixes
    - r154660: Fix numerous build warnings in release builds.
  - Please don't resubmit this until the three commits above are
    included, and the issues in review addressed.

Primary commit r154695: Pass to replace transfer/copy ...
  - Reverted to minimize merge conflicts. I'm not aware of specific
    issues with this patch.

Primary commit r154703: New Value Jump.
  - Primarily reverted due to merge conflicts.
  - Follow-up commits that should be folded back into this when
    reposting:
    - r154703: Remove iostream usage
    - r154758: Fix CMake builds
    - r154759: Fix build warnings in release builds
  - Please incorporate these fixes and and review feedback before
    resubmitting.

Primary commit r154829: Hexagon V5 (floating point) support.
  - Primarily reverted due to merge conflicts.
  - Follow-up commits that should be folded back into this when
    reposting:
    - r154841: Remove unused variable (fixing build warnings)

There are also accompanying Clang commits that will be reverted for
consistency.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155047 91177308-0d34-0410-b5e6-96231b3b80d8
2012-04-18 21:31:19 +00:00

316 lines
11 KiB
C++

//===-- HexagonRegisterInfo.cpp - Hexagon Register Information ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the Hexagon implementation of the TargetRegisterInfo
// class.
//
//===----------------------------------------------------------------------===//
#include "HexagonRegisterInfo.h"
#include "Hexagon.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include "HexagonMachineFunctionInfo.h"
#include "llvm/Function.h"
#include "llvm/Type.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st,
const HexagonInstrInfo &tii)
: HexagonGenRegisterInfo(Hexagon::R31),
Subtarget(st),
TII(tii) {
}
const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
*MF)
const {
static const uint16_t CalleeSavedRegsV2[] = {
Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
};
static const uint16_t 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
};
switch(Subtarget.getHexagonArchVersion()) {
case HexagonSubtarget::V1:
break;
case HexagonSubtarget::V2:
return CalleeSavedRegsV2;
case HexagonSubtarget::V3:
case HexagonSubtarget::V4:
return CalleeSavedRegsV3;
}
llvm_unreachable("Callee saved registers requested for unknown architecture "
"version");
}
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
const {
BitVector Reserved(getNumRegs());
Reserved.set(HEXAGON_RESERVED_REG_1);
Reserved.set(HEXAGON_RESERVED_REG_2);
Reserved.set(Hexagon::R29);
Reserved.set(Hexagon::R30);
Reserved.set(Hexagon::R31);
Reserved.set(Hexagon::D14);
Reserved.set(Hexagon::D15);
Reserved.set(Hexagon::LC0);
Reserved.set(Hexagon::LC1);
Reserved.set(Hexagon::SA0);
Reserved.set(Hexagon::SA1);
return Reserved;
}
const TargetRegisterClass* const*
HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
};
static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
};
switch(Subtarget.getHexagonArchVersion()) {
case HexagonSubtarget::V1:
break;
case HexagonSubtarget::V2:
return CalleeSavedRegClassesV2;
case HexagonSubtarget::V3:
case HexagonSubtarget::V4:
return CalleeSavedRegClassesV3;
}
llvm_unreachable("Callee saved register classes requested for unknown "
"architecture version");
}
void HexagonRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
MachineInstr &MI = *I;
if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
// Hexagon_TODO: add code
} else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
// Hexagon_TODO: add code
} else {
llvm_unreachable("Cannot handle this call frame pseudo instruction");
}
MBB.erase(I);
}
void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, RegScavenger *RS) const {
//
// Hexagon_TODO: Do we need to enforce this for Hexagon?
assert(SPAdj == 0 && "Unexpected");
unsigned i = 0;
MachineInstr &MI = *II;
while (!MI.getOperand(i).isFI()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getIndex();
// Addressable stack objects are accessed using neg. offsets from %fp.
MachineFunction &MF = *MI.getParent()->getParent();
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
MachineFrameInfo &MFI = *MF.getFrameInfo();
unsigned FrameReg = getFrameRegister(MF);
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
if (!TFI->hasFP(MF)) {
// We will not reserve space on the stack for the lr and fp registers.
Offset -= 2 * Hexagon_WordSize;
}
const unsigned FrameSize = MFI.getStackSize();
if (!MFI.hasVarSizedObjects() &&
TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
!TII.isSpillPredRegOp(&MI)) {
// Replace frame index with a stack pointer reference.
MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true);
MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
} else {
// Replace frame index with a frame pointer reference.
if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
// If the offset overflows, then correct it.
//
// For loads, we do not need a reserved register
// r0 = memw(r30 + #10000) to:
//
// r0 = add(r30, #10000)
// r0 = memw(r0)
if ( (MI.getOpcode() == Hexagon::LDriw) ||
(MI.getOpcode() == Hexagon::LDrid) ||
(MI.getOpcode() == Hexagon::LDrih) ||
(MI.getOpcode() == Hexagon::LDriuh) ||
(MI.getOpcode() == Hexagon::LDrib) ||
(MI.getOpcode() == Hexagon::LDriub) ) {
unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
*getSubRegisters(MI.getOperand(0).getReg()) :
MI.getOperand(0).getReg();
// Check if offset can fit in addi.
if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_rr),
dstReg).addReg(FrameReg).addReg(dstReg);
} else {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_ri),
dstReg).addReg(FrameReg).addImm(Offset);
}
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
MI.getOperand(i+1).ChangeToImmediate(0);
} else if ((MI.getOpcode() == Hexagon::STriw) ||
(MI.getOpcode() == Hexagon::STrid) ||
(MI.getOpcode() == Hexagon::STrih) ||
(MI.getOpcode() == Hexagon::STrib)) {
// For stores, we need a reserved register. Change
// memw(r30 + #10000) = r0 to:
//
// rs = add(r30, #10000);
// memw(rs) = r0
unsigned resReg = HEXAGON_RESERVED_REG_1;
// Check if offset can fit in addi.
if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_rr),
resReg).addReg(FrameReg).addReg(resReg);
} else {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_ri),
resReg).addReg(FrameReg).addImm(Offset);
}
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
MI.getOperand(i+1).ChangeToImmediate(0);
} else if (TII.isMemOp(&MI)) {
unsigned resReg = HEXAGON_RESERVED_REG_1;
if (!MFI.hasVarSizedObjects() &&
TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false,
true);
MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
} else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_rr),
resReg).addReg(FrameReg).addReg(resReg);
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
MI.getOperand(i+1).ChangeToImmediate(0);
} else {
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_ri),
resReg).addReg(FrameReg).addImm(Offset);
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
MI.getOperand(i+1).ChangeToImmediate(0);
}
} else {
unsigned dstReg = MI.getOperand(0).getReg();
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
TII.get(Hexagon::ADD_rr),
dstReg).addReg(FrameReg).addReg(dstReg);
// Can we delete MI??? r2 = add (r2, #0).
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
MI.getOperand(i+1).ChangeToImmediate(0);
}
} else {
// If the offset is small enough to fit in the immediate field, directly
// encode it.
MI.getOperand(i).ChangeToRegister(FrameReg, false);
MI.getOperand(i+1).ChangeToImmediate(Offset);
}
}
}
unsigned HexagonRegisterInfo::getRARegister() const {
return Hexagon::R31;
}
unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
&MF) const {
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
if (TFI->hasFP(MF)) {
return Hexagon::R30;
}
return Hexagon::R29;
}
unsigned HexagonRegisterInfo::getFrameRegister() const {
return Hexagon::R30;
}
unsigned HexagonRegisterInfo::getStackRegister() const {
return Hexagon::R29;
}
void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
&Moves) const
{
// VirtualFP = (R30 + #0).
unsigned FPReg = getFrameRegister();
MachineLocation Dst(MachineLocation::VirtualFP);
MachineLocation Src(FPReg, 0);
Moves.push_back(MachineMove(0, Dst, Src));
}
unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
llvm_unreachable("What is the exception register");
}
unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
}
#define GET_REGINFO_TARGET_DESC
#include "HexagonGenRegisterInfo.inc"