[ARM] GlobalISel: Use TableGen instruction selector

Emit and use the TableGen instruction selector for ARM. At the moment,
this allows us to remove the hand-written code for selecting G_SDIV and
G_UDIV.

Future commits will focus on increasing the code coverage for it and
removing more dead code from the current instruction selector.

llvm-svn: 301905
This commit is contained in:
Diana Picus 2017-05-02 09:40:49 +00:00
parent b7101479a8
commit 8abcbbb24b
6 changed files with 66 additions and 25 deletions

View File

@ -47,7 +47,7 @@ FunctionPass *createARMOptimizeBarriersPass();
FunctionPass *createThumb2SizeReductionPass(
std::function<bool(const Function &)> Ftor = nullptr);
InstructionSelector *
createARMInstructionSelector(const ARMSubtarget &STI,
createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
const ARMRegisterBankInfo &RBI);
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,

View File

@ -317,8 +317,10 @@ def UseNegativeImmediates :
"NegativeImmediates">;
// FIXME: Eventually this will be just "hasV6T2Ops".
def UseMovt : Predicate<"Subtarget->useMovt(*MF)">;
def DontUseMovt : Predicate<"!Subtarget->useMovt(*MF)">;
let RecomputePerFunction = 1 in {
def UseMovt : Predicate<"Subtarget->useMovt(*MF)">;
def DontUseMovt : Predicate<"!Subtarget->useMovt(*MF)">;
}
def UseFPVMLx : Predicate<"Subtarget->useFPVMLx()">;
def UseMulOps : Predicate<"Subtarget->useMulOps()">;
@ -345,8 +347,10 @@ def UseVMOVSR : Predicate<"Subtarget->preferVMOVSR() ||"
def DontUseVMOVSR : Predicate<"!Subtarget->preferVMOVSR() &&"
"Subtarget->useNEONForSinglePrecisionFP()">;
def IsLE : Predicate<"MF->getDataLayout().isLittleEndian()">;
def IsBE : Predicate<"MF->getDataLayout().isBigEndian()">;
let RecomputePerFunction = 1 in {
def IsLE : Predicate<"MF->getDataLayout().isLittleEndian()">;
def IsBE : Predicate<"MF->getDataLayout().isBigEndian()">;
}
def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">;

View File

@ -27,32 +27,67 @@ using namespace llvm;
#endif
namespace {
#define GET_GLOBALISEL_PREDICATE_BITSET
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATE_BITSET
class ARMInstructionSelector : public InstructionSelector {
public:
ARMInstructionSelector(const ARMSubtarget &STI,
ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
const ARMRegisterBankInfo &RBI);
bool select(MachineInstr &I) const override;
private:
bool selectImpl(MachineInstr &I) const;
const ARMBaseInstrInfo &TII;
const ARMBaseRegisterInfo &TRI;
const ARMBaseTargetMachine &TM;
const ARMRegisterBankInfo &RBI;
const ARMSubtarget &STI;
#define GET_GLOBALISEL_PREDICATES_DECL
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATES_DECL
// We declare the temporaries used by selectImpl() in the class to minimize the
// cost of constructing placeholder values.
#define GET_GLOBALISEL_TEMPORARIES_DECL
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_DECL
};
} // end anonymous namespace
namespace llvm {
InstructionSelector *
createARMInstructionSelector(const ARMSubtarget &STI,
createARMInstructionSelector(const ARMBaseTargetMachine &TM,
const ARMSubtarget &STI,
const ARMRegisterBankInfo &RBI) {
return new ARMInstructionSelector(STI, RBI);
return new ARMInstructionSelector(TM, STI, RBI);
}
}
ARMInstructionSelector::ARMInstructionSelector(const ARMSubtarget &STI,
unsigned zero_reg = 0;
#define GET_GLOBALISEL_IMPL
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_IMPL
ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
const ARMSubtarget &STI,
const ARMRegisterBankInfo &RBI)
: InstructionSelector(), TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()), RBI(RBI) {}
TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
#include "ARMGenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_INIT
{
}
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
@ -255,6 +290,9 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
return true;
}
if (selectImpl(I))
return true;
MachineInstrBuilder MIB{MF, I};
bool isSExt = false;
@ -355,16 +393,6 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
}
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
case G_SDIV:
assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
I.setDesc(TII.get(ARM::SDIV));
MIB.add(predOps(ARMCC::AL));
break;
case G_UDIV:
assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
I.setDesc(TII.get(ARM::UDIV));
MIB.add(predOps(ARMCC::AL));
break;
case G_FADD:
if (!selectFAdd(MIB, TII, MRI))
return false;

View File

@ -338,7 +338,7 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
// FIXME: At this point, we can't rely on Subtarget having RBI.
// It's awkward to mix passing RBI and the Subtarget; should we pass
// TII/TRI as well?
GISel->InstSelector.reset(createARMInstructionSelector(*I, *RBI));
GISel->InstSelector.reset(createARMInstructionSelector(*this, *I, *RBI));
GISel->RegBankInfo.reset(RBI);
#endif

View File

@ -1,6 +1,9 @@
set(LLVM_TARGET_DEFINITIONS ARM.td)
tablegen(LLVM ARMGenRegisterBank.inc -gen-register-bank)
if(LLVM_BUILD_GLOBAL_ISEL)
tablegen(LLVM ARMGenRegisterBank.inc -gen-register-bank)
tablegen(LLVM ARMGenGlobalISel.inc -gen-global-isel)
endif()
tablegen(LLVM ARMGenRegisterInfo.inc -gen-register-info)
tablegen(LLVM ARMGenInstrInfo.inc -gen-instr-info)
tablegen(LLVM ARMGenMCCodeEmitter.inc -gen-emitter)

View File

@ -854,7 +854,9 @@ public:
}
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
OS << " MIB.addReg(" << RegisterDef->getValueAsString("Namespace")
OS << " MIB.addReg(" << (RegisterDef->getValue("Namespace")
? RegisterDef->getValueAsString("Namespace")
: "")
<< "::" << RegisterDef->getName() << ");\n";
}
};
@ -987,12 +989,16 @@ public:
<< ");\n";
for (auto Def : I->ImplicitDefs) {
auto Namespace = Def->getValueAsString("Namespace");
auto Namespace = Def->getValue("Namespace")
? Def->getValueAsString("Namespace")
: "";
OS << " MIB.addDef(" << Namespace << "::" << Def->getName()
<< ", RegState::Implicit);\n";
}
for (auto Use : I->ImplicitUses) {
auto Namespace = Use->getValueAsString("Namespace");
auto Namespace = Use->getValue("Namespace")
? Use->getValueAsString("Namespace")
: "";
OS << " MIB.addUse(" << Namespace << "::" << Use->getName()
<< ", RegState::Implicit);\n";
}