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