mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[globalisel][tablegen] Compute available feature bits correctly.
Summary: Predicate<> now has a field to indicate how often it must be recomputed. Currently, there are two frequencies, per-module (RecomputePerFunction==0) and per-function (RecomputePerFunction==1). Per-function predicates are currently recomputed more frequently than necessary since the only predicate in this category is cheap to test. Per-module predicates are now computed in getSubtargetImpl() while per-function predicates are computed in selectImpl(). Tablegen now manages the PredicateBitset internally. It should only be necessary to add the required includes. Also fixed a problem revealed by the test case where constrainSelectedInstRegOperands() would attempt to tie operands that BuildMI had already tied. Reviewers: ab, qcolombet, t.p.northover, rovka, aditya_nandakumar Reviewed By: rovka Subscribers: kristof.beyls, igorb, llvm-commits Differential Revision: https://reviews.llvm.org/D32491 llvm-svn: 301750
This commit is contained in:
parent
4493f8350b
commit
6ad3513c78
@ -61,9 +61,6 @@ class InstructionSelector {
|
|||||||
public:
|
public:
|
||||||
virtual ~InstructionSelector() {}
|
virtual ~InstructionSelector() {}
|
||||||
|
|
||||||
/// This is executed before selecting a function.
|
|
||||||
virtual void beginFunction(const MachineFunction &MF) {}
|
|
||||||
|
|
||||||
/// Select the (possibly generic) instruction \p I to only use target-specific
|
/// Select the (possibly generic) instruction \p I to only use target-specific
|
||||||
/// opcodes. It is OK to insert multiple instructions, but they cannot be
|
/// opcodes. It is OK to insert multiple instructions, but they cannot be
|
||||||
/// generic pre-isel instructions.
|
/// generic pre-isel instructions.
|
||||||
|
@ -530,6 +530,12 @@ class Predicate<string cond> {
|
|||||||
/// PredicateName - User-level name to use for the predicate. Mainly for use
|
/// PredicateName - User-level name to use for the predicate. Mainly for use
|
||||||
/// in diagnostics such as missing feature errors in the asm matcher.
|
/// in diagnostics such as missing feature errors in the asm matcher.
|
||||||
string PredicateName = "";
|
string PredicateName = "";
|
||||||
|
|
||||||
|
/// Setting this to '1' indicates that the predicate must be recomputed on
|
||||||
|
/// every function change. Most predicates can leave this at '0'.
|
||||||
|
///
|
||||||
|
/// Ignored by SelectionDAG, it always recomputes the predicate on every use.
|
||||||
|
bit RecomputePerFunction = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NoHonorSignDependentRounding - This predicate is true if support for
|
/// NoHonorSignDependentRounding - This predicate is true if support for
|
||||||
|
@ -58,10 +58,11 @@ bool InstructionSelector::constrainSelectedInstRegOperands(
|
|||||||
MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(),
|
MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(),
|
||||||
Reg, OpI));
|
Reg, OpI));
|
||||||
|
|
||||||
// Tie uses to defs as indicated in MCInstrDesc.
|
// Tie uses to defs as indicated in MCInstrDesc if this hasn't already been
|
||||||
|
// done.
|
||||||
if (MO.isUse()) {
|
if (MO.isUse()) {
|
||||||
int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
|
int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO);
|
||||||
if (DefIdx != -1)
|
if (DefIdx != -1 && !I.isRegTiedToUseOperand(DefIdx))
|
||||||
I.tieOperands(DefIdx, OpI);
|
I.tieOperands(DefIdx, OpI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,8 +314,8 @@ def AArch64umaxv : SDNode<"AArch64ISD::UMAXV", SDT_AArch64UnaryVec>;
|
|||||||
// AArch64 Instruction Predicate Definitions.
|
// AArch64 Instruction Predicate Definitions.
|
||||||
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
|
def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">;
|
||||||
def IsNotDarwin: Predicate<"!Subtarget->isTargetDarwin()">;
|
def IsNotDarwin: Predicate<"!Subtarget->isTargetDarwin()">;
|
||||||
def ForCodeSize : Predicate<"ForCodeSize">;
|
def ForCodeSize : Predicate<"Subtarget->getForCodeSize()">;
|
||||||
def NotForCodeSize : Predicate<"!ForCodeSize">;
|
def NotForCodeSize : Predicate<"!Subtarget->getForCodeSize()">;
|
||||||
|
|
||||||
include "AArch64InstrFormats.td"
|
include "AArch64InstrFormats.td"
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ public:
|
|||||||
const AArch64Subtarget &STI,
|
const AArch64Subtarget &STI,
|
||||||
const AArch64RegisterBankInfo &RBI);
|
const AArch64RegisterBankInfo &RBI);
|
||||||
|
|
||||||
void beginFunction(const MachineFunction &MF) override;
|
|
||||||
bool select(MachineInstr &I) const override;
|
bool select(MachineInstr &I) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -74,12 +73,10 @@ private:
|
|||||||
const AArch64InstrInfo &TII;
|
const AArch64InstrInfo &TII;
|
||||||
const AArch64RegisterInfo &TRI;
|
const AArch64RegisterInfo &TRI;
|
||||||
const AArch64RegisterBankInfo &RBI;
|
const AArch64RegisterBankInfo &RBI;
|
||||||
bool ForCodeSize;
|
|
||||||
|
|
||||||
PredicateBitset AvailableFeatures;
|
#define GET_GLOBALISEL_PREDICATES_DECL
|
||||||
PredicateBitset
|
#include "AArch64GenGlobalISel.inc"
|
||||||
computeAvailableFeatures(const MachineFunction *MF,
|
#undef GET_GLOBALISEL_PREDICATES_DECL
|
||||||
const AArch64Subtarget *Subtarget) const;
|
|
||||||
|
|
||||||
// We declare the temporaries used by selectImpl() in the class to minimize the
|
// We declare the temporaries used by selectImpl() in the class to minimize the
|
||||||
// cost of constructing placeholder values.
|
// cost of constructing placeholder values.
|
||||||
@ -98,7 +95,10 @@ AArch64InstructionSelector::AArch64InstructionSelector(
|
|||||||
const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
|
const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
|
||||||
const AArch64RegisterBankInfo &RBI)
|
const AArch64RegisterBankInfo &RBI)
|
||||||
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
||||||
TRI(*STI.getRegisterInfo()), RBI(RBI), ForCodeSize(), AvailableFeatures()
|
TRI(*STI.getRegisterInfo()), RBI(RBI),
|
||||||
|
#define GET_GLOBALISEL_PREDICATES_INIT
|
||||||
|
#include "AArch64GenGlobalISel.inc"
|
||||||
|
#undef GET_GLOBALISEL_PREDICATES_INIT
|
||||||
#define GET_GLOBALISEL_TEMPORARIES_INIT
|
#define GET_GLOBALISEL_TEMPORARIES_INIT
|
||||||
#include "AArch64GenGlobalISel.inc"
|
#include "AArch64GenGlobalISel.inc"
|
||||||
#undef GET_GLOBALISEL_TEMPORARIES_INIT
|
#undef GET_GLOBALISEL_TEMPORARIES_INIT
|
||||||
@ -577,12 +577,6 @@ bool AArch64InstructionSelector::selectVaStartDarwin(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AArch64InstructionSelector::beginFunction(
|
|
||||||
const MachineFunction &MF) {
|
|
||||||
ForCodeSize = MF.getFunction()->optForSize();
|
|
||||||
AvailableFeatures = computeAvailableFeatures(&MF, &STI);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AArch64InstructionSelector::select(MachineInstr &I) const {
|
bool AArch64InstructionSelector::select(MachineInstr &I) const {
|
||||||
assert(I.getParent() && "Instruction should be in a basic block!");
|
assert(I.getParent() && "Instruction should be in a basic block!");
|
||||||
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
||||||
|
@ -113,11 +113,12 @@ void AArch64Subtarget::initializeProperties() {
|
|||||||
|
|
||||||
AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
|
AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
|
||||||
const std::string &FS,
|
const std::string &FS,
|
||||||
const TargetMachine &TM, bool LittleEndian)
|
const TargetMachine &TM, bool LittleEndian,
|
||||||
|
bool ForCodeSize)
|
||||||
: AArch64GenSubtargetInfo(TT, CPU, FS), ReserveX18(TT.isOSDarwin()),
|
: AArch64GenSubtargetInfo(TT, CPU, FS), ReserveX18(TT.isOSDarwin()),
|
||||||
IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
|
IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
|
||||||
InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
|
InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
|
||||||
TLInfo(TM, *this), GISel() {}
|
TLInfo(TM, *this), GISel(), ForCodeSize(ForCodeSize) {}
|
||||||
|
|
||||||
const CallLowering *AArch64Subtarget::getCallLowering() const {
|
const CallLowering *AArch64Subtarget::getCallLowering() const {
|
||||||
assert(GISel && "Access to GlobalISel APIs not set");
|
assert(GISel && "Access to GlobalISel APIs not set");
|
||||||
|
@ -124,6 +124,8 @@ protected:
|
|||||||
/// an optional library.
|
/// an optional library.
|
||||||
std::unique_ptr<GISelAccessor> GISel;
|
std::unique_ptr<GISelAccessor> GISel;
|
||||||
|
|
||||||
|
bool ForCodeSize;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// initializeSubtargetDependencies - Initializes using CPUString and the
|
/// initializeSubtargetDependencies - Initializes using CPUString and the
|
||||||
/// passed in feature string so that we can use initializer lists for
|
/// passed in feature string so that we can use initializer lists for
|
||||||
@ -139,7 +141,7 @@ public:
|
|||||||
/// of the specified triple.
|
/// of the specified triple.
|
||||||
AArch64Subtarget(const Triple &TT, const std::string &CPU,
|
AArch64Subtarget(const Triple &TT, const std::string &CPU,
|
||||||
const std::string &FS, const TargetMachine &TM,
|
const std::string &FS, const TargetMachine &TM,
|
||||||
bool LittleEndian);
|
bool LittleEndian, bool ForCodeSize);
|
||||||
|
|
||||||
/// This object will take onwership of \p GISelAccessor.
|
/// This object will take onwership of \p GISelAccessor.
|
||||||
void setGISelAccessor(GISelAccessor &GISel) {
|
void setGISelAccessor(GISelAccessor &GISel) {
|
||||||
@ -262,6 +264,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getForCodeSize() const { return ForCodeSize; }
|
||||||
|
|
||||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||||
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
||||||
|
@ -255,6 +255,7 @@ const AArch64Subtarget *
|
|||||||
AArch64TargetMachine::getSubtargetImpl(const Function &F) const {
|
AArch64TargetMachine::getSubtargetImpl(const Function &F) const {
|
||||||
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
||||||
Attribute FSAttr = F.getFnAttribute("target-features");
|
Attribute FSAttr = F.getFnAttribute("target-features");
|
||||||
|
bool ForCodeSize = F.optForSize();
|
||||||
|
|
||||||
std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
|
std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
|
||||||
? CPUAttr.getValueAsString().str()
|
? CPUAttr.getValueAsString().str()
|
||||||
@ -262,15 +263,17 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const {
|
|||||||
std::string FS = !FSAttr.hasAttribute(Attribute::None)
|
std::string FS = !FSAttr.hasAttribute(Attribute::None)
|
||||||
? FSAttr.getValueAsString().str()
|
? FSAttr.getValueAsString().str()
|
||||||
: TargetFS;
|
: TargetFS;
|
||||||
|
std::string ForCodeSizeStr =
|
||||||
|
std::string(ForCodeSize ? "+" : "-") + "forcodesize";
|
||||||
|
|
||||||
auto &I = SubtargetMap[CPU + FS];
|
auto &I = SubtargetMap[CPU + FS + ForCodeSizeStr];
|
||||||
if (!I) {
|
if (!I) {
|
||||||
// This needs to be done before we create a new subtarget since any
|
// This needs to be done before we create a new subtarget since any
|
||||||
// creation will depend on the TM and the code generation flags on the
|
// creation will depend on the TM and the code generation flags on the
|
||||||
// function that reside in TargetOptions.
|
// function that reside in TargetOptions.
|
||||||
resetTargetOptions(F);
|
resetTargetOptions(F);
|
||||||
I = llvm::make_unique<AArch64Subtarget>(TargetTriple, CPU, FS, *this,
|
I = llvm::make_unique<AArch64Subtarget>(TargetTriple, CPU, FS, *this,
|
||||||
isLittle);
|
isLittle, ForCodeSize);
|
||||||
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
||||||
GISelAccessor *GISel = new GISelAccessor();
|
GISelAccessor *GISel = new GISelAccessor();
|
||||||
#else
|
#else
|
||||||
|
@ -877,7 +877,9 @@ def In32BitMode : Predicate<"Subtarget->is32Bit()">,
|
|||||||
def IsWin64 : Predicate<"Subtarget->isTargetWin64()">;
|
def IsWin64 : Predicate<"Subtarget->isTargetWin64()">;
|
||||||
def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">;
|
def NotWin64 : Predicate<"!Subtarget->isTargetWin64()">;
|
||||||
def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||"
|
def NotWin64WithoutFP : Predicate<"!Subtarget->isTargetWin64() ||"
|
||||||
"Subtarget->getFrameLowering()->hasFP(*MF)">;
|
"Subtarget->getFrameLowering()->hasFP(*MF)"> {
|
||||||
|
let RecomputePerFunction = 1;
|
||||||
|
}
|
||||||
def IsPS4 : Predicate<"Subtarget->isTargetPS4()">;
|
def IsPS4 : Predicate<"Subtarget->isTargetPS4()">;
|
||||||
def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">;
|
def NotPS4 : Predicate<"!Subtarget->isTargetPS4()">;
|
||||||
def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">;
|
def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">;
|
||||||
@ -887,9 +889,9 @@ def KernelCode : Predicate<"TM.getCodeModel() == CodeModel::Kernel">;
|
|||||||
def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
|
def NearData : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
|
||||||
"TM.getCodeModel() == CodeModel::Kernel">;
|
"TM.getCodeModel() == CodeModel::Kernel">;
|
||||||
def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
|
def IsNotPIC : Predicate<"!TM.isPositionIndependent()">;
|
||||||
def OptForSize : Predicate<"OptForSize">;
|
def OptForSize : Predicate<"Subtarget->getOptForSize()">;
|
||||||
def OptForMinSize : Predicate<"OptForMinSize">;
|
def OptForMinSize : Predicate<"Subtarget->getOptForMinSize()">;
|
||||||
def OptForSpeed : Predicate<"!OptForSize">;
|
def OptForSpeed : Predicate<"!Subtarget->getOptForSize()">;
|
||||||
def FastBTMem : Predicate<"!Subtarget->isBTMemSlow()">;
|
def FastBTMem : Predicate<"!Subtarget->isBTMemSlow()">;
|
||||||
def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">;
|
def CallImmAddr : Predicate<"Subtarget->isLegalToCallImmediateAddr()">;
|
||||||
def FavorMemIndirectCall : Predicate<"!Subtarget->callRegIndirect()">;
|
def FavorMemIndirectCall : Predicate<"!Subtarget->callRegIndirect()">;
|
||||||
|
@ -48,7 +48,6 @@ public:
|
|||||||
X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
|
X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
|
||||||
const X86RegisterBankInfo &RBI);
|
const X86RegisterBankInfo &RBI);
|
||||||
|
|
||||||
void beginFunction(const MachineFunction &MF) override;
|
|
||||||
bool select(MachineInstr &I) const override;
|
bool select(MachineInstr &I) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -80,12 +79,10 @@ private:
|
|||||||
const X86InstrInfo &TII;
|
const X86InstrInfo &TII;
|
||||||
const X86RegisterInfo &TRI;
|
const X86RegisterInfo &TRI;
|
||||||
const X86RegisterBankInfo &RBI;
|
const X86RegisterBankInfo &RBI;
|
||||||
bool OptForSize;
|
|
||||||
bool OptForMinSize;
|
|
||||||
|
|
||||||
PredicateBitset AvailableFeatures;
|
#define GET_GLOBALISEL_PREDICATES_DECL
|
||||||
PredicateBitset computeAvailableFeatures(const MachineFunction *MF,
|
#include "X86GenGlobalISel.inc"
|
||||||
const X86Subtarget *Subtarget) const;
|
#undef GET_GLOBALISEL_PREDICATES_DECL
|
||||||
|
|
||||||
#define GET_GLOBALISEL_TEMPORARIES_DECL
|
#define GET_GLOBALISEL_TEMPORARIES_DECL
|
||||||
#include "X86GenGlobalISel.inc"
|
#include "X86GenGlobalISel.inc"
|
||||||
@ -102,8 +99,10 @@ X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
|
|||||||
const X86Subtarget &STI,
|
const X86Subtarget &STI,
|
||||||
const X86RegisterBankInfo &RBI)
|
const X86RegisterBankInfo &RBI)
|
||||||
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
: InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
|
||||||
TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(false),
|
TRI(*STI.getRegisterInfo()), RBI(RBI),
|
||||||
OptForMinSize(false), AvailableFeatures()
|
#define GET_GLOBALISEL_PREDICATES_INIT
|
||||||
|
#include "X86GenGlobalISel.inc"
|
||||||
|
#undef GET_GLOBALISEL_PREDICATES_INIT
|
||||||
#define GET_GLOBALISEL_TEMPORARIES_INIT
|
#define GET_GLOBALISEL_TEMPORARIES_INIT
|
||||||
#include "X86GenGlobalISel.inc"
|
#include "X86GenGlobalISel.inc"
|
||||||
#undef GET_GLOBALISEL_TEMPORARIES_INIT
|
#undef GET_GLOBALISEL_TEMPORARIES_INIT
|
||||||
@ -206,12 +205,6 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X86InstructionSelector::beginFunction(const MachineFunction &MF) {
|
|
||||||
OptForSize = MF.getFunction()->optForSize();
|
|
||||||
OptForMinSize = MF.getFunction()->optForMinSize();
|
|
||||||
AvailableFeatures = computeAvailableFeatures(&MF, &STI);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool X86InstructionSelector::select(MachineInstr &I) const {
|
bool X86InstructionSelector::select(MachineInstr &I) const {
|
||||||
assert(I.getParent() && "Instruction should be in a basic block!");
|
assert(I.getParent() && "Instruction should be in a basic block!");
|
||||||
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
assert(I.getParent()->getParent() && "Instruction should be in a function!");
|
||||||
|
@ -326,7 +326,8 @@ X86Subtarget &X86Subtarget::initializeSubtargetDependencies(StringRef CPU,
|
|||||||
|
|
||||||
X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||||
const X86TargetMachine &TM,
|
const X86TargetMachine &TM,
|
||||||
unsigned StackAlignOverride)
|
unsigned StackAlignOverride, bool OptForSize,
|
||||||
|
bool OptForMinSize)
|
||||||
: X86GenSubtargetInfo(TT, CPU, FS), X86ProcFamily(Others),
|
: X86GenSubtargetInfo(TT, CPU, FS), X86ProcFamily(Others),
|
||||||
PICStyle(PICStyles::None), TM(TM), TargetTriple(TT),
|
PICStyle(PICStyles::None), TM(TM), TargetTriple(TT),
|
||||||
StackAlignOverride(StackAlignOverride),
|
StackAlignOverride(StackAlignOverride),
|
||||||
@ -335,8 +336,9 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
|||||||
TargetTriple.getEnvironment() != Triple::CODE16),
|
TargetTriple.getEnvironment() != Triple::CODE16),
|
||||||
In16BitMode(TargetTriple.getArch() == Triple::x86 &&
|
In16BitMode(TargetTriple.getArch() == Triple::x86 &&
|
||||||
TargetTriple.getEnvironment() == Triple::CODE16),
|
TargetTriple.getEnvironment() == Triple::CODE16),
|
||||||
InstrInfo(initializeSubtargetDependencies(CPU, FS)),
|
InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
|
||||||
TLInfo(TM, *this), FrameLowering(*this, getStackAlignment()) {
|
FrameLowering(*this, getStackAlignment()), OptForSize(OptForSize),
|
||||||
|
OptForMinSize(OptForMinSize) {
|
||||||
// Determine the PICStyle based on the target selected.
|
// Determine the PICStyle based on the target selected.
|
||||||
if (!isPositionIndependent())
|
if (!isPositionIndependent())
|
||||||
setPICStyle(PICStyles::None);
|
setPICStyle(PICStyles::None);
|
||||||
|
@ -328,12 +328,16 @@ private:
|
|||||||
X86TargetLowering TLInfo;
|
X86TargetLowering TLInfo;
|
||||||
X86FrameLowering FrameLowering;
|
X86FrameLowering FrameLowering;
|
||||||
|
|
||||||
|
bool OptForSize;
|
||||||
|
bool OptForMinSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// This constructor initializes the data members to match that
|
/// This constructor initializes the data members to match that
|
||||||
/// of the specified triple.
|
/// of the specified triple.
|
||||||
///
|
///
|
||||||
X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||||
const X86TargetMachine &TM, unsigned StackAlignOverride);
|
const X86TargetMachine &TM, unsigned StackAlignOverride,
|
||||||
|
bool OptForSize, bool OptForMinSize);
|
||||||
|
|
||||||
/// This object will take onwership of \p GISelAccessor.
|
/// This object will take onwership of \p GISelAccessor.
|
||||||
void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); }
|
void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); }
|
||||||
@ -499,6 +503,9 @@ public:
|
|||||||
bool isSLM() const { return X86ProcFamily == IntelSLM; }
|
bool isSLM() const { return X86ProcFamily == IntelSLM; }
|
||||||
bool useSoftFloat() const { return UseSoftFloat; }
|
bool useSoftFloat() const { return UseSoftFloat; }
|
||||||
|
|
||||||
|
bool getOptForSize() const { return OptForSize; }
|
||||||
|
bool getOptForMinSize() const { return OptForMinSize; }
|
||||||
|
|
||||||
/// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
|
/// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
|
||||||
/// no-sse2). There isn't any reason to disable it if the target processor
|
/// no-sse2). There isn't any reason to disable it if the target processor
|
||||||
/// supports it.
|
/// supports it.
|
||||||
|
@ -268,6 +268,12 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
|||||||
|
|
||||||
FS = Key.substr(CPU.size());
|
FS = Key.substr(CPU.size());
|
||||||
|
|
||||||
|
bool OptForSize = F.optForSize();
|
||||||
|
bool OptForMinSize = F.optForMinSize();
|
||||||
|
|
||||||
|
Key += std::string(OptForSize ? "+" : "-") + "optforsize";
|
||||||
|
Key += std::string(OptForMinSize ? "+" : "-") + "optforminsize";
|
||||||
|
|
||||||
auto &I = SubtargetMap[Key];
|
auto &I = SubtargetMap[Key];
|
||||||
if (!I) {
|
if (!I) {
|
||||||
// This needs to be done before we create a new subtarget since any
|
// This needs to be done before we create a new subtarget since any
|
||||||
@ -275,7 +281,8 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
|||||||
// function that reside in TargetOptions.
|
// function that reside in TargetOptions.
|
||||||
resetTargetOptions(F);
|
resetTargetOptions(F);
|
||||||
I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
|
I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
|
||||||
Options.StackAlignmentOverride);
|
Options.StackAlignmentOverride,
|
||||||
|
OptForSize, OptForMinSize);
|
||||||
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
#ifndef LLVM_BUILD_GLOBAL_ISEL
|
||||||
GISelAccessor *GISel = new GISelAccessor();
|
GISelAccessor *GISel = new GISelAccessor();
|
||||||
#else
|
#else
|
||||||
@ -286,7 +293,8 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
|||||||
|
|
||||||
auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
|
auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
|
||||||
GISel->RegBankInfo.reset(RBI);
|
GISel->RegBankInfo.reset(RBI);
|
||||||
GISel->InstSelector.reset(createX86InstructionSelector(*this, *I, *RBI));
|
GISel->InstSelector.reset(createX86InstructionSelector(
|
||||||
|
*this, *I, *RBI));
|
||||||
#endif
|
#endif
|
||||||
I->setGISelAccessor(*GISel);
|
I->setGISelAccessor(*GISel);
|
||||||
}
|
}
|
||||||
|
37
test/CodeGen/X86/GlobalISel/select-inc.mir
Normal file
37
test/CodeGen/X86/GlobalISel/select-inc.mir
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=ALL,INC
|
||||||
|
# RUN: llc -mtriple=x86_64-linux-gnu -mattr=+slow-incdec -global-isel -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=ALL,ADD
|
||||||
|
|
||||||
|
--- |
|
||||||
|
define i8 @test_add_i8(i8 %arg1) {
|
||||||
|
%ret = add i8 %arg1, 1
|
||||||
|
ret i8 %ret
|
||||||
|
}
|
||||||
|
...
|
||||||
|
|
||||||
|
---
|
||||||
|
name: test_add_i8
|
||||||
|
legalized: true
|
||||||
|
regBankSelected: true
|
||||||
|
# ALL: registers:
|
||||||
|
# ALL-NEXT: - { id: 0, class: gr8 }
|
||||||
|
# INC-NEXT: - { id: 1, class: gpr }
|
||||||
|
# ADD-NEXT: - { id: 1, class: gr8 }
|
||||||
|
# ALL-NEXT: - { id: 2, class: gr8 }
|
||||||
|
registers:
|
||||||
|
- { id: 0, class: gpr }
|
||||||
|
- { id: 1, class: gpr }
|
||||||
|
- { id: 2, class: gpr }
|
||||||
|
# ALL: %0 = COPY %al
|
||||||
|
# INC-NEXT: %2 = INC8r %0
|
||||||
|
# ADD-NEXT: %1 = MOV8ri 1
|
||||||
|
# ADD-NEXT: %2 = ADD8rr %0, %1
|
||||||
|
body: |
|
||||||
|
bb.1 (%ir-block.0):
|
||||||
|
liveins: %al
|
||||||
|
|
||||||
|
%0(s8) = COPY %al
|
||||||
|
%1(s8) = G_CONSTANT i8 1
|
||||||
|
%2(s8) = G_ADD %0, %1
|
||||||
|
%al = COPY %2(s8)
|
||||||
|
|
||||||
|
...
|
@ -32,22 +32,25 @@ def m1Z : OperandWithDefaultOps <i32, (ops (i32 -1), R0)>;
|
|||||||
|
|
||||||
def HasA : Predicate<"Subtarget->hasA()">;
|
def HasA : Predicate<"Subtarget->hasA()">;
|
||||||
def HasB : Predicate<"Subtarget->hasB()">;
|
def HasB : Predicate<"Subtarget->hasB()">;
|
||||||
|
def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
|
||||||
|
|
||||||
//===- Test the function boilerplate. -------------------------------------===//
|
//===- Test the function boilerplate. -------------------------------------===//
|
||||||
|
|
||||||
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
|
// CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
|
||||||
// CHECK-NEXT: Feature_HasABit = 0,
|
// CHECK-NEXT: Feature_HasABit = 0,
|
||||||
// CHECK-NEXT: Feature_HasBBit = 1,
|
// CHECK-NEXT: Feature_HasBBit = 1,
|
||||||
|
// CHECK-NEXT: Feature_HasCBit = 2,
|
||||||
// CHECK-NEXT: };
|
// CHECK-NEXT: };
|
||||||
|
|
||||||
// CHECK-LABEL: static const char *SubtargetFeatureNames[] = {
|
// CHECK-LABEL: static const char *SubtargetFeatureNames[] = {
|
||||||
// CHECK-NEXT: "Feature_HasA",
|
// CHECK-NEXT: "Feature_HasA",
|
||||||
// CHECK-NEXT: "Feature_HasB",
|
// CHECK-NEXT: "Feature_HasB",
|
||||||
|
// CHECK-NEXT: "Feature_HasC",
|
||||||
// CHECK-NEXT: nullptr
|
// CHECK-NEXT: nullptr
|
||||||
// CHECK-NEXT: };
|
// CHECK-NEXT: };
|
||||||
|
|
||||||
// CHECK-LABEL: PredicateBitset MyTargetInstructionSelector::
|
// CHECK-LABEL: PredicateBitset MyTargetInstructionSelector::
|
||||||
// CHECK-NEXT: computeAvailableFeatures(const MachineFunction *MF, const MyTargetSubtarget *Subtarget) const {
|
// CHECK-NEXT: computeAvailableModuleFeatures(const MyTargetSubtarget *Subtarget) const {
|
||||||
// CHECK-NEXT: PredicateBitset Features;
|
// CHECK-NEXT: PredicateBitset Features;
|
||||||
// CHECK-NEXT: if (Subtarget->hasA())
|
// CHECK-NEXT: if (Subtarget->hasA())
|
||||||
// CHECK-NEXT: Features[Feature_HasABit] = 1;
|
// CHECK-NEXT: Features[Feature_HasABit] = 1;
|
||||||
@ -56,6 +59,14 @@ def HasB : Predicate<"Subtarget->hasB()">;
|
|||||||
// CHECK-NEXT: return Features;
|
// CHECK-NEXT: return Features;
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
|
// CHECK-LABEL: PredicateBitset MyTargetInstructionSelector::
|
||||||
|
// CHECK-NEXT: computeAvailableFunctionFeatures(const MyTargetSubtarget *Subtarget, const MachineFunction *MF) const {
|
||||||
|
// CHECK-NEXT: PredicateBitset Features;
|
||||||
|
// CHECK-NEXT: if (Subtarget->hasC())
|
||||||
|
// CHECK-NEXT: Features[Feature_HasCBit] = 1;
|
||||||
|
// CHECK-NEXT: return Features;
|
||||||
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const {
|
// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const {
|
||||||
// CHECK: MachineFunction &MF = *I.getParent()->getParent();
|
// CHECK: MachineFunction &MF = *I.getParent()->getParent();
|
||||||
// CHECK: const MachineRegisterInfo &MRI = MF.getRegInfo();
|
// CHECK: const MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||||
@ -216,7 +227,7 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
|
|||||||
//===- Test another simple pattern with regclass operands. ----------------===//
|
//===- Test another simple pattern with regclass operands. ----------------===//
|
||||||
|
|
||||||
// CHECK-LABEL: if ([&]() {
|
// CHECK-LABEL: if ([&]() {
|
||||||
// CHECK-NEXT: PredicateBitset ExpectedFeatures = {Feature_HasABit, Feature_HasBBit};
|
// CHECK-NEXT: PredicateBitset ExpectedFeatures = {Feature_HasABit, Feature_HasBBit, Feature_HasCBit};
|
||||||
// CHECK-NEXT: if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)
|
// CHECK-NEXT: if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)
|
||||||
// CHECK-NEXT: return false;
|
// CHECK-NEXT: return false;
|
||||||
// CHECK-NEXT: MachineInstr &MI0 = I;
|
// CHECK-NEXT: MachineInstr &MI0 = I;
|
||||||
@ -247,7 +258,7 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
|
|||||||
|
|
||||||
def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
|
def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
|
||||||
[(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>,
|
[(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>,
|
||||||
Requires<[HasA, HasB]>;
|
Requires<[HasA, HasB, HasC]>;
|
||||||
|
|
||||||
//===- Test a pattern with ComplexPattern operands. -----------------------===//
|
//===- Test a pattern with ComplexPattern operands. -----------------------===//
|
||||||
//
|
//
|
||||||
|
@ -30,7 +30,8 @@ std::unique_ptr<TargetMachine> createTargetMachine() {
|
|||||||
|
|
||||||
std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
|
std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
|
||||||
AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
|
AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
|
||||||
TM->getTargetFeatureString(), *TM, /* isLittle */ false);
|
TM->getTargetFeatureString(), *TM, /* isLittle */ false,
|
||||||
|
/* ForCodeSize */ false);
|
||||||
return llvm::make_unique<AArch64InstrInfo>(ST);
|
return llvm::make_unique<AArch64InstrInfo>(ST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,21 +199,19 @@ public:
|
|||||||
void emitCxxCapturedInsnList(raw_ostream &OS);
|
void emitCxxCapturedInsnList(raw_ostream &OS);
|
||||||
void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr);
|
void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr);
|
||||||
|
|
||||||
void emit(raw_ostream &OS,
|
void emit(raw_ostream &OS, SubtargetFeatureInfoMap SubtargetFeatures);
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
|
||||||
SubtargetFeatures);
|
|
||||||
|
|
||||||
/// Compare the priority of this object and B.
|
/// Compare the priority of this object and B.
|
||||||
///
|
///
|
||||||
/// Returns true if this object is more important than B.
|
/// Returns true if this object is more important than B.
|
||||||
bool isHigherPriorityThan(const RuleMatcher &B) const;
|
bool isHigherPriorityThan(const RuleMatcher &B) const;
|
||||||
|
|
||||||
/// Report the maximum number of temporary operands needed by the rule
|
/// Report the maximum number of temporary operands needed by the rule
|
||||||
/// matcher.
|
/// matcher.
|
||||||
unsigned countRendererFns() const;
|
unsigned countRendererFns() const;
|
||||||
|
|
||||||
// FIXME: Remove this as soon as possible
|
// FIXME: Remove this as soon as possible
|
||||||
InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); }
|
InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class PredicateTy> class PredicateListMatcher {
|
template <class PredicateTy> class PredicateListMatcher {
|
||||||
@ -951,6 +949,9 @@ private:
|
|||||||
|
|
||||||
/// True if the instruction can be built solely by mutating the opcode.
|
/// True if the instruction can be built solely by mutating the opcode.
|
||||||
bool canMutate() const {
|
bool canMutate() const {
|
||||||
|
if (OperandRenderers.size() != Matched.getNumOperands())
|
||||||
|
return false;
|
||||||
|
|
||||||
for (const auto &Renderer : enumerate(OperandRenderers)) {
|
for (const auto &Renderer : enumerate(OperandRenderers)) {
|
||||||
if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
|
if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
|
||||||
const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName());
|
const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName());
|
||||||
@ -1072,8 +1073,7 @@ void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RuleMatcher::emit(raw_ostream &OS,
|
void RuleMatcher::emit(raw_ostream &OS,
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
SubtargetFeatureInfoMap SubtargetFeatures) {
|
||||||
SubtargetFeatures) {
|
|
||||||
if (Matchers.empty())
|
if (Matchers.empty())
|
||||||
llvm_unreachable("Unexpected empty matcher!");
|
llvm_unreachable("Unexpected empty matcher!");
|
||||||
|
|
||||||
@ -1218,7 +1218,7 @@ private:
|
|||||||
DenseMap<const Record *, const Record *> ComplexPatternEquivs;
|
DenseMap<const Record *, const Record *> ComplexPatternEquivs;
|
||||||
|
|
||||||
// Map of predicates to their subtarget features.
|
// Map of predicates to their subtarget features.
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
|
SubtargetFeatureInfoMap SubtargetFeatures;
|
||||||
|
|
||||||
void gatherNodeEquivs();
|
void gatherNodeEquivs();
|
||||||
const CodeGenInstruction *findNodeEquiv(Record *N) const;
|
const CodeGenInstruction *findNodeEquiv(Record *N) const;
|
||||||
@ -1713,14 +1713,36 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
|
|||||||
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
|
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
|
||||||
OS);
|
OS);
|
||||||
SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);
|
SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS);
|
||||||
|
|
||||||
|
// Separate subtarget features by how often they must be recomputed.
|
||||||
|
SubtargetFeatureInfoMap ModuleFeatures;
|
||||||
|
std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(),
|
||||||
|
std::inserter(ModuleFeatures, ModuleFeatures.end()),
|
||||||
|
[](const SubtargetFeatureInfoMap::value_type &X) {
|
||||||
|
return !X.second.mustRecomputePerFunction();
|
||||||
|
});
|
||||||
|
SubtargetFeatureInfoMap FunctionFeatures;
|
||||||
|
std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(),
|
||||||
|
std::inserter(FunctionFeatures, FunctionFeatures.end()),
|
||||||
|
[](const SubtargetFeatureInfoMap::value_type &X) {
|
||||||
|
return X.second.mustRecomputePerFunction();
|
||||||
|
});
|
||||||
|
|
||||||
SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
||||||
Target.getName(), "InstructionSelector", "computeAvailableFeatures",
|
Target.getName(), "InstructionSelector", "computeAvailableModuleFeatures",
|
||||||
SubtargetFeatures, OS);
|
ModuleFeatures, OS);
|
||||||
|
SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
||||||
|
Target.getName(), "InstructionSelector",
|
||||||
|
"computeAvailableFunctionFeatures", FunctionFeatures, OS,
|
||||||
|
"const MachineFunction *MF");
|
||||||
|
|
||||||
OS << "bool " << Target.getName()
|
OS << "bool " << Target.getName()
|
||||||
<< "InstructionSelector::selectImpl(MachineInstr &I) const {\n"
|
<< "InstructionSelector::selectImpl(MachineInstr &I) const {\n"
|
||||||
<< " MachineFunction &MF = *I.getParent()->getParent();\n"
|
<< " MachineFunction &MF = *I.getParent()->getParent();\n"
|
||||||
<< " const MachineRegisterInfo &MRI = MF.getRegInfo();\n";
|
<< " const MachineRegisterInfo &MRI = MF.getRegInfo();\n"
|
||||||
|
<< " // FIXME: This should be computed on a per-function basis rather than per-insn.\n"
|
||||||
|
<< " AvailableFunctionFeatures = computeAvailableFunctionFeatures(&STI, &MF);\n"
|
||||||
|
<< " const PredicateBitset AvailableFeatures = getAvailableFeatures();\n";
|
||||||
|
|
||||||
for (auto &Rule : Rules) {
|
for (auto &Rule : Rules) {
|
||||||
Rule.emit(OS, SubtargetFeatures);
|
Rule.emit(OS, SubtargetFeatures);
|
||||||
@ -1730,6 +1752,26 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
|
|||||||
OS << " return false;\n"
|
OS << " return false;\n"
|
||||||
<< "}\n"
|
<< "}\n"
|
||||||
<< "#endif // ifdef GET_GLOBALISEL_IMPL\n";
|
<< "#endif // ifdef GET_GLOBALISEL_IMPL\n";
|
||||||
|
|
||||||
|
OS << "#ifdef GET_GLOBALISEL_PREDICATES_DECL\n"
|
||||||
|
<< "PredicateBitset AvailableModuleFeatures;\n"
|
||||||
|
<< "mutable PredicateBitset AvailableFunctionFeatures;\n"
|
||||||
|
<< "PredicateBitset getAvailableFeatures() const {\n"
|
||||||
|
<< " return AvailableModuleFeatures | AvailableFunctionFeatures;\n"
|
||||||
|
<< "}\n"
|
||||||
|
<< "PredicateBitset\n"
|
||||||
|
<< "computeAvailableModuleFeatures(const " << Target.getName()
|
||||||
|
<< "Subtarget *Subtarget) const;\n"
|
||||||
|
<< "PredicateBitset\n"
|
||||||
|
<< "computeAvailableFunctionFeatures(const " << Target.getName()
|
||||||
|
<< "Subtarget *Subtarget,\n"
|
||||||
|
<< " const MachineFunction *MF) const;\n"
|
||||||
|
<< "#endif // ifdef GET_GLOBALISEL_PREDICATES_DECL\n";
|
||||||
|
|
||||||
|
OS << "#ifdef GET_GLOBALISEL_PREDICATES_INIT\n"
|
||||||
|
<< "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n"
|
||||||
|
<< "AvailableFunctionFeatures()\n"
|
||||||
|
<< "#endif // ifdef GET_GLOBALISEL_PREDICATES_INIT\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
|
void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
|
||||||
|
@ -45,8 +45,7 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
|
void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
|
||||||
raw_ostream &OS) {
|
|
||||||
OS << "// Flags for subtarget features that participate in "
|
OS << "// Flags for subtarget features that participate in "
|
||||||
<< "instruction matching.\n";
|
<< "instruction matching.\n";
|
||||||
OS << "enum SubtargetFeatureFlag : "
|
OS << "enum SubtargetFeatureFlag : "
|
||||||
@ -60,8 +59,7 @@ void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
|
void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
|
||||||
raw_ostream &OS) {
|
|
||||||
OS << "// Bits for subtarget features that participate in "
|
OS << "// Bits for subtarget features that participate in "
|
||||||
<< "instruction matching.\n";
|
<< "instruction matching.\n";
|
||||||
OS << "enum SubtargetFeatureBits : "
|
OS << "enum SubtargetFeatureBits : "
|
||||||
@ -74,8 +72,7 @@ void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SubtargetFeatureInfo::emitNameTable(
|
void SubtargetFeatureInfo::emitNameTable(
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
|
||||||
raw_ostream &OS) {
|
|
||||||
// Need to sort the name table so that lookup by the log of the enum value
|
// Need to sort the name table so that lookup by the log of the enum value
|
||||||
// gives the proper name. More specifically, for a feature of value 1<<n,
|
// gives the proper name. More specifically, for a feature of value 1<<n,
|
||||||
// SubtargetFeatureNames[n] should be the name of the feature.
|
// SubtargetFeatureNames[n] should be the name of the feature.
|
||||||
@ -102,11 +99,13 @@ void SubtargetFeatureInfo::emitNameTable(
|
|||||||
|
|
||||||
void SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
void SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
||||||
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS,
|
||||||
raw_ostream &OS) {
|
StringRef ExtraParams) {
|
||||||
OS << "PredicateBitset " << TargetName << ClassName << "::\n"
|
OS << "PredicateBitset " << TargetName << ClassName << "::\n"
|
||||||
<< FuncName << "(const MachineFunction *MF, const " << TargetName
|
<< FuncName << "(const " << TargetName << "Subtarget *Subtarget";
|
||||||
<< "Subtarget *Subtarget) const {\n";
|
if (!ExtraParams.empty())
|
||||||
|
OS << ", " << ExtraParams;
|
||||||
|
OS << ") const {\n";
|
||||||
OS << " PredicateBitset Features;\n";
|
OS << " PredicateBitset Features;\n";
|
||||||
for (const auto &SF : SubtargetFeatures) {
|
for (const auto &SF : SubtargetFeatures) {
|
||||||
const SubtargetFeatureInfo &SFI = SF.second;
|
const SubtargetFeatureInfo &SFI = SF.second;
|
||||||
@ -120,8 +119,7 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
|
|||||||
|
|
||||||
void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
|
void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
|
||||||
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
|
||||||
raw_ostream &OS) {
|
|
||||||
OS << "uint64_t " << TargetName << ClassName << "::\n"
|
OS << "uint64_t " << TargetName << ClassName << "::\n"
|
||||||
<< FuncName << "(const FeatureBitset& FB) const {\n";
|
<< FuncName << "(const FeatureBitset& FB) const {\n";
|
||||||
OS << " uint64_t Features = 0;\n";
|
OS << " uint64_t Features = 0;\n";
|
||||||
|
@ -21,6 +21,9 @@ namespace llvm {
|
|||||||
class Record;
|
class Record;
|
||||||
class RecordKeeper;
|
class RecordKeeper;
|
||||||
|
|
||||||
|
struct SubtargetFeatureInfo;
|
||||||
|
using SubtargetFeatureInfoMap = std::map<Record *, SubtargetFeatureInfo, LessRecordByID>;
|
||||||
|
|
||||||
/// Helper class for storing information on a subtarget feature which
|
/// Helper class for storing information on a subtarget feature which
|
||||||
/// participates in instruction matching.
|
/// participates in instruction matching.
|
||||||
struct SubtargetFeatureInfo {
|
struct SubtargetFeatureInfo {
|
||||||
@ -43,6 +46,10 @@ struct SubtargetFeatureInfo {
|
|||||||
return "Feature_" + TheDef->getName().str() + "Bit";
|
return "Feature_" + TheDef->getName().str() + "Bit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mustRecomputePerFunction() const {
|
||||||
|
return TheDef->getValueAsBit("RecomputePerFunction");
|
||||||
|
}
|
||||||
|
|
||||||
void dump() const;
|
void dump() const;
|
||||||
static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
|
static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
|
||||||
getAll(const RecordKeeper &Records);
|
getAll(const RecordKeeper &Records);
|
||||||
@ -52,21 +59,17 @@ struct SubtargetFeatureInfo {
|
|||||||
/// This version emits the bit value for the feature and is therefore limited
|
/// This version emits the bit value for the feature and is therefore limited
|
||||||
/// to 64 feature bits.
|
/// to 64 feature bits.
|
||||||
static void emitSubtargetFeatureFlagEnumeration(
|
static void emitSubtargetFeatureFlagEnumeration(
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS);
|
||||||
&SubtargetFeatures,
|
|
||||||
raw_ostream &OS);
|
|
||||||
|
|
||||||
/// Emit the subtarget feature flag definitions.
|
/// Emit the subtarget feature flag definitions.
|
||||||
///
|
///
|
||||||
/// This version emits the bit index for the feature and can therefore support
|
/// This version emits the bit index for the feature and can therefore support
|
||||||
/// more than 64 feature bits.
|
/// more than 64 feature bits.
|
||||||
static void emitSubtargetFeatureBitEnumeration(
|
static void
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
emitSubtargetFeatureBitEnumeration(SubtargetFeatureInfoMap &SubtargetFeatures,
|
||||||
&SubtargetFeatures,
|
raw_ostream &OS);
|
||||||
raw_ostream &OS);
|
|
||||||
|
|
||||||
static void emitNameTable(std::map<Record *, SubtargetFeatureInfo,
|
static void emitNameTable(SubtargetFeatureInfoMap &SubtargetFeatures,
|
||||||
LessRecordByID> &SubtargetFeatures,
|
|
||||||
raw_ostream &OS);
|
raw_ostream &OS);
|
||||||
|
|
||||||
/// Emit the function to compute the list of available features given a
|
/// Emit the function to compute the list of available features given a
|
||||||
@ -82,11 +85,12 @@ struct SubtargetFeatureInfo {
|
|||||||
/// \param FuncName The name of the function to emit.
|
/// \param FuncName The name of the function to emit.
|
||||||
/// \param SubtargetFeatures A map of TableGen records to the
|
/// \param SubtargetFeatures A map of TableGen records to the
|
||||||
/// SubtargetFeatureInfo equivalent.
|
/// SubtargetFeatureInfo equivalent.
|
||||||
static void emitComputeAvailableFeatures(
|
/// \param ExtraParams Additional arguments to the generated function.
|
||||||
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
static void
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
emitComputeAvailableFeatures(StringRef TargetName, StringRef ClassName,
|
||||||
&SubtargetFeatures,
|
StringRef FuncName,
|
||||||
raw_ostream &OS);
|
SubtargetFeatureInfoMap &SubtargetFeatures,
|
||||||
|
raw_ostream &OS, StringRef ExtraParams = "");
|
||||||
|
|
||||||
/// Emit the function to compute the list of available features given a
|
/// Emit the function to compute the list of available features given a
|
||||||
/// subtarget.
|
/// subtarget.
|
||||||
@ -103,9 +107,7 @@ struct SubtargetFeatureInfo {
|
|||||||
/// SubtargetFeatureInfo equivalent.
|
/// SubtargetFeatureInfo equivalent.
|
||||||
static void emitComputeAssemblerAvailableFeatures(
|
static void emitComputeAssemblerAvailableFeatures(
|
||||||
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
StringRef TargetName, StringRef ClassName, StringRef FuncName,
|
||||||
std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
|
SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS);
|
||||||
&SubtargetFeatures,
|
|
||||||
raw_ostream &OS);
|
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user