Home | History | Annotate | Line # | Download | only in CodeGen
CGLoopInfo.h revision 1.1.1.2
      1 //===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- 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 //
      9 // This is the internal state used for llvm translation for loop statement
     10 // metadata.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
     15 #define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H
     16 
     17 #include "llvm/ADT/ArrayRef.h"
     18 #include "llvm/ADT/SmallVector.h"
     19 #include "llvm/IR/DebugLoc.h"
     20 #include "llvm/IR/Value.h"
     21 #include "llvm/Support/Compiler.h"
     22 
     23 namespace llvm {
     24 class BasicBlock;
     25 class Instruction;
     26 class MDNode;
     27 } // end namespace llvm
     28 
     29 namespace clang {
     30 class Attr;
     31 class ASTContext;
     32 class CodeGenOptions;
     33 namespace CodeGen {
     34 
     35 /// Attributes that may be specified on loops.
     36 struct LoopAttributes {
     37   explicit LoopAttributes(bool IsParallel = false);
     38   void clear();
     39 
     40   /// Generate llvm.loop.parallel metadata for loads and stores.
     41   bool IsParallel;
     42 
     43   /// State of loop vectorization or unrolling.
     44   enum LVEnableState { Unspecified, Enable, Disable, Full };
     45 
     46   /// Value for llvm.loop.vectorize.enable metadata.
     47   LVEnableState VectorizeEnable;
     48 
     49   /// Value for llvm.loop.unroll.* metadata (enable, disable, or full).
     50   LVEnableState UnrollEnable;
     51 
     52   /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full).
     53   LVEnableState UnrollAndJamEnable;
     54 
     55   /// Value for llvm.loop.vectorize.predicate metadata
     56   LVEnableState VectorizePredicateEnable;
     57 
     58   /// Value for llvm.loop.vectorize.width metadata.
     59   unsigned VectorizeWidth;
     60 
     61   // Value for llvm.loop.vectorize.scalable.enable
     62   LVEnableState VectorizeScalable;
     63 
     64   /// Value for llvm.loop.interleave.count metadata.
     65   unsigned InterleaveCount;
     66 
     67   /// llvm.unroll.
     68   unsigned UnrollCount;
     69 
     70   /// llvm.unroll.
     71   unsigned UnrollAndJamCount;
     72 
     73   /// Value for llvm.loop.distribute.enable metadata.
     74   LVEnableState DistributeEnable;
     75 
     76   /// Value for llvm.loop.pipeline.disable metadata.
     77   bool PipelineDisabled;
     78 
     79   /// Value for llvm.loop.pipeline.iicount metadata.
     80   unsigned PipelineInitiationInterval;
     81 
     82   /// Value for whether the loop is required to make progress.
     83   bool MustProgress;
     84 };
     85 
     86 /// Information used when generating a structured loop.
     87 class LoopInfo {
     88 public:
     89   /// Construct a new LoopInfo for the loop with entry Header.
     90   LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs,
     91            const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc,
     92            LoopInfo *Parent);
     93 
     94   /// Get the loop id metadata for this loop.
     95   llvm::MDNode *getLoopID() const { return TempLoopID.get(); }
     96 
     97   /// Get the header block of this loop.
     98   llvm::BasicBlock *getHeader() const { return Header; }
     99 
    100   /// Get the set of attributes active for this loop.
    101   const LoopAttributes &getAttributes() const { return Attrs; }
    102 
    103   /// Return this loop's access group or nullptr if it does not have one.
    104   llvm::MDNode *getAccessGroup() const { return AccGroup; }
    105 
    106   /// Create the loop's metadata. Must be called after its nested loops have
    107   /// been processed.
    108   void finish();
    109 
    110 private:
    111   /// Loop ID metadata.
    112   llvm::TempMDTuple TempLoopID;
    113   /// Header block of this loop.
    114   llvm::BasicBlock *Header;
    115   /// The attributes for this loop.
    116   LoopAttributes Attrs;
    117   /// The access group for memory accesses parallel to this loop.
    118   llvm::MDNode *AccGroup = nullptr;
    119   /// Start location of this loop.
    120   llvm::DebugLoc StartLoc;
    121   /// End location of this loop.
    122   llvm::DebugLoc EndLoc;
    123   /// The next outer loop, or nullptr if this is the outermost loop.
    124   LoopInfo *Parent;
    125   /// If this loop has unroll-and-jam metadata, this can be set by the inner
    126   /// loop's LoopInfo to set the llvm.loop.unroll_and_jam.followup_inner
    127   /// metadata.
    128   llvm::MDNode *UnrollAndJamInnerFollowup = nullptr;
    129 
    130   /// Create a LoopID without any transformations.
    131   llvm::MDNode *
    132   createLoopPropertiesMetadata(llvm::ArrayRef<llvm::Metadata *> LoopProperties);
    133 
    134   /// Create a LoopID for transformations.
    135   ///
    136   /// The methods call each other in case multiple transformations are applied
    137   /// to a loop. The transformation first to be applied will use LoopID of the
    138   /// next transformation in its followup attribute.
    139   ///
    140   /// @param Attrs             The loop's transformations.
    141   /// @param LoopProperties    Non-transformation properties such as debug
    142   ///                          location, parallel accesses and disabled
    143   ///                          transformations. These are added to the returned
    144   ///                          LoopID.
    145   /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes
    146   ///                          at least one transformation.
    147   ///
    148   /// @return A LoopID (metadata node) that can be used for the llvm.loop
    149   ///         annotation or followup-attribute.
    150   /// @{
    151   llvm::MDNode *
    152   createPipeliningMetadata(const LoopAttributes &Attrs,
    153                            llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    154                            bool &HasUserTransforms);
    155   llvm::MDNode *
    156   createPartialUnrollMetadata(const LoopAttributes &Attrs,
    157                               llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    158                               bool &HasUserTransforms);
    159   llvm::MDNode *
    160   createUnrollAndJamMetadata(const LoopAttributes &Attrs,
    161                              llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    162                              bool &HasUserTransforms);
    163   llvm::MDNode *
    164   createLoopVectorizeMetadata(const LoopAttributes &Attrs,
    165                               llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    166                               bool &HasUserTransforms);
    167   llvm::MDNode *
    168   createLoopDistributeMetadata(const LoopAttributes &Attrs,
    169                                llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    170                                bool &HasUserTransforms);
    171   llvm::MDNode *
    172   createFullUnrollMetadata(const LoopAttributes &Attrs,
    173                            llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    174                            bool &HasUserTransforms);
    175   /// @}
    176 
    177   /// Create a LoopID for this loop, including transformation-unspecific
    178   /// metadata such as debug location.
    179   ///
    180   /// @param Attrs             This loop's attributes and transformations.
    181   /// @param LoopProperties    Additional non-transformation properties to add
    182   ///                          to the LoopID, such as transformation-specific
    183   ///                          metadata that are not covered by @p Attrs.
    184   /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes
    185   ///                          at least one transformation.
    186   ///
    187   /// @return A LoopID (metadata node) that can be used for the llvm.loop
    188   ///         annotation.
    189   llvm::MDNode *createMetadata(const LoopAttributes &Attrs,
    190                                llvm::ArrayRef<llvm::Metadata *> LoopProperties,
    191                                bool &HasUserTransforms);
    192 };
    193 
    194 /// A stack of loop information corresponding to loop nesting levels.
    195 /// This stack can be used to prepare attributes which are applied when a loop
    196 /// is emitted.
    197 class LoopInfoStack {
    198   LoopInfoStack(const LoopInfoStack &) = delete;
    199   void operator=(const LoopInfoStack &) = delete;
    200 
    201 public:
    202   LoopInfoStack() {}
    203 
    204   /// Begin a new structured loop. The set of staged attributes will be
    205   /// applied to the loop and then cleared.
    206   void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc,
    207             const llvm::DebugLoc &EndLoc);
    208 
    209   /// Begin a new structured loop. Stage attributes from the Attrs list.
    210   /// The staged attributes are applied to the loop and then cleared.
    211   void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
    212             const clang::CodeGenOptions &CGOpts,
    213             llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc,
    214             const llvm::DebugLoc &EndLoc, bool MustProgress = false);
    215 
    216   /// End the current loop.
    217   void pop();
    218 
    219   /// Return the top loop id metadata.
    220   llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); }
    221 
    222   /// Return true if the top loop is parallel.
    223   bool getCurLoopParallel() const {
    224     return hasInfo() ? getInfo().getAttributes().IsParallel : false;
    225   }
    226 
    227   /// Function called by the CodeGenFunction when an instruction is
    228   /// created.
    229   void InsertHelper(llvm::Instruction *I) const;
    230 
    231   /// Set the next pushed loop as parallel.
    232   void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; }
    233 
    234   /// Set the next pushed loop 'vectorize.enable'
    235   void setVectorizeEnable(bool Enable = true) {
    236     StagedAttrs.VectorizeEnable =
    237         Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
    238   }
    239 
    240   /// Set the next pushed loop as a distribution candidate.
    241   void setDistributeState(bool Enable = true) {
    242     StagedAttrs.DistributeEnable =
    243         Enable ? LoopAttributes::Enable : LoopAttributes::Disable;
    244   }
    245 
    246   /// Set the next pushed loop unroll state.
    247   void setUnrollState(const LoopAttributes::LVEnableState &State) {
    248     StagedAttrs.UnrollEnable = State;
    249   }
    250 
    251   /// Set the next pushed vectorize predicate state.
    252   void setVectorizePredicateState(const LoopAttributes::LVEnableState &State) {
    253     StagedAttrs.VectorizePredicateEnable = State;
    254   }
    255 
    256   /// Set the next pushed loop unroll_and_jam state.
    257   void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) {
    258     StagedAttrs.UnrollAndJamEnable = State;
    259   }
    260 
    261   /// Set the vectorize width for the next loop pushed.
    262   void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; }
    263 
    264   void setVectorizeScalable(const LoopAttributes::LVEnableState &State) {
    265     StagedAttrs.VectorizeScalable = State;
    266   }
    267 
    268   /// Set the interleave count for the next loop pushed.
    269   void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; }
    270 
    271   /// Set the unroll count for the next loop pushed.
    272   void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; }
    273 
    274   /// \brief Set the unroll count for the next loop pushed.
    275   void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; }
    276 
    277   /// Set the pipeline disabled state.
    278   void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; }
    279 
    280   /// Set the pipeline initiation interval.
    281   void setPipelineInitiationInterval(unsigned C) {
    282     StagedAttrs.PipelineInitiationInterval = C;
    283   }
    284 
    285   /// Set no progress for the next loop pushed.
    286   void setMustProgress(bool P) { StagedAttrs.MustProgress = P; }
    287 
    288 private:
    289   /// Returns true if there is LoopInfo on the stack.
    290   bool hasInfo() const { return !Active.empty(); }
    291   /// Return the LoopInfo for the current loop. HasInfo should be called
    292   /// first to ensure LoopInfo is present.
    293   const LoopInfo &getInfo() const { return *Active.back(); }
    294   /// The set of attributes that will be applied to the next pushed loop.
    295   LoopAttributes StagedAttrs;
    296   /// Stack of active loops.
    297   llvm::SmallVector<std::unique_ptr<LoopInfo>, 4> Active;
    298 };
    299 
    300 } // end namespace CodeGen
    301 } // end namespace clang
    302 
    303 #endif
    304