68 changes: 64 additions & 4 deletions llvm/lib/Target/Mips/MipsInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/Mips/MipsLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
74 changes: 71 additions & 3 deletions llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

#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}
};

MipsGenRegisterBankInfo::MipsGenRegisterBankInfo()
: RegisterBankInfo(nullptr, 0) {}
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);
}
14 changes: 11 additions & 3 deletions llvm/lib/Target/Mips/MipsRegisterBankInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions llvm/lib/Target/Mips/MipsRegisterBanks.td
Original file line number Diff line number Diff line change
@@ -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]>;
35 changes: 35 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/instruction-select/add.mir
Original file line number Diff line number Diff line change
@@ -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
...
16 changes: 16 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/irtranslator/add.ll
Original file line number Diff line number Diff line change
@@ -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
}
34 changes: 34 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir
Original file line number Diff line number Diff line change
@@ -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
...
12 changes: 12 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/add.ll
Original file line number Diff line number Diff line change
@@ -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
}
34 changes: 34 additions & 0 deletions llvm/test/CodeGen/Mips/GlobalISel/regbankselect/add.mir
Original file line number Diff line number Diff line change
@@ -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
...