1 //===- IR/OpenMPIRBuilder.h - OpenMP encoding builder for LLVM IR - 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 file defines the OpenMPIRBuilder class and helpers used as a convenient 10 // way to create LLVM instructions for OpenMP directives. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_OPENMP_IR_IRBUILDER_H 15 #define LLVM_OPENMP_IR_IRBUILDER_H 16 17 #include "llvm/IR/DebugLoc.h" 18 #include "llvm/IR/IRBuilder.h" 19 #include "llvm/Frontend/OpenMP/OMPConstants.h" 20 21 namespace llvm { 22 23 /// An interface to create LLVM-IR for OpenMP directives. 24 /// 25 /// Each OpenMP directive has a corresponding public generator method. 26 class OpenMPIRBuilder { 27 public: 28 /// Create a new OpenMPIRBuilder operating on the given module \p M. This will 29 /// not have an effect on \p M (see initialize). 30 OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {} 31 32 /// Initialize the internal state, this will put structures types and 33 /// potentially other helpers into the underlying module. Must be called 34 /// before any other method and only once! 35 void initialize(); 36 37 /// Add attributes known for \p FnID to \p Fn. 38 void addAttributes(omp::RuntimeFunction FnID, Function &Fn); 39 40 /// Type used throughout for insertion points. 41 using InsertPointTy = IRBuilder<>::InsertPoint; 42 43 /// Callback type for variable finalization (think destructors). 44 /// 45 /// \param CodeGenIP is the insertion point at which the finalization code 46 /// should be placed. 47 /// 48 /// A finalize callback knows about all objects that need finalization, e.g. 49 /// destruction, when the scope of the currently generated construct is left 50 /// at the time, and location, the callback is invoked. 51 using FinalizeCallbackTy = std::function<void(InsertPointTy CodeGenIP)>; 52 53 struct FinalizationInfo { 54 /// The finalization callback provided by the last in-flight invocation of 55 /// CreateXXXX for the directive of kind DK. 56 FinalizeCallbackTy FiniCB; 57 58 /// The directive kind of the innermost directive that has an associated 59 /// region which might require finalization when it is left. 60 omp::Directive DK; 61 62 /// Flag to indicate if the directive is cancellable. 63 bool IsCancellable; 64 }; 65 66 /// Push a finalization callback on the finalization stack. 67 /// 68 /// NOTE: Temporary solution until Clang CG is gone. 69 void pushFinalizationCB(const FinalizationInfo &FI) { 70 FinalizationStack.push_back(FI); 71 } 72 73 /// Pop the last finalization callback from the finalization stack. 74 /// 75 /// NOTE: Temporary solution until Clang CG is gone. 76 void popFinalizationCB() { FinalizationStack.pop_back(); } 77 78 /// Callback type for body (=inner region) code generation 79 /// 80 /// The callback takes code locations as arguments, each describing a 81 /// location at which code might need to be generated or a location that is 82 /// the target of control transfer. 83 /// 84 /// \param AllocaIP is the insertion point at which new alloca instructions 85 /// should be placed. 86 /// \param CodeGenIP is the insertion point at which the body code should be 87 /// placed. 88 /// \param ContinuationBB is the basic block target to leave the body. 89 /// 90 /// Note that all blocks pointed to by the arguments have terminators. 91 using BodyGenCallbackTy = 92 function_ref<void(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, 93 BasicBlock &ContinuationBB)>; 94 95 /// Callback type for variable privatization (think copy & default 96 /// constructor). 97 /// 98 /// \param AllocaIP is the insertion point at which new alloca instructions 99 /// should be placed. 100 /// \param CodeGenIP is the insertion point at which the privatization code 101 /// should be placed. 102 /// \param Val The value beeing copied/created. 103 /// \param ReplVal The replacement value, thus a copy or new created version 104 /// of \p Val. 105 /// 106 /// \returns The new insertion point where code generation continues and 107 /// \p ReplVal the replacement of \p Val. 108 using PrivatizeCallbackTy = function_ref<InsertPointTy( 109 InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Val, 110 Value *&ReplVal)>; 111 112 /// Description of a LLVM-IR insertion point (IP) and a debug/source location 113 /// (filename, line, column, ...). 114 struct LocationDescription { 115 template <typename T, typename U> 116 LocationDescription(const IRBuilder<T, U> &IRB) 117 : IP(IRB.saveIP()), DL(IRB.getCurrentDebugLocation()) {} 118 LocationDescription(const InsertPointTy &IP) : IP(IP) {} 119 LocationDescription(const InsertPointTy &IP, const DebugLoc &DL) 120 : IP(IP), DL(DL) {} 121 InsertPointTy IP; 122 DebugLoc DL; 123 }; 124 125 /// Emitter methods for OpenMP directives. 126 /// 127 ///{ 128 129 /// Generator for '#omp barrier' 130 /// 131 /// \param Loc The location where the barrier directive was encountered. 132 /// \param DK The kind of directive that caused the barrier. 133 /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. 134 /// \param CheckCancelFlag Flag to indicate a cancel barrier return value 135 /// should be checked and acted upon. 136 /// 137 /// \returns The insertion point after the barrier. 138 InsertPointTy CreateBarrier(const LocationDescription &Loc, omp::Directive DK, 139 bool ForceSimpleCall = false, 140 bool CheckCancelFlag = true); 141 142 /// Generator for '#omp cancel' 143 /// 144 /// \param Loc The location where the directive was encountered. 145 /// \param IfCondition The evaluated 'if' clause expression, if any. 146 /// \param CanceledDirective The kind of directive that is cancled. 147 /// 148 /// \returns The insertion point after the barrier. 149 InsertPointTy CreateCancel(const LocationDescription &Loc, 150 Value *IfCondition, 151 omp::Directive CanceledDirective); 152 153 /// Generator for '#omp parallel' 154 /// 155 /// \param Loc The insert and source location description. 156 /// \param BodyGenCB Callback that will generate the region code. 157 /// \param PrivCB Callback to copy a given variable (think copy constructor). 158 /// \param FiniCB Callback to finalize variable copies. 159 /// \param IfCondition The evaluated 'if' clause expression, if any. 160 /// \param NumThreads The evaluated 'num_threads' clause expression, if any. 161 /// \param ProcBind The value of the 'proc_bind' clause (see ProcBindKind). 162 /// \param IsCancellable Flag to indicate a cancellable parallel region. 163 /// 164 /// \returns The insertion position *after* the parallel. 165 IRBuilder<>::InsertPoint 166 CreateParallel(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, 167 PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, 168 Value *IfCondition, Value *NumThreads, 169 omp::ProcBindKind ProcBind, bool IsCancellable); 170 171 ///} 172 173 private: 174 /// Update the internal location to \p Loc. 175 bool updateToLocation(const LocationDescription &Loc) { 176 Builder.restoreIP(Loc.IP); 177 Builder.SetCurrentDebugLocation(Loc.DL); 178 return Loc.IP.getBlock() != nullptr; 179 } 180 181 /// Return the function declaration for the runtime function with \p FnID. 182 Function *getOrCreateRuntimeFunction(omp::RuntimeFunction FnID); 183 184 /// Return the (LLVM-IR) string describing the source location \p LocStr. 185 Constant *getOrCreateSrcLocStr(StringRef LocStr); 186 187 /// Return the (LLVM-IR) string describing the default source location. 188 Constant *getOrCreateDefaultSrcLocStr(); 189 190 /// Return the (LLVM-IR) string describing the source location \p Loc. 191 Constant *getOrCreateSrcLocStr(const LocationDescription &Loc); 192 193 /// Return an ident_t* encoding the source location \p SrcLocStr and \p Flags. 194 Value *getOrCreateIdent(Constant *SrcLocStr, 195 omp::IdentFlag Flags = omp::IdentFlag(0)); 196 197 /// Generate control flow and cleanup for cancellation. 198 /// 199 /// \param CancelFlag Flag indicating if the cancellation is performed. 200 /// \param CanceledDirective The kind of directive that is cancled. 201 void emitCancelationCheckImpl(Value *CancelFlag, 202 omp::Directive CanceledDirective); 203 204 /// Generate a barrier runtime call. 205 /// 206 /// \param Loc The location at which the request originated and is fulfilled. 207 /// \param DK The directive which caused the barrier 208 /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. 209 /// \param CheckCancelFlag Flag to indicate a cancel barrier return value 210 /// should be checked and acted upon. 211 /// 212 /// \returns The insertion point after the barrier. 213 InsertPointTy emitBarrierImpl(const LocationDescription &Loc, 214 omp::Directive DK, bool ForceSimpleCall, 215 bool CheckCancelFlag); 216 217 /// The finalization stack made up of finalize callbacks currently in-flight, 218 /// wrapped into FinalizationInfo objects that reference also the finalization 219 /// target block and the kind of cancellable directive. 220 SmallVector<FinalizationInfo, 8> FinalizationStack; 221 222 /// Return true if the last entry in the finalization stack is of kind \p DK 223 /// and cancellable. 224 bool isLastFinalizationInfoCancellable(omp::Directive DK) { 225 return !FinalizationStack.empty() && 226 FinalizationStack.back().IsCancellable && 227 FinalizationStack.back().DK == DK; 228 } 229 230 /// Return the current thread ID. 231 /// 232 /// \param Ident The ident (ident_t*) describing the query origin. 233 Value *getOrCreateThreadID(Value *Ident); 234 235 /// The underlying LLVM-IR module 236 Module &M; 237 238 /// The LLVM-IR Builder used to create IR. 239 IRBuilder<> Builder; 240 241 /// Map to remember source location strings 242 StringMap<Constant *> SrcLocStrMap; 243 244 /// Map to remember existing ident_t*. 245 DenseMap<std::pair<Constant *, uint64_t>, GlobalVariable *> IdentMap; 246 }; 247 248 } // end namespace llvm 249 250 #endif // LLVM_IR_IRBUILDER_H 251