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