| //===- IR/OpenMPIRBuilder.h - OpenMP encoding builder for LLVM IR - C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the OpenMPIRBuilder class and helpers used as a convenient |
| // way to create LLVM instructions for OpenMP directives. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_OPENMP_IR_IRBUILDER_H |
| #define LLVM_OPENMP_IR_IRBUILDER_H |
| |
| #include "llvm/IR/DebugLoc.h" |
| #include "llvm/IR/IRBuilder.h" |
| #include "llvm/Frontend/OpenMP/OMPConstants.h" |
| |
| namespace llvm { |
| |
| /// An interface to create LLVM-IR for OpenMP directives. |
| /// |
| /// Each OpenMP directive has a corresponding public generator method. |
| class OpenMPIRBuilder { |
| public: |
| /// Create a new OpenMPIRBuilder operating on the given module \p M. This will |
| /// not have an effect on \p M (see initialize). |
| OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {} |
| |
| /// Initialize the internal state, this will put structures types and |
| /// potentially other helpers into the underlying module. Must be called |
| /// before any other method and only once! |
| void initialize(); |
| |
| /// Add attributes known for \p FnID to \p Fn. |
| void addAttributes(omp::RuntimeFunction FnID, Function &Fn); |
| |
| /// Type used throughout for insertion points. |
| using InsertPointTy = IRBuilder<>::InsertPoint; |
| |
| /// Callback type for variable finalization (think destructors). |
| /// |
| /// \param CodeGenIP is the insertion point at which the finalization code |
| /// should be placed. |
| /// |
| /// A finalize callback knows about all objects that need finalization, e.g. |
| /// destruction, when the scope of the currently generated construct is left |
| /// at the time, and location, the callback is invoked. |
| using FinalizeCallbackTy = std::function<void(InsertPointTy CodeGenIP)>; |
| |
| struct FinalizationInfo { |
| /// The finalization callback provided by the last in-flight invocation of |
| /// CreateXXXX for the directive of kind DK. |
| FinalizeCallbackTy FiniCB; |
| |
| /// The directive kind of the innermost directive that has an associated |
| /// region which might require finalization when it is left. |
| omp::Directive DK; |
| |
| /// Flag to indicate if the directive is cancellable. |
| bool IsCancellable; |
| }; |
| |
| /// Push a finalization callback on the finalization stack. |
| /// |
| /// NOTE: Temporary solution until Clang CG is gone. |
| void pushFinalizationCB(const FinalizationInfo &FI) { |
| FinalizationStack.push_back(FI); |
| } |
| |
| /// Pop the last finalization callback from the finalization stack. |
| /// |
| /// NOTE: Temporary solution until Clang CG is gone. |
| void popFinalizationCB() { FinalizationStack.pop_back(); } |
| |
| /// Callback type for body (=inner region) code generation |
| /// |
| /// The callback takes code locations as arguments, each describing a |
| /// location at which code might need to be generated or a location that is |
| /// the target of control transfer. |
| /// |
| /// \param AllocaIP is the insertion point at which new alloca instructions |
| /// should be placed. |
| /// \param CodeGenIP is the insertion point at which the body code should be |
| /// placed. |
| /// \param ContinuationBB is the basic block target to leave the body. |
| /// |
| /// Note that all blocks pointed to by the arguments have terminators. |
| using BodyGenCallbackTy = |
| function_ref<void(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, |
| BasicBlock &ContinuationBB)>; |
| |
| /// Callback type for variable privatization (think copy & default |
| /// constructor). |
| /// |
| /// \param AllocaIP is the insertion point at which new alloca instructions |
| /// should be placed. |
| /// \param CodeGenIP is the insertion point at which the privatization code |
| /// should be placed. |
| /// \param Val The value beeing copied/created. |
| /// \param ReplVal The replacement value, thus a copy or new created version |
| /// of \p Val. |
| /// |
| /// \returns The new insertion point where code generation continues and |
| /// \p ReplVal the replacement of \p Val. |
| using PrivatizeCallbackTy = function_ref<InsertPointTy( |
| InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Val, |
| Value *&ReplVal)>; |
| |
| /// Description of a LLVM-IR insertion point (IP) and a debug/source location |
| /// (filename, line, column, ...). |
| struct LocationDescription { |
| template <typename T, typename U> |
| LocationDescription(const IRBuilder<T, U> &IRB) |
| : IP(IRB.saveIP()), DL(IRB.getCurrentDebugLocation()) {} |
| LocationDescription(const InsertPointTy &IP) : IP(IP) {} |
| LocationDescription(const InsertPointTy &IP, const DebugLoc &DL) |
| : IP(IP), DL(DL) {} |
| InsertPointTy IP; |
| DebugLoc DL; |
| }; |
| |
| /// Emitter methods for OpenMP directives. |
| /// |
| ///{ |
| |
| /// Generator for '#omp barrier' |
| /// |
| /// \param Loc The location where the barrier directive was encountered. |
| /// \param DK The kind of directive that caused the barrier. |
| /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. |
| /// \param CheckCancelFlag Flag to indicate a cancel barrier return value |
| /// should be checked and acted upon. |
| /// |
| /// \returns The insertion point after the barrier. |
| InsertPointTy CreateBarrier(const LocationDescription &Loc, omp::Directive DK, |
| bool ForceSimpleCall = false, |
| bool CheckCancelFlag = true); |
| |
| /// Generator for '#omp cancel' |
| /// |
| /// \param Loc The location where the directive was encountered. |
| /// \param IfCondition The evaluated 'if' clause expression, if any. |
| /// \param CanceledDirective The kind of directive that is cancled. |
| /// |
| /// \returns The insertion point after the barrier. |
| InsertPointTy CreateCancel(const LocationDescription &Loc, |
| Value *IfCondition, |
| omp::Directive CanceledDirective); |
| |
| /// Generator for '#omp parallel' |
| /// |
| /// \param Loc The insert and source location description. |
| /// \param BodyGenCB Callback that will generate the region code. |
| /// \param PrivCB Callback to copy a given variable (think copy constructor). |
| /// \param FiniCB Callback to finalize variable copies. |
| /// \param IfCondition The evaluated 'if' clause expression, if any. |
| /// \param NumThreads The evaluated 'num_threads' clause expression, if any. |
| /// \param ProcBind The value of the 'proc_bind' clause (see ProcBindKind). |
| /// \param IsCancellable Flag to indicate a cancellable parallel region. |
| /// |
| /// \returns The insertion position *after* the parallel. |
| IRBuilder<>::InsertPoint |
| CreateParallel(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, |
| PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, |
| Value *IfCondition, Value *NumThreads, |
| omp::ProcBindKind ProcBind, bool IsCancellable); |
| |
| ///} |
| |
| private: |
| /// Update the internal location to \p Loc. |
| bool updateToLocation(const LocationDescription &Loc) { |
| Builder.restoreIP(Loc.IP); |
| Builder.SetCurrentDebugLocation(Loc.DL); |
| return Loc.IP.getBlock() != nullptr; |
| } |
| |
| /// Return the function declaration for the runtime function with \p FnID. |
| Function *getOrCreateRuntimeFunction(omp::RuntimeFunction FnID); |
| |
| /// Return the (LLVM-IR) string describing the source location \p LocStr. |
| Constant *getOrCreateSrcLocStr(StringRef LocStr); |
| |
| /// Return the (LLVM-IR) string describing the default source location. |
| Constant *getOrCreateDefaultSrcLocStr(); |
| |
| /// Return the (LLVM-IR) string describing the source location \p Loc. |
| Constant *getOrCreateSrcLocStr(const LocationDescription &Loc); |
| |
| /// Return an ident_t* encoding the source location \p SrcLocStr and \p Flags. |
| Value *getOrCreateIdent(Constant *SrcLocStr, |
| omp::IdentFlag Flags = omp::IdentFlag(0)); |
| |
| /// Generate control flow and cleanup for cancellation. |
| /// |
| /// \param CancelFlag Flag indicating if the cancellation is performed. |
| /// \param CanceledDirective The kind of directive that is cancled. |
| void emitCancelationCheckImpl(Value *CancelFlag, |
| omp::Directive CanceledDirective); |
| |
| /// Generate a barrier runtime call. |
| /// |
| /// \param Loc The location at which the request originated and is fulfilled. |
| /// \param DK The directive which caused the barrier |
| /// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier. |
| /// \param CheckCancelFlag Flag to indicate a cancel barrier return value |
| /// should be checked and acted upon. |
| /// |
| /// \returns The insertion point after the barrier. |
| InsertPointTy emitBarrierImpl(const LocationDescription &Loc, |
| omp::Directive DK, bool ForceSimpleCall, |
| bool CheckCancelFlag); |
| |
| /// The finalization stack made up of finalize callbacks currently in-flight, |
| /// wrapped into FinalizationInfo objects that reference also the finalization |
| /// target block and the kind of cancellable directive. |
| SmallVector<FinalizationInfo, 8> FinalizationStack; |
| |
| /// Return true if the last entry in the finalization stack is of kind \p DK |
| /// and cancellable. |
| bool isLastFinalizationInfoCancellable(omp::Directive DK) { |
| return !FinalizationStack.empty() && |
| FinalizationStack.back().IsCancellable && |
| FinalizationStack.back().DK == DK; |
| } |
| |
| /// Return the current thread ID. |
| /// |
| /// \param Ident The ident (ident_t*) describing the query origin. |
| Value *getOrCreateThreadID(Value *Ident); |
| |
| /// The underlying LLVM-IR module |
| Module &M; |
| |
| /// The LLVM-IR Builder used to create IR. |
| IRBuilder<> Builder; |
| |
| /// Map to remember source location strings |
| StringMap<Constant *> SrcLocStrMap; |
| |
| /// Map to remember existing ident_t*. |
| DenseMap<std::pair<Constant *, uint64_t>, GlobalVariable *> IdentMap; |
| }; |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_IR_IRBUILDER_H |