106f32e7eSjoerg //===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- C++ -*---------===// 206f32e7eSjoerg // 306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg // 706f32e7eSjoerg //===----------------------------------------------------------------------===// 806f32e7eSjoerg // 906f32e7eSjoerg // This is the internal state used for llvm translation for loop statement 1006f32e7eSjoerg // metadata. 1106f32e7eSjoerg // 1206f32e7eSjoerg //===----------------------------------------------------------------------===// 1306f32e7eSjoerg 1406f32e7eSjoerg #ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H 1506f32e7eSjoerg #define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H 1606f32e7eSjoerg 1706f32e7eSjoerg #include "llvm/ADT/ArrayRef.h" 1806f32e7eSjoerg #include "llvm/ADT/SmallVector.h" 1906f32e7eSjoerg #include "llvm/IR/DebugLoc.h" 2006f32e7eSjoerg #include "llvm/IR/Value.h" 2106f32e7eSjoerg #include "llvm/Support/Compiler.h" 2206f32e7eSjoerg 2306f32e7eSjoerg namespace llvm { 2406f32e7eSjoerg class BasicBlock; 2506f32e7eSjoerg class Instruction; 2606f32e7eSjoerg class MDNode; 2706f32e7eSjoerg } // end namespace llvm 2806f32e7eSjoerg 2906f32e7eSjoerg namespace clang { 3006f32e7eSjoerg class Attr; 3106f32e7eSjoerg class ASTContext; 32*13fbcb42Sjoerg class CodeGenOptions; 3306f32e7eSjoerg namespace CodeGen { 3406f32e7eSjoerg 3506f32e7eSjoerg /// Attributes that may be specified on loops. 3606f32e7eSjoerg struct LoopAttributes { 3706f32e7eSjoerg explicit LoopAttributes(bool IsParallel = false); 3806f32e7eSjoerg void clear(); 3906f32e7eSjoerg 4006f32e7eSjoerg /// Generate llvm.loop.parallel metadata for loads and stores. 4106f32e7eSjoerg bool IsParallel; 4206f32e7eSjoerg 4306f32e7eSjoerg /// State of loop vectorization or unrolling. 4406f32e7eSjoerg enum LVEnableState { Unspecified, Enable, Disable, Full }; 4506f32e7eSjoerg 4606f32e7eSjoerg /// Value for llvm.loop.vectorize.enable metadata. 4706f32e7eSjoerg LVEnableState VectorizeEnable; 4806f32e7eSjoerg 4906f32e7eSjoerg /// Value for llvm.loop.unroll.* metadata (enable, disable, or full). 5006f32e7eSjoerg LVEnableState UnrollEnable; 5106f32e7eSjoerg 5206f32e7eSjoerg /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full). 5306f32e7eSjoerg LVEnableState UnrollAndJamEnable; 5406f32e7eSjoerg 5506f32e7eSjoerg /// Value for llvm.loop.vectorize.predicate metadata 5606f32e7eSjoerg LVEnableState VectorizePredicateEnable; 5706f32e7eSjoerg 5806f32e7eSjoerg /// Value for llvm.loop.vectorize.width metadata. 5906f32e7eSjoerg unsigned VectorizeWidth; 6006f32e7eSjoerg 61*13fbcb42Sjoerg // Value for llvm.loop.vectorize.scalable.enable 62*13fbcb42Sjoerg LVEnableState VectorizeScalable; 63*13fbcb42Sjoerg 6406f32e7eSjoerg /// Value for llvm.loop.interleave.count metadata. 6506f32e7eSjoerg unsigned InterleaveCount; 6606f32e7eSjoerg 6706f32e7eSjoerg /// llvm.unroll. 6806f32e7eSjoerg unsigned UnrollCount; 6906f32e7eSjoerg 7006f32e7eSjoerg /// llvm.unroll. 7106f32e7eSjoerg unsigned UnrollAndJamCount; 7206f32e7eSjoerg 7306f32e7eSjoerg /// Value for llvm.loop.distribute.enable metadata. 7406f32e7eSjoerg LVEnableState DistributeEnable; 7506f32e7eSjoerg 7606f32e7eSjoerg /// Value for llvm.loop.pipeline.disable metadata. 7706f32e7eSjoerg bool PipelineDisabled; 7806f32e7eSjoerg 7906f32e7eSjoerg /// Value for llvm.loop.pipeline.iicount metadata. 8006f32e7eSjoerg unsigned PipelineInitiationInterval; 81*13fbcb42Sjoerg 82*13fbcb42Sjoerg /// Value for whether the loop is required to make progress. 83*13fbcb42Sjoerg bool MustProgress; 8406f32e7eSjoerg }; 8506f32e7eSjoerg 8606f32e7eSjoerg /// Information used when generating a structured loop. 8706f32e7eSjoerg class LoopInfo { 8806f32e7eSjoerg public: 8906f32e7eSjoerg /// Construct a new LoopInfo for the loop with entry Header. 9006f32e7eSjoerg LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, 9106f32e7eSjoerg const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, 9206f32e7eSjoerg LoopInfo *Parent); 9306f32e7eSjoerg 9406f32e7eSjoerg /// Get the loop id metadata for this loop. getLoopID()9506f32e7eSjoerg llvm::MDNode *getLoopID() const { return TempLoopID.get(); } 9606f32e7eSjoerg 9706f32e7eSjoerg /// Get the header block of this loop. getHeader()9806f32e7eSjoerg llvm::BasicBlock *getHeader() const { return Header; } 9906f32e7eSjoerg 10006f32e7eSjoerg /// Get the set of attributes active for this loop. getAttributes()10106f32e7eSjoerg const LoopAttributes &getAttributes() const { return Attrs; } 10206f32e7eSjoerg 10306f32e7eSjoerg /// Return this loop's access group or nullptr if it does not have one. getAccessGroup()10406f32e7eSjoerg llvm::MDNode *getAccessGroup() const { return AccGroup; } 10506f32e7eSjoerg 10606f32e7eSjoerg /// Create the loop's metadata. Must be called after its nested loops have 10706f32e7eSjoerg /// been processed. 10806f32e7eSjoerg void finish(); 10906f32e7eSjoerg 11006f32e7eSjoerg private: 11106f32e7eSjoerg /// Loop ID metadata. 11206f32e7eSjoerg llvm::TempMDTuple TempLoopID; 11306f32e7eSjoerg /// Header block of this loop. 11406f32e7eSjoerg llvm::BasicBlock *Header; 11506f32e7eSjoerg /// The attributes for this loop. 11606f32e7eSjoerg LoopAttributes Attrs; 11706f32e7eSjoerg /// The access group for memory accesses parallel to this loop. 11806f32e7eSjoerg llvm::MDNode *AccGroup = nullptr; 11906f32e7eSjoerg /// Start location of this loop. 12006f32e7eSjoerg llvm::DebugLoc StartLoc; 12106f32e7eSjoerg /// End location of this loop. 12206f32e7eSjoerg llvm::DebugLoc EndLoc; 12306f32e7eSjoerg /// The next outer loop, or nullptr if this is the outermost loop. 12406f32e7eSjoerg LoopInfo *Parent; 12506f32e7eSjoerg /// If this loop has unroll-and-jam metadata, this can be set by the inner 12606f32e7eSjoerg /// loop's LoopInfo to set the llvm.loop.unroll_and_jam.followup_inner 12706f32e7eSjoerg /// metadata. 12806f32e7eSjoerg llvm::MDNode *UnrollAndJamInnerFollowup = nullptr; 12906f32e7eSjoerg 13006f32e7eSjoerg /// Create a LoopID without any transformations. 13106f32e7eSjoerg llvm::MDNode * 13206f32e7eSjoerg createLoopPropertiesMetadata(llvm::ArrayRef<llvm::Metadata *> LoopProperties); 13306f32e7eSjoerg 13406f32e7eSjoerg /// Create a LoopID for transformations. 13506f32e7eSjoerg /// 13606f32e7eSjoerg /// The methods call each other in case multiple transformations are applied 13706f32e7eSjoerg /// to a loop. The transformation first to be applied will use LoopID of the 13806f32e7eSjoerg /// next transformation in its followup attribute. 13906f32e7eSjoerg /// 14006f32e7eSjoerg /// @param Attrs The loop's transformations. 14106f32e7eSjoerg /// @param LoopProperties Non-transformation properties such as debug 14206f32e7eSjoerg /// location, parallel accesses and disabled 14306f32e7eSjoerg /// transformations. These are added to the returned 14406f32e7eSjoerg /// LoopID. 14506f32e7eSjoerg /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes 14606f32e7eSjoerg /// at least one transformation. 14706f32e7eSjoerg /// 14806f32e7eSjoerg /// @return A LoopID (metadata node) that can be used for the llvm.loop 14906f32e7eSjoerg /// annotation or followup-attribute. 15006f32e7eSjoerg /// @{ 15106f32e7eSjoerg llvm::MDNode * 15206f32e7eSjoerg createPipeliningMetadata(const LoopAttributes &Attrs, 15306f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 15406f32e7eSjoerg bool &HasUserTransforms); 15506f32e7eSjoerg llvm::MDNode * 15606f32e7eSjoerg createPartialUnrollMetadata(const LoopAttributes &Attrs, 15706f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 15806f32e7eSjoerg bool &HasUserTransforms); 15906f32e7eSjoerg llvm::MDNode * 16006f32e7eSjoerg createUnrollAndJamMetadata(const LoopAttributes &Attrs, 16106f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 16206f32e7eSjoerg bool &HasUserTransforms); 16306f32e7eSjoerg llvm::MDNode * 16406f32e7eSjoerg createLoopVectorizeMetadata(const LoopAttributes &Attrs, 16506f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 16606f32e7eSjoerg bool &HasUserTransforms); 16706f32e7eSjoerg llvm::MDNode * 16806f32e7eSjoerg createLoopDistributeMetadata(const LoopAttributes &Attrs, 16906f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 17006f32e7eSjoerg bool &HasUserTransforms); 17106f32e7eSjoerg llvm::MDNode * 17206f32e7eSjoerg createFullUnrollMetadata(const LoopAttributes &Attrs, 17306f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 17406f32e7eSjoerg bool &HasUserTransforms); 17506f32e7eSjoerg /// @} 17606f32e7eSjoerg 17706f32e7eSjoerg /// Create a LoopID for this loop, including transformation-unspecific 17806f32e7eSjoerg /// metadata such as debug location. 17906f32e7eSjoerg /// 18006f32e7eSjoerg /// @param Attrs This loop's attributes and transformations. 18106f32e7eSjoerg /// @param LoopProperties Additional non-transformation properties to add 18206f32e7eSjoerg /// to the LoopID, such as transformation-specific 18306f32e7eSjoerg /// metadata that are not covered by @p Attrs. 18406f32e7eSjoerg /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes 18506f32e7eSjoerg /// at least one transformation. 18606f32e7eSjoerg /// 18706f32e7eSjoerg /// @return A LoopID (metadata node) that can be used for the llvm.loop 18806f32e7eSjoerg /// annotation. 18906f32e7eSjoerg llvm::MDNode *createMetadata(const LoopAttributes &Attrs, 19006f32e7eSjoerg llvm::ArrayRef<llvm::Metadata *> LoopProperties, 19106f32e7eSjoerg bool &HasUserTransforms); 19206f32e7eSjoerg }; 19306f32e7eSjoerg 19406f32e7eSjoerg /// A stack of loop information corresponding to loop nesting levels. 19506f32e7eSjoerg /// This stack can be used to prepare attributes which are applied when a loop 19606f32e7eSjoerg /// is emitted. 19706f32e7eSjoerg class LoopInfoStack { 19806f32e7eSjoerg LoopInfoStack(const LoopInfoStack &) = delete; 19906f32e7eSjoerg void operator=(const LoopInfoStack &) = delete; 20006f32e7eSjoerg 20106f32e7eSjoerg public: LoopInfoStack()20206f32e7eSjoerg LoopInfoStack() {} 20306f32e7eSjoerg 20406f32e7eSjoerg /// Begin a new structured loop. The set of staged attributes will be 20506f32e7eSjoerg /// applied to the loop and then cleared. 20606f32e7eSjoerg void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, 20706f32e7eSjoerg const llvm::DebugLoc &EndLoc); 20806f32e7eSjoerg 20906f32e7eSjoerg /// Begin a new structured loop. Stage attributes from the Attrs list. 21006f32e7eSjoerg /// The staged attributes are applied to the loop and then cleared. 21106f32e7eSjoerg void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx, 212*13fbcb42Sjoerg const clang::CodeGenOptions &CGOpts, 21306f32e7eSjoerg llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc, 214*13fbcb42Sjoerg const llvm::DebugLoc &EndLoc, bool MustProgress = false); 21506f32e7eSjoerg 21606f32e7eSjoerg /// End the current loop. 21706f32e7eSjoerg void pop(); 21806f32e7eSjoerg 21906f32e7eSjoerg /// Return the top loop id metadata. getCurLoopID()22006f32e7eSjoerg llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); } 22106f32e7eSjoerg 22206f32e7eSjoerg /// Return true if the top loop is parallel. getCurLoopParallel()22306f32e7eSjoerg bool getCurLoopParallel() const { 22406f32e7eSjoerg return hasInfo() ? getInfo().getAttributes().IsParallel : false; 22506f32e7eSjoerg } 22606f32e7eSjoerg 22706f32e7eSjoerg /// Function called by the CodeGenFunction when an instruction is 22806f32e7eSjoerg /// created. 22906f32e7eSjoerg void InsertHelper(llvm::Instruction *I) const; 23006f32e7eSjoerg 23106f32e7eSjoerg /// Set the next pushed loop as parallel. 23206f32e7eSjoerg void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; } 23306f32e7eSjoerg 23406f32e7eSjoerg /// Set the next pushed loop 'vectorize.enable' 23506f32e7eSjoerg void setVectorizeEnable(bool Enable = true) { 23606f32e7eSjoerg StagedAttrs.VectorizeEnable = 23706f32e7eSjoerg Enable ? LoopAttributes::Enable : LoopAttributes::Disable; 23806f32e7eSjoerg } 23906f32e7eSjoerg 24006f32e7eSjoerg /// Set the next pushed loop as a distribution candidate. 24106f32e7eSjoerg void setDistributeState(bool Enable = true) { 24206f32e7eSjoerg StagedAttrs.DistributeEnable = 24306f32e7eSjoerg Enable ? LoopAttributes::Enable : LoopAttributes::Disable; 24406f32e7eSjoerg } 24506f32e7eSjoerg 24606f32e7eSjoerg /// Set the next pushed loop unroll state. setUnrollState(const LoopAttributes::LVEnableState & State)24706f32e7eSjoerg void setUnrollState(const LoopAttributes::LVEnableState &State) { 24806f32e7eSjoerg StagedAttrs.UnrollEnable = State; 24906f32e7eSjoerg } 25006f32e7eSjoerg 25106f32e7eSjoerg /// Set the next pushed vectorize predicate state. setVectorizePredicateState(const LoopAttributes::LVEnableState & State)25206f32e7eSjoerg void setVectorizePredicateState(const LoopAttributes::LVEnableState &State) { 25306f32e7eSjoerg StagedAttrs.VectorizePredicateEnable = State; 25406f32e7eSjoerg } 25506f32e7eSjoerg 25606f32e7eSjoerg /// Set the next pushed loop unroll_and_jam state. setUnrollAndJamState(const LoopAttributes::LVEnableState & State)25706f32e7eSjoerg void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) { 25806f32e7eSjoerg StagedAttrs.UnrollAndJamEnable = State; 25906f32e7eSjoerg } 26006f32e7eSjoerg 26106f32e7eSjoerg /// Set the vectorize width for the next loop pushed. setVectorizeWidth(unsigned W)26206f32e7eSjoerg void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; } 26306f32e7eSjoerg setVectorizeScalable(const LoopAttributes::LVEnableState & State)264*13fbcb42Sjoerg void setVectorizeScalable(const LoopAttributes::LVEnableState &State) { 265*13fbcb42Sjoerg StagedAttrs.VectorizeScalable = State; 266*13fbcb42Sjoerg } 267*13fbcb42Sjoerg 26806f32e7eSjoerg /// Set the interleave count for the next loop pushed. setInterleaveCount(unsigned C)26906f32e7eSjoerg void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; } 27006f32e7eSjoerg 27106f32e7eSjoerg /// Set the unroll count for the next loop pushed. setUnrollCount(unsigned C)27206f32e7eSjoerg void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; } 27306f32e7eSjoerg 27406f32e7eSjoerg /// \brief Set the unroll count for the next loop pushed. setUnrollAndJamCount(unsigned C)27506f32e7eSjoerg void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; } 27606f32e7eSjoerg 27706f32e7eSjoerg /// Set the pipeline disabled state. setPipelineDisabled(bool S)27806f32e7eSjoerg void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; } 27906f32e7eSjoerg 28006f32e7eSjoerg /// Set the pipeline initiation interval. setPipelineInitiationInterval(unsigned C)28106f32e7eSjoerg void setPipelineInitiationInterval(unsigned C) { 28206f32e7eSjoerg StagedAttrs.PipelineInitiationInterval = C; 28306f32e7eSjoerg } 28406f32e7eSjoerg 285*13fbcb42Sjoerg /// Set no progress for the next loop pushed. setMustProgress(bool P)286*13fbcb42Sjoerg void setMustProgress(bool P) { StagedAttrs.MustProgress = P; } 287*13fbcb42Sjoerg 28806f32e7eSjoerg private: 28906f32e7eSjoerg /// Returns true if there is LoopInfo on the stack. hasInfo()29006f32e7eSjoerg bool hasInfo() const { return !Active.empty(); } 29106f32e7eSjoerg /// Return the LoopInfo for the current loop. HasInfo should be called 29206f32e7eSjoerg /// first to ensure LoopInfo is present. getInfo()29306f32e7eSjoerg const LoopInfo &getInfo() const { return *Active.back(); } 29406f32e7eSjoerg /// The set of attributes that will be applied to the next pushed loop. 29506f32e7eSjoerg LoopAttributes StagedAttrs; 29606f32e7eSjoerg /// Stack of active loops. 29706f32e7eSjoerg llvm::SmallVector<std::unique_ptr<LoopInfo>, 4> Active; 29806f32e7eSjoerg }; 29906f32e7eSjoerg 30006f32e7eSjoerg } // end namespace CodeGen 30106f32e7eSjoerg } // end namespace clang 30206f32e7eSjoerg 30306f32e7eSjoerg #endif 304