forked from OSchip/llvm-project
[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:
parent
b7101479a8
commit
8abcbbb24b
|
@ -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,
|
||||
|
|
|
@ -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()">;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue