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 MipsGenDAGISel.inc -gen-dag-isel)
|
||||||
tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler)
|
tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler)
|
||||||
tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel)
|
tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel)
|
||||||
|
tablegen(LLVM MipsGenGlobalISel.inc -gen-global-isel)
|
||||||
tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info)
|
tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info)
|
||||||
tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter)
|
tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter)
|
||||||
tablegen(LLVM MipsGenMCPseudoLowering.inc -gen-pseudo-lowering)
|
tablegen(LLVM MipsGenMCPseudoLowering.inc -gen-pseudo-lowering)
|
||||||
|
tablegen(LLVM MipsGenRegisterBank.inc -gen-register-bank)
|
||||||
tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info)
|
tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info)
|
||||||
tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget)
|
tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget)
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ include "MipsRegisterInfo.td"
|
||||||
include "MipsSchedule.td"
|
include "MipsSchedule.td"
|
||||||
include "MipsInstrInfo.td"
|
include "MipsInstrInfo.td"
|
||||||
include "MipsCallingConv.td"
|
include "MipsCallingConv.td"
|
||||||
|
include "MipsRegisterBanks.td"
|
||||||
|
|
||||||
// Avoid forward declaration issues.
|
// Avoid forward declaration issues.
|
||||||
include "MipsScheduleP5600.td"
|
include "MipsScheduleP5600.td"
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "MipsCallLowering.h"
|
#include "MipsCallLowering.h"
|
||||||
|
#include "MipsCCState.h"
|
||||||
#include "MipsISelLowering.h"
|
#include "MipsISelLowering.h"
|
||||||
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
||||||
|
|
||||||
|
@ -22,13 +23,125 @@ using namespace llvm;
|
||||||
MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
|
MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI)
|
||||||
: CallLowering(&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,
|
bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
||||||
const Value *Val, unsigned VReg) const {
|
const Value *Val, unsigned VReg) const {
|
||||||
|
|
||||||
MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
|
MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA);
|
||||||
|
|
||||||
if (Val != nullptr) {
|
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);
|
MIRBuilder.insertInstr(Ret);
|
||||||
return true;
|
return true;
|
||||||
|
@ -42,6 +155,80 @@ bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
||||||
if (F.arg_empty())
|
if (F.arg_empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Function had args, but we didn't lower them.
|
if (F.isVarArg()) {
|
||||||
return false;
|
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 {
|
class MipsCallLowering : public CallLowering {
|
||||||
|
|
||||||
public:
|
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);
|
MipsCallLowering(const MipsTargetLowering &TLI);
|
||||||
|
|
||||||
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
|
bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
|
||||||
|
@ -33,6 +49,26 @@ public:
|
||||||
|
|
||||||
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
|
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
|
||||||
ArrayRef<unsigned> VRegs) const override;
|
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
|
} // end namespace llvm
|
||||||
|
|
|
@ -2833,6 +2833,13 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
|
||||||
|
|
||||||
#include "MipsGenCallingConv.inc"
|
#include "MipsGenCallingConv.inc"
|
||||||
|
|
||||||
|
CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{
|
||||||
|
return CC_Mips;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{
|
||||||
|
return RetCC_Mips;
|
||||||
|
}
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Call Calling Convention Implementation
|
// Call Calling Convention Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||||
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
#include "MCTargetDesc/MipsMCTargetDesc.h"
|
||||||
#include "Mips.h"
|
#include "Mips.h"
|
||||||
|
#include "llvm/CodeGen/CallingConvLower.h"
|
||||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
|
@ -365,6 +366,10 @@ class TargetRegisterClass;
|
||||||
return getTargetMachine().isPositionIndependent();
|
return getTargetMachine().isPositionIndependent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCAssignFn *CCAssignFnForCall() const;
|
||||||
|
|
||||||
|
CCAssignFn *CCAssignFnForReturn() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
|
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
|
||||||
|
|
||||||
|
|
|
@ -15,41 +15,101 @@
|
||||||
#include "MipsRegisterBankInfo.h"
|
#include "MipsRegisterBankInfo.h"
|
||||||
#include "MipsSubtarget.h"
|
#include "MipsSubtarget.h"
|
||||||
#include "MipsTargetMachine.h"
|
#include "MipsTargetMachine.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
|
||||||
|
#define DEBUG_TYPE "mips-isel"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
#define GET_GLOBALISEL_PREDICATE_BITSET
|
||||||
|
#include "MipsGenGlobalISel.inc"
|
||||||
|
#undef GET_GLOBALISEL_PREDICATE_BITSET
|
||||||
|
|
||||||
class MipsInstructionSelector : public InstructionSelector {
|
class MipsInstructionSelector : public InstructionSelector {
|
||||||
public:
|
public:
|
||||||
MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
||||||
const MipsRegisterBankInfo &RBI);
|
const MipsRegisterBankInfo &RBI);
|
||||||
|
|
||||||
bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
|
bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override;
|
||||||
|
static const char *getName() { return DEBUG_TYPE; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
|
||||||
|
|
||||||
|
const MipsTargetMachine &TM;
|
||||||
|
const MipsSubtarget &STI;
|
||||||
const MipsInstrInfo &TII;
|
const MipsInstrInfo &TII;
|
||||||
const MipsRegisterInfo &TRI;
|
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
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
#define GET_GLOBALISEL_IMPL
|
||||||
|
#include "MipsGenGlobalISel.inc"
|
||||||
|
#undef GET_GLOBALISEL_IMPL
|
||||||
|
|
||||||
MipsInstructionSelector::MipsInstructionSelector(
|
MipsInstructionSelector::MipsInstructionSelector(
|
||||||
const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
const MipsTargetMachine &TM, const MipsSubtarget &STI,
|
||||||
const MipsRegisterBankInfo &RBI)
|
const MipsRegisterBankInfo &RBI)
|
||||||
: InstructionSelector(), TII(*STI.getInstrInfo()),
|
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
||||||
TRI(*STI.getRegisterInfo()) {}
|
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,
|
bool MipsInstructionSelector::select(MachineInstr &I,
|
||||||
CodeGenCoverage &CoverageInfo) const {
|
CodeGenCoverage &CoverageInfo) const {
|
||||||
|
|
||||||
|
MachineBasicBlock &MBB = *I.getParent();
|
||||||
|
MachineFunction &MF = *MBB.getParent();
|
||||||
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||||
|
|
||||||
if (!isPreISelGenericOpcode(I.getOpcode())) {
|
if (!isPreISelGenericOpcode(I.getOpcode())) {
|
||||||
// Not global isel generic opcode.
|
if (I.isCopy())
|
||||||
// TODO: select copy
|
return selectCopy(I, TII, MRI, TRI, RBI);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selectImpl(I, CoverageInfo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// We didn't select anything.
|
// We didn't select anything.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,5 +20,11 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
|
MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
|
||||||
|
using namespace TargetOpcode;
|
||||||
|
|
||||||
|
const LLT s32 = LLT::scalar(32);
|
||||||
|
|
||||||
|
getActionDefinitionsBuilder(G_ADD).legalFor({s32});
|
||||||
|
|
||||||
computeTables();
|
computeTables();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,84 @@
|
||||||
/// \todo This should be generated by TableGen.
|
/// \todo This should be generated by TableGen.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "MipsInstrInfo.h"
|
||||||
#include "MipsRegisterBankInfo.h"
|
#include "MipsRegisterBankInfo.h"
|
||||||
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
|
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
|
||||||
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||||
|
|
||||||
using namespace llvm;
|
#define GET_TARGET_REGBANK_IMPL
|
||||||
|
|
||||||
MipsGenRegisterBankInfo::MipsGenRegisterBankInfo()
|
#define DEBUG_TYPE "registerbankinfo"
|
||||||
: RegisterBankInfo(nullptr, 0) {}
|
|
||||||
|
#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)
|
MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
|
||||||
: MipsGenRegisterBankInfo() {}
|
: 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"
|
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
|
||||||
|
|
||||||
|
#define GET_REGBANK_DECLARATIONS
|
||||||
|
#include "MipsGenRegisterBank.inc"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class TargetRegisterInfo;
|
class TargetRegisterInfo;
|
||||||
|
|
||||||
class MipsGenRegisterBankInfo : public RegisterBankInfo {
|
class MipsGenRegisterBankInfo : public RegisterBankInfo {
|
||||||
// TODO: This should be auto-generated by TableGen.
|
#define GET_TARGET_REGBANK_CLASS
|
||||||
public:
|
#include "MipsGenRegisterBank.inc"
|
||||||
MipsGenRegisterBankInfo();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class provides the information for the target register banks.
|
/// This class provides the information for the target register banks.
|
||||||
class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo {
|
class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo {
|
||||||
public:
|
public:
|
||||||
MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
|
MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
|
||||||
|
|
||||||
|
const RegisterBank &
|
||||||
|
getRegBankFromRegClass(const TargetRegisterClass &RC) const override;
|
||||||
|
|
||||||
|
const InstructionMapping &
|
||||||
|
getInstrMapping(const MachineInstr &MI) const override;
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
#endif
|
#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