Index: include/llvm/CodeGen/GlobalISel/InstructionSelector.h =================================================================== --- include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -61,9 +61,6 @@ public: 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 /// opcodes. It is OK to insert multiple instructions, but they cannot be /// generic pre-isel instructions. Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -530,6 +530,12 @@ /// PredicateName - User-level name to use for the predicate. Mainly for use /// in diagnostics such as missing feature errors in the asm matcher. 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 Index: lib/CodeGen/GlobalISel/InstructionSelector.cpp =================================================================== --- lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -58,10 +58,11 @@ MO.setReg(constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, I.getDesc(), 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()) { int DefIdx = I.getDesc().getOperandConstraint(OpI, MCOI::TIED_TO); - if (DefIdx != -1) + if (DefIdx != -1 && !I.isRegTiedToUseOperand(DefIdx)) I.tieOperands(DefIdx, OpI); } } Index: lib/Target/AArch64/AArch64.h =================================================================== --- lib/Target/AArch64/AArch64.h +++ lib/Target/AArch64/AArch64.h @@ -50,7 +50,8 @@ FunctionPass *createAArch64CollectLOHPass(); InstructionSelector * createAArch64InstructionSelector(const AArch64TargetMachine &, - AArch64Subtarget &, AArch64RegisterBankInfo &); + AArch64Subtarget &, AArch64RegisterBankInfo &, + bool ForCodeSize); void initializeAArch64A53Fix835769Pass(PassRegistry&); void initializeAArch64A57FPLoadBalancingPass(PassRegistry&); Index: lib/Target/AArch64/AArch64InstructionSelector.cpp =================================================================== --- lib/Target/AArch64/AArch64InstructionSelector.cpp +++ lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -49,9 +49,9 @@ public: AArch64InstructionSelector(const AArch64TargetMachine &TM, const AArch64Subtarget &STI, - const AArch64RegisterBankInfo &RBI); + const AArch64RegisterBankInfo &RBI, + bool ForCodeSize); - void beginFunction(const MachineFunction &MF) override; bool select(MachineInstr &I) const override; private: @@ -76,10 +76,9 @@ const AArch64RegisterBankInfo &RBI; bool ForCodeSize; - PredicateBitset AvailableFeatures; - PredicateBitset - computeAvailableFeatures(const MachineFunction *MF, - const AArch64Subtarget *Subtarget) const; +#define GET_GLOBALISEL_PREDICATES_DECL +#include "AArch64GenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_DECL // We declare the temporaries used by selectImpl() in the class to minimize the // cost of constructing placeholder values. @@ -96,9 +95,12 @@ AArch64InstructionSelector::AArch64InstructionSelector( const AArch64TargetMachine &TM, const AArch64Subtarget &STI, - const AArch64RegisterBankInfo &RBI) + const AArch64RegisterBankInfo &RBI, bool ForCodeSize) : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), - TRI(*STI.getRegisterInfo()), RBI(RBI), ForCodeSize(), AvailableFeatures() + TRI(*STI.getRegisterInfo()), RBI(RBI), ForCodeSize(ForCodeSize), +#define GET_GLOBALISEL_PREDICATES_INIT +#include "AArch64GenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_INIT #define GET_GLOBALISEL_TEMPORARIES_INIT #include "AArch64GenGlobalISel.inc" #undef GET_GLOBALISEL_TEMPORARIES_INIT @@ -577,12 +579,6 @@ return true; } -void AArch64InstructionSelector::beginFunction( - const MachineFunction &MF) { - ForCodeSize = MF.getFunction()->optForSize(); - AvailableFeatures = computeAvailableFeatures(&MF, &STI); -} - bool AArch64InstructionSelector::select(MachineInstr &I) const { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -1371,10 +1367,9 @@ } namespace llvm { -InstructionSelector * -createAArch64InstructionSelector(const AArch64TargetMachine &TM, - AArch64Subtarget &Subtarget, - AArch64RegisterBankInfo &RBI) { - return new AArch64InstructionSelector(TM, Subtarget, RBI); +InstructionSelector *createAArch64InstructionSelector( + const AArch64TargetMachine &TM, AArch64Subtarget &Subtarget, + AArch64RegisterBankInfo &RBI, bool ForCodeSize) { + return new AArch64InstructionSelector(TM, Subtarget, RBI, ForCodeSize); } } Index: lib/Target/AArch64/AArch64TargetMachine.cpp =================================================================== --- lib/Target/AArch64/AArch64TargetMachine.cpp +++ lib/Target/AArch64/AArch64TargetMachine.cpp @@ -255,6 +255,7 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); Attribute FSAttr = F.getFnAttribute("target-features"); + bool ForCodeSize = F.optForSize(); std::string CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString().str() @@ -262,8 +263,9 @@ std::string FS = !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString().str() : TargetFS; + std::string ForCodeSizeStr = ForCodeSize ? "-forcodesize" : ""; - auto &I = SubtargetMap[CPU + FS]; + auto &I = SubtargetMap[CPU + FS + ForCodeSizeStr]; if (!I) { // 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 @@ -286,7 +288,7 @@ // It's awkward to mix passing RBI and the Subtarget; should we pass // TII/TRI as well? GISel->InstSelector.reset( - createAArch64InstructionSelector(*this, *I, *RBI)); + createAArch64InstructionSelector(*this, *I, *RBI, ForCodeSize)); GISel->RegBankInfo.reset(RBI); #endif Index: lib/Target/X86/X86.h =================================================================== --- lib/Target/X86/X86.h +++ lib/Target/X86/X86.h @@ -97,7 +97,9 @@ InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &, - X86RegisterBankInfo &); + X86RegisterBankInfo &, + bool OptForSize, + bool OptForMinSize); void initializeEvexToVexInstPassPass(PassRegistry &); Index: lib/Target/X86/X86InstrInfo.td =================================================================== --- lib/Target/X86/X86InstrInfo.td +++ lib/Target/X86/X86InstrInfo.td @@ -877,7 +877,9 @@ def IsWin64 : Predicate<"Subtarget->isTargetWin64()">; def NotWin64 : 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 NotPS4 : Predicate<"!Subtarget->isTargetPS4()">; def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">; Index: lib/Target/X86/X86InstructionSelector.cpp =================================================================== --- lib/Target/X86/X86InstructionSelector.cpp +++ lib/Target/X86/X86InstructionSelector.cpp @@ -46,9 +46,9 @@ class X86InstructionSelector : public InstructionSelector { public: X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI, - const X86RegisterBankInfo &RBI); + const X86RegisterBankInfo &RBI, bool OptForSize, + bool OptForMinSize); - void beginFunction(const MachineFunction &MF) override; bool select(MachineInstr &I) const override; private: @@ -83,9 +83,9 @@ bool OptForSize; bool OptForMinSize; - PredicateBitset AvailableFeatures; - PredicateBitset computeAvailableFeatures(const MachineFunction *MF, - const X86Subtarget *Subtarget) const; +#define GET_GLOBALISEL_PREDICATES_DECL +#include "X86GenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_DECL #define GET_GLOBALISEL_TEMPORARIES_DECL #include "X86GenGlobalISel.inc" @@ -100,10 +100,15 @@ X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI, - const X86RegisterBankInfo &RBI) + const X86RegisterBankInfo &RBI, + bool OptForSize, + bool OptForMinSize) : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), - TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(false), - OptForMinSize(false), AvailableFeatures() + TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(OptForSize), + OptForMinSize(OptForMinSize), +#define GET_GLOBALISEL_PREDICATES_INIT +#include "X86GenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_INIT #define GET_GLOBALISEL_TEMPORARIES_INIT #include "X86GenGlobalISel.inc" #undef GET_GLOBALISEL_TEMPORARIES_INIT @@ -195,12 +200,6 @@ 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 { assert(I.getParent() && "Instruction should be in a basic block!"); assert(I.getParent()->getParent() && "Instruction should be in a function!"); @@ -593,6 +592,6 @@ InstructionSelector * llvm::createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &Subtarget, - X86RegisterBankInfo &RBI) { - return new X86InstructionSelector(TM, Subtarget, RBI); + X86RegisterBankInfo &RBI, bool OptForSize, bool OptForMinSize) { + return new X86InstructionSelector(TM, Subtarget, RBI, OptForSize, OptForMinSize); } Index: lib/Target/X86/X86TargetMachine.cpp =================================================================== --- lib/Target/X86/X86TargetMachine.cpp +++ lib/Target/X86/X86TargetMachine.cpp @@ -268,6 +268,12 @@ FS = Key.substr(CPU.size()); + bool OptForSize = F.optForSize(); + bool OptForMinSize = F.optForMinSize(); + + Key += OptForSize ? "-optforsize" : ""; + Key += OptForMinSize ? "-optforminsize" : ""; + auto &I = SubtargetMap[Key]; if (!I) { // This needs to be done before we create a new subtarget since any @@ -286,7 +292,8 @@ auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo()); GISel->RegBankInfo.reset(RBI); - GISel->InstSelector.reset(createX86InstructionSelector(*this, *I, *RBI)); + GISel->InstSelector.reset(createX86InstructionSelector( + *this, *I, *RBI, OptForSize, OptForMinSize)); #endif I->setGISelAccessor(*GISel); } Index: test/CodeGen/X86/GlobalISel/select-inc.mir =================================================================== --- /dev/null +++ test/CodeGen/X86/GlobalISel/select-inc.mir @@ -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) + +... Index: test/TableGen/GlobalISelEmitter.td =================================================================== --- test/TableGen/GlobalISelEmitter.td +++ test/TableGen/GlobalISelEmitter.td @@ -32,22 +32,25 @@ def HasA : Predicate<"Subtarget->hasA()">; def HasB : Predicate<"Subtarget->hasB()">; +def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } //===- Test the function boilerplate. -------------------------------------===// // CHECK-LABEL: enum SubtargetFeatureBits : uint8_t { // CHECK-NEXT: Feature_HasABit = 0, // CHECK-NEXT: Feature_HasBBit = 1, +// CHECK-NEXT: Feature_HasCBit = 2, // CHECK-NEXT: }; // CHECK-LABEL: static const char *SubtargetFeatureNames[] = { // CHECK-NEXT: "Feature_HasA", // CHECK-NEXT: "Feature_HasB", +// CHECK-NEXT: "Feature_HasC", // CHECK-NEXT: nullptr // CHECK-NEXT: }; // 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: if (Subtarget->hasA()) // CHECK-NEXT: Features[Feature_HasABit] = 1; @@ -56,6 +59,14 @@ // CHECK-NEXT: return Features; // 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: MachineFunction &MF = *I.getParent()->getParent(); // CHECK: const MachineRegisterInfo &MRI = MF.getRegInfo(); @@ -216,7 +227,7 @@ //===- Test another simple pattern with regclass operands. ----------------===// // 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: return false; // CHECK-NEXT: MachineInstr &MI0 = I; @@ -247,7 +258,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1), [(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>, - Requires<[HasA, HasB]>; + Requires<[HasA, HasB, HasC]>; //===- Test a pattern with ComplexPattern operands. -----------------------===// // Index: utils/TableGen/GlobalISelEmitter.cpp =================================================================== --- utils/TableGen/GlobalISelEmitter.cpp +++ utils/TableGen/GlobalISelEmitter.cpp @@ -199,21 +199,19 @@ void emitCxxCapturedInsnList(raw_ostream &OS); void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr); - void emit(raw_ostream &OS, - std::map - SubtargetFeatures); +void emit(raw_ostream &OS, SubtargetFeatureInfoMap SubtargetFeatures); - /// Compare the priority of this object and B. - /// - /// Returns true if this object is more important than B. - bool isHigherPriorityThan(const RuleMatcher &B) const; +/// Compare the priority of this object and B. +/// +/// Returns true if this object is more important than B. +bool isHigherPriorityThan(const RuleMatcher &B) const; - /// Report the maximum number of temporary operands needed by the rule - /// matcher. - unsigned countRendererFns() const; +/// Report the maximum number of temporary operands needed by the rule +/// matcher. +unsigned countRendererFns() const; - // FIXME: Remove this as soon as possible - InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); } +// FIXME: Remove this as soon as possible +InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); } }; template class PredicateListMatcher { @@ -951,6 +949,9 @@ /// True if the instruction can be built solely by mutating the opcode. bool canMutate() const { + if (OperandRenderers.size() != Matched.getNumOperands()) + return false; + for (const auto &Renderer : enumerate(OperandRenderers)) { if (const auto *Copy = dyn_cast(&*Renderer.value())) { const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName()); @@ -1072,8 +1073,7 @@ } void RuleMatcher::emit(raw_ostream &OS, - std::map - SubtargetFeatures) { + SubtargetFeatureInfoMap SubtargetFeatures) { if (Matchers.empty()) llvm_unreachable("Unexpected empty matcher!"); @@ -1218,7 +1218,7 @@ DenseMap ComplexPatternEquivs; // Map of predicates to their subtarget features. - std::map SubtargetFeatures; + SubtargetFeatureInfoMap SubtargetFeatures; void gatherNodeEquivs(); const CodeGenInstruction *findNodeEquiv(Record *N) const; @@ -1713,14 +1713,36 @@ SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(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( - Target.getName(), "InstructionSelector", "computeAvailableFeatures", - SubtargetFeatures, OS); + Target.getName(), "InstructionSelector", "computeAvailableModuleFeatures", + ModuleFeatures, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "InstructionSelector", + "computeAvailableFunctionFeatures", FunctionFeatures, OS, + "const MachineFunction *MF"); OS << "bool " << Target.getName() << "InstructionSelector::selectImpl(MachineInstr &I) const {\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) { Rule.emit(OS, SubtargetFeatures); @@ -1730,6 +1752,26 @@ OS << " return false;\n" << "}\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) { Index: utils/TableGen/SubtargetFeatureInfo.h =================================================================== --- utils/TableGen/SubtargetFeatureInfo.h +++ utils/TableGen/SubtargetFeatureInfo.h @@ -21,6 +21,9 @@ class Record; class RecordKeeper; +struct SubtargetFeatureInfo; +using SubtargetFeatureInfoMap = std::map; + /// Helper class for storing information on a subtarget feature which /// participates in instruction matching. struct SubtargetFeatureInfo { @@ -43,6 +46,10 @@ return "Feature_" + TheDef->getName().str() + "Bit"; } + bool mustRecomputePerFunction() const { + return TheDef->getValueAsBit("RecomputePerFunction"); + } + void dump() const; static std::vector> getAll(const RecordKeeper &Records); @@ -52,21 +59,17 @@ /// This version emits the bit value for the feature and is therefore limited /// to 64 feature bits. static void emitSubtargetFeatureFlagEnumeration( - std::map - &SubtargetFeatures, - raw_ostream &OS); + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); /// Emit the subtarget feature flag definitions. /// /// This version emits the bit index for the feature and can therefore support /// more than 64 feature bits. - static void emitSubtargetFeatureBitEnumeration( - std::map - &SubtargetFeatures, - raw_ostream &OS); + static void + emitSubtargetFeatureBitEnumeration(SubtargetFeatureInfoMap &SubtargetFeatures, + raw_ostream &OS); - static void emitNameTable(std::map &SubtargetFeatures, + static void emitNameTable(SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); /// Emit the function to compute the list of available features given a @@ -82,11 +85,12 @@ /// \param FuncName The name of the function to emit. /// \param SubtargetFeatures A map of TableGen records to the /// SubtargetFeatureInfo equivalent. - static void emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map - &SubtargetFeatures, - raw_ostream &OS); + /// \param ExtraParams Additional arguments to the generated function. + static void + emitComputeAvailableFeatures(StringRef TargetName, StringRef ClassName, + StringRef FuncName, + SubtargetFeatureInfoMap &SubtargetFeatures, + raw_ostream &OS, StringRef ExtraParams = ""); /// Emit the function to compute the list of available features given a /// subtarget. @@ -103,9 +107,7 @@ /// SubtargetFeatureInfo equivalent. static void emitComputeAssemblerAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map - &SubtargetFeatures, - raw_ostream &OS); + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); }; } // end namespace llvm Index: utils/TableGen/SubtargetFeatureInfo.cpp =================================================================== --- utils/TableGen/SubtargetFeatureInfo.cpp +++ utils/TableGen/SubtargetFeatureInfo.cpp @@ -45,8 +45,7 @@ } void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( - std::map &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "// Flags for subtarget features that participate in " << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " @@ -60,8 +59,7 @@ } void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( - std::map &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "// Bits for subtarget features that participate in " << "instruction matching.\n"; OS << "enum SubtargetFeatureBits : " @@ -74,8 +72,7 @@ } void SubtargetFeatureInfo::emitNameTable( - std::map &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { // 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< &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + StringRef ExtraParams) { OS << "PredicateBitset " << TargetName << ClassName << "::\n" - << FuncName << "(const MachineFunction *MF, const " << TargetName - << "Subtarget *Subtarget) const {\n"; + << FuncName << "(const " << TargetName << "Subtarget *Subtarget"; + if (!ExtraParams.empty()) + OS << ", " << ExtraParams; + OS << ") const {\n"; OS << " PredicateBitset Features;\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -120,8 +119,7 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - std::map &SubtargetFeatures, - raw_ostream &OS) { + SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { OS << "uint64_t " << TargetName << ClassName << "::\n" << FuncName << "(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n";