Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- llvm/CodeGen/GlobalISel/CSEInfo.h ------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. /// \file
  9. /// Provides analysis for continuously CSEing during GISel passes.
  10. ///
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_CODEGEN_GLOBALISEL_CSEINFO_H
  13. #define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H
  14.  
  15. #include "llvm/ADT/FoldingSet.h"
  16. #include "llvm/CodeGen/CSEConfigBase.h"
  17. #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
  18. #include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
  19. #include "llvm/CodeGen/MachineFunctionPass.h"
  20. #include "llvm/Support/Allocator.h"
  21. #include "llvm/Support/CodeGen.h"
  22.  
  23. namespace llvm {
  24. class MachineBasicBlock;
  25.  
  26. /// A class that wraps MachineInstrs and derives from FoldingSetNode in order to
  27. /// be uniqued in a CSEMap. The tradeoff here is extra memory allocations for
  28. /// UniqueMachineInstr vs making MachineInstr bigger.
  29. class UniqueMachineInstr : public FoldingSetNode {
  30.   friend class GISelCSEInfo;
  31.   const MachineInstr *MI;
  32.   explicit UniqueMachineInstr(const MachineInstr *MI) : MI(MI) {}
  33.  
  34. public:
  35.   void Profile(FoldingSetNodeID &ID);
  36. };
  37.  
  38. // A CSE config for fully optimized builds.
  39. class CSEConfigFull : public CSEConfigBase {
  40. public:
  41.   virtual ~CSEConfigFull() = default;
  42.   bool shouldCSEOpc(unsigned Opc) override;
  43. };
  44.  
  45. // Commonly used for O0 config.
  46. class CSEConfigConstantOnly : public CSEConfigBase {
  47. public:
  48.   virtual ~CSEConfigConstantOnly() = default;
  49.   bool shouldCSEOpc(unsigned Opc) override;
  50. };
  51.  
  52. // Returns the standard expected CSEConfig for the given optimization level.
  53. // We have this logic here so targets can make use of it from their derived
  54. // TargetPassConfig, but can't put this logic into TargetPassConfig directly
  55. // because the CodeGen library can't depend on GlobalISel.
  56. std::unique_ptr<CSEConfigBase>
  57. getStandardCSEConfigForOpt(CodeGenOpt::Level Level);
  58.  
  59. /// The CSE Analysis object.
  60. /// This installs itself as a delegate to the MachineFunction to track
  61. /// new instructions as well as deletions. It however will not be able to
  62. /// track instruction mutations. In such cases, recordNewInstruction should be
  63. /// called (for eg inside MachineIRBuilder::recordInsertion).
  64. /// Also because of how just the instruction can be inserted without adding any
  65. /// operands to the instruction, instructions are uniqued and inserted lazily.
  66. /// CSEInfo should assert when trying to enter an incomplete instruction into
  67. /// the CSEMap. There is Opcode level granularity on which instructions can be
  68. /// CSE'd and for now, only Generic instructions are CSEable.
  69. class GISelCSEInfo : public GISelChangeObserver {
  70.   // Make it accessible only to CSEMIRBuilder.
  71.   friend class CSEMIRBuilder;
  72.  
  73.   BumpPtrAllocator UniqueInstrAllocator;
  74.   FoldingSet<UniqueMachineInstr> CSEMap;
  75.   MachineRegisterInfo *MRI = nullptr;
  76.   MachineFunction *MF = nullptr;
  77.   std::unique_ptr<CSEConfigBase> CSEOpt;
  78.   /// Keep a cache of UniqueInstrs for each MachineInstr. In GISel,
  79.   /// often instructions are mutated (while their ID has completely changed).
  80.   /// Whenever mutation happens, invalidate the UniqueMachineInstr for the
  81.   /// MachineInstr
  82.   DenseMap<const MachineInstr *, UniqueMachineInstr *> InstrMapping;
  83.  
  84.   /// Store instructions that are not fully formed in TemporaryInsts.
  85.   /// Also because CSE insertion happens lazily, we can remove insts from this
  86.   /// list and avoid inserting and then removing from the CSEMap.
  87.   GISelWorkList<8> TemporaryInsts;
  88.  
  89.   // Only used in asserts.
  90.   DenseMap<unsigned, unsigned> OpcodeHitTable;
  91.  
  92.   bool isUniqueMachineInstValid(const UniqueMachineInstr &UMI) const;
  93.  
  94.   void invalidateUniqueMachineInstr(UniqueMachineInstr *UMI);
  95.  
  96.   UniqueMachineInstr *getNodeIfExists(FoldingSetNodeID &ID,
  97.                                       MachineBasicBlock *MBB, void *&InsertPos);
  98.  
  99.   /// Allocate and construct a new UniqueMachineInstr for MI and return.
  100.   UniqueMachineInstr *getUniqueInstrForMI(const MachineInstr *MI);
  101.  
  102.   void insertNode(UniqueMachineInstr *UMI, void *InsertPos = nullptr);
  103.  
  104.   /// Get the MachineInstr(Unique) if it exists already in the CSEMap and the
  105.   /// same MachineBasicBlock.
  106.   MachineInstr *getMachineInstrIfExists(FoldingSetNodeID &ID,
  107.                                         MachineBasicBlock *MBB,
  108.                                         void *&InsertPos);
  109.  
  110.   /// Use this method to allocate a new UniqueMachineInstr for MI and insert it
  111.   /// into the CSEMap. MI should return true for shouldCSE(MI->getOpcode())
  112.   void insertInstr(MachineInstr *MI, void *InsertPos = nullptr);
  113.  
  114. public:
  115.   GISelCSEInfo() = default;
  116.  
  117.   virtual ~GISelCSEInfo();
  118.  
  119.   void setMF(MachineFunction &MF);
  120.  
  121.   Error verify();
  122.  
  123.   /// Records a newly created inst in a list and lazily insert it to the CSEMap.
  124.   /// Sometimes, this method might be called with a partially constructed
  125.   /// MachineInstr,
  126.   //  (right after BuildMI without adding any operands) - and in such cases,
  127.   //  defer the hashing of the instruction to a later stage.
  128.   void recordNewInstruction(MachineInstr *MI);
  129.  
  130.   /// Use this callback to inform CSE about a newly fully created instruction.
  131.   void handleRecordedInst(MachineInstr *MI);
  132.  
  133.   /// Use this callback to insert all the recorded instructions. At this point,
  134.   /// all of these insts need to be fully constructed and should not be missing
  135.   /// any operands.
  136.   void handleRecordedInsts();
  137.  
  138.   /// Remove this inst from the CSE map. If this inst has not been inserted yet,
  139.   /// it will be removed from the Tempinsts list if it exists.
  140.   void handleRemoveInst(MachineInstr *MI);
  141.  
  142.   void releaseMemory();
  143.  
  144.   void setCSEConfig(std::unique_ptr<CSEConfigBase> Opt) {
  145.     CSEOpt = std::move(Opt);
  146.   }
  147.  
  148.   bool shouldCSE(unsigned Opc) const;
  149.  
  150.   void analyze(MachineFunction &MF);
  151.  
  152.   void countOpcodeHit(unsigned Opc);
  153.  
  154.   void print();
  155.  
  156.   // Observer API
  157.   void erasingInstr(MachineInstr &MI) override;
  158.   void createdInstr(MachineInstr &MI) override;
  159.   void changingInstr(MachineInstr &MI) override;
  160.   void changedInstr(MachineInstr &MI) override;
  161. };
  162.  
  163. class TargetRegisterClass;
  164. class RegisterBank;
  165.  
  166. // Simple builder class to easily profile properties about MIs.
  167. class GISelInstProfileBuilder {
  168.   FoldingSetNodeID &ID;
  169.   const MachineRegisterInfo &MRI;
  170.  
  171. public:
  172.   GISelInstProfileBuilder(FoldingSetNodeID &ID, const MachineRegisterInfo &MRI)
  173.       : ID(ID), MRI(MRI) {}
  174.   // Profiling methods.
  175.   const GISelInstProfileBuilder &addNodeIDOpcode(unsigned Opc) const;
  176.   const GISelInstProfileBuilder &addNodeIDRegType(const LLT Ty) const;
  177.   const GISelInstProfileBuilder &addNodeIDRegType(const Register) const;
  178.  
  179.   const GISelInstProfileBuilder &
  180.   addNodeIDRegType(const TargetRegisterClass *RC) const;
  181.   const GISelInstProfileBuilder &addNodeIDRegType(const RegisterBank *RB) const;
  182.  
  183.   const GISelInstProfileBuilder &addNodeIDRegNum(Register Reg) const;
  184.  
  185.   const GISelInstProfileBuilder &addNodeIDReg(Register Reg) const;
  186.  
  187.   const GISelInstProfileBuilder &addNodeIDImmediate(int64_t Imm) const;
  188.   const GISelInstProfileBuilder &
  189.   addNodeIDMBB(const MachineBasicBlock *MBB) const;
  190.  
  191.   const GISelInstProfileBuilder &
  192.   addNodeIDMachineOperand(const MachineOperand &MO) const;
  193.  
  194.   const GISelInstProfileBuilder &addNodeIDFlag(unsigned Flag) const;
  195.   const GISelInstProfileBuilder &addNodeID(const MachineInstr *MI) const;
  196. };
  197.  
  198. /// Simple wrapper that does the following.
  199. /// 1) Lazily evaluate the MachineFunction to compute CSEable instructions.
  200. /// 2) Allows configuration of which instructions are CSEd through CSEConfig
  201. /// object. Provides a method called get which takes a CSEConfig object.
  202. class GISelCSEAnalysisWrapper {
  203.   GISelCSEInfo Info;
  204.   MachineFunction *MF = nullptr;
  205.   bool AlreadyComputed = false;
  206.  
  207. public:
  208.   /// Takes a CSEConfigBase object that defines what opcodes get CSEd.
  209.   /// If CSEConfig is already set, and the CSE Analysis has been preserved,
  210.   /// it will not use the new CSEOpt(use Recompute to force using the new
  211.   /// CSEOpt).
  212.   GISelCSEInfo &get(std::unique_ptr<CSEConfigBase> CSEOpt,
  213.                     bool ReCompute = false);
  214.   void setMF(MachineFunction &MFunc) { MF = &MFunc; }
  215.   void setComputed(bool Computed) { AlreadyComputed = Computed; }
  216.   void releaseMemory() { Info.releaseMemory(); }
  217. };
  218.  
  219. /// The actual analysis pass wrapper.
  220. class GISelCSEAnalysisWrapperPass : public MachineFunctionPass {
  221.   GISelCSEAnalysisWrapper Wrapper;
  222.  
  223. public:
  224.   static char ID;
  225.   GISelCSEAnalysisWrapperPass();
  226.  
  227.   void getAnalysisUsage(AnalysisUsage &AU) const override;
  228.  
  229.   const GISelCSEAnalysisWrapper &getCSEWrapper() const { return Wrapper; }
  230.   GISelCSEAnalysisWrapper &getCSEWrapper() { return Wrapper; }
  231.  
  232.   bool runOnMachineFunction(MachineFunction &MF) override;
  233.  
  234.   void releaseMemory() override {
  235.     Wrapper.releaseMemory();
  236.     Wrapper.setComputed(false);
  237.   }
  238. };
  239.  
  240. } // namespace llvm
  241.  
  242. #endif
  243.