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