Index: llvm/CMakeLists.txt =================================================================== --- llvm/CMakeLists.txt +++ llvm/CMakeLists.txt @@ -714,6 +714,11 @@ set(LLVMOPTIONALCOMPONENTS ${LLVMOPTIONALCOMPONENTS} PerfJITEvents) endif (LLVM_USE_PERF) +# LLVM_COLLAB +SET(LLVM_COLLAB ON) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLLVM_COLLAB=1") +# end LLVM_COLLAB + message(STATUS "Constructing LLVMBuild project information") execute_process( COMMAND ${PYTHON_EXECUTABLE} -B ${LLVMBUILDTOOL} Index: llvm/aaa =================================================================== --- /dev/null +++ llvm/aaa @@ -0,0 +1,3064 @@ +commit 37750fae1175c3615ce0b5198101938c9ffe6145 +Author: Xinmin Tian +Date: Wed Apr 3 18:43:30 2019 -0700 + + IR extensions to support directives + +diff --git a/llvm/include/llvm/IR/CMakeLists.txt b/llvm/include/llvm/IR/CMakeLists.txt +index 830f375..667323d 100644 +--- a/llvm/include/llvm/IR/CMakeLists.txt ++++ b/llvm/include/llvm/IR/CMakeLists.txt +@@ -1,7 +1,12 @@ + set(LLVM_TARGET_DEFINITIONS Attributes.td) + tablegen(LLVM Attributes.inc -gen-attrs) + + set(LLVM_TARGET_DEFINITIONS Intrinsics.td) + tablegen(LLVM IntrinsicEnums.inc -gen-intrinsic-enums) + tablegen(LLVM IntrinsicImpl.inc -gen-intrinsic-impl) + add_public_tablegen_target(intrinsics_gen) ++if (INTEL_COLLAB) ++set(LLVM_TARGET_DEFINITIONS Intel_Directives.td) ++tablegen(LLVM Intel_Directives.gen -gen-directives) ++add_public_tablegen_target(intel_directives_gen) ++endif(INTEL_COLLAB) +diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h +index d78ce62..aff50f5 100644 +--- a/llvm/include/llvm/IR/GlobalValue.h ++++ b/llvm/include/llvm/IR/GlobalValue.h +@@ -1,586 +1,612 @@ + //===-- llvm/GlobalValue.h - Class to represent a global value --*- 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 is a common base class of all globally definable objects. As such, + // it is subclassed by GlobalVariable, GlobalAlias and by Function. This is + // used because you can do certain things with these global objects that you + // can't do to anything else. For example, use the address of one as a + // constant. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_IR_GLOBALVALUE_H + #define LLVM_IR_GLOBALVALUE_H + + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/Twine.h" + #include "llvm/IR/Constant.h" + #include "llvm/IR/DerivedTypes.h" + #include "llvm/IR/Value.h" + #include "llvm/Support/Casting.h" + #include "llvm/Support/ErrorHandling.h" + #include "llvm/Support/MD5.h" + #include + #include + #include + + namespace llvm { + + class Comdat; + class ConstantRange; + class Error; + class GlobalObject; + class Module; + + namespace Intrinsic { + enum ID : unsigned; + } // end namespace Intrinsic + + class GlobalValue : public Constant { + public: + /// An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + AvailableExternallyLinkage, ///< Available for inspection, not emission. + LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) + LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. + WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) + WeakODRLinkage, ///< Same, but only replaced by something equivalent. + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions). + PrivateLinkage, ///< Like Internal, but omit from symbol table. + ExternalWeakLinkage,///< ExternalWeak linkage description. + CommonLinkage ///< Tentative definitions. + }; + + /// An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + + /// Storage classes of global values for PE targets. + enum DLLStorageClassTypes { + DefaultStorageClass = 0, + DLLImportStorageClass = 1, ///< Function to be imported from DLL + DLLExportStorageClass = 2 ///< Function to be accessible from DLL. + }; + + protected: + GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) + : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), + ValueType(Ty), Visibility(DefaultVisibility), + UnnamedAddrVal(unsigned(UnnamedAddr::None)), + DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), ++#if INTEL_COLLAB ++ ThreadPrivate(0), TargetDeclare(0), ++#endif // INTEL_COLLAB + HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U), + Parent(nullptr) { + setLinkage(Linkage); + setName(Name); + } + + Type *ValueType; + ++#if INTEL_COLLAB ++ // INTEL - This needs to be two less than it is in the community version to ++ // account for the ThreadPrivate bit and TargetDeclare bit. See also ++ // the comment at the SubClassData declaration. ++ static const unsigned GlobalValueSubClassDataBits = 15; ++#else + static const unsigned GlobalValueSubClassDataBits = 17; ++#endif // INTEL_COLLAB + + // All bitfields use unsigned as the underlying type so that MSVC will pack + // them. + unsigned Linkage : 4; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned UnnamedAddrVal : 2; // This value's address is not significant + unsigned DllStorageClass : 2; // DLL storage class + + unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is + // the desired model? ++#if INTEL_COLLAB ++ unsigned ThreadPrivate : 1; // The thread_private attribute indicates ++ // if the global variable is associated ++ // with an OpenMP threadprivate directive ++ // and the threadprivate mode is legacy. ++ unsigned TargetDeclare : 1; // The target declare attribute indicates ++ // if the global variable is associated ++ // with an OpenMP declare target directive. ++#endif // INTEL_COLLAB + + /// True if the function's name starts with "llvm.". This corresponds to the + /// value of Function::isIntrinsic(), which may be true even if + /// Function::intrinsicID() returns Intrinsic::not_intrinsic. + unsigned HasLLVMReservedName : 1; + + /// If true then there is a definition within the same linkage unit and that + /// definition cannot be runtime preempted. + unsigned IsDSOLocal : 1; + + private: + // Give subclasses access to what otherwise would be wasted padding. + // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32. + unsigned SubClassData : GlobalValueSubClassDataBits; + + friend class Constant; + + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To); + + /// Returns true if the definition of this global may be replaced by a + /// differently optimized variant of the same source level function at link + /// time. + bool mayBeDerefined() const { + switch (getLinkage()) { + case WeakODRLinkage: + case LinkOnceODRLinkage: + case AvailableExternallyLinkage: + return true; + + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return isInterposable(); + } + + llvm_unreachable("Fully covered switch above!"); + } + + void maybeSetDsoLocal() { + if (hasLocalLinkage() || + (!hasDefaultVisibility() && !hasExternalWeakLinkage())) + setDSOLocal(true); + } + + protected: + /// The intrinsic ID for this subclass (which must be a Function). + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their intrinsic ID, if they have one. + /// + /// This is stored here to save space in Function on 64-bit hosts. + Intrinsic::ID IntID; + + unsigned getGlobalValueSubClassData() const { + return SubClassData; + } + void setGlobalValueSubClassData(unsigned V) { + assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit"); + SubClassData = V; + } + + Module *Parent; // The containing module. + + // Used by SymbolTableListTraits. + void setParent(Module *parent) { + Parent = parent; + } + + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + public: + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + + GlobalValue(const GlobalValue &) = delete; + + unsigned getAlignment() const; + unsigned getAddressSpace() const; + + enum class UnnamedAddr { + None, + Local, + Global, + }; + + bool hasGlobalUnnamedAddr() const { + return getUnnamedAddr() == UnnamedAddr::Global; + } + + /// Returns true if this value's address is not significant in this module. + /// This attribute is intended to be used only by the code generator and LTO + /// to allow the linker to decide whether the global needs to be in the symbol + /// table. It should probably not be used in optimizations, as the value may + /// have uses outside the module; use hasGlobalUnnamedAddr() instead. + bool hasAtLeastLocalUnnamedAddr() const { + return getUnnamedAddr() != UnnamedAddr::None; + } + + UnnamedAddr getUnnamedAddr() const { + return UnnamedAddr(UnnamedAddrVal); + } + void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } + + static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { + if (A == UnnamedAddr::None || B == UnnamedAddr::None) + return UnnamedAddr::None; + if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) + return UnnamedAddr::Local; + return UnnamedAddr::Global; + } + + bool hasComdat() const { return getComdat() != nullptr; } + const Comdat *getComdat() const; + Comdat *getComdat() { + return const_cast( + static_cast(this)->getComdat()); + } + + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } + bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { + assert((!hasLocalLinkage() || V == DefaultVisibility) && + "local linkage requires default visibility"); + Visibility = V; + maybeSetDsoLocal(); + } + ++#if INTEL_COLLAB ++ bool isThreadPrivate() const { return ThreadPrivate; } ++ void setThreadPrivate(bool Val) { ThreadPrivate = Val; } ++ ++ bool isTargetDeclare() const { return TargetDeclare; } ++ void setTargetDeclare(bool Val) { TargetDeclare = Val; } ++#endif // INTEL_COLLAB + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } + void setThreadLocal(bool Val) { + setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); + } + void setThreadLocalMode(ThreadLocalMode Val) { + assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); + ThreadLocal = Val; + } + ThreadLocalMode getThreadLocalMode() const { + return static_cast(ThreadLocal); + } + + DLLStorageClassTypes getDLLStorageClass() const { + return DLLStorageClassTypes(DllStorageClass); + } + bool hasDLLImportStorageClass() const { + return DllStorageClass == DLLImportStorageClass; + } + bool hasDLLExportStorageClass() const { + return DllStorageClass == DLLExportStorageClass; + } + void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } + + bool hasSection() const { return !getSection().empty(); } + StringRef getSection() const; + + /// Global values are always pointers. + PointerType *getType() const { return cast(User::getType()); } + + Type *getValueType() const { return ValueType; } + + void setDSOLocal(bool Local) { IsDSOLocal = Local; } + + bool isDSOLocal() const { + return IsDSOLocal; + } + + static LinkageTypes getLinkOnceLinkage(bool ODR) { + return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; + } + static LinkageTypes getWeakLinkage(bool ODR) { + return ODR ? WeakODRLinkage : WeakAnyLinkage; + } + + static bool isExternalLinkage(LinkageTypes Linkage) { + return Linkage == ExternalLinkage; + } + static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { + return Linkage == AvailableExternallyLinkage; + } + static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRLinkage; + } + static bool isLinkOnceLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; + } + static bool isWeakAnyLinkage(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage; + } + static bool isWeakODRLinkage(LinkageTypes Linkage) { + return Linkage == WeakODRLinkage; + } + static bool isWeakLinkage(LinkageTypes Linkage) { + return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage); + } + static bool isAppendingLinkage(LinkageTypes Linkage) { + return Linkage == AppendingLinkage; + } + static bool isInternalLinkage(LinkageTypes Linkage) { + return Linkage == InternalLinkage; + } + static bool isPrivateLinkage(LinkageTypes Linkage) { + return Linkage == PrivateLinkage; + } + static bool isLocalLinkage(LinkageTypes Linkage) { + return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage); + } + static bool isExternalWeakLinkage(LinkageTypes Linkage) { + return Linkage == ExternalWeakLinkage; + } + static bool isCommonLinkage(LinkageTypes Linkage) { + return Linkage == CommonLinkage; + } + static bool isValidDeclarationLinkage(LinkageTypes Linkage) { + return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage); + } + + /// Whether the definition of this global may be replaced by something + /// non-equivalent at link time. For example, if a function has weak linkage + /// then the code defining it may be replaced by different code. + static bool isInterposableLinkage(LinkageTypes Linkage) { + switch (Linkage) { + case WeakAnyLinkage: + case LinkOnceAnyLinkage: + case CommonLinkage: + case ExternalWeakLinkage: + return true; + + case AvailableExternallyLinkage: + case LinkOnceODRLinkage: + case WeakODRLinkage: + // The above three cannot be overridden but can be de-refined. + + case ExternalLinkage: + case AppendingLinkage: + case InternalLinkage: + case PrivateLinkage: + return false; + } + llvm_unreachable("Fully covered switch above!"); + } + + /// Whether the definition of this global may be discarded if it is not used + /// in its compilation unit. + static bool isDiscardableIfUnused(LinkageTypes Linkage) { + return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage) || + isAvailableExternallyLinkage(Linkage); + } + + /// Whether the definition of this global may be replaced at link time. NB: + /// Using this method outside of the code generators is almost always a + /// mistake: when working at the IR level use isInterposable instead as it + /// knows about ODR semantics. + static bool isWeakForLinker(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; + } + + /// Return true if the currently visible definition of this global (if any) is + /// exactly the definition we will see at runtime. + /// + /// Non-exact linkage types inhibits most non-inlining IPO, since a + /// differently optimized variant of the same function can have different + /// observable or undefined behavior than in the variant currently visible. + /// For instance, we could have started with + /// + /// void foo(int *v) { + /// int t = 5 / v[0]; + /// (void) t; + /// } + /// + /// and "refined" it to + /// + /// void foo(int *v) { } + /// + /// However, we cannot infer readnone for `foo`, since that would justify + /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause + /// undefined behavior if the linker replaces the actual call destination with + /// the unoptimized `foo`. + /// + /// Inlining is okay across non-exact linkage types as long as they're not + /// interposable (see \c isInterposable), since in such cases the currently + /// visible variant is *a* correct implementation of the original source + /// function; it just isn't the *only* correct implementation. + bool isDefinitionExact() const { + return !mayBeDerefined(); + } + + /// Return true if this global has an exact defintion. + bool hasExactDefinition() const { + // While this computes exactly the same thing as + // isStrongDefinitionForLinker, the intended uses are different. This + // function is intended to help decide if specific inter-procedural + // transforms are correct, while isStrongDefinitionForLinker's intended use + // is in low level code generation. + return !isDeclaration() && isDefinitionExact(); + } + + /// Return true if this global's definition can be substituted with an + /// *arbitrary* definition at link time. We cannot do any IPO or inlinining + /// across interposable call edges, since the callee can be replaced with + /// something arbitrary at link time. + bool isInterposable() const { return isInterposableLinkage(getLinkage()); } + + bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); } + bool hasAvailableExternallyLinkage() const { + return isAvailableExternallyLinkage(getLinkage()); + } + bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); } + bool hasLinkOnceODRLinkage() const { + return isLinkOnceODRLinkage(getLinkage()); + } + bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); } + bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); } + bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); } + bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); } + bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); } + bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); } + bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); } + bool hasExternalWeakLinkage() const { + return isExternalWeakLinkage(getLinkage()); + } + bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); } + bool hasValidDeclarationLinkage() const { + return isValidDeclarationLinkage(getLinkage()); + } + + void setLinkage(LinkageTypes LT) { + if (isLocalLinkage(LT)) + Visibility = DefaultVisibility; + Linkage = LT; + maybeSetDsoLocal(); + } + LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } + + bool isDiscardableIfUnused() const { + return isDiscardableIfUnused(getLinkage()); + } + + bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } + + protected: + /// Copy all additional attributes (those not needed to create a GlobalValue) + /// from the GlobalValue Src to this one. + void copyAttributesFrom(const GlobalValue *Src); + + public: + /// If the given string begins with the GlobalValue name mangling escape + /// character '\1', drop it. + /// + /// This function applies a specific mangling that is used in PGO profiles, + /// among other things. If you're trying to get a symbol name for an + /// arbitrary GlobalValue, this is not the function you're looking for; see + /// Mangler.h. + static StringRef dropLLVMManglingEscape(StringRef Name) { + if (!Name.empty() && Name[0] == '\1') + return Name.substr(1); + return Name; + } + + /// Return the modified name for a global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + /// The value's original name is \c Name and has linkage of type + /// \c Linkage. The value is defined in module \c FileName. + static std::string getGlobalIdentifier(StringRef Name, + GlobalValue::LinkageTypes Linkage, + StringRef FileName); + + /// Return the modified name for this global value suitable to be + /// used as the key for a global lookup (e.g. profile or ThinLTO). + std::string getGlobalIdentifier() const; + + /// Declare a type to represent a global unique identifier for a global value. + /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact + /// unique way to identify a symbol. + using GUID = uint64_t; + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } + + /// Return a 64-bit global unique ID constructed from global value name + /// (i.e. returned by getGlobalIdentifier()). + GUID getGUID() const { return getGUID(getGlobalIdentifier()); } + + /// @name Materialization + /// Materialization is used to construct functions only as they're needed. + /// This + /// is useful to reduce memory usage in LLVM or parsing work done by the + /// BitcodeReader to load the Module. + /// @{ + + /// If this function's Module is being lazily streamed in functions from disk + /// or some other source, this method can be used to check to see if the + /// function has been read in yet or not. + bool isMaterializable() const; + + /// Make sure this GlobalValue is fully read. + Error materialize(); + + /// @} + + /// Return true if the primary definition of this global value is outside of + /// the current translation unit. + bool isDeclaration() const; + + bool isDeclarationForLinker() const { + if (hasAvailableExternallyLinkage()) + return true; + + return isDeclaration(); + } + + /// Returns true if this global's definition will be the one chosen by the + /// linker. + /// + /// NB! Ideally this should not be used at the IR level at all. If you're + /// interested in optimization constraints implied by the linker's ability to + /// choose an implementation, prefer using \c hasExactDefinition. + bool isStrongDefinitionForLinker() const { + return !(isDeclarationForLinker() || isWeakForLinker()); + } + + // Returns true if the alignment of the value can be unilaterally + // increased. + bool canIncreaseAlignment() const; + + const GlobalObject *getBaseObject() const; + GlobalObject *getBaseObject() { + return const_cast( + static_cast(this)->getBaseObject()); + } + + /// Returns whether this is a reference to an absolute symbol. + bool isAbsoluteSymbolRef() const; + + /// If this is an absolute symbol reference, returns the range of the symbol, + /// otherwise returns None. + Optional getAbsoluteSymbolRange() const; + + /// This method unlinks 'this' from the containing module, but does not delete + /// it. + void removeFromParent(); + + /// This method unlinks 'this' from the containing module and deletes it. + void eraseFromParent(); + + /// Get the module that this global value is contained inside of... + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal || + V->getValueID() == Value::GlobalIFuncVal; + } + + /// True if GV can be left out of the object symbol table. This is the case + /// for linkonce_odr values whose address is not significant. While legal, it + /// is not normally profitable to omit them from the .o symbol table. Using + /// this analysis makes sense when the information can be passed down to the + /// linker or we are in LTO. + bool canBeOmittedFromSymbolTable() const; + }; + + } // end namespace llvm + + #endif // LLVM_IR_GLOBALVALUE_H +diff --git a/llvm/include/llvm/IR/Intel_Directives.td b/llvm/include/llvm/IR/Intel_Directives.td +new file mode 100644 +index 0000000..960704f +--- /dev/null ++++ b/llvm/include/llvm/IR/Intel_Directives.td +@@ -0,0 +1,254 @@ ++// INTEL_COLLAB -*- tablegen -*- ++//==- Intel_Directives.td - Defines all parallelization and -*- tablegen -*-==// ++// vectorization directives and clauses. ++// ++// Copyright (C) 2016 Intel Corporation. All rights reserved. ++// ++// The information and source code contained herein is the exclusive property ++// of Intel Corporation and may not be disclosed, examined or reproduced in ++// whole or in part without explicit written authorization from the company. ++// ++// ===--------------------------------------------------------------------=== // ++/// ++/// \file ++/// This file defines the classes used to represent parallelization and ++/// vectorization directives and clauses. Each different type of directive and ++/// clause is then instantiated accordingly. TableGen parses these records and ++/// generates enums for both classes, as well as tables which provide an ++/// enum->string and string->enum mapping. The enums and tables are used to ++/// generate Metadata strings that are used as arguments to llvm.directive ++/// intrinsics. These intrinsics are used to mark parallel/vector constructs ++/// and behavior. ++/// ++// ===--------------------------------------------------------------------=== // ++ ++// The Directive class represents all parallel/vector constructs that can be ++// represented within LLVM IR. For example, the "#pragma omp parallel" ++// directive for OpenMP. ++class Directive; ++ ++// The Clause class represents additional information provided to Directives ++// that can be used to control parallel/vector execution. For example, ++// "#pragma omp parallel" could be modified to include the "if (expr)" clause ++// to determine if the region should be executed in parallel or not. ++class Clause; ++ ++// For additional information on the supported Directives and Clauses, please ++// refer to the following documentation. Currently, this file defines only ++// the directives and clauses associated with OpenMP, but will be extended in ++// the future for other parallel/vector programming models and APIs. ++// ++// http://openmp.org/wp/openmp-specifications ++ ++// *** Begin OpenMP Directives *** ++ ++def "DIR.OMP.PARALLEL" : Directive; ++def "DIR.OMP.END.PARALLEL" : Directive; ++ ++def "DIR.OMP.LOOP" : Directive; ++def "DIR.OMP.END.LOOP" : Directive; ++ ++def "DIR.OMP.PARALLEL.LOOP" : Directive; ++def "DIR.OMP.END.PARALLEL.LOOP" : Directive; ++ ++def "DIR.OMP.SECTIONS" : Directive; ++def "DIR.OMP.END.SECTIONS" : Directive; ++ ++def "DIR.OMP.PARALLEL.SECTIONS" : Directive; ++def "DIR.OMP.END.PARALLEL.SECTIONS" : Directive; ++ ++def "DIR.OMP.WORKSHARE" : Directive; ++def "DIR.OMP.END.WORKSHARE" : Directive; ++ ++def "DIR.OMP.PARALLEL.WORKSHARE" : Directive; ++def "DIR.OMP.END.PARALLEL.WORKSHARE" : Directive; ++ ++def "DIR.OMP.SECTION" : Directive; ++def "DIR.OMP.END.SECTION" : Directive; ++ ++def "DIR.OMP.SINGLE" : Directive; ++def "DIR.OMP.END.SINGLE" : Directive; ++ ++def "DIR.OMP.TASK" : Directive; ++def "DIR.OMP.END.TASK" : Directive; ++ ++def "DIR.OMP.MASTER" : Directive; ++def "DIR.OMP.END.MASTER" : Directive; ++ ++def "DIR.OMP.CRITICAL" : Directive; ++def "DIR.OMP.END.CRITICAL" : Directive; ++ ++def "DIR.OMP.BARRIER" : Directive; ++def "DIR.OMP.END.BARRIER" : Directive; ++ ++def "DIR.OMP.TASKWAIT" : Directive; ++def "DIR.OMP.END.TASKWAIT" : Directive; ++ ++def "DIR.OMP.TASKYIELD" : Directive; ++def "DIR.OMP.END.TASKYIELD" : Directive; ++ ++def "DIR.OMP.ATOMIC" : Directive; ++def "DIR.OMP.END.ATOMIC" : Directive; ++ ++def "DIR.OMP.FLUSH" : Directive; ++def "DIR.OMP.END.FLUSH" : Directive; ++ ++def "DIR.OMP.THREADPRIVATE" : Directive; ++ ++def "DIR.OMP.ORDERED" : Directive; ++def "DIR.OMP.END.ORDERED" : Directive; ++ ++def "DIR.OMP.SIMD" : Directive; ++def "DIR.OMP.END.SIMD" : Directive; ++ ++def "DIR.OMP.TASKGROUP" : Directive; ++def "DIR.OMP.END.TASKGROUP" : Directive; ++ ++def "DIR.OMP.TASKLOOP" : Directive; ++def "DIR.OMP.END.TASKLOOP" : Directive; ++ ++def "DIR.OMP.TARGET" : Directive; ++def "DIR.OMP.END.TARGET" : Directive; ++ ++def "DIR.OMP.TARGET.DATA" : Directive; ++def "DIR.OMP.END.TARGET.DATA" : Directive; ++ ++def "DIR.OMP.TARGET.UPDATE" : Directive; ++def "DIR.OMP.END.TARGET.UPDATE" : Directive; ++ ++def "DIR.OMP.TEAMS" : Directive; ++def "DIR.OMP.END.TEAMS" : Directive; ++ ++def "DIR.OMP.DISTRIBUTE" : Directive; ++def "DIR.OMP.END.DISTRIBUTE" : Directive; ++ ++def "DIR.OMP.DISTRIBUTE.PARLOOP" : Directive; ++def "DIR.OMP.END.DISTRIBUTE.PARLOOP" : Directive; ++ ++def "DIR.OMP.TARGET.ENTER.DATA" : Directive; ++def "DIR.OMP.END.TARGET.ENTER.DATA" : Directive; ++ ++def "DIR.OMP.TARGET.EXIT.DATA" : Directive; ++def "DIR.OMP.END.TARGET.EXIT.DATA" : Directive; ++ ++def "DIR.OMP.CANCEL" : Directive; ++def "DIR.OMP.END.CANCEL" : Directive; ++ ++def "DIR.OMP.CANCELLATION.POINT" : Directive; ++def "DIR.OMP.END.CANCELLATION.POINT" : Directive; ++ ++ ++// *** Begin OpenMP Clauses *** ++ ++def "QUAL.OMP.DEFAULT.NONE" : Clause; ++def "QUAL.OMP.DEFAULT.SHARED" : Clause; ++def "QUAL.OMP.DEFAULT.PRIVATE" : Clause; ++def "QUAL.OMP.DEFAULT.FIRSTPRIVATE" : Clause; ++def "QUAL.OMP.MERGEABLE" : Clause; ++def "QUAL.OMP.NOWAIT" : Clause; ++def "QUAL.OMP.NOGROUP" : Clause; ++def "QUAL.OMP.UNTIED" : Clause; ++def "QUAL.OMP.READ" : Clause; ++def "QUAL.OMP.READ.SEQ_CST" : Clause; ++def "QUAL.OMP.WRITE" : Clause; ++def "QUAL.OMP.WRITE.SEQ_CST" : Clause; ++def "QUAL.OMP.UPDATE" : Clause; ++def "QUAL.OMP.UPDATE.SEQ_CST" : Clause; ++def "QUAL.OMP.CAPTURE" : Clause; ++def "QUAL.OMP.CAPTURE.SEQ_CST" : Clause; ++def "QUAL.OMP.PROC.BIND.MASTER" : Clause; ++def "QUAL.OMP.PROC.BIND.CLOSE" : Clause; ++def "QUAL.OMP.PROC.BIND.SPREAD" : Clause; ++def "QUAL.OMP.IF" : Clause; ++def "QUAL.OMP.COLLAPSE" : Clause; ++def "QUAL.OMP.NUM_THREADS" : Clause; ++def "QUAL.OMP.ORDERED" : Clause; ++def "QUAL.OMP.SAFELEN" : Clause; ++def "QUAL.OMP.SIMDLEN" : Clause; ++def "QUAL.OMP.FINAL" : Clause; ++def "QUAL.OMP.GRAINSIZE" : Clause; ++def "QUAL.OMP.NUM_TASKS" : Clause; ++def "QUAL.OMP.PRIORITY" : Clause; ++def "QUAL.OMP.NUM_TEAMS" : Clause; ++def "QUAL.OMP.THREAD_LIMIT" : Clause; ++def "QUAL.OMP.DIST_SCHEDULE.STATIC" : Clause; ++def "QUAL.OMP.SCHEDULE.STATIC" : Clause; ++def "QUAL.OMP.SCHEDULE.DYNAMIC" : Clause; ++def "QUAL.OMP.SCHEDULE.GUIDED" : Clause; ++def "QUAL.OMP.SCHEDULE.AUTO" : Clause; ++def "QUAL.OMP.SCHEDULE.RUNTIME" : Clause; ++def "QUAL.OMP.SHARED" : Clause; ++def "QUAL.OMP.PRIVATE" : Clause; ++def "QUAL.OMP.FIRSTPRIVATE" : Clause; ++def "QUAL.OMP.LASTPRIVATE" : Clause; ++def "QUAL.OMP.COPYIN" : Clause; ++def "QUAL.OMP.COPYPRIVATE" : Clause; ++def "QUAL.OMP.REDUCTION.ADD" : Clause; ++def "QUAL.OMP.REDUCTION.SUB" : Clause; ++def "QUAL.OMP.REDUCTION.MUL" : Clause; ++def "QUAL.OMP.REDUCTION.AND" : Clause; ++def "QUAL.OMP.REDUCTION.OR" : Clause; ++def "QUAL.OMP.REDUCTION.BXOR" : Clause; ++def "QUAL.OMP.REDUCTION.BAND" : Clause; ++def "QUAL.OMP.REDUCTION.BOR" : Clause; ++def "QUAL.OMP.REDUCTION.MAX" : Clause; ++def "QUAL.OMP.REDUCTION.MIN" : Clause; ++def "QUAL.OMP.REDUCTION.UDR" : Clause; ++def "QUAL.OMP.INREDUCTION.ADD" : Clause; ++def "QUAL.OMP.INREDUCTION.SUB" : Clause; ++def "QUAL.OMP.INREDUCTION.MUL" : Clause; ++def "QUAL.OMP.INREDUCTION.AND" : Clause; ++def "QUAL.OMP.INREDUCTION.OR" : Clause; ++def "QUAL.OMP.INREDUCTION.BXOR" : Clause; ++def "QUAL.OMP.INREDUCTION.BAND" : Clause; ++def "QUAL.OMP.INREDUCTION.BOR" : Clause; ++def "QUAL.OMP.INREDUCTION.MAX" : Clause; ++def "QUAL.OMP.INREDUCTION.MIN" : Clause; ++def "QUAL.OMP.INREDUCTION.UDR" : Clause; ++def "QUAL.OMP.TO" : Clause; ++def "QUAL.OMP.FROM" : Clause; ++def "QUAL.OMP.LINEAR" : Clause; ++def "QUAL.OMP.UNIFORM" : Clause; ++def "QUAL.OMP.ALIGNED" : Clause; ++def "QUAL.OMP.FLUSH" : Clause; ++def "QUAL.OMP.THREADPRIVATE" : Clause; ++def "QUAL.OMP.DEVICE" : Clause; ++def "QUAL.OMP.IS_DEVICE_PTR" : Clause; ++def "QUAL.OMP.USE_DEVICE_PTR" : Clause; ++def "QUAL.OMP.DEFAULTMAP.TOFROM.SCALAR" : Clause; ++def "QUAL.OMP.MAP.TO" : Clause; ++def "QUAL.OMP.MAP.FROM" : Clause; ++def "QUAL.OMP.MAP.TOFROM" : Clause; ++def "QUAL.OMP.MAP.ALLOC" : Clause; ++def "QUAL.OMP.MAP.RELEASE" : Clause; ++def "QUAL.OMP.MAP.DELETE" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.TO" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.FROM" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.TOFROM" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.ALLOC" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.RELEASE" : Clause; ++def "QUAL.OMP.MAP.ALWAYS.DELETE" : Clause; ++def "QUAL.OMP.DEPEND.IN" : Clause; ++def "QUAL.OMP.DEPEND.OUT" : Clause; ++def "QUAL.OMP.DEPEND.INOUT" : Clause; ++def "QUAL.OMP.DEPEND.SOURCE" : Clause; ++def "QUAL.OMP.DEPEND.SINK" : Clause; ++def "QUAL.OMP.ORDERED.THREADS" : Clause; ++def "QUAL.OMP.ORDERED.SIMD" : Clause; ++def "QUAL.OMP.CANCEL.PARALLEL" : Clause; ++def "QUAL.OMP.CANCEL.LOOP" : Clause; ++def "QUAL.OMP.CANCEL.SECTIONS" : Clause; ++def "QUAL.OMP.CANCEL.TASKGROUP" : Clause; ++def "QUAL.OMP.HINT" : Clause; ++def "QUAL.OMP.NAME" : Clause; ++ ++// *** Begin Auxiliary Clauses *** ++// These "clauses" don't correspond to actual OpenMP clauses, but are used ++// to carry additional information ++ ++def "QUAL.OMP.NORMALIZED.IV" : Clause; ++def "QUAL.OMP.NORMALIZED.UB" : Clause; ++def "QUAL.OMP.CANCELLATION.POINTS" : Clause; ++def "QUAL.OMP.OFFLOAD.ENTRY.IDX" : Clause; ++ ++// end INTEL_COLLAB +diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td +index b26a26f..33ac71f 100644 +--- a/llvm/include/llvm/IR/Intrinsics.td ++++ b/llvm/include/llvm/IR/Intrinsics.td +@@ -1,1187 +1,1217 @@ + //===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// + // + // 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 properties of all LLVM intrinsics. + // + //===----------------------------------------------------------------------===// + + include "llvm/CodeGen/ValueTypes.td" + include "llvm/CodeGen/SDNodeProperties.td" + + //===----------------------------------------------------------------------===// + // Properties we keep track of for intrinsics. + //===----------------------------------------------------------------------===// + + class IntrinsicProperty; + + // Intr*Mem - Memory properties. If no property is set, the worst case + // is assumed (it may read and write any memory it can get access to and it may + // have other side effects). + + // IntrNoMem - The intrinsic does not access memory or have any other side + // effects. It may be CSE'd deleted if dead, etc. + def IntrNoMem : IntrinsicProperty; + + // IntrReadMem - This intrinsic only reads from memory. It does not write to + // memory and has no other side effects. Therefore, it cannot be moved across + // potentially aliasing stores. However, it can be reordered otherwise and can + // be deleted if dead. + def IntrReadMem : IntrinsicProperty; + + // IntrWriteMem - This intrinsic only writes to memory, but does not read from + // memory, and has no other side effects. This means dead stores before calls + // to this intrinsics may be removed. + def IntrWriteMem : IntrinsicProperty; + + // IntrArgMemOnly - This intrinsic only accesses memory that its pointer-typed + // argument(s) points to, but may access an unspecified amount. Other than + // reads from and (possibly volatile) writes to memory, it has no side effects. + def IntrArgMemOnly : IntrinsicProperty; + + // IntrInaccessibleMemOnly -- This intrinsic only accesses memory that is not + // accessible by the module being compiled. This is a weaker form of IntrNoMem. + def IntrInaccessibleMemOnly : IntrinsicProperty; + + // IntrInaccessibleMemOrArgMemOnly -- This intrinsic only accesses memory that + // its pointer-typed arguments point to or memory that is not accessible + // by the module being compiled. This is a weaker form of IntrArgMemOnly. + def IntrInaccessibleMemOrArgMemOnly : IntrinsicProperty; + + // Commutative - This intrinsic is commutative: X op Y == Y op X. + def Commutative : IntrinsicProperty; + + // Throws - This intrinsic can throw. + def Throws : IntrinsicProperty; + + // NoCapture - The specified argument pointer is not captured by the intrinsic. + class NoCapture : IntrinsicProperty { + int ArgNo = argNo; + } + + // Returned - The specified argument is always the return value of the + // intrinsic. + class Returned : IntrinsicProperty { + int ArgNo = argNo; + } + + // ImmArg - The specified argument must be an immediate. + class ImmArg : IntrinsicProperty { + int ArgNo = argNo; + } + + // ReadOnly - The specified argument pointer is not written to through the + // pointer by the intrinsic. + class ReadOnly : IntrinsicProperty { + int ArgNo = argNo; + } + + // WriteOnly - The intrinsic does not read memory through the specified + // argument pointer. + class WriteOnly : IntrinsicProperty { + int ArgNo = argNo; + } + + // ReadNone - The specified argument pointer is not dereferenced by the + // intrinsic. + class ReadNone : IntrinsicProperty { + int ArgNo = argNo; + } + + def IntrNoReturn : IntrinsicProperty; + + // IntrCold - Calls to this intrinsic are cold. + // Parallels the cold attribute on LLVM IR functions. + def IntrCold : IntrinsicProperty; + + // IntrNoduplicate - Calls to this intrinsic cannot be duplicated. + // Parallels the noduplicate attribute on LLVM IR functions. + def IntrNoDuplicate : IntrinsicProperty; + + // IntrConvergent - Calls to this intrinsic are convergent and may not be made + // control-dependent on any additional values. + // Parallels the convergent attribute on LLVM IR functions. + def IntrConvergent : IntrinsicProperty; + + // This property indicates that the intrinsic is safe to speculate. + def IntrSpeculatable : IntrinsicProperty; + + // This property can be used to override the 'has no other side effects' + // language of the IntrNoMem, IntrReadMem, IntrWriteMem, and IntrArgMemOnly + // intrinsic properties. By default, intrinsics are assumed to have side + // effects, so this property is only necessary if you have defined one of + // the memory properties listed above. + // For this property, 'side effects' has the same meaning as 'side effects' + // defined by the hasSideEffects property of the TableGen Instruction class. + def IntrHasSideEffects : IntrinsicProperty; + + //===----------------------------------------------------------------------===// + // Types used by intrinsics. + //===----------------------------------------------------------------------===// + + class LLVMType { + ValueType VT = vt; + int isAny = 0; + } + + class LLVMQualPointerType + : LLVMType{ + LLVMType ElTy = elty; + int AddrSpace = addrspace; + } + + class LLVMPointerType + : LLVMQualPointerType; + + class LLVMAnyPointerType + : LLVMType{ + LLVMType ElTy = elty; + + let isAny = 1; + } + + // Match the type of another intrinsic parameter. Number is an index into the + // list of overloaded types for the intrinsic, excluding all the fixed types. + // The Number value must refer to a previously listed type. For example: + // Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> + // has two overloaded types, the 2nd and 3rd arguments. LLVMMatchType<0> + // refers to the first overloaded type, which is the 2nd argument. + class LLVMMatchType + : LLVMType{ + int Number = num; + } + + // Match the type of another intrinsic parameter that is expected to be based on + // an integral type (i.e. either iN or ), but change the scalar size to + // be twice as wide or half as wide as the other type. This is only useful when + // the intrinsic is overloaded, so the matched type should be declared as iAny. + class LLVMExtendedType : LLVMMatchType; + class LLVMTruncatedType : LLVMMatchType; + + // Match the scalar/vector of another intrinsic parameter but with a different + // element type. Either both are scalars or both are vectors with the same + // number of elements. + class LLVMScalarOrSameVectorWidth + : LLVMMatchType { + ValueType ElTy = elty.VT; + } + + class LLVMPointerTo : LLVMMatchType; + class LLVMPointerToElt : LLVMMatchType; + class LLVMVectorOfAnyPointersToElt : LLVMMatchType; + + // Match the type of another intrinsic parameter that is expected to be a + // vector type, but change the element count to be half as many + class LLVMHalfElementsVectorType : LLVMMatchType; + + def llvm_void_ty : LLVMType; + let isAny = 1 in { + def llvm_any_ty : LLVMType; + def llvm_anyint_ty : LLVMType; + def llvm_anyfloat_ty : LLVMType; + def llvm_anyvector_ty : LLVMType; + } + def llvm_i1_ty : LLVMType; + def llvm_i8_ty : LLVMType; + def llvm_i16_ty : LLVMType; + def llvm_i32_ty : LLVMType; + def llvm_i64_ty : LLVMType; + def llvm_half_ty : LLVMType; + def llvm_float_ty : LLVMType; + def llvm_double_ty : LLVMType; + def llvm_f80_ty : LLVMType; + def llvm_f128_ty : LLVMType; + def llvm_ppcf128_ty : LLVMType; + def llvm_ptr_ty : LLVMPointerType; // i8* + def llvm_ptrptr_ty : LLVMPointerType; // i8** + def llvm_anyptr_ty : LLVMAnyPointerType; // (space)i8* + def llvm_empty_ty : LLVMType; // { } + def llvm_descriptor_ty : LLVMPointerType; // { }* + def llvm_metadata_ty : LLVMType; // !{...} + def llvm_token_ty : LLVMType; // token + + def llvm_x86mmx_ty : LLVMType; + def llvm_ptrx86mmx_ty : LLVMPointerType; // <1 x i64>* + + def llvm_v2i1_ty : LLVMType; // 2 x i1 + def llvm_v4i1_ty : LLVMType; // 4 x i1 + def llvm_v8i1_ty : LLVMType; // 8 x i1 + def llvm_v16i1_ty : LLVMType; // 16 x i1 + def llvm_v32i1_ty : LLVMType; // 32 x i1 + def llvm_v64i1_ty : LLVMType; // 64 x i1 + def llvm_v512i1_ty : LLVMType; // 512 x i1 + def llvm_v1024i1_ty : LLVMType; //1024 x i1 + + def llvm_v1i8_ty : LLVMType; // 1 x i8 + def llvm_v2i8_ty : LLVMType; // 2 x i8 + def llvm_v4i8_ty : LLVMType; // 4 x i8 + def llvm_v8i8_ty : LLVMType; // 8 x i8 + def llvm_v16i8_ty : LLVMType; // 16 x i8 + def llvm_v32i8_ty : LLVMType; // 32 x i8 + def llvm_v64i8_ty : LLVMType; // 64 x i8 + def llvm_v128i8_ty : LLVMType; //128 x i8 + def llvm_v256i8_ty : LLVMType; //256 x i8 + + def llvm_v1i16_ty : LLVMType; // 1 x i16 + def llvm_v2i16_ty : LLVMType; // 2 x i16 + def llvm_v4i16_ty : LLVMType; // 4 x i16 + def llvm_v8i16_ty : LLVMType; // 8 x i16 + def llvm_v16i16_ty : LLVMType; // 16 x i16 + def llvm_v32i16_ty : LLVMType; // 32 x i16 + def llvm_v64i16_ty : LLVMType; // 64 x i16 + def llvm_v128i16_ty : LLVMType; //128 x i16 + + def llvm_v1i32_ty : LLVMType; // 1 x i32 + def llvm_v2i32_ty : LLVMType; // 2 x i32 + def llvm_v4i32_ty : LLVMType; // 4 x i32 + def llvm_v8i32_ty : LLVMType; // 8 x i32 + def llvm_v16i32_ty : LLVMType; // 16 x i32 + def llvm_v32i32_ty : LLVMType; // 32 x i32 + def llvm_v64i32_ty : LLVMType; // 64 x i32 + + def llvm_v1i64_ty : LLVMType; // 1 x i64 + def llvm_v2i64_ty : LLVMType; // 2 x i64 + def llvm_v4i64_ty : LLVMType; // 4 x i64 + def llvm_v8i64_ty : LLVMType; // 8 x i64 + def llvm_v16i64_ty : LLVMType; // 16 x i64 + def llvm_v32i64_ty : LLVMType; // 32 x i64 + + def llvm_v1i128_ty : LLVMType; // 1 x i128 + + def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) + def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) + def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) + def llvm_v1f32_ty : LLVMType; // 1 x float + def llvm_v2f32_ty : LLVMType; // 2 x float + def llvm_v4f32_ty : LLVMType; // 4 x float + def llvm_v8f32_ty : LLVMType; // 8 x float + def llvm_v16f32_ty : LLVMType; // 16 x float + def llvm_v1f64_ty : LLVMType; // 1 x double + def llvm_v2f64_ty : LLVMType; // 2 x double + def llvm_v4f64_ty : LLVMType; // 4 x double + def llvm_v8f64_ty : LLVMType; // 8 x double + + def llvm_vararg_ty : LLVMType; // this means vararg here + + //===----------------------------------------------------------------------===// + // Intrinsic Definitions. + //===----------------------------------------------------------------------===// + + // Intrinsic class - This is used to define one LLVM intrinsic. The name of the + // intrinsic definition should start with "int_", then match the LLVM intrinsic + // name with the "llvm." prefix removed, and all "."s turned into "_"s. For + // example, llvm.bswap.i16 -> int_bswap_i16. + // + // * RetTypes is a list containing the return types expected for the + // intrinsic. + // * ParamTypes is a list containing the parameter types expected for the + // intrinsic. + // * Properties can be set to describe the behavior of the intrinsic. + // + class Intrinsic ret_types, + list param_types = [], + list intr_properties = [], + string name = "", + list sd_properties = []> : SDPatternOperator { + string LLVMName = name; + string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. + list RetTypes = ret_types; + list ParamTypes = param_types; + list IntrProperties = intr_properties; + let Properties = sd_properties; + + bit isTarget = 0; + } + + /// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this + /// specifies the name of the builtin. This provides automatic CBE and CFE + /// support. + class GCCBuiltin { + string GCCBuiltinName = name; + } + + class MSBuiltin { + string MSBuiltinName = name; + } + + + //===--------------- Variable Argument Handling Intrinsics ----------------===// + // + + def int_vastart : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; + def int_vacopy : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], + "llvm.va_copy">; + def int_vaend : Intrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; + + //===------------------- Garbage Collection Intrinsics --------------------===// + // + def int_gcroot : Intrinsic<[], + [llvm_ptrptr_ty, llvm_ptr_ty]>; + def int_gcread : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadMem, IntrArgMemOnly]>; + def int_gcwrite : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], + [IntrArgMemOnly, NoCapture<1>, NoCapture<2>]>; + + //===------------------- ObjC ARC runtime Intrinsics --------------------===// + // + // Note these are to support the Objective-C ARC optimizer which wants to + // eliminate retain and releases where possible. + + def int_objc_autorelease : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_autoreleasePoolPop : Intrinsic<[], [llvm_ptr_ty]>; + def int_objc_autoreleasePoolPush : Intrinsic<[llvm_ptr_ty], []>; + def int_objc_autoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_copyWeak : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + def int_objc_destroyWeak : Intrinsic<[], [llvm_ptrptr_ty]>; + def int_objc_initWeak : Intrinsic<[llvm_ptr_ty], + [llvm_ptrptr_ty, + llvm_ptr_ty]>; + def int_objc_loadWeak : Intrinsic<[llvm_ptr_ty], + [llvm_ptrptr_ty]>; + def int_objc_loadWeakRetained : Intrinsic<[llvm_ptr_ty], + [llvm_ptrptr_ty]>; + def int_objc_moveWeak : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + def int_objc_release : Intrinsic<[], [llvm_ptr_ty]>; + def int_objc_retain : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retainAutorelease : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retainAutoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retainAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retainBlock : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_storeStrong : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptr_ty]>; + def int_objc_storeWeak : Intrinsic<[llvm_ptr_ty], + [llvm_ptrptr_ty, + llvm_ptr_ty]>; + def int_objc_clang_arc_use : Intrinsic<[], + [llvm_vararg_ty]>; + def int_objc_unsafeClaimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retainedObject : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_unretainedObject : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_unretainedPointer : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_retain_autorelease : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty]>; + def int_objc_sync_enter : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty]>; + def int_objc_sync_exit : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty]>; + def int_objc_arc_annotation_topdown_bbstart : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + def int_objc_arc_annotation_topdown_bbend : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + def int_objc_arc_annotation_bottomup_bbstart : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + def int_objc_arc_annotation_bottomup_bbend : Intrinsic<[], + [llvm_ptrptr_ty, + llvm_ptrptr_ty]>; + + + //===--------------------- Code Generator Intrinsics ----------------------===// + // + def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; + def int_addressofreturnaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg<0>]>; + def int_sponentry : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], + [IntrReadMem], "llvm.read_register">; + def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], + [], "llvm.write_register">; + + // Gets the address of the local variable area. This is typically a copy of the + // stack, frame, or base pointer depending on the type of prologue. + def int_localaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + + // Escapes local variables to allow access from other functions. + def int_localescape : Intrinsic<[], [llvm_vararg_ty]>; + + // Given a function and the localaddress of a parent frame, returns a pointer + // to an escaped allocation indicated by the index. + def int_localrecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem, ImmArg<2>]>; + + // Given the frame pointer passed into an SEH filter function, returns a + // pointer to the local variable area suitable for use with llvm.localrecover. + def int_eh_recoverfp : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; + + // Note: we treat stacksave/stackrestore as writemem because we don't otherwise + // model their dependencies on allocas. + def int_stacksave : Intrinsic<[llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_save">; + def int_stackrestore : Intrinsic<[], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_restore">; + + def int_get_dynamic_area_offset : Intrinsic<[llvm_anyint_ty]>; + + def int_thread_pointer : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>, + GCCBuiltin<"__builtin_thread_pointer">; + + // IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly + // necessary for prefetch, however it does conveniently prevent the prefetch + // from being reordered overly much with respect to nearby access to the same + // memory while not impeding optimization. + def int_prefetch + : Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], + [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0>, + ImmArg<1>, ImmArg<2>]>; + def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; + + def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; + + // The assume intrinsic is marked as arbitrarily writing so that proper + // control dependencies will be maintained. + def int_assume : Intrinsic<[], [llvm_i1_ty], []>; + + // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack + // guard to the correct place on the stack frame. + def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; + def int_stackguard : Intrinsic<[llvm_ptr_ty], [], []>; + + // A counter increment for instrumentation based profiling. + def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + + // A counter increment with step for instrumentation based profiling. + def int_instrprof_increment_step : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], + []>; + + // A call to profile runtime for value profiling of target expressions + // through instrumentation based profiling. + def int_instrprof_value_profile : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + []>; + + //===------------------- Standard C Library Intrinsics --------------------===// + // + + def int_memcpy : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i1_ty], + [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, + WriteOnly<0>, ReadOnly<1>, ImmArg<3>]>; + def int_memmove : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, + llvm_i1_ty], + [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, + ReadOnly<1>, ImmArg<3>]>; + def int_memset : Intrinsic<[], + [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, + llvm_i1_ty], + [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, + ImmArg<3>]>; + + // FIXME: Add version of these floating point intrinsics which allow non-default + // rounding modes and FP exception handling. + + let IntrProperties = [IntrNoMem, IntrSpeculatable] in { + def int_fma : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; + def int_fmuladd : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; + + // These functions do not read memory, but are sensitive to the + // rounding mode. LLVM purposely does not model changes to the FP + // environment so they can be treated as readnone. + def int_sqrt : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_powi : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty]>; + def int_sin : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_cos : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_pow : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_log : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log10: Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_log2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_copysign : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_ceil : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_trunc : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_canonicalize : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], + [IntrNoMem]>; + } + + def int_minnum : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] + >; + def int_maxnum : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] + >; + def int_minimum : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] + >; + def int_maximum : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative] + >; + + // NOTE: these are internal interfaces. + def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; + def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; + def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>; + def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; + + // Internal interface for object size checking + def int_objectsize : Intrinsic<[llvm_anyint_ty], + [llvm_anyptr_ty, llvm_i1_ty, + llvm_i1_ty, llvm_i1_ty], + [IntrNoMem, IntrSpeculatable, ImmArg<1>, ImmArg<2>, ImmArg<3>]>, + GCCBuiltin<"__builtin_object_size">; + + //===--------------- Constrained Floating Point Intrinsics ----------------===// + // + + let IntrProperties = [IntrInaccessibleMemOnly] in { + def int_experimental_constrained_fadd : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_fsub : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_fmul : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_fdiv : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_frem : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + + def int_experimental_constrained_fma : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + + // These intrinsics are sensitive to the rounding mode so we need constrained + // versions of each of them. When strict rounding and exception control are + // not required the non-constrained versions of these intrinsics should be + // used. + def int_experimental_constrained_sqrt : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_powi : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_i32_ty, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_sin : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_cos : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_pow : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_log : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_log10: Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_log2 : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_exp : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_exp2 : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_rint : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_nearbyint : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_maxnum : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_minnum : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_ceil : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_floor : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_round : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + def int_experimental_constrained_trunc : Intrinsic<[ llvm_anyfloat_ty ], + [ LLVMMatchType<0>, + llvm_metadata_ty, + llvm_metadata_ty ]>; + } + // FIXME: Add intrinsics for fcmp, fptrunc, fpext, fptoui and fptosi. + // FIXME: Add intrinsics for fabs and copysign? + + + //===------------------------- Expect Intrinsics --------------------------===// + // + def int_expect : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + + //===-------------------- Bit Manipulation Intrinsics ---------------------===// + // + + // None of these intrinsics accesses memory at all. + let IntrProperties = [IntrNoMem, IntrSpeculatable] in { + def int_bswap: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_ctpop: Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_bitreverse : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_fshl : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_fshr : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; + } + + let IntrProperties = [IntrNoMem, IntrSpeculatable, ImmArg<1>] in { + def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; + def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; + } + + //===------------------------ Debugger Intrinsics -------------------------===// + // + + // None of these intrinsics accesses memory at all...but that doesn't + // mean the optimizers can change them aggressively. Special handling + // needed in a few places. These synthetic intrinsics have no + // side-effects and just mark information about their operands. + let IntrProperties = [IntrNoMem, IntrSpeculatable] in { + def int_dbg_declare : Intrinsic<[], + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; + def int_dbg_value : Intrinsic<[], + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; + def int_dbg_addr : Intrinsic<[], + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; + def int_dbg_label : Intrinsic<[], + [llvm_metadata_ty]>; + } + + //===------------------ Exception Handling Intrinsics----------------------===// + // + + // The result of eh.typeid.for depends on the enclosing function, but inside a + // given function it is 'const' and may be CSE'd etc. + def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; + + def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; + def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; + + // eh.exceptionpointer returns the pointer to the exception caught by + // the given `catchpad`. + def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], + [IntrNoMem]>; + + // Gets the exception code from a catchpad token. Only used on some platforms. + def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>; + + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all + // callee-saved registers to be saved and restored (regardless of whether they + // are used) in the calling function. It is used by libgcc_eh. + def int_eh_unwind_init: Intrinsic<[]>, + GCCBuiltin<"__builtin_unwind_init">; + + def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; + + let IntrProperties = [IntrNoMem] in { + def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; + def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty]>; + } + def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; + def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; + def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; + def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>; + + //===---------------- Generic Variable Attribute Intrinsics----------------===// + // + def int_var_annotation : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.var.annotation">; + def int_ptr_annotation : Intrinsic<[LLVMAnyPointerType], + [LLVMMatchType<0>, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty], + [], "llvm.ptr.annotation">; + def int_annotation : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.annotation">; + + // Annotates the current program point with metadata strings which are emitted + // as CodeView debug info records. This is expensive, as it disables inlining + // and is modelled as having side effects. + def int_codeview_annotation : Intrinsic<[], [llvm_metadata_ty], + [IntrInaccessibleMemOnly, IntrNoDuplicate], + "llvm.codeview.annotation">; + + //===------------------------ Trampoline Intrinsics -----------------------===// + // + def int_init_trampoline : Intrinsic<[], + [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<0>]>, + GCCBuiltin<"__builtin_init_trampoline">; + + def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], + [IntrReadMem, IntrArgMemOnly]>, + GCCBuiltin<"__builtin_adjust_trampoline">; + + //===------------------------ Overflow Intrinsics -------------------------===// + // + + // Expose the carry flag from add operations on two integrals. + def int_sadd_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_uadd_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + + def int_ssub_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_usub_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + + def int_smul_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + + //===------------------------- Saturation Arithmetic Intrinsics ---------------------===// + // + def int_sadd_sat : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative]>; + def int_uadd_sat : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable, Commutative]>; + def int_ssub_sat : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_usub_sat : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + + //===------------------------- Fixed Point Arithmetic Intrinsics ---------------------===// + // + def int_smul_fix : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; + + def int_umul_fix : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem, IntrSpeculatable, Commutative, ImmArg<2>]>; + + //===------------------------- Memory Use Markers -------------------------===// + // + def int_lifetime_start : Intrinsic<[], + [llvm_i64_ty, llvm_anyptr_ty], + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; + def int_lifetime_end : Intrinsic<[], + [llvm_i64_ty, llvm_anyptr_ty], + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; + def int_invariant_start : Intrinsic<[llvm_descriptor_ty], + [llvm_i64_ty, llvm_anyptr_ty], + [IntrArgMemOnly, NoCapture<1>, ImmArg<0>]>; + def int_invariant_end : Intrinsic<[], + [llvm_descriptor_ty, llvm_i64_ty, + llvm_anyptr_ty], + [IntrArgMemOnly, NoCapture<2>, ImmArg<1>]>; + + // launder.invariant.group can't be marked with 'readnone' (IntrNoMem), + // because it would cause CSE of two barriers with the same argument. + // Inaccessiblememonly says that the barrier doesn't read the argument, + // but it changes state not accessible to this module. This way + // we can DSE through the barrier because it doesn't read the value + // after store. Although the barrier doesn't modify any memory it + // can't be marked as readonly, because it would be possible to + // CSE 2 barriers with store in between. + // The argument also can't be marked with 'returned' attribute, because + // it would remove barrier. + // Note that it is still experimental, which means that its semantics + // might change in the future. + def int_launder_invariant_group : Intrinsic<[llvm_anyptr_ty], + [LLVMMatchType<0>], + [IntrInaccessibleMemOnly, IntrSpeculatable]>; + + + def int_strip_invariant_group : Intrinsic<[llvm_anyptr_ty], + [LLVMMatchType<0>], + [IntrSpeculatable, IntrNoMem]>; + + //===------------------------ Stackmap Intrinsics -------------------------===// + // + def int_experimental_stackmap : Intrinsic<[], + [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty], + [Throws]>; + def int_experimental_patchpoint_void : Intrinsic<[], + [llvm_i64_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty], + [Throws]>; + def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty], + [Throws]>; + + + //===------------------------ Garbage Collection Intrinsics ---------------===// + // These are documented in docs/Statepoint.rst + + def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty], + [Throws, ImmArg<0>, ImmArg<1>, ImmArg<3>, ImmArg<4>]>; + + def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_token_ty], + [IntrReadMem]>; + def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty], + [llvm_token_ty, llvm_i32_ty, llvm_i32_ty], + [IntrReadMem, ImmArg<1>, ImmArg<2>]>; + ++// INTEL_COLLAB ++//===------------------------ Directive Intrinsics ------------------------===// ++// ++def int_directive_region_entry : Intrinsic<[llvm_token_ty], [], []>; ++def int_directive_region_exit : Intrinsic<[], [llvm_token_ty], []>; ++// end INTEL_COLLAB + //===------------------------ Coroutine Intrinsics ---------------===// + // These are documented in docs/Coroutines.rst + + // Coroutine Structure Intrinsics. + + def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_ptr_ty], + [IntrArgMemOnly, IntrReadMem, + ReadNone<1>, ReadOnly<2>, NoCapture<2>]>; + def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>; + def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], + [WriteOnly<1>]>; + + def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], + [IntrReadMem, IntrArgMemOnly, ReadOnly<1>, + NoCapture<1>]>; + def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>; + + def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + def int_coro_noop : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; + + def int_coro_save : Intrinsic<[llvm_token_ty], [llvm_ptr_ty], []>; + def int_coro_suspend : Intrinsic<[llvm_i8_ty], [llvm_token_ty, llvm_i1_ty], []>; + + def int_coro_param : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem, ReadNone<0>, ReadNone<1>]>; + + // Coroutine Manipulation Intrinsics. + + def int_coro_resume : Intrinsic<[], [llvm_ptr_ty], [Throws]>; + def int_coro_destroy : Intrinsic<[], [llvm_ptr_ty], [Throws]>; + def int_coro_done : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], + [IntrArgMemOnly, ReadOnly<0>, NoCapture<0>]>; + def int_coro_promise : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i1_ty], + [IntrNoMem, NoCapture<0>]>; + + // Coroutine Lowering Intrinsics. Used internally by coroutine passes. + + def int_coro_subfn_addr : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i8_ty], + [IntrReadMem, IntrArgMemOnly, ReadOnly<0>, + NoCapture<0>]>; + + ///===-------------------------- Other Intrinsics --------------------------===// + // + def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, + GCCBuiltin<"__builtin_flt_rounds">; + def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold]>, + GCCBuiltin<"__builtin_trap">; + def int_debugtrap : Intrinsic<[]>, + GCCBuiltin<"__builtin_debugtrap">; + + // Support for dynamic deoptimization (or de-specialization) + def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], + [Throws]>; + + // Support for speculative runtime guards + def int_experimental_guard : Intrinsic<[], [llvm_i1_ty, llvm_vararg_ty], + [Throws]>; + + // Supports widenable conditions for guards represented as explicit branches. + def int_experimental_widenable_condition : Intrinsic<[llvm_i1_ty], [], + [IntrInaccessibleMemOnly]>; + + // NOP: calls/invokes to this intrinsic are removed by codegen + def int_donothing : Intrinsic<[], [], [IntrNoMem]>; + + // This instruction has no actual effect, though it is treated by the optimizer + // has having opaque side effects. This may be inserted into loops to ensure + // that they are not removed even if they turn out to be empty, for languages + // which specify that infinite loops must be preserved. + def int_sideeffect : Intrinsic<[], [], [IntrInaccessibleMemOnly]>; + + // Intrisics to support half precision floating point format + let IntrProperties = [IntrNoMem] in { + def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>; + def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>; + } + + // Clear cache intrinsic, default to ignore (ie. emit nothing) + // maps to void __clear_cache() on supporting platforms + def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [], "llvm.clear_cache">; + + // Intrinsic to detect whether its argument is a constant. + def int_is_constant : Intrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem], "llvm.is.constant">; + + + //===-------------------------- Masked Intrinsics -------------------------===// + // + def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, + LLVMAnyPointerType>, + llvm_i32_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [IntrArgMemOnly, ImmArg<2>]>; + + def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMAnyPointerType>, llvm_i32_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadMem, IntrArgMemOnly, ImmArg<1>]>; + + def int_masked_gather: Intrinsic<[llvm_anyvector_ty], + [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadMem, ImmArg<1>]>; + + def int_masked_scatter: Intrinsic<[], + [llvm_anyvector_ty, + LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [ImmArg<2>]>; + + def int_masked_expandload: Intrinsic<[llvm_anyvector_ty], + [LLVMPointerToElt<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, + LLVMMatchType<0>], + [IntrReadMem]>; + + def int_masked_compressstore: Intrinsic<[], + [llvm_anyvector_ty, + LLVMPointerToElt<0>, + LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [IntrArgMemOnly]>; + + // Test whether a pointer is associated with a type metadata identifier. + def int_type_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], + [IntrNoMem]>; + ++// INTEL_COLLAB ++// These intrinsics will be deprecated. ++// Use int_directive_region_entry/exit instead. ++//===--------------------- Intel Directive Intrinsics ---------------------===// ++ ++def int_intel_directive : Intrinsic<[], [llvm_metadata_ty], ++ [IntrArgMemOnly], ++ "llvm.intel.directive">; ++ ++def int_intel_directive_qual : Intrinsic<[], [llvm_metadata_ty], ++ [IntrArgMemOnly], ++ "llvm.intel.directive.qual">; ++ ++def int_intel_directive_qual_opnd : Intrinsic<[], ++ [llvm_metadata_ty, llvm_any_ty], ++ [IntrArgMemOnly], ++ "llvm.intel.directive.qual.opnd">; ++ ++def int_intel_directive_qual_opndlist : Intrinsic< ++ [], ++ [llvm_metadata_ty, llvm_vararg_ty], ++ [IntrArgMemOnly], ++ "llvm.intel.directive.qual.opndlist">; ++// end INTEL_COLLAB + // Safely loads a function pointer from a virtual table pointer using type metadata. + def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], + [IntrNoMem]>; + + // Create a branch funnel that implements an indirect call to a limited set of + // callees. This needs to be a musttail call. + def int_icall_branch_funnel : Intrinsic<[], [llvm_vararg_ty], []>; + + def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], + [IntrReadMem, IntrArgMemOnly]>; + + def int_hwasan_check_memaccess : + Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], [IntrInaccessibleMemOnly, ImmArg<2>]>; + + // Xray intrinsics + //===----------------------------------------------------------------------===// + // Custom event logging for x-ray. + // Takes a pointer to a string and the length of the string. + def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [NoCapture<0>, ReadOnly<0>, IntrWriteMem]>; + // Typed event logging for x-ray. + // Takes a numeric type tag, a pointer to a string and the length of the string. + def int_xray_typedevent : Intrinsic<[], [llvm_i16_ty, llvm_ptr_ty, llvm_i32_ty], + [NoCapture<1>, ReadOnly<1>, IntrWriteMem]>; + //===----------------------------------------------------------------------===// + + //===------ Memory intrinsics with element-wise atomicity guarantees ------===// + // + + // @llvm.memcpy.element.unordered.atomic.*(dest, src, length, elementsize) + def int_memcpy_element_unordered_atomic + : Intrinsic<[], + [ + llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty + ], + [ + IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, + ReadOnly<1>, ImmArg<3> + ]>; + + // @llvm.memmove.element.unordered.atomic.*(dest, src, length, elementsize) + def int_memmove_element_unordered_atomic + : Intrinsic<[], + [ + llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty + ], + [ + IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, + ReadOnly<1>, ImmArg<3> + ]>; + + // @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize) + def int_memset_element_unordered_atomic + : Intrinsic<[], [ llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty ], + [ IntrArgMemOnly, NoCapture<0>, WriteOnly<0>, ImmArg<3> ]>; + + //===------------------------ Reduction Intrinsics ------------------------===// + // + def int_experimental_vector_reduce_fadd : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyfloat_ty, + llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_fmul : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyfloat_ty, + llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_add : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_mul : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_and : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_or : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_xor : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_smax : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_smin : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_umax : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_umin : Intrinsic<[llvm_anyint_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_fmax : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + def int_experimental_vector_reduce_fmin : Intrinsic<[llvm_anyfloat_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + + //===----- Intrinsics that are used to provide predicate information -----===// + + def int_ssa_copy : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], + [IntrNoMem, Returned<0>]>; + //===----------------------------------------------------------------------===// + // Target-specific intrinsics + //===----------------------------------------------------------------------===// + + include "llvm/IR/IntrinsicsPowerPC.td" + include "llvm/IR/IntrinsicsX86.td" + include "llvm/IR/IntrinsicsARM.td" + include "llvm/IR/IntrinsicsAArch64.td" + include "llvm/IR/IntrinsicsXCore.td" + include "llvm/IR/IntrinsicsHexagon.td" + include "llvm/IR/IntrinsicsNVVM.td" + include "llvm/IR/IntrinsicsMips.td" + include "llvm/IR/IntrinsicsAMDGPU.td" + include "llvm/IR/IntrinsicsBPF.td" + include "llvm/IR/IntrinsicsSystemZ.td" + include "llvm/IR/IntrinsicsWebAssembly.td" + include "llvm/IR/IntrinsicsRISCV.td" +diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h +index f458680..3ecc0e4 100644 +--- a/llvm/include/llvm/IR/Module.h ++++ b/llvm/include/llvm/IR/Module.h +@@ -1,925 +1,937 @@ + //===- llvm/Module.h - C++ class to represent a VM module -------*- 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 + // + //===----------------------------------------------------------------------===// + // + /// @file + /// Module.h This file contains the declarations for the Module class. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_IR_MODULE_H + #define LLVM_IR_MODULE_H + + #include "llvm-c/Types.h" + #include "llvm/ADT/Optional.h" + #include "llvm/ADT/STLExtras.h" + #include "llvm/ADT/StringMap.h" + #include "llvm/ADT/StringRef.h" + #include "llvm/ADT/iterator_range.h" + #include "llvm/IR/Attributes.h" + #include "llvm/IR/Comdat.h" + #include "llvm/IR/DataLayout.h" + #include "llvm/IR/Function.h" + #include "llvm/IR/GlobalAlias.h" + #include "llvm/IR/GlobalIFunc.h" + #include "llvm/IR/GlobalVariable.h" + #include "llvm/IR/Metadata.h" + #include "llvm/IR/ProfileSummary.h" + #include "llvm/IR/SymbolTableListTraits.h" + #include "llvm/Support/CBindingWrapping.h" + #include "llvm/Support/CodeGen.h" + #include + #include + #include + #include + #include + #include + + namespace llvm { + + class Error; + class FunctionType; + class GVMaterializer; + class LLVMContext; + class MemoryBuffer; + class RandomNumberGenerator; + template class SmallPtrSetImpl; + class StructType; + class VersionTuple; + + /// A Module instance is used to store all the information related to an + /// LLVM module. Modules are the top level container of all other LLVM + /// Intermediate Representation (IR) objects. Each module directly contains a + /// list of globals variables, a list of functions, a list of libraries (or + /// other modules) this module depends on, a symbol table, and various data + /// about the target's characteristics. + /// + /// A module maintains a GlobalValRefMap object that is used to hold all + /// constant references to global variables in the module. When a global + /// variable is destroyed, it should have no entries in the GlobalValueRefMap. + /// The main container class for the LLVM Intermediate Representation. + class Module { + /// @name Types And Enumerations + /// @{ + public: + /// The type for the list of global variables. + using GlobalListType = SymbolTableList; + /// The type for the list of functions. + using FunctionListType = SymbolTableList; + /// The type for the list of aliases. + using AliasListType = SymbolTableList; + /// The type for the list of ifuncs. + using IFuncListType = SymbolTableList; + /// The type for the list of named metadata. + using NamedMDListType = ilist; + /// The type of the comdat "symbol" table. + using ComdatSymTabType = StringMap; + + /// The Global Variable iterator. + using global_iterator = GlobalListType::iterator; + /// The Global Variable constant iterator. + using const_global_iterator = GlobalListType::const_iterator; + + /// The Function iterators. + using iterator = FunctionListType::iterator; + /// The Function constant iterator + using const_iterator = FunctionListType::const_iterator; + + /// The Function reverse iterator. + using reverse_iterator = FunctionListType::reverse_iterator; + /// The Function constant reverse iterator. + using const_reverse_iterator = FunctionListType::const_reverse_iterator; + + /// The Global Alias iterators. + using alias_iterator = AliasListType::iterator; + /// The Global Alias constant iterator + using const_alias_iterator = AliasListType::const_iterator; + + /// The Global IFunc iterators. + using ifunc_iterator = IFuncListType::iterator; + /// The Global IFunc constant iterator + using const_ifunc_iterator = IFuncListType::const_iterator; + + /// The named metadata iterators. + using named_metadata_iterator = NamedMDListType::iterator; + /// The named metadata constant iterators. + using const_named_metadata_iterator = NamedMDListType::const_iterator; + + /// This enumeration defines the supported behaviors of module flags. + enum ModFlagBehavior { + /// Emits an error if two values disagree, otherwise the resulting value is + /// that of the operands. + Error = 1, + + /// Emits a warning if two values disagree. The result value will be the + /// operand for the flag from the first module being linked. + Warning = 2, + + /// Adds a requirement that another module flag be present and have a + /// specified value after linking is performed. The value must be a metadata + /// pair, where the first element of the pair is the ID of the module flag + /// to be restricted, and the second element of the pair is the value the + /// module flag should be restricted to. This behavior can be used to + /// restrict the allowable results (via triggering of an error) of linking + /// IDs with the **Override** behavior. + Require = 3, + + /// Uses the specified value, regardless of the behavior or value of the + /// other module. If both modules specify **Override**, but the values + /// differ, an error will be emitted. + Override = 4, + + /// Appends the two values, which are required to be metadata nodes. + Append = 5, + + /// Appends the two values, which are required to be metadata + /// nodes. However, duplicate entries in the second list are dropped + /// during the append operation. + AppendUnique = 6, + + /// Takes the max of the two values, which are required to be integers. + Max = 7, + + // Markers: + ModFlagBehaviorFirstVal = Error, + ModFlagBehaviorLastVal = Max + }; + + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the + /// converted result in MFB. + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); + + struct ModuleFlagEntry { + ModFlagBehavior Behavior; + MDString *Key; + Metadata *Val; + + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} + }; + + /// @} + /// @name Member Variables + /// @{ + private: + LLVMContext &Context; ///< The LLVMContext from which types and + ///< constants are allocated. + GlobalListType GlobalList; ///< The Global Variables in the module + FunctionListType FunctionList; ///< The Functions in the module + AliasListType AliasList; ///< The Aliases in the module + IFuncListType IFuncList; ///< The IFuncs in the module + NamedMDListType NamedMDList; ///< The named metadata in the module + std::string GlobalScopeAsm; ///< Inline Asm at global scope. + ValueSymbolTable *ValSymTab; ///< Symbol table for values + ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs + std::unique_ptr + OwnedMemoryBuffer; ///< Memory buffer directly owned by this + ///< module, for legacy clients only. + std::unique_ptr + Materializer; ///< Used to materialize GlobalValues + std::string ModuleID; ///< Human readable identifier for the module + std::string SourceFileName; ///< Original source file name for module, + ///< recorded in bitcode. + std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) + void *NamedMDSymTab; ///< NamedMDNode names. + DataLayout DL; ///< DataLayout associated with the module + ++#if INTEL_COLLAB ++ std::string TargetDevices; ///< Target devices ++#endif // INTEL_COLLAB + friend class Constant; + + /// @} + /// @name Constructors + /// @{ + public: + /// The Module constructor. Note that there is no default constructor. You + /// must provide a name for the module upon construction. + explicit Module(StringRef ModuleID, LLVMContext& C); + /// The module destructor. This will dropAllReferences. + ~Module(); + + /// @} + /// @name Module Level Accessors + /// @{ + + /// Get the module identifier which is, essentially, the name of the module. + /// @returns the module identifier as a string + const std::string &getModuleIdentifier() const { return ModuleID; } + + /// Returns the number of non-debug IR instructions in the module. + /// This is equivalent to the sum of the IR instruction counts of each + /// function contained in the module. + unsigned getInstructionCount(); + + /// Get the module's original source file name. When compiling from + /// bitcode, this is taken from a bitcode record where it was recorded. + /// For other compiles it is the same as the ModuleID, which would + /// contain the source file name. + const std::string &getSourceFileName() const { return SourceFileName; } + + /// Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + + /// Get the data layout string for the module's target platform. This is + /// equivalent to getDataLayout()->getStringRepresentation(). + const std::string &getDataLayoutStr() const { + return DL.getStringRepresentation(); + } + + /// Get the data layout for the module's target platform. + const DataLayout &getDataLayout() const; + + /// Get the target triple which is a string describing the target host. + /// @returns a string containing the target triple. + const std::string &getTargetTriple() const { return TargetTriple; } + ++#if INTEL_COLLAB ++ /// Get the target device information which is a comma-separated string ++ /// describing one or more devices. ++ const std::string &getTargetDevices() const { return TargetDevices; } ++#endif // INTEL_COLLAB + /// Get the global data context. + /// @returns LLVMContext - a container for LLVM's global information + LLVMContext &getContext() const { return Context; } + + /// Get any module-scope inline assembly blocks. + /// @returns a string containing the module-scope inline assembly blocks. + const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } + + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed= and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + std::unique_ptr createRNG(const Pass* P) const; + + /// Return true if size-info optimization remark is enabled, false + /// otherwise. + bool shouldEmitInstrCountChangedRemark() { + return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled( + "size-info"); + } + + /// @} + /// @name Module Level Mutators + /// @{ + + /// Set the module identifier. + void setModuleIdentifier(StringRef ID) { ModuleID = ID; } + + /// Set the module's original source file name. + void setSourceFileName(StringRef Name) { SourceFileName = Name; } + + /// Set the data layout + void setDataLayout(StringRef Desc); + void setDataLayout(const DataLayout &Other); + + /// Set the target triple. + void setTargetTriple(StringRef T) { TargetTriple = T; } + ++#if INTEL_COLLAB ++ /// set the target device information. ++ void setTargetDevices(StringRef T) { TargetDevices = T; } ++#endif // INTEL_COLLAB + /// Set the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. + void setModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm = Asm; + if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n') + GlobalScopeAsm += '\n'; + } + + /// Append to the module-scope inline assembly blocks. + /// A trailing newline is added if the input doesn't have one. + void appendModuleInlineAsm(StringRef Asm) { + GlobalScopeAsm += Asm; + if (!GlobalScopeAsm.empty() && GlobalScopeAsm.back() != '\n') + GlobalScopeAsm += '\n'; + } + + /// @} + /// @name Generic Value Accessors + /// @{ + + /// Return the global value in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. + GlobalValue *getNamedValue(StringRef Name) const; + + /// Return a unique non-zero ID for the specified metadata kind. This ID is + /// uniqued across modules in the current LLVMContext. + unsigned getMDKindID(StringRef Name) const; + + /// Populate client supplied SmallVector with the name for custom metadata IDs + /// registered in this LLVMContext. + void getMDKindNames(SmallVectorImpl &Result) const; + + /// Populate client supplied SmallVector with the bundle tags registered in + /// this LLVMContext. The bundle tags are ordered by increasing bundle IDs. + /// \see LLVMContext::getOperandBundleTagID + void getOperandBundleTags(SmallVectorImpl &Result) const; + + /// Return the type with the specified name, or null if there is none by that + /// name. + StructType *getTypeByName(StringRef Name) const; + + std::vector getIdentifiedStructTypes() const; + + /// @} + /// @name Function Accessors + /// @{ + + /// Look up the specified function in the module symbol table. Four + /// possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 3. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + /// + /// In all cases, the returned value is a FunctionCallee wrapper around the + /// 'FunctionType *T' passed in, as well as a 'Value*' either of the Function or + /// the bitcast to the function. + FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, + AttributeList AttributeList); + + FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T); + + /// Look up the specified function in the module symbol table. If it does not + /// exist, add a prototype for the function and return it. This function + /// guarantees to return a constant of pointer to the specified function type + /// or a ConstantExpr BitCast of that type if the named function has a + /// different type. This version of the method takes a list of + /// function arguments, which makes it easier for clients to use. + template + FunctionCallee getOrInsertFunction(StringRef Name, + AttributeList AttributeList, Type *RetTy, + ArgsTy... Args) { + SmallVector ArgTys{Args...}; + return getOrInsertFunction(Name, + FunctionType::get(RetTy, ArgTys, false), + AttributeList); + } + + /// Same as above, but without the attributes. + template + FunctionCallee getOrInsertFunction(StringRef Name, Type *RetTy, + ArgsTy... Args) { + return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...); + } + + // Avoid an incorrect ordering that'd otherwise compile incorrectly. + template + FunctionCallee + getOrInsertFunction(StringRef Name, AttributeList AttributeList, + FunctionType *Invalid, ArgsTy... Args) = delete; + + /// Look up the specified function in the module symbol table. If it does not + /// exist, return null. + Function *getFunction(StringRef Name) const; + + /// @} + /// @name Global Variable Accessors + /// @{ + + /// Look up the specified global variable in the module symbol table. If it + /// does not exist, return null. If AllowInternal is set to true, this + /// function will return types that have InternalLinkage. By default, these + /// types are not returned. + GlobalVariable *getGlobalVariable(StringRef Name) const { + return getGlobalVariable(Name, false); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const; + + GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) { + return static_cast(this)->getGlobalVariable(Name, + AllowInternal); + } + + /// Return the global variable in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. + const GlobalVariable *getNamedGlobal(StringRef Name) const { + return getGlobalVariable(Name, true); + } + GlobalVariable *getNamedGlobal(StringRef Name) { + return const_cast( + static_cast(this)->getNamedGlobal(Name)); + } + + /// Look up the specified global in the module symbol table. + /// If it does not exist, invoke a callback to create a declaration of the + /// global and return it. The global is constantexpr casted to the expected + /// type if necessary. + Constant * + getOrInsertGlobal(StringRef Name, Type *Ty, + function_ref CreateGlobalCallback); + + /// Look up the specified global in the module symbol table. If required, this + /// overload constructs the global variable using its constructor's defaults. + Constant *getOrInsertGlobal(StringRef Name, Type *Ty); + + /// @} + /// @name Global Alias Accessors + /// @{ + + /// Return the global alias in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. + GlobalAlias *getNamedAlias(StringRef Name) const; + + /// @} + /// @name Global IFunc Accessors + /// @{ + + /// Return the global ifunc in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. + GlobalIFunc *getNamedIFunc(StringRef Name) const; + + /// @} + /// @name Named Metadata Accessors + /// @{ + + /// Return the first NamedMDNode in the module with the specified name. This + /// method returns null if a NamedMDNode with the specified name is not found. + NamedMDNode *getNamedMetadata(const Twine &Name) const; + + /// Return the named MDNode in the module with the specified name. This method + /// returns a new NamedMDNode if a NamedMDNode with the specified name is not + /// found. + NamedMDNode *getOrInsertNamedMetadata(StringRef Name); + + /// Remove the given NamedMDNode from this module and delete it. + void eraseNamedMetadata(NamedMDNode *NMD); + + /// @} + /// @name Comdat Accessors + /// @{ + + /// Return the Comdat in the module with the specified name. It is created + /// if it didn't already exist. + Comdat *getOrInsertComdat(StringRef Name); + + /// @} + /// @name Module Flags Accessors + /// @{ + + /// Returns the module flags in the provided vector. + void getModuleFlagsMetadata(SmallVectorImpl &Flags) const; + + /// Return the corresponding value if Key appears in module flags, otherwise + /// return null. + Metadata *getModuleFlag(StringRef Key) const; + + /// Returns the NamedMDNode in the module that represents module-level flags. + /// This method returns null if there are no module-level flags. + NamedMDNode *getModuleFlagsMetadata() const; + + /// Returns the NamedMDNode in the module that represents module-level flags. + /// If module-level flags aren't found, it creates the named metadata that + /// contains them. + NamedMDNode *getOrInsertModuleFlagsMetadata(); + + /// Add a module-level flag to the module-level flags metadata. It will create + /// the module-level flags named metadata if it doesn't already exist. + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); + void addModuleFlag(MDNode *Node); + + /// @} + /// @name Materialization + /// @{ + + /// Sets the GVMaterializer to GVM. This module must not yet have a + /// Materializer. To reset the materializer for a module that already has one, + /// call materializeAll first. Destroying this module will destroy + /// its materializer without materializing any more GlobalValues. Without + /// destroying the Module, there is no way to detach or destroy a materializer + /// without materializing all the GVs it controls, to avoid leaving orphan + /// unmaterialized GVs. + void setMaterializer(GVMaterializer *GVM); + /// Retrieves the GVMaterializer, if any, for this Module. + GVMaterializer *getMaterializer() const { return Materializer.get(); } + bool isMaterialized() const { return !getMaterializer(); } + + /// Make sure the GlobalValue is fully read. + llvm::Error materialize(GlobalValue *GV); + + /// Make sure all GlobalValues in this Module are fully read and clear the + /// Materializer. + llvm::Error materializeAll(); + + llvm::Error materializeMetadata(); + + /// @} + /// @name Direct access to the globals list, functions list, and symbol table + /// @{ + + /// Get the Module's list of global variables (constant). + const GlobalListType &getGlobalList() const { return GlobalList; } + /// Get the Module's list of global variables. + GlobalListType &getGlobalList() { return GlobalList; } + + static GlobalListType Module::*getSublistAccess(GlobalVariable*) { + return &Module::GlobalList; + } + + /// Get the Module's list of functions (constant). + const FunctionListType &getFunctionList() const { return FunctionList; } + /// Get the Module's list of functions. + FunctionListType &getFunctionList() { return FunctionList; } + static FunctionListType Module::*getSublistAccess(Function*) { + return &Module::FunctionList; + } + + /// Get the Module's list of aliases (constant). + const AliasListType &getAliasList() const { return AliasList; } + /// Get the Module's list of aliases. + AliasListType &getAliasList() { return AliasList; } + + static AliasListType Module::*getSublistAccess(GlobalAlias*) { + return &Module::AliasList; + } + + /// Get the Module's list of ifuncs (constant). + const IFuncListType &getIFuncList() const { return IFuncList; } + /// Get the Module's list of ifuncs. + IFuncListType &getIFuncList() { return IFuncList; } + + static IFuncListType Module::*getSublistAccess(GlobalIFunc*) { + return &Module::IFuncList; + } + + /// Get the Module's list of named metadata (constant). + const NamedMDListType &getNamedMDList() const { return NamedMDList; } + /// Get the Module's list of named metadata. + NamedMDListType &getNamedMDList() { return NamedMDList; } + + static NamedMDListType Module::*getSublistAccess(NamedMDNode*) { + return &Module::NamedMDList; + } + + /// Get the symbol table of global variable and function identifiers + const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } + /// Get the Module's symbol table of global variable and function identifiers. + ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + + /// Get the Module's symbol table for COMDATs (constant). + const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; } + /// Get the Module's symbol table for COMDATs. + ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; } + + /// @} + /// @name Global Variable Iteration + /// @{ + + global_iterator global_begin() { return GlobalList.begin(); } + const_global_iterator global_begin() const { return GlobalList.begin(); } + global_iterator global_end () { return GlobalList.end(); } + const_global_iterator global_end () const { return GlobalList.end(); } + bool global_empty() const { return GlobalList.empty(); } + + iterator_range globals() { + return make_range(global_begin(), global_end()); + } + iterator_range globals() const { + return make_range(global_begin(), global_end()); + } + + /// @} + /// @name Function Iteration + /// @{ + + iterator begin() { return FunctionList.begin(); } + const_iterator begin() const { return FunctionList.begin(); } + iterator end () { return FunctionList.end(); } + const_iterator end () const { return FunctionList.end(); } + reverse_iterator rbegin() { return FunctionList.rbegin(); } + const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); } + reverse_iterator rend() { return FunctionList.rend(); } + const_reverse_iterator rend() const { return FunctionList.rend(); } + size_t size() const { return FunctionList.size(); } + bool empty() const { return FunctionList.empty(); } + + iterator_range functions() { + return make_range(begin(), end()); + } + iterator_range functions() const { + return make_range(begin(), end()); + } + + /// @} + /// @name Alias Iteration + /// @{ + + alias_iterator alias_begin() { return AliasList.begin(); } + const_alias_iterator alias_begin() const { return AliasList.begin(); } + alias_iterator alias_end () { return AliasList.end(); } + const_alias_iterator alias_end () const { return AliasList.end(); } + size_t alias_size () const { return AliasList.size(); } + bool alias_empty() const { return AliasList.empty(); } + + iterator_range aliases() { + return make_range(alias_begin(), alias_end()); + } + iterator_range aliases() const { + return make_range(alias_begin(), alias_end()); + } + + /// @} + /// @name IFunc Iteration + /// @{ + + ifunc_iterator ifunc_begin() { return IFuncList.begin(); } + const_ifunc_iterator ifunc_begin() const { return IFuncList.begin(); } + ifunc_iterator ifunc_end () { return IFuncList.end(); } + const_ifunc_iterator ifunc_end () const { return IFuncList.end(); } + size_t ifunc_size () const { return IFuncList.size(); } + bool ifunc_empty() const { return IFuncList.empty(); } + + iterator_range ifuncs() { + return make_range(ifunc_begin(), ifunc_end()); + } + iterator_range ifuncs() const { + return make_range(ifunc_begin(), ifunc_end()); + } + + /// @} + /// @name Convenience iterators + /// @{ + + using global_object_iterator = + concat_iterator; + using const_global_object_iterator = + concat_iterator; + + iterator_range global_objects() { + return concat(functions(), globals()); + } + iterator_range global_objects() const { + return concat(functions(), globals()); + } + + global_object_iterator global_object_begin() { + return global_objects().begin(); + } + global_object_iterator global_object_end() { return global_objects().end(); } + + const_global_object_iterator global_object_begin() const { + return global_objects().begin(); + } + const_global_object_iterator global_object_end() const { + return global_objects().end(); + } + + using global_value_iterator = + concat_iterator; + using const_global_value_iterator = + concat_iterator; + + iterator_range global_values() { + return concat(functions(), globals(), aliases(), ifuncs()); + } + iterator_range global_values() const { + return concat(functions(), globals(), aliases(), + ifuncs()); + } + + global_value_iterator global_value_begin() { return global_values().begin(); } + global_value_iterator global_value_end() { return global_values().end(); } + + const_global_value_iterator global_value_begin() const { + return global_values().begin(); + } + const_global_value_iterator global_value_end() const { + return global_values().end(); + } + + /// @} + /// @name Named Metadata Iteration + /// @{ + + named_metadata_iterator named_metadata_begin() { return NamedMDList.begin(); } + const_named_metadata_iterator named_metadata_begin() const { + return NamedMDList.begin(); + } + + named_metadata_iterator named_metadata_end() { return NamedMDList.end(); } + const_named_metadata_iterator named_metadata_end() const { + return NamedMDList.end(); + } + + size_t named_metadata_size() const { return NamedMDList.size(); } + bool named_metadata_empty() const { return NamedMDList.empty(); } + + iterator_range named_metadata() { + return make_range(named_metadata_begin(), named_metadata_end()); + } + iterator_range named_metadata() const { + return make_range(named_metadata_begin(), named_metadata_end()); + } + + /// An iterator for DICompileUnits that skips those marked NoDebug. + class debug_compile_units_iterator + : public std::iterator { + NamedMDNode *CUs; + unsigned Idx; + + void SkipNoDebugCUs(); + + public: + explicit debug_compile_units_iterator(NamedMDNode *CUs, unsigned Idx) + : CUs(CUs), Idx(Idx) { + SkipNoDebugCUs(); + } + + debug_compile_units_iterator &operator++() { + ++Idx; + SkipNoDebugCUs(); + return *this; + } + + debug_compile_units_iterator operator++(int) { + debug_compile_units_iterator T(*this); + ++Idx; + return T; + } + + bool operator==(const debug_compile_units_iterator &I) const { + return Idx == I.Idx; + } + + bool operator!=(const debug_compile_units_iterator &I) const { + return Idx != I.Idx; + } + + DICompileUnit *operator*() const; + DICompileUnit *operator->() const; + }; + + debug_compile_units_iterator debug_compile_units_begin() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return debug_compile_units_iterator(CUs, 0); + } + + debug_compile_units_iterator debug_compile_units_end() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0); + } + + /// Return an iterator for all DICompileUnits listed in this Module's + /// llvm.dbg.cu named metadata node and aren't explicitly marked as + /// NoDebug. + iterator_range debug_compile_units() const { + auto *CUs = getNamedMetadata("llvm.dbg.cu"); + return make_range( + debug_compile_units_iterator(CUs, 0), + debug_compile_units_iterator(CUs, CUs ? CUs->getNumOperands() : 0)); + } + /// @} + + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + + /// @name Utility functions for printing and dumping Module objects + /// @{ + + /// Print the module to an output stream with an optional + /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include + /// uselistorder directives so that use-lists can be recreated when reading + /// the assembly. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false, + bool IsForDebug = false) const; + + /// Dump the module to stderr (for debugging). + void dump() const; + + /// This function causes all the subinstructions to "let go" of all references + /// that they are maintaining. This allows one to 'delete' a whole class at + /// a time, even though there may be circular references... first all + /// references are dropped, and all use counts go to zero. Then everything + /// is delete'd for real. Note that no operations are valid on an object + /// that has "dropped all references", except operator delete. + void dropAllReferences(); + + /// @} + /// @name Utility functions for querying Debug information. + /// @{ + + /// Returns the Number of Register ParametersDwarf Version by checking + /// module flags. + unsigned getNumberRegisterParameters() const; + + /// Returns the Dwarf Version by checking module flags. + unsigned getDwarfVersion() const; + + /// Returns the CodeView Version by checking module flags. + /// Returns zero if not present in module. + unsigned getCodeViewFlag() const; + + /// @} + /// @name Utility functions for querying and setting PIC level + /// @{ + + /// Returns the PIC level (small or large model) + PICLevel::Level getPICLevel() const; + + /// Set the PIC level (small or large model) + void setPICLevel(PICLevel::Level PL); + /// @} + + /// @} + /// @name Utility functions for querying and setting PIE level + /// @{ + + /// Returns the PIE level (small or large model) + PIELevel::Level getPIELevel() const; + + /// Set the PIE level (small or large model) + void setPIELevel(PIELevel::Level PL); + /// @} + + /// @} + /// @name Utility function for querying and setting code model + /// @{ + + /// Returns the code model (tiny, small, kernel, medium or large model) + Optional getCodeModel() const; + + /// Set the code model (tiny, small, kernel, medium or large) + void setCodeModel(CodeModel::Model CL); + /// @} + + /// @name Utility functions for querying and setting PGO summary + /// @{ + + /// Attach profile summary metadata to this module. + void setProfileSummary(Metadata *M, ProfileSummary::Kind Kind); + + /// Returns profile summary metadata. When IsCS is true, use the context + /// sensitive profile summary. + Metadata *getProfileSummary(bool IsCS); + /// @} + + /// Returns true if PLT should be avoided for RTLib calls. + bool getRtLibUseGOT() const; + + /// Set that PLT should be avoid for RTLib calls. + void setRtLibUseGOT(); + + /// @name Utility functions for querying and setting the build SDK version + /// @{ + + /// Attach a build SDK version metadata to this module. + void setSDKVersion(const VersionTuple &V); + + /// Get the build SDK version metadata. + /// + /// An empty version is returned if no such metadata is attached. + VersionTuple getSDKVersion() const; + /// @} + + /// Take ownership of the given memory buffer. + void setOwnedMemoryBuffer(std::unique_ptr MB); + }; + + /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect + /// the initializer elements of that global in Set and return the global itself. + GlobalVariable *collectUsedGlobalVariables(const Module &M, + SmallPtrSetImpl &Set, + bool CompilerUsed); + + /// An raw_ostream inserter for modules. + inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { + M.print(O, nullptr); + return O; + } + + // Create wrappers for C Binding types (see CBindingWrapping.h). + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef) + + /* LLVMModuleProviderRef exists for historical reasons, but now just holds a + * Module. + */ + inline Module *unwrap(LLVMModuleProviderRef MP) { + return reinterpret_cast(MP); + } + + } // end namespace llvm + + #endif // LLVM_IR_MODULE_H Index: llvm/include/llvm/IR/CMakeLists.txt =================================================================== --- llvm/include/llvm/IR/CMakeLists.txt +++ llvm/include/llvm/IR/CMakeLists.txt @@ -5,8 +5,8 @@ tablegen(LLVM IntrinsicEnums.inc -gen-intrinsic-enums) tablegen(LLVM IntrinsicImpl.inc -gen-intrinsic-impl) add_public_tablegen_target(intrinsics_gen) -if (INTEL_COLLAB) +if (LLVM_COLLAB) set(LLVM_TARGET_DEFINITIONS Intel_Directives.td) tablegen(LLVM Intel_Directives.gen -gen-directives) add_public_tablegen_target(intel_directives_gen) -endif(INTEL_COLLAB) +endif(LLVM_COLLAB) Index: llvm/include/llvm/IR/GlobalValue.h =================================================================== --- llvm/include/llvm/IR/GlobalValue.h +++ llvm/include/llvm/IR/GlobalValue.h @@ -79,9 +79,9 @@ ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), -#if INTEL_COLLAB +#if LLVM_COLLAB ThreadPrivate(0), TargetDeclare(0), -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U), Parent(nullptr) { setLinkage(Linkage); @@ -90,14 +90,14 @@ Type *ValueType; -#if INTEL_COLLAB +#if LLVM_COLLAB // INTEL - This needs to be two less than it is in the community version to // account for the ThreadPrivate bit and TargetDeclare bit. See also // the comment at the SubClassData declaration. static const unsigned GlobalValueSubClassDataBits = 15; #else static const unsigned GlobalValueSubClassDataBits = 17; -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB // All bitfields use unsigned as the underlying type so that MSVC will pack // them. @@ -108,7 +108,7 @@ unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is // the desired model? -#if INTEL_COLLAB +#if LLVM_COLLAB unsigned ThreadPrivate : 1; // The thread_private attribute indicates // if the global variable is associated // with an OpenMP threadprivate directive @@ -116,7 +116,7 @@ unsigned TargetDeclare : 1; // The target declare attribute indicates // if the global variable is associated // with an OpenMP declare target directive. -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB /// True if the function's name starts with "llvm.". This corresponds to the /// value of Function::isIntrinsic(), which may be true even if @@ -261,13 +261,13 @@ maybeSetDsoLocal(); } -#if INTEL_COLLAB +#if LLVM_COLLAB bool isThreadPrivate() const { return ThreadPrivate; } void setThreadPrivate(bool Val) { ThreadPrivate = Val; } bool isTargetDeclare() const { return TargetDeclare; } void setTargetDeclare(bool Val) { TargetDeclare = Val; } -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB /// If the value is "Thread Local", its value isn't shared by the threads. bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } void setThreadLocal(bool Val) { Index: llvm/include/llvm/IR/Intel_Directives.td =================================================================== --- llvm/include/llvm/IR/Intel_Directives.td +++ llvm/include/llvm/IR/Intel_Directives.td @@ -1,12 +1,11 @@ -// INTEL_COLLAB -*- tablegen -*- -//==- Intel_Directives.td - Defines all parallelization and -*- tablegen -*-==// +// LLVM_COLLAB -*- tablegen -*- + +//===- Directives.td - Defines all parallelization and -----*- tablegen -*-===// // vectorization directives and clauses. // -// Copyright (C) 2016 Intel Corporation. All rights reserved. -// -// The information and source code contained herein is the exclusive property -// of Intel Corporation and may not be disclosed, examined or reproduced in -// whole or in part without explicit written authorization from the company. +// 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 // // ===--------------------------------------------------------------------=== // /// @@ -30,7 +29,7 @@ // The Clause class represents additional information provided to Directives // that can be used to control parallel/vector execution. For example, // "#pragma omp parallel" could be modified to include the "if (expr)" clause -// to determine if the region should be executed in parallel or not. +// to determine if the region should be executed in parallel or not. class Clause; // For additional information on the supported Directives and Clauses, please @@ -251,4 +250,4 @@ def "QUAL.OMP.CANCELLATION.POINTS" : Clause; def "QUAL.OMP.OFFLOAD.ENTRY.IDX" : Clause; -// end INTEL_COLLAB +// end LLVM_COLLAB Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -933,12 +933,14 @@ [llvm_token_ty, llvm_i32_ty, llvm_i32_ty], [IntrReadMem, ImmArg<1>, ImmArg<2>]>; -// INTEL_COLLAB +// LLVM_COLLAB //===------------------------ Directive Intrinsics ------------------------===// // def int_directive_region_entry : Intrinsic<[llvm_token_ty], [], []>; def int_directive_region_exit : Intrinsic<[], [llvm_token_ty], []>; -// end INTEL_COLLAB +def int_directive_marker : Intrinsic<[], [], []>; + +// end LLVM_COLLAB //===------------------------ Coroutine Intrinsics ---------------===// // These are documented in docs/Coroutines.rst @@ -1069,30 +1071,6 @@ def int_type_test : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], [IntrNoMem]>; -// INTEL_COLLAB -// These intrinsics will be deprecated. -// Use int_directive_region_entry/exit instead. -//===--------------------- Intel Directive Intrinsics ---------------------===// - -def int_intel_directive : Intrinsic<[], [llvm_metadata_ty], - [IntrArgMemOnly], - "llvm.intel.directive">; - -def int_intel_directive_qual : Intrinsic<[], [llvm_metadata_ty], - [IntrArgMemOnly], - "llvm.intel.directive.qual">; - -def int_intel_directive_qual_opnd : Intrinsic<[], - [llvm_metadata_ty, llvm_any_ty], - [IntrArgMemOnly], - "llvm.intel.directive.qual.opnd">; - -def int_intel_directive_qual_opndlist : Intrinsic< - [], - [llvm_metadata_ty, llvm_vararg_ty], - [IntrArgMemOnly], - "llvm.intel.directive.qual.opndlist">; -// end INTEL_COLLAB // Safely loads a function pointer from a virtual table pointer using type metadata. def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], Index: llvm/include/llvm/IR/Module.h =================================================================== --- llvm/include/llvm/IR/Module.h +++ llvm/include/llvm/IR/Module.h @@ -189,9 +189,9 @@ void *NamedMDSymTab; ///< NamedMDNode names. DataLayout DL; ///< DataLayout associated with the module -#if INTEL_COLLAB +#if LLVM_COLLAB std::string TargetDevices; ///< Target devices -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB friend class Constant; /// @} @@ -242,11 +242,11 @@ /// @returns a string containing the target triple. const std::string &getTargetTriple() const { return TargetTriple; } -#if INTEL_COLLAB +#if LLVM_COLLAB /// Get the target device information which is a comma-separated string /// describing one or more devices. const std::string &getTargetDevices() const { return TargetDevices; } -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB /// Get the global data context. /// @returns LLVMContext - a container for LLVM's global information LLVMContext &getContext() const { return Context; } @@ -290,10 +290,10 @@ /// Set the target triple. void setTargetTriple(StringRef T) { TargetTriple = T; } -#if INTEL_COLLAB +#if LLVM_COLLAB /// set the target device information. void setTargetDevices(StringRef T) { TargetDevices = T; } -#endif // INTEL_COLLAB +#endif // LLVM_COLLAB /// Set the module-scope inline assembly blocks. /// A trailing newline is added if the input doesn't have one. void setModuleInlineAsm(StringRef Asm) {