1274958Sdim//===---- CGLoopInfo.h - LLVM CodeGen for loop metadata -*- C++ -*---------===// 2274958Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6274958Sdim// 7274958Sdim//===----------------------------------------------------------------------===// 8274958Sdim// 9274958Sdim// This is the internal state used for llvm translation for loop statement 10274958Sdim// metadata. 11274958Sdim// 12274958Sdim//===----------------------------------------------------------------------===// 13274958Sdim 14280031Sdim#ifndef LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H 15280031Sdim#define LLVM_CLANG_LIB_CODEGEN_CGLOOPINFO_H 16274958Sdim 17288943Sdim#include "llvm/ADT/ArrayRef.h" 18274958Sdim#include "llvm/ADT/SmallVector.h" 19309124Sdim#include "llvm/IR/DebugLoc.h" 20274958Sdim#include "llvm/IR/Value.h" 21274958Sdim#include "llvm/Support/Compiler.h" 22274958Sdim 23274958Sdimnamespace llvm { 24274958Sdimclass BasicBlock; 25274958Sdimclass Instruction; 26274958Sdimclass MDNode; 27274958Sdim} // end namespace llvm 28274958Sdim 29274958Sdimnamespace clang { 30288943Sdimclass Attr; 31296417Sdimclass ASTContext; 32274958Sdimnamespace CodeGen { 33274958Sdim 34341825Sdim/// Attributes that may be specified on loops. 35274958Sdimstruct LoopAttributes { 36274958Sdim explicit LoopAttributes(bool IsParallel = false); 37274958Sdim void clear(); 38274958Sdim 39341825Sdim /// Generate llvm.loop.parallel metadata for loads and stores. 40274958Sdim bool IsParallel; 41274958Sdim 42341825Sdim /// State of loop vectorization or unrolling. 43296417Sdim enum LVEnableState { Unspecified, Enable, Disable, Full }; 44274958Sdim 45341825Sdim /// Value for llvm.loop.vectorize.enable metadata. 46296417Sdim LVEnableState VectorizeEnable; 47274958Sdim 48341825Sdim /// Value for llvm.loop.unroll.* metadata (enable, disable, or full). 49296417Sdim LVEnableState UnrollEnable; 50274958Sdim 51344779Sdim /// Value for llvm.loop.unroll_and_jam.* metadata (enable, disable, or full). 52344779Sdim LVEnableState UnrollAndJamEnable; 53344779Sdim 54360784Sdim /// Value for llvm.loop.vectorize.predicate metadata 55360784Sdim LVEnableState VectorizePredicateEnable; 56360784Sdim 57341825Sdim /// Value for llvm.loop.vectorize.width metadata. 58296417Sdim unsigned VectorizeWidth; 59296417Sdim 60341825Sdim /// Value for llvm.loop.interleave.count metadata. 61296417Sdim unsigned InterleaveCount; 62296417Sdim 63341825Sdim /// llvm.unroll. 64296417Sdim unsigned UnrollCount; 65309124Sdim 66344779Sdim /// llvm.unroll. 67344779Sdim unsigned UnrollAndJamCount; 68344779Sdim 69341825Sdim /// Value for llvm.loop.distribute.enable metadata. 70309124Sdim LVEnableState DistributeEnable; 71344779Sdim 72344779Sdim /// Value for llvm.loop.pipeline.disable metadata. 73344779Sdim bool PipelineDisabled; 74344779Sdim 75344779Sdim /// Value for llvm.loop.pipeline.iicount metadata. 76344779Sdim unsigned PipelineInitiationInterval; 77274958Sdim}; 78274958Sdim 79341825Sdim/// Information used when generating a structured loop. 80274958Sdimclass LoopInfo { 81274958Sdimpublic: 82341825Sdim /// Construct a new LoopInfo for the loop with entry Header. 83309124Sdim LoopInfo(llvm::BasicBlock *Header, const LoopAttributes &Attrs, 84353358Sdim const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc, 85353358Sdim LoopInfo *Parent); 86274958Sdim 87341825Sdim /// Get the loop id metadata for this loop. 88353358Sdim llvm::MDNode *getLoopID() const { return TempLoopID.get(); } 89274958Sdim 90341825Sdim /// Get the header block of this loop. 91274958Sdim llvm::BasicBlock *getHeader() const { return Header; } 92274958Sdim 93341825Sdim /// Get the set of attributes active for this loop. 94274958Sdim const LoopAttributes &getAttributes() const { return Attrs; } 95274958Sdim 96344779Sdim /// Return this loop's access group or nullptr if it does not have one. 97344779Sdim llvm::MDNode *getAccessGroup() const { return AccGroup; } 98344779Sdim 99353358Sdim /// Create the loop's metadata. Must be called after its nested loops have 100353358Sdim /// been processed. 101353358Sdim void finish(); 102353358Sdim 103274958Sdimprivate: 104341825Sdim /// Loop ID metadata. 105353358Sdim llvm::TempMDTuple TempLoopID; 106341825Sdim /// Header block of this loop. 107274958Sdim llvm::BasicBlock *Header; 108341825Sdim /// The attributes for this loop. 109274958Sdim LoopAttributes Attrs; 110344779Sdim /// The access group for memory accesses parallel to this loop. 111344779Sdim llvm::MDNode *AccGroup = nullptr; 112353358Sdim /// Start location of this loop. 113353358Sdim llvm::DebugLoc StartLoc; 114353358Sdim /// End location of this loop. 115353358Sdim llvm::DebugLoc EndLoc; 116353358Sdim /// The next outer loop, or nullptr if this is the outermost loop. 117353358Sdim LoopInfo *Parent; 118353358Sdim /// If this loop has unroll-and-jam metadata, this can be set by the inner 119353358Sdim /// loop's LoopInfo to set the llvm.loop.unroll_and_jam.followup_inner 120353358Sdim /// metadata. 121353358Sdim llvm::MDNode *UnrollAndJamInnerFollowup = nullptr; 122353358Sdim 123353358Sdim /// Create a LoopID without any transformations. 124353358Sdim llvm::MDNode * 125353358Sdim createLoopPropertiesMetadata(llvm::ArrayRef<llvm::Metadata *> LoopProperties); 126353358Sdim 127353358Sdim /// Create a LoopID for transformations. 128353358Sdim /// 129353358Sdim /// The methods call each other in case multiple transformations are applied 130353358Sdim /// to a loop. The transformation first to be applied will use LoopID of the 131353358Sdim /// next transformation in its followup attribute. 132353358Sdim /// 133353358Sdim /// @param Attrs The loop's transformations. 134353358Sdim /// @param LoopProperties Non-transformation properties such as debug 135353358Sdim /// location, parallel accesses and disabled 136353358Sdim /// transformations. These are added to the returned 137353358Sdim /// LoopID. 138353358Sdim /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes 139353358Sdim /// at least one transformation. 140353358Sdim /// 141353358Sdim /// @return A LoopID (metadata node) that can be used for the llvm.loop 142353358Sdim /// annotation or followup-attribute. 143353358Sdim /// @{ 144353358Sdim llvm::MDNode * 145353358Sdim createPipeliningMetadata(const LoopAttributes &Attrs, 146353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 147353358Sdim bool &HasUserTransforms); 148353358Sdim llvm::MDNode * 149353358Sdim createPartialUnrollMetadata(const LoopAttributes &Attrs, 150353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 151353358Sdim bool &HasUserTransforms); 152353358Sdim llvm::MDNode * 153353358Sdim createUnrollAndJamMetadata(const LoopAttributes &Attrs, 154353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 155353358Sdim bool &HasUserTransforms); 156353358Sdim llvm::MDNode * 157353358Sdim createLoopVectorizeMetadata(const LoopAttributes &Attrs, 158353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 159353358Sdim bool &HasUserTransforms); 160353358Sdim llvm::MDNode * 161353358Sdim createLoopDistributeMetadata(const LoopAttributes &Attrs, 162353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 163353358Sdim bool &HasUserTransforms); 164353358Sdim llvm::MDNode * 165353358Sdim createFullUnrollMetadata(const LoopAttributes &Attrs, 166353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 167353358Sdim bool &HasUserTransforms); 168353358Sdim /// @} 169353358Sdim 170353358Sdim /// Create a LoopID for this loop, including transformation-unspecific 171353358Sdim /// metadata such as debug location. 172353358Sdim /// 173353358Sdim /// @param Attrs This loop's attributes and transformations. 174353358Sdim /// @param LoopProperties Additional non-transformation properties to add 175353358Sdim /// to the LoopID, such as transformation-specific 176353358Sdim /// metadata that are not covered by @p Attrs. 177353358Sdim /// @param HasUserTransforms [out] Set to true if the returned MDNode encodes 178353358Sdim /// at least one transformation. 179353358Sdim /// 180353358Sdim /// @return A LoopID (metadata node) that can be used for the llvm.loop 181353358Sdim /// annotation. 182353358Sdim llvm::MDNode *createMetadata(const LoopAttributes &Attrs, 183353358Sdim llvm::ArrayRef<llvm::Metadata *> LoopProperties, 184353358Sdim bool &HasUserTransforms); 185274958Sdim}; 186274958Sdim 187341825Sdim/// A stack of loop information corresponding to loop nesting levels. 188274958Sdim/// This stack can be used to prepare attributes which are applied when a loop 189274958Sdim/// is emitted. 190274958Sdimclass LoopInfoStack { 191288943Sdim LoopInfoStack(const LoopInfoStack &) = delete; 192288943Sdim void operator=(const LoopInfoStack &) = delete; 193274958Sdim 194274958Sdimpublic: 195274958Sdim LoopInfoStack() {} 196274958Sdim 197341825Sdim /// Begin a new structured loop. The set of staged attributes will be 198274958Sdim /// applied to the loop and then cleared. 199314564Sdim void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, 200314564Sdim const llvm::DebugLoc &EndLoc); 201274958Sdim 202341825Sdim /// Begin a new structured loop. Stage attributes from the Attrs list. 203296417Sdim /// The staged attributes are applied to the loop and then cleared. 204296417Sdim void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx, 205314564Sdim llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc, 206314564Sdim const llvm::DebugLoc &EndLoc); 207296417Sdim 208341825Sdim /// End the current loop. 209274958Sdim void pop(); 210274958Sdim 211341825Sdim /// Return the top loop id metadata. 212274958Sdim llvm::MDNode *getCurLoopID() const { return getInfo().getLoopID(); } 213274958Sdim 214341825Sdim /// Return true if the top loop is parallel. 215274958Sdim bool getCurLoopParallel() const { 216274958Sdim return hasInfo() ? getInfo().getAttributes().IsParallel : false; 217274958Sdim } 218274958Sdim 219341825Sdim /// Function called by the CodeGenFunction when an instruction is 220274958Sdim /// created. 221274958Sdim void InsertHelper(llvm::Instruction *I) const; 222274958Sdim 223341825Sdim /// Set the next pushed loop as parallel. 224274958Sdim void setParallel(bool Enable = true) { StagedAttrs.IsParallel = Enable; } 225274958Sdim 226341825Sdim /// Set the next pushed loop 'vectorize.enable' 227296417Sdim void setVectorizeEnable(bool Enable = true) { 228296417Sdim StagedAttrs.VectorizeEnable = 229296417Sdim Enable ? LoopAttributes::Enable : LoopAttributes::Disable; 230274958Sdim } 231274958Sdim 232341825Sdim /// Set the next pushed loop as a distribution candidate. 233309124Sdim void setDistributeState(bool Enable = true) { 234309124Sdim StagedAttrs.DistributeEnable = 235309124Sdim Enable ? LoopAttributes::Enable : LoopAttributes::Disable; 236309124Sdim } 237309124Sdim 238341825Sdim /// Set the next pushed loop unroll state. 239296417Sdim void setUnrollState(const LoopAttributes::LVEnableState &State) { 240296417Sdim StagedAttrs.UnrollEnable = State; 241296417Sdim } 242274958Sdim 243360784Sdim /// Set the next pushed vectorize predicate state. 244360784Sdim void setVectorizePredicateState(const LoopAttributes::LVEnableState &State) { 245360784Sdim StagedAttrs.VectorizePredicateEnable = State; 246360784Sdim } 247360784Sdim 248344779Sdim /// Set the next pushed loop unroll_and_jam state. 249344779Sdim void setUnrollAndJamState(const LoopAttributes::LVEnableState &State) { 250344779Sdim StagedAttrs.UnrollAndJamEnable = State; 251344779Sdim } 252344779Sdim 253341825Sdim /// Set the vectorize width for the next loop pushed. 254296417Sdim void setVectorizeWidth(unsigned W) { StagedAttrs.VectorizeWidth = W; } 255274958Sdim 256341825Sdim /// Set the interleave count for the next loop pushed. 257296417Sdim void setInterleaveCount(unsigned C) { StagedAttrs.InterleaveCount = C; } 258296417Sdim 259341825Sdim /// Set the unroll count for the next loop pushed. 260296417Sdim void setUnrollCount(unsigned C) { StagedAttrs.UnrollCount = C; } 261296417Sdim 262344779Sdim /// \brief Set the unroll count for the next loop pushed. 263344779Sdim void setUnrollAndJamCount(unsigned C) { StagedAttrs.UnrollAndJamCount = C; } 264344779Sdim 265344779Sdim /// Set the pipeline disabled state. 266344779Sdim void setPipelineDisabled(bool S) { StagedAttrs.PipelineDisabled = S; } 267344779Sdim 268344779Sdim /// Set the pipeline initiation interval. 269344779Sdim void setPipelineInitiationInterval(unsigned C) { 270344779Sdim StagedAttrs.PipelineInitiationInterval = C; 271344779Sdim } 272344779Sdim 273274958Sdimprivate: 274341825Sdim /// Returns true if there is LoopInfo on the stack. 275274958Sdim bool hasInfo() const { return !Active.empty(); } 276341825Sdim /// Return the LoopInfo for the current loop. HasInfo should be called 277274958Sdim /// first to ensure LoopInfo is present. 278360784Sdim const LoopInfo &getInfo() const { return *Active.back(); } 279341825Sdim /// The set of attributes that will be applied to the next pushed loop. 280274958Sdim LoopAttributes StagedAttrs; 281341825Sdim /// Stack of active loops. 282360784Sdim llvm::SmallVector<std::unique_ptr<LoopInfo>, 4> Active; 283274958Sdim}; 284274958Sdim 285274958Sdim} // end namespace CodeGen 286274958Sdim} // end namespace clang 287274958Sdim 288280031Sdim#endif 289