[llvm] r301750 - [globalisel][tablegen] Compute available feature bits correctly.

Daniel Sanders via llvm-commits llvm-commits at lists.llvm.org
Wed May 3 03:34:28 PDT 2017


Hi Eric and Quentin,

There will be a test that requires it very shortly. It consists of the changes made in the latest revision of D32491 (this commit is the penultimate revision of D32491). These changes were deferred to a second patch because a further change was required to the X86 target to make the test pass and because it would have been doing too much if that update had been included in the same change. Now that X86 has moved its selectImpl() call, I can add the importer feature that exposes the test case and use that as a test case for OptForSize. I'm currently re-testing it and expect to post it today.

>> That said, there could be something I've missed. Can you explain this patch much more thoroughly? The subtarget change is even missing from your patch description.


GlobalISel is taking a different approach to predicates compared to SelectionDAG but it still supports the existing Predicate<> definitions. Predicates are evaluated in advance (at the lowest frequency possible) and the results are held in a bitset. The tablegen-erated matcher can then test multiple predicates together using '(FeatureSet & AvailableFeatures) == FeatureSet' rather than being limited to testing each predicate individually with OPC_CheckPredicate which is equivalent to 'F1 && F2 && F3 && F4 ...'. This will also reduce the overhead of parsing the matcher table since it will have to interpret fewer opcodes. I'm expecting this to work out noticeably faster than SelectionDAG even though predicates are calculated in advance and selectImpl() might not use all of them on a particular input.

An important aspect of this is that predicates are evaluated at the lowest frequency possible. Ideally, predicates should be evaluated once per module and retained for each function/bb/instruction but this is not always possible. Fortunately this is mitigated by the existence of multiple <Target>Subtarget instances. The target-features attribute for example would have required most predicates to be re-computed on a per-function basis if there were a single <Target>Subtarget instance but the implementation of getSubtargetImpl() allows us to reduce this to once per subtarget-instance which is nearly as good. Similarly, ForCodeSize/NotForCodeSize in AArch64 and OptForSize/OptForMinSize/OptForSpeed in X86 are examples of function-level predicates that can be computed once per subtarget using the same technique and they have been added to the key to take advantage of this. We could evaluate them using Function directly but this comes at the cost of having to re-evaluate them on a per-function basis.

The only predicate that genuinely needs to be calculated on a per-function basis so far is NotWin64WithoutFP on X86 which needs the MachineFunction to determine whether the frame pointer is available.

>> I don't see a reason to pass whether or not we're optimizing for size through the subtarget constructor - it's not being used to initialize anything in the subtarget and it can be gotten from the function directly. I think this is the wrong direction to take this and would prefer that we use the function attributes in places that we need them.


The main cost of taking it from the Function directly is the increased frequency with which we need to re-evaluate the predicate. Instead of being once per unique subtarget, it would be once per function*. I'd expect per-unique subtarget to be a win in the general case because most codebases have a single subtarget for all functions.

* It's actually worse than this right now, it's once per instruction. However, that's just a case not having fully implemented the per-function frequency yet.

> On 3 May 2017, at 00:26, Quentin Colombet <qcolombet at apple.com> wrote:
> 
> Hi Daniel,
> 
> We’ve talked with Eric on IRC and we agreed that this part of the patch is not needed for now.
> 
> I am actually supportive of this kind of approach where we could derive different selector/legalizer/etc. based on this “attribute”. E.g., we could have a NeonInstructionSelector and a CodeSizeSelector. However, Eric pointed out that this feature is not used right now and thus, we should postpone the design of such approach whenever we need it.
> 
> Cheers,
> -Quentin
> 
>> On May 2, 2017, at 11:50 AM, Eric Christopher <echristo at gmail.com <mailto:echristo at gmail.com>> wrote:
>> 
>> Hi Daniel,
>> 
>> I don't see a reason to pass whether or not we're optimizing for size through the subtarget constructor - it's not being used to initialize anything in the subtarget and it can be gotten from the function directly. I think this is the wrong direction to take this and would prefer that we use the function attributes in places that we need them.
>> 
>> That said, there could be something I've missed. Can you explain this patch much more thoroughly? The subtarget change is even missing from your patch description.
>> 
>> -eric
>> 
>> On Sat, Apr 29, 2017 at 10:43 AM Daniel Sanders via llvm-commits <llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>> wrote:
>> Author: dsanders
>> Date: Sat Apr 29 12:30:09 2017
>> New Revision: 301750
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=301750&view=rev <http://llvm.org/viewvc/llvm-project?rev=301750&view=rev>
>> Log:
>> [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 <https://reviews.llvm.org/D32491>
>> 
>> Added:
>>     llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir
>> Modified:
>>     llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
>>     llvm/trunk/include/llvm/Target/Target.td
>>     llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp
>>     llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
>>     llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
>>     llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp
>>     llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
>>     llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
>>     llvm/trunk/lib/Target/X86/X86InstrInfo.td
>>     llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp
>>     llvm/trunk/lib/Target/X86/X86Subtarget.cpp
>>     llvm/trunk/lib/Target/X86/X86Subtarget.h
>>     llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
>>     llvm/trunk/test/TableGen/GlobalISelEmitter.td
>>     llvm/trunk/unittests/Target/AArch64/InstSizes.cpp
>>     llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
>>     llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp
>>     llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h
>> 
>> Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h (original)
>> +++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Sat Apr 29 12:30:09 2017
>> @@ -61,9 +61,6 @@ class InstructionSelector {
>>  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.
>> 
>> Modified: llvm/trunk/include/llvm/Target/Target.td
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Target/Target.td (original)
>> +++ llvm/trunk/include/llvm/Target/Target.td Sat Apr 29 12:30:09 2017
>> @@ -530,6 +530,12 @@ class Predicate<string cond> {
>>    /// 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
>> 
>> Modified: llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp Sat Apr 29 12:30:09 2017
>> @@ -58,10 +58,11 @@ bool InstructionSelector::constrainSelec
>>      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);
>>      }
>>    }
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.td Sat Apr 29 12:30:09 2017
>> @@ -314,8 +314,8 @@ def AArch64umaxv    : SDNode<"AArch64ISD
>>  // AArch64 Instruction Predicate Definitions.
>>  def IsDarwin  : Predicate<"Subtarget->isTargetDarwin()">;
>>  def IsNotDarwin: Predicate<"!Subtarget->isTargetDarwin()">;
>> -def ForCodeSize   : Predicate<"ForCodeSize">;
>> -def NotForCodeSize   : Predicate<"!ForCodeSize">;
>> +def ForCodeSize   : Predicate<"Subtarget->getForCodeSize()">;
>> +def NotForCodeSize   : Predicate<"!Subtarget->getForCodeSize()">;
>> 
>>  include "AArch64InstrFormats.td"
>> 
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Sat Apr 29 12:30:09 2017
>> @@ -51,7 +51,6 @@ public:
>>                               const AArch64Subtarget &STI,
>>                               const AArch64RegisterBankInfo &RBI);
>> 
>> -  void beginFunction(const MachineFunction &MF) override;
>>    bool select(MachineInstr &I) const override;
>> 
>>  private:
>> @@ -74,12 +73,10 @@ private:
>>    const AArch64InstrInfo &TII;
>>    const AArch64RegisterInfo &TRI;
>>    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.
>> @@ -98,7 +95,10 @@ AArch64InstructionSelector::AArch64Instr
>>      const AArch64TargetMachine &TM, const AArch64Subtarget &STI,
>>      const AArch64RegisterBankInfo &RBI)
>>      : 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
>>  #include "AArch64GenGlobalISel.inc"
>>  #undef GET_GLOBALISEL_TEMPORARIES_INIT
>> @@ -577,12 +577,6 @@ bool AArch64InstructionSelector::selectV
>>    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!");
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp Sat Apr 29 12:30:09 2017
>> @@ -113,11 +113,12 @@ void AArch64Subtarget::initializePropert
>> 
>>  AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
>>                                     const std::string &FS,
>> -                                   const TargetMachine &TM, bool LittleEndian)
>> +                                   const TargetMachine &TM, bool LittleEndian,
>> +                                   bool ForCodeSize)
>>      : AArch64GenSubtargetInfo(TT, CPU, FS), ReserveX18(TT.isOSDarwin()),
>>        IsLittle(LittleEndian), TargetTriple(TT), FrameLowering(),
>>        InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
>> -      TLInfo(TM, *this), GISel() {}
>> +      TLInfo(TM, *this), GISel(), ForCodeSize(ForCodeSize) {}
>> 
>>  const CallLowering *AArch64Subtarget::getCallLowering() const {
>>    assert(GISel && "Access to GlobalISel APIs not set");
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h Sat Apr 29 12:30:09 2017
>> @@ -124,6 +124,8 @@ protected:
>>    /// an optional library.
>>    std::unique_ptr<GISelAccessor> GISel;
>> 
>> +  bool ForCodeSize;
>> +
>>  private:
>>    /// initializeSubtargetDependencies - Initializes using CPUString and the
>>    /// passed in feature string so that we can use initializer lists for
>> @@ -139,7 +141,7 @@ public:
>>    /// of the specified triple.
>>    AArch64Subtarget(const Triple &TT, const std::string &CPU,
>>                     const std::string &FS, const TargetMachine &TM,
>> -                   bool LittleEndian);
>> +                   bool LittleEndian, bool ForCodeSize);
>> 
>>    /// This object will take onwership of \p GISelAccessor.
>>    void setGISelAccessor(GISelAccessor &GISel) {
>> @@ -262,6 +264,8 @@ public:
>>      }
>>    }
>> 
>> +  bool getForCodeSize() const { return ForCodeSize; }
>> +
>>    /// ParseSubtargetFeatures - Parses features string setting specified
>>    /// subtarget options.  Definition of function is auto generated by tblgen.
>>    void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
>> 
>> Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp (original)
>> +++ llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp Sat Apr 29 12:30:09 2017
>> @@ -255,6 +255,7 @@ const AArch64Subtarget *
>>  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,15 +263,17 @@ AArch64TargetMachine::getSubtargetImpl(c
>>    std::string FS = !FSAttr.hasAttribute(Attribute::None)
>>                         ? FSAttr.getValueAsString().str()
>>                         : TargetFS;
>> +  std::string ForCodeSizeStr =
>> +      std::string(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
>>      // function that reside in TargetOptions.
>>      resetTargetOptions(F);
>>      I = llvm::make_unique<AArch64Subtarget>(TargetTriple, CPU, FS, *this,
>> -                                            isLittle);
>> +                                            isLittle, ForCodeSize);
>>  #ifndef LLVM_BUILD_GLOBAL_ISEL
>>      GISelAccessor *GISel = new GISelAccessor();
>>  #else
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
>> +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Sat Apr 29 12:30:09 2017
>> @@ -877,7 +877,9 @@ def In32BitMode  : Predicate<"Subtarget-
>>  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()">;
>> @@ -887,9 +889,9 @@ def KernelCode   : Predicate<"TM.getCode
>>  def NearData     : Predicate<"TM.getCodeModel() == CodeModel::Small ||"
>>                               "TM.getCodeModel() == CodeModel::Kernel">;
>>  def IsNotPIC     : Predicate<"!TM.isPositionIndependent()">;
>> -def OptForSize   : Predicate<"OptForSize">;
>> -def OptForMinSize : Predicate<"OptForMinSize">;
>> -def OptForSpeed  : Predicate<"!OptForSize">;
>> +def OptForSize   : Predicate<"Subtarget->getOptForSize()">;
>> +def OptForMinSize : Predicate<"Subtarget->getOptForMinSize()">;
>> +def OptForSpeed  : Predicate<"!Subtarget->getOptForSize()">;
>>  def FastBTMem    : Predicate<"!Subtarget->isBTMemSlow()">;
>>  def CallImmAddr  : Predicate<"Subtarget->isLegalToCallImmediateAddr()">;
>>  def FavorMemIndirectCall  : Predicate<"!Subtarget->callRegIndirect()">;
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp (original)
>> +++ llvm/trunk/lib/Target/X86/X86InstructionSelector.cpp Sat Apr 29 12:30:09 2017
>> @@ -48,7 +48,6 @@ public:
>>    X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
>>                           const X86RegisterBankInfo &RBI);
>> 
>> -  void beginFunction(const MachineFunction &MF) override;
>>    bool select(MachineInstr &I) const override;
>> 
>>  private:
>> @@ -80,12 +79,10 @@ private:
>>    const X86InstrInfo &TII;
>>    const X86RegisterInfo &TRI;
>>    const X86RegisterBankInfo &RBI;
>> -  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"
>> @@ -102,8 +99,10 @@ X86InstructionSelector::X86InstructionSe
>>                                                 const X86Subtarget &STI,
>>                                                 const X86RegisterBankInfo &RBI)
>>      : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
>> -      TRI(*STI.getRegisterInfo()), RBI(RBI), OptForSize(false),
>> -      OptForMinSize(false), AvailableFeatures()
>> +      TRI(*STI.getRegisterInfo()), RBI(RBI),
>> +#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
>> @@ -206,12 +205,6 @@ static bool selectCopy(MachineInstr &I,
>>    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!");
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)
>> +++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Sat Apr 29 12:30:09 2017
>> @@ -326,7 +326,8 @@ X86Subtarget &X86Subtarget::initializeSu
>> 
>>  X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
>>                             const X86TargetMachine &TM,
>> -                           unsigned StackAlignOverride)
>> +                           unsigned StackAlignOverride, bool OptForSize,
>> +                           bool OptForMinSize)
>>      : X86GenSubtargetInfo(TT, CPU, FS), X86ProcFamily(Others),
>>        PICStyle(PICStyles::None), TM(TM), TargetTriple(TT),
>>        StackAlignOverride(StackAlignOverride),
>> @@ -335,8 +336,9 @@ X86Subtarget::X86Subtarget(const Triple
>>                    TargetTriple.getEnvironment() != Triple::CODE16),
>>        In16BitMode(TargetTriple.getArch() == Triple::x86 &&
>>                    TargetTriple.getEnvironment() == Triple::CODE16),
>> -      InstrInfo(initializeSubtargetDependencies(CPU, FS)),
>> -      TLInfo(TM, *this), FrameLowering(*this, getStackAlignment()) {
>> +      InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
>> +      FrameLowering(*this, getStackAlignment()), OptForSize(OptForSize),
>> +      OptForMinSize(OptForMinSize) {
>>    // Determine the PICStyle based on the target selected.
>>    if (!isPositionIndependent())
>>      setPICStyle(PICStyles::None);
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.h?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86Subtarget.h (original)
>> +++ llvm/trunk/lib/Target/X86/X86Subtarget.h Sat Apr 29 12:30:09 2017
>> @@ -328,12 +328,16 @@ private:
>>    X86TargetLowering TLInfo;
>>    X86FrameLowering FrameLowering;
>> 
>> +  bool OptForSize;
>> +  bool OptForMinSize;
>> +
>>  public:
>>    /// This constructor initializes the data members to match that
>>    /// of the specified triple.
>>    ///
>>    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.
>>    void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); }
>> @@ -499,6 +503,9 @@ public:
>>    bool isSLM() const { return X86ProcFamily == IntelSLM; }
>>    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
>>    /// no-sse2). There isn't any reason to disable it if the target processor
>>    /// supports it.
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original)
>> +++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Sat Apr 29 12:30:09 2017
>> @@ -268,6 +268,12 @@ X86TargetMachine::getSubtargetImpl(const
>> 
>>    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];
>>    if (!I) {
>>      // This needs to be done before we create a new subtarget since any
>> @@ -275,7 +281,8 @@ X86TargetMachine::getSubtargetImpl(const
>>      // function that reside in TargetOptions.
>>      resetTargetOptions(F);
>>      I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
>> -                                        Options.StackAlignmentOverride);
>> +                                        Options.StackAlignmentOverride,
>> +                                        OptForSize, OptForMinSize);
>>  #ifndef LLVM_BUILD_GLOBAL_ISEL
>>      GISelAccessor *GISel = new GISelAccessor();
>>  #else
>> @@ -286,7 +293,8 @@ X86TargetMachine::getSubtargetImpl(const
>> 
>>      auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo());
>>      GISel->RegBankInfo.reset(RBI);
>> -    GISel->InstSelector.reset(createX86InstructionSelector(*this, *I, *RBI));
>> +    GISel->InstSelector.reset(createX86InstructionSelector(
>> +        *this, *I, *RBI));
>>  #endif
>>      I->setGISelAccessor(*GISel);
>>    }
>> 
>> Added: llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir?rev=301750&view=auto <http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir?rev=301750&view=auto>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir (added)
>> +++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir Sat Apr 29 12:30:09 2017
>> @@ -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)
>> +
>> +...
>> 
>> Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/GlobalISelEmitter.td?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/GlobalISelEmitter.td?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
>> +++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Sat Apr 29 12:30:09 2017
>> @@ -32,22 +32,25 @@ def m1Z : OperandWithDefaultOps <i32, (o
>> 
>>  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 @@ def HasB : Predicate<"Subtarget->hasB()"
>>  // 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 @@ def MULADD : I<(outs GPR32:$dst), (ins G
>>  //===- 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 MULADD : I<(outs GPR32:$dst), (ins G
>> 
>>  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. -----------------------===//
>>  //
>> 
>> Modified: llvm/trunk/unittests/Target/AArch64/InstSizes.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Target/AArch64/InstSizes.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Target/AArch64/InstSizes.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/unittests/Target/AArch64/InstSizes.cpp (original)
>> +++ llvm/trunk/unittests/Target/AArch64/InstSizes.cpp Sat Apr 29 12:30:09 2017
>> @@ -30,7 +30,8 @@ std::unique_ptr<TargetMachine> createTar
>> 
>>  std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) {
>>    AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
>> -                      TM->getTargetFeatureString(), *TM, /* isLittle */ false);
>> +                      TM->getTargetFeatureString(), *TM, /* isLittle */ false,
>> +                      /* ForCodeSize */ false);
>>    return llvm::make_unique<AArch64InstrInfo>(ST);
>>  }
>> 
>> 
>> Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
>> +++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Sat Apr 29 12:30:09 2017
>> @@ -199,21 +199,19 @@ public:
>>    void emitCxxCapturedInsnList(raw_ostream &OS);
>>    void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr);
>> 
>> -  void emit(raw_ostream &OS,
>> -            std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -                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 PredicateTy> class PredicateListMatcher {
>> @@ -951,6 +949,9 @@ private:
>> 
>>    /// 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<CopyRenderer>(&*Renderer.value())) {
>>          const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName());
>> @@ -1072,8 +1073,7 @@ void RuleMatcher::emitCxxCaptureStmts(ra
>>  }
>> 
>>  void RuleMatcher::emit(raw_ostream &OS,
>> -                       std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -                           SubtargetFeatures) {
>> +                       SubtargetFeatureInfoMap SubtargetFeatures) {
>>    if (Matchers.empty())
>>      llvm_unreachable("Unexpected empty matcher!");
>> 
>> @@ -1218,7 +1218,7 @@ private:
>>    DenseMap<const Record *, const Record *> ComplexPatternEquivs;
>> 
>>    // Map of predicates to their subtarget features.
>> -  std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
>> +  SubtargetFeatureInfoMap SubtargetFeatures;
>> 
>>    void gatherNodeEquivs();
>>    const CodeGenInstruction *findNodeEquiv(Record *N) const;
>> @@ -1713,14 +1713,36 @@ void GlobalISelEmitter::run(raw_ostream
>>    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 @@ void GlobalISelEmitter::run(raw_ostream
>>    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) {
>> 
>> Modified: llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp (original)
>> +++ llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp Sat Apr 29 12:30:09 2017
>> @@ -45,8 +45,7 @@ SubtargetFeatureInfo::getAll(const Recor
>>  }
>> 
>>  void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
>> -    std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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::emitSubtarget
>>  }
>> 
>>  void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
>> -    std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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::emitSubtarget
>>  }
>> 
>>  void SubtargetFeatureInfo::emitNameTable(
>> -    std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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<<n,
>>    // SubtargetFeatureNames[n] should be the name of the feature.
>> @@ -102,11 +99,13 @@ void SubtargetFeatureInfo::emitNameTable
>> 
>>  void SubtargetFeatureInfo::emitComputeAvailableFeatures(
>>      StringRef TargetName, StringRef ClassName, StringRef FuncName,
>> -    std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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::emitComputeAv
>> 
>>  void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
>>      StringRef TargetName, StringRef ClassName, StringRef FuncName,
>> -    std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &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";
>> 
>> Modified: llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h?rev=301750&r1=301749&r2=301750&view=diff <http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h?rev=301750&r1=301749&r2=301750&view=diff>
>> ==============================================================================
>> --- llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h (original)
>> +++ llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h Sat Apr 29 12:30:09 2017
>> @@ -21,6 +21,9 @@ namespace llvm {
>>  class Record;
>>  class RecordKeeper;
>> 
>> +struct SubtargetFeatureInfo;
>> +using SubtargetFeatureInfoMap = std::map<Record *, SubtargetFeatureInfo, LessRecordByID>;
>> +
>>  /// Helper class for storing information on a subtarget feature which
>>  /// participates in instruction matching.
>>  struct SubtargetFeatureInfo {
>> @@ -43,6 +46,10 @@ struct SubtargetFeatureInfo {
>>      return "Feature_" + TheDef->getName().str() + "Bit";
>>    }
>> 
>> +  bool mustRecomputePerFunction() const {
>> +    return TheDef->getValueAsBit("RecomputePerFunction");
>> +  }
>> +
>>    void dump() const;
>>    static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
>>    getAll(const RecordKeeper &Records);
>> @@ -52,21 +59,17 @@ struct SubtargetFeatureInfo {
>>    /// This version emits the bit value for the feature and is therefore limited
>>    /// to 64 feature bits.
>>    static void emitSubtargetFeatureFlagEnumeration(
>> -      std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -          &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<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -          &SubtargetFeatures,
>> -      raw_ostream &OS);
>> +  static void
>> +  emitSubtargetFeatureBitEnumeration(SubtargetFeatureInfoMap &SubtargetFeatures,
>> +                                     raw_ostream &OS);
>> 
>> -  static void emitNameTable(std::map<Record *, SubtargetFeatureInfo,
>> -                                     LessRecordByID> &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 @@ struct SubtargetFeatureInfo {
>>    /// \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<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -          &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 @@ struct SubtargetFeatureInfo {
>>    ///                          SubtargetFeatureInfo equivalent.
>>    static void emitComputeAssemblerAvailableFeatures(
>>        StringRef TargetName, StringRef ClassName, StringRef FuncName,
>> -      std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
>> -          &SubtargetFeatures,
>> -      raw_ostream &OS);
>> +      SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS);
>>  };
>>  } // end namespace llvm
>> 
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits>
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170503/1fe7884b/attachment-0001.html>


More information about the llvm-commits mailing list