forked from OSchip/llvm-project
[MIPS GlobalISel] Select add i32, i32
Add the minimal support necessary to lower a function that returns the sum of two i32 values. Support argument/return lowering of i32 values through registers only. Add tablegen for regbankselect and instructionselect. Patch by Petar Avramovic. Differential Revision: https://reviews.llvm.org/D44304 llvm-svn: 329819
This commit is contained in:
parent
5ba379557d
commit
366857a23a
|
@ -6,9 +6,11 @@ tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv)
|
|||
tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler)
|
||||
tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel)
|
||||
tablegen(LLVM MipsGenGlobalISel.inc -gen-global-isel)
|
||||
tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter)
|
||||
tablegen(LLVM MipsGenMCPseudoLowering.inc -gen-pseudo-lowering)
|
||||
tablegen(LLVM MipsGenRegisterBank.inc -gen-register-bank)
|
||||
tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget)
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ include "MipsRegisterInfo.td"
|
|||
include "MipsSchedule.td"
|
||||
include "MipsInstrInfo.td"
|
||||
include "MipsCallingConv.td"
|
||||
include "MipsRegisterBanks.td"
|
||||
|
||||
// Avoid forward declaration issues.
|
||||
include "MipsScheduleP5600.td"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MipsCallLowering.h"
|
||||
#include "MipsCCState.h"
|
||||
#include "MipsISelLowering.h"
|
||||
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||
|
||||
|
@ -22,13 +23,125 @@ using namespace llvm;
|
|||
MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
|
||||
: CallLowering(&TLI) {}
|
||||
|
||||
bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA,
|
||||
unsigned vreg) {
|
||||
if (VA.isRegLoc()) {
|
||||
assignValueToReg(vreg, VA.getLocReg());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class IncomingValueHandler : public MipsCallLowering::MipsHandler {
|
||||
public:
|
||||
IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
|
||||
: MipsHandler(MIRBuilder, MRI) {}
|
||||
|
||||
bool handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args);
|
||||
|
||||
private:
|
||||
virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
|
||||
|
||||
void markPhysRegUsed(unsigned PhysReg) {
|
||||
MIRBuilder.getMBB().addLiveIn(PhysReg);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void IncomingValueHandler::assignValueToReg(unsigned ValVReg,
|
||||
unsigned PhysReg) {
|
||||
MIRBuilder.buildCopy(ValVReg, PhysReg);
|
||||
markPhysRegUsed(PhysReg);
|
||||
}
|
||||
|
||||
bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args) {
|
||||
for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) {
|
||||
if (!assign(ArgLocs[i], Args[i].Reg))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class OutgoingValueHandler : public MipsCallLowering::MipsHandler {
|
||||
public:
|
||||
OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
||||
MachineInstrBuilder &MIB)
|
||||
: MipsHandler(MIRBuilder, MRI), MIB(MIB) {}
|
||||
|
||||
bool handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args);
|
||||
|
||||
private:
|
||||
virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override;
|
||||
|
||||
MachineInstrBuilder &MIB;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void OutgoingValueHandler::assignValueToReg(unsigned ValVReg,
|
||||
unsigned PhysReg) {
|
||||
MIRBuilder.buildCopy(PhysReg, ValVReg);
|
||||
MIB.addUse(PhysReg, RegState::Implicit);
|
||||
}
|
||||
|
||||
bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs,
|
||||
ArrayRef<CallLowering::ArgInfo> Args) {
|
||||
for (unsigned i = 0; i < Args.size(); ++i) {
|
||||
if (!assign(ArgLocs[i], Args[i].Reg))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isSupportedType(Type *T) {
|
||||
if (T->isIntegerTy() && T->getScalarSizeInBits() == 32)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
||||
const Value *Val, unsigned VReg) const {
|
||||
|
||||
MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
|
||||
|
||||
if (Val != nullptr) {
|
||||
return false;
|
||||
if (!isSupportedType(Val->getType()))
|
||||
return false;
|
||||
|
||||
MachineFunction &MF = MIRBuilder.getMF();
|
||||
const Function &F = MF.getFunction();
|
||||
const DataLayout &DL = MF.getDataLayout();
|
||||
const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
|
||||
|
||||
SmallVector<ArgInfo, 8> RetInfos;
|
||||
SmallVector<unsigned, 8> OrigArgIndices;
|
||||
|
||||
ArgInfo ArgRetInfo(VReg, Val->getType());
|
||||
setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F);
|
||||
splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices);
|
||||
|
||||
SmallVector<ISD::OutputArg, 8> Outs;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, RetInfos, OrigArgIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
|
||||
unsigned origIdx, unsigned partOffs) {
|
||||
Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
F.getContext());
|
||||
CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn());
|
||||
|
||||
OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret);
|
||||
if (!RetHandler.handle(ArgLocs, RetInfos)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
MIRBuilder.insertInstr(Ret);
|
||||
return true;
|
||||
|
@ -42,6 +155,80 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
|||
if (F.arg_empty())
|
||||
return true;
|
||||
|
||||
// Function had args, but we didn't lower them.
|
||||
return false;
|
||||
if (F.isVarArg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &Arg : F.args()) {
|
||||
if (!isSupportedType(Arg.getType()))
|
||||
return false;
|
||||
}
|
||||
|
||||
MachineFunction &MF = MIRBuilder.getMF();
|
||||
const DataLayout &DL = MF.getDataLayout();
|
||||
const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
|
||||
|
||||
SmallVector<ArgInfo, 8> ArgInfos;
|
||||
SmallVector<unsigned, 8> OrigArgIndices;
|
||||
unsigned i = 0;
|
||||
for (auto &Arg : F.args()) {
|
||||
ArgInfo AInfo(VRegs[i], Arg.getType());
|
||||
setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F);
|
||||
splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices);
|
||||
++i;
|
||||
}
|
||||
|
||||
SmallVector<ISD::InputArg, 8> Ins;
|
||||
subTargetRegTypeForCallingConv(
|
||||
MIRBuilder, ArgInfos, OrigArgIndices,
|
||||
[&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx,
|
||||
unsigned partOffs) {
|
||||
Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs);
|
||||
});
|
||||
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs,
|
||||
F.getContext());
|
||||
|
||||
CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall());
|
||||
|
||||
IncomingValueHandler Handler(MIRBuilder, MIRBuilder.getMF().getRegInfo());
|
||||
if (!Handler.handle(ArgLocs, ArgInfos))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MipsCallLowering::subTargetRegTypeForCallingConv(
|
||||
MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args,
|
||||
ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const {
|
||||
MachineFunction &MF = MIRBuilder.getMF();
|
||||
const Function &F = MF.getFunction();
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>();
|
||||
|
||||
unsigned ArgNo = 0;
|
||||
for (auto &Arg : Args) {
|
||||
|
||||
EVT VT = TLI.getValueType(DL, Arg.Ty);
|
||||
MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT);
|
||||
|
||||
ISD::ArgFlagsTy Flags = Arg.Flags;
|
||||
Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL));
|
||||
|
||||
PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0);
|
||||
|
||||
++ArgNo;
|
||||
}
|
||||
}
|
||||
|
||||
void MipsCallLowering::splitToValueTypes(
|
||||
const ArgInfo &OrigArg, unsigned OriginalIndex,
|
||||
SmallVectorImpl<ArgInfo> &SplitArgs,
|
||||
SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const {
|
||||
|
||||
// TODO : perform structure and array split. For now we only deal with
|
||||
// types that pass isSupportedType check.
|
||||
SplitArgs.push_back(OrigArg);
|
||||
SplitArgsOrigIndices.push_back(OriginalIndex);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,22 @@ class MipsTargetLowering;
|
|||
class MipsCallLowering : public CallLowering {
|
||||
|
||||
public:
|
||||
class MipsHandler {
|
||||
public:
|
||||
MipsHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
|
||||
: MIRBuilder(MIRBuilder), MRI(MRI) {}
|
||||
|
||||
virtual ~MipsHandler() = default;
|
||||
|
||||
protected:
|
||||
virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) = 0;
|
||||
|
||||
bool assign(const CCValAssign &VA, unsigned vreg);
|
||||
|
||||
MachineIRBuilder &MIRBuilder;
|
||||
MachineRegisterInfo &MRI;
|
||||
};
|
||||
|
||||
MipsCallLowering(const MipsTargetLowering &TLI);
|
||||
|
||||
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
|
||||
|
@ -33,6 +49,26 @@ public:
|
|||
|
||||
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
|
||||
ArrayRef<unsigned> VRegs) const override;
|
||||
|
||||
private:
|
||||
using FunTy =
|
||||
std::function<void(ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
|
||||
unsigned origIdx, unsigned partOffs)>;
|
||||
|
||||
/// Based on registers available on target machine split or extend
|
||||
/// type if needed, also change pointer type to appropriate integer
|
||||
/// type. Lambda will fill some info so we can tell MipsCCState to
|
||||
/// assign physical registers.
|
||||
void subTargetRegTypeForCallingConv(MachineIRBuilder &MIRBuilder,
|
||||
ArrayRef<ArgInfo> Args,
|
||||
ArrayRef<unsigned> OrigArgIndices,
|
||||
const FunTy &PushBack) const;
|
||||
|
||||
/// Split structures and arrays, save original argument indices since
|
||||
/// Mips calling conv needs info about original argument type.
|
||||
void splitToValueTypes(const ArgInfo &OrigArg, unsigned OriginalIndex,
|
||||
SmallVectorImpl<ArgInfo> &SplitArgs,
|
||||
SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -2833,6 +2833,13 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
|
|||
|
||||
#include "MipsGenCallingConv.inc"
|
||||
|
||||
CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{
|
||||
return CC_Mips;
|
||||
}
|
||||
|
||||
CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{
|
||||
return RetCC_Mips;
|
||||
}
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
||||
#include "Mips.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
|
@ -365,6 +366,10 @@ class TargetRegisterClass;
|
|||
return getTargetMachine().isPositionIndependent();
|
||||
}
|
||||
|
||||
CCAssignFn *CCAssignFnForCall() const;
|
||||
|
||||
CCAssignFn *CCAssignFnForReturn() const;
|
||||
|
||||
protected:
|
||||
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
|
||||
|
||||
|
|
|
@ -15,41 +15,101 @@
|
|||
#include "MipsRegisterBankInfo.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
#define DEBUG_TYPE "mips-isel"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
#define GET_GLOBALISEL_PREDICATE_BITSET
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_PREDICATE_BITSET
|
||||
|
||||
class MipsInstructionSelector : public InstructionSelector {
|
||||
public:
|
||||
MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
||||
const MipsRegisterBankInfo &RBI);
|
||||
|
||||
bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
|
||||
static const char *getName() { return DEBUG_TYPE; }
|
||||
|
||||
private:
|
||||
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
|
||||
|
||||
const MipsTargetMachine &TM;
|
||||
const MipsSubtarget &STI;
|
||||
const MipsInstrInfo &TII;
|
||||
const MipsRegisterInfo &TRI;
|
||||
const MipsRegisterBankInfo &RBI;
|
||||
|
||||
#define GET_GLOBALISEL_PREDICATES_DECL
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_PREDICATES_DECL
|
||||
|
||||
#define GET_GLOBALISEL_TEMPORARIES_DECL
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_TEMPORARIES_DECL
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
#define GET_GLOBALISEL_IMPL
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_IMPL
|
||||
|
||||
MipsInstructionSelector::MipsInstructionSelector(
|
||||
const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
||||
const MipsRegisterBankInfo &RBI)
|
||||
: InstructionSelector(), TII(*STI.getInstrInfo()),
|
||||
TRI(*STI.getRegisterInfo()) {}
|
||||
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
||||
TRI(*STI.getRegisterInfo()), RBI(RBI),
|
||||
|
||||
#define GET_GLOBALISEL_PREDICATES_INIT
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_PREDICATES_INIT
|
||||
#define GET_GLOBALISEL_TEMPORARIES_INIT
|
||||
#include "MipsGenGlobalISel.inc"
|
||||
#undef GET_GLOBALISEL_TEMPORARIES_INIT
|
||||
{
|
||||
}
|
||||
|
||||
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
|
||||
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
|
||||
const RegisterBankInfo &RBI) {
|
||||
unsigned DstReg = I.getOperand(0).getReg();
|
||||
if (TargetRegisterInfo::isPhysicalRegister(DstReg))
|
||||
return true;
|
||||
|
||||
const TargetRegisterClass *RC = &Mips::GPR32RegClass;
|
||||
|
||||
if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
|
||||
DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
|
||||
<< " operand\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MipsInstructionSelector::select(MachineInstr &I,
|
||||
CodeGenCoverage &CoverageInfo) const {
|
||||
|
||||
MachineBasicBlock &MBB = *I.getParent();
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
|
||||
if (!isPreISelGenericOpcode(I.getOpcode())) {
|
||||
// Not global isel generic opcode.
|
||||
// TODO: select copy
|
||||
if (I.isCopy())
|
||||
return selectCopy(I, TII, MRI, TRI, RBI);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (selectImpl(I, CoverageInfo)) {
|
||||
return true;
|
||||
}
|
||||
// We didn't select anything.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -20,5 +20,11 @@
|
|||
using namespace llvm;
|
||||
|
||||
MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
|
||||
using namespace TargetOpcode;
|
||||
|
||||
const LLT s32 = LLT::scalar(32);
|
||||
|
||||
getActionDefinitionsBuilder(G_ADD).legalFor({s32});
|
||||
|
||||
computeTables();
|
||||
}
|
||||
|
|
|
@ -11,16 +11,84 @@
|
|||
/// \todo This should be generated by TableGen.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsRegisterBankInfo.h"
|
||||
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
|
||||
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
#define GET_TARGET_REGBANK_IMPL
|
||||
|
||||
MipsGenRegisterBankInfo::MipsGenRegisterBankInfo()
|
||||
: RegisterBankInfo(nullptr, 0) {}
|
||||
#define DEBUG_TYPE "registerbankinfo"
|
||||
|
||||
#include "MipsGenRegisterBank.inc"
|
||||
|
||||
namespace llvm {
|
||||
namespace Mips {
|
||||
enum PartialMappingIdx {
|
||||
PMI_GPR,
|
||||
PMI_Min = PMI_GPR,
|
||||
};
|
||||
|
||||
RegisterBankInfo::PartialMapping PartMappings[]{
|
||||
{0, 32, GPRBRegBank}
|
||||
};
|
||||
|
||||
enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1 };
|
||||
|
||||
RegisterBankInfo::ValueMapping ValueMappings[] = {
|
||||
// invalid
|
||||
{nullptr, 0},
|
||||
// 3 operands in GPRs
|
||||
{&PartMappings[PMI_GPR - PMI_Min], 1},
|
||||
{&PartMappings[PMI_GPR - PMI_Min], 1},
|
||||
{&PartMappings[PMI_GPR - PMI_Min], 1}};
|
||||
|
||||
} // end namespace Mips
|
||||
} // end namespace llvm
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
|
||||
: MipsGenRegisterBankInfo() {}
|
||||
|
||||
const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
|
||||
const TargetRegisterClass &RC) const {
|
||||
using namespace Mips;
|
||||
|
||||
switch (RC.getID()) {
|
||||
case Mips::GPR32RegClassID:
|
||||
case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
|
||||
case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
|
||||
return getRegBank(Mips::GPRBRegBankID);
|
||||
default:
|
||||
llvm_unreachable("Register class not supported");
|
||||
}
|
||||
}
|
||||
|
||||
const RegisterBankInfo::InstructionMapping &
|
||||
MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
||||
|
||||
unsigned Opc = MI.getOpcode();
|
||||
|
||||
const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI);
|
||||
if (Mapping.isValid())
|
||||
return Mapping;
|
||||
|
||||
using namespace TargetOpcode;
|
||||
|
||||
unsigned NumOperands = MI.getNumOperands();
|
||||
const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
|
||||
|
||||
switch (Opc) {
|
||||
case G_ADD:
|
||||
OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
|
||||
break;
|
||||
default:
|
||||
return getInvalidInstructionMapping();
|
||||
}
|
||||
|
||||
return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
|
||||
NumOperands);
|
||||
}
|
||||
|
|
|
@ -16,20 +16,28 @@
|
|||
|
||||
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
||||
|
||||
#define GET_REGBANK_DECLARATIONS
|
||||
#include "MipsGenRegisterBank.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class TargetRegisterInfo;
|
||||
|
||||
class MipsGenRegisterBankInfo : public RegisterBankInfo {
|
||||
// TODO: This should be auto-generated by TableGen.
|
||||
public:
|
||||
MipsGenRegisterBankInfo();
|
||||
#define GET_TARGET_REGBANK_CLASS
|
||||
#include "MipsGenRegisterBank.inc"
|
||||
};
|
||||
|
||||
/// This class provides the information for the target register banks.
|
||||
class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo {
|
||||
public:
|
||||
MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
|
||||
|
||||
const RegisterBank &
|
||||
getRegBankFromRegClass(const TargetRegisterClass &RC) const override;
|
||||
|
||||
const InstructionMapping &
|
||||
getInstrMapping(const MachineInstr &MI) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
//===- MipsRegisterBank.td ---------------------------------*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def GPRBRegBank : RegisterBank<"GPRB", [GPR32]>;
|
|
@ -0,0 +1,35 @@
|
|||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
define void @add_i32(i32 %x, i32 %y) {entry: ret void}
|
||||
|
||||
...
|
||||
---
|
||||
name: add_i32
|
||||
alignment: 2
|
||||
legalized: true
|
||||
regBankSelected: true
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: gprb }
|
||||
- { id: 1, class: gprb }
|
||||
- { id: 2, class: gprb }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $a0, $a1
|
||||
|
||||
; MIPS32-LABEL: name: add_i32
|
||||
; MIPS32: liveins: $a0, $a1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
|
||||
; MIPS32: [[ADDu:%[0-9]+]]:gpr32 = ADDu [[COPY]], [[COPY1]]
|
||||
; MIPS32: $v0 = COPY [[ADDu]]
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:gprb(s32) = COPY $a0
|
||||
%1:gprb(s32) = COPY $a1
|
||||
%2:gprb(s32) = G_ADD %0, %1
|
||||
$v0 = COPY %2(s32)
|
||||
RetRA implicit $v0
|
||||
|
||||
...
|
|
@ -0,0 +1,16 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
|
||||
define i32 @add_i32(i32 %x, i32 %y) {
|
||||
; MIPS32-LABEL: name: add_i32
|
||||
; MIPS32: bb.1.entry:
|
||||
; MIPS32: liveins: $a0, $a1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]]
|
||||
; MIPS32: $v0 = COPY [[ADD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
entry:
|
||||
%z = add i32 %x, %y
|
||||
ret i32 %z
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
define void @add_i32(i32 %x, i32 %y) {entry: ret void}
|
||||
|
||||
...
|
||||
---
|
||||
name: add_i32
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: _ }
|
||||
- { id: 1, class: _ }
|
||||
- { id: 2, class: _ }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $a0, $a1
|
||||
|
||||
; MIPS32-LABEL: name: add_i32
|
||||
; MIPS32: liveins: $a0, $a1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
|
||||
; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]]
|
||||
; MIPS32: $v0 = COPY [[ADD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:_(s32) = COPY $a0
|
||||
%1:_(s32) = COPY $a1
|
||||
%2:_(s32) = G_ADD %0, %1
|
||||
$v0 = COPY %2(s32)
|
||||
RetRA implicit $v0
|
||||
|
||||
...
|
|
@ -0,0 +1,12 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
|
||||
define i32 @add_i32(i32 %x, i32 %y) {
|
||||
; MIPS32-LABEL: add_i32:
|
||||
; MIPS32: # %bb.0: # %entry
|
||||
; MIPS32-NEXT: addu $2, $4, $5
|
||||
; MIPS32-NEXT: jr $ra
|
||||
; MIPS32-NEXT: nop
|
||||
entry:
|
||||
%z = add i32 %x, %y
|
||||
ret i32 %z
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
|
||||
--- |
|
||||
|
||||
define void @add_i32(i32 %x, i32 %y) {entry: ret void}
|
||||
|
||||
...
|
||||
---
|
||||
name: add_i32
|
||||
alignment: 2
|
||||
legalized: true
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: _ }
|
||||
- { id: 1, class: _ }
|
||||
- { id: 2, class: _ }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: $a0, $a1
|
||||
|
||||
; MIPS32-LABEL: name: add_i32
|
||||
; MIPS32: liveins: $a0, $a1
|
||||
; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0
|
||||
; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1
|
||||
; MIPS32: [[ADD:%[0-9]+]]:gprb(s32) = G_ADD [[COPY]], [[COPY1]]
|
||||
; MIPS32: $v0 = COPY [[ADD]](s32)
|
||||
; MIPS32: RetRA implicit $v0
|
||||
%0:_(s32) = COPY $a0
|
||||
%1:_(s32) = COPY $a1
|
||||
%2:_(s32) = G_ADD %0, %1
|
||||
$v0 = COPY %2(s32)
|
||||
RetRA implicit $v0
|
||||
|
||||
...
|
Loading…
Reference in New Issue