[llvm] r316668 - Represent runtime preemption in the IR.

Rafael Avila de Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 27 14:00:25 PDT 2017


Thanks!

Sean Fertile via llvm-commits <llvm-commits at lists.llvm.org> writes:

> Author: sfertile
> Date: Thu Oct 26 08:00:26 2017
> New Revision: 316668
>
> URL: http://llvm.org/viewvc/llvm-project?rev=316668&view=rev
> Log:
> Represent runtime preemption in the IR.
>
> Currently we do not represent runtime preemption in the IR, which has several
> drawbacks:
>
>   1) The semantics of GlobalValues differ depending on the object file format
>      you are targeting (as well as the relocation-model and -fPIE value).
>   2) We have no way of disabling inlining of run time interposable functions,
>      since in the IR we only know if a function is link-time interposable.
>      Because of this llvm cannot support elf-interposition semantics.
>   3) In LTO builds of executables we will have extra knowledge that a symbol
>      resolved to a local definition and can't be preemptable, but have no way to
>      propagate that knowledge through the compiler.
>
> This patch adds preemptability specifiers to the IR with the following meaning:
>
> dso_local --> means the compiler may assume the symbol will resolve to a
>  definition within the current linkage unit and the symbol may be accessed
>  directly even if the definition is not within this compilation unit.
>
> dso_preemptable --> means that the compiler must assume the GlobalValue may be
> replaced with a definition from outside the current linkage unit at runtime.
>
> To ease transitioning dso_preemptable is treated as a 'default' in that
> low-level codegen will still do the same checks it did previously to see if a
> symbol should be accessed indirectly. Eventually when IR producers emit the
> specifiers on all Globalvalues we can change dso_preemptable to mean 'always
> access indirectly', and remove the current logic.
>
> Differential Revision: https://reviews.llvm.org/D20217
>
> Added:
>     llvm/trunk/test/Assembler/dllimport-dsolocal-diag.ll
>     llvm/trunk/test/Assembler/ifunc-dsolocal-daig.ll
>     llvm/trunk/test/Bitcode/dso_location.ll
>     llvm/trunk/test/CodeGen/PowerPC/preemption.ll
>     llvm/trunk/test/CodeGen/X86/darwin-preemption.ll
>     llvm/trunk/test/CodeGen/X86/linux-preemption.ll
>     llvm/trunk/test/CodeGen/X86/win32-preemption.ll
> Modified:
>     llvm/trunk/docs/BitCodeFormat.rst
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm/IR/GlobalValue.h
>     llvm/trunk/lib/AsmParser/LLLexer.cpp
>     llvm/trunk/lib/AsmParser/LLParser.cpp
>     llvm/trunk/lib/AsmParser/LLParser.h
>     llvm/trunk/lib/AsmParser/LLToken.h
>     llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>     llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>     llvm/trunk/lib/IR/AsmWriter.cpp
>     llvm/trunk/lib/IR/Globals.cpp
>     llvm/trunk/lib/IR/Verifier.cpp
>     llvm/trunk/lib/Target/TargetMachine.cpp
>
> Modified: llvm/trunk/docs/BitCodeFormat.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/docs/BitCodeFormat.rst (original)
> +++ llvm/trunk/docs/BitCodeFormat.rst Thu Oct 26 08:00:26 2017
> @@ -681,7 +681,7 @@ for each library name referenced.
>  MODULE_CODE_GLOBALVAR Record
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  
> -``[GLOBALVAR, strtab offset, strtab size, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, externally_initialized, dllstorageclass, comdat]``
> +``[GLOBALVAR, strtab offset, strtab size, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, externally_initialized, dllstorageclass, comdat, attributes, preemptionspecifier]``
>  
>  The ``GLOBALVAR`` record (code 7) marks the declaration or definition of a
>  global variable. The operand fields are:
> @@ -761,12 +761,21 @@ global variable. The operand fields are:
>  
>  * *comdat*: An encoding of the COMDAT of this function
>  
> +* *attributes*: If nonzero, the 1-based index into the table of AttributeLists.
> +
> +.. _bcpreemptionspecifier:
> +
> +* *preemptionspecifier*: If present, an encoding of the runtime preemption specifier of this variable:
> +
> +  * ``dso_preemptable``: code 0
> +  * ``dso_local``: code 1
> +
>  .. _FUNCTION:
>  
>  MODULE_CODE_FUNCTION Record
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>  
> -``[FUNCTION, strtab offset, strtab size, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]``
> +``[FUNCTION, strtab offset, strtab size, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn, preemptionspecifier]``
>  
>  The ``FUNCTION`` record (code 8) marks the declaration or definition of a
>  function. The operand fields are:
> @@ -828,10 +837,12 @@ function. The operand fields are:
>  * *personalityfn*: If non-zero, the value index of the personality function for this function,
>    plus 1.
>  
> +* *preemptionspecifier*: If present, an encoding of the :ref:`runtime preemption specifier<bcpreemptionspecifier>`  of this function.
> + 
>  MODULE_CODE_ALIAS Record
>  ^^^^^^^^^^^^^^^^^^^^^^^^
>  
> -``[ALIAS, strtab offset, strtab size, alias type, aliasee val#, linkage, visibility, dllstorageclass, threadlocal, unnamed_addr]``
> +``[ALIAS, strtab offset, strtab size, alias type, aliasee val#, linkage, visibility, dllstorageclass, threadlocal, unnamed_addr, preemptionspecifier]``
>  
>  The ``ALIAS`` record (code 9) marks the definition of an alias. The operand
>  fields are
> @@ -856,6 +867,8 @@ fields are
>  * *unnamed_addr*: If present, an encoding of the
>    :ref:`unnamed_addr<bcunnamedaddr>` attribute of this alias
>  
> +* *preemptionspecifier*: If present, an encoding of the :ref:`runtime preemption specifier<bcpreemptionspecifier>`  of this alias.
> +
>  .. _MODULE_CODE_GCNAME:
>  
>  MODULE_CODE_GCNAME Record
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Thu Oct 26 08:00:26 2017
> @@ -527,6 +527,24 @@ the alias is accessed. It will not have
>  For platforms without linker support of ELF TLS model, the -femulated-tls
>  flag can be used to generate GCC compatible emulated TLS code.
>  
> +.. _runtime_preemption_model:
> +
> +Runtime Preemption Specifiers
> +-----------------------------
> +
> +Global variables, functions and aliases may have an optional runtime preemption
> +specifier. If a preemption specifier isn't given explicitly, then a
> +symbol is assumed to be ``dso_preemptable``.
> +
> +``dso_preemptable``
> +    Indicates that the function or variable may be replaced by a symbol from
> +    outside the linkage unit at runtime.
> +
> +``dso_local``
> +    The compiler may assume that a function or variable marked as ``dso_local``
> +    will resolve to a symbol within the same linkage unit. Direct access will 
> +    be generated even if the definition is not within this compilation unit.
> +
>  .. _namedtypes:
>  
>  Structure Types
> @@ -650,6 +668,7 @@ iterate over them as an array, alignment
>  iteration. The maximum alignment is ``1 << 29``.
>  
>  Globals can also have a :ref:`DLL storage class <dllstorageclass>`,
> +an optional :ref:`runtime preemption specifier <runtime_preemption_model>`,
>  an optional :ref:`global attributes <glattrs>` and
>  an optional list of attached :ref:`metadata <metadata>`.
>  
> @@ -658,7 +677,8 @@ Variables and aliases can have a
>  
>  Syntax::
>  
> -      @<GlobalVarName> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal]
> +      @<GlobalVarName> = [Linkage] [PreemptionSpecifier] [Visibility]
> +                         [DLLStorageClass] [ThreadLocal]
>                           [(unnamed_addr|local_unnamed_addr)] [AddrSpace]
>                           [ExternallyInitialized]
>                           <global | constant> <Type> [<InitializerConstant>]
> @@ -691,7 +711,8 @@ Functions
>  ---------
>  
>  LLVM function definitions consist of the "``define``" keyword, an
> -optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
> +optional :ref:`linkage type <linkage>`, an optional :ref:`runtime preemption
> +specifier <runtime_preemption_model>`,  an optional :ref:`visibility
>  style <visibility>`, an optional :ref:`DLL storage class <dllstorageclass>`,
>  an optional :ref:`calling convention <callingconv>`,
>  an optional ``unnamed_addr`` attribute, a return type, an optional
> @@ -750,7 +771,7 @@ not be significant within the module.
>  
>  Syntax::
>  
> -    define [linkage] [visibility] [DLLStorageClass]
> +    define [linkage] [PreemptionSpecifier] [visibility] [DLLStorageClass]
>             [cconv] [ret attrs]
>             <ResultType> @<FunctionName> ([argument list])
>             [(unnamed_addr|local_unnamed_addr)] [fn Attrs] [section "name"]
> @@ -777,12 +798,13 @@ Aliases have a name and an aliasee that
>  constant expression.
>  
>  Aliases may have an optional :ref:`linkage type <linkage>`, an optional
> +:ref:`runtime preemption specifier <runtime_preemption_model>`, an optional
>  :ref:`visibility style <visibility>`, an optional :ref:`DLL storage class
>  <dllstorageclass>` and an optional :ref:`tls model <tls_model>`.
>  
>  Syntax::
>  
> -    @<Name> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
> +    @<Name> = [Linkage] [PreemptionSpecifier] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
>  
>  The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``,
>  ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers
>
> Modified: llvm/trunk/include/llvm/IR/GlobalValue.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/GlobalValue.h?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/GlobalValue.h (original)
> +++ llvm/trunk/include/llvm/IR/GlobalValue.h Thu Oct 26 08:00:26 2017
> @@ -80,13 +80,14 @@ protected:
>          ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility),
>          UnnamedAddrVal(unsigned(UnnamedAddr::None)),
>          DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal),
> -        HasLLVMReservedName(false), IntID((Intrinsic::ID)0U), Parent(nullptr) {
> +        HasLLVMReservedName(false), IsDSOLocal(false),
> +        IntID((Intrinsic::ID)0U), Parent(nullptr) {
>      setName(Name);
>    }
>  
>    Type *ValueType;
>  
> -  static const unsigned GlobalValueSubClassDataBits = 18;
> +  static const unsigned GlobalValueSubClassDataBits = 17;
>  
>    // All bitfields use unsigned as the underlying type so that MSVC will pack
>    // them.
> @@ -103,11 +104,15 @@ protected:
>    /// 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:
>    friend class Constant;
>  
>    // Give subclasses access to what otherwise would be wasted padding.
> -  // (18 + 4 + 2 + 2 + 2 + 3 + 1) == 32.
> +  // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32.
>    unsigned SubClassData : GlobalValueSubClassDataBits;
>  
>    void destroyConstantImpl();
> @@ -261,6 +266,12 @@ public:
>  
>    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;
>    }
>
> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Thu Oct 26 08:00:26 2017
> @@ -494,6 +494,9 @@ lltok::Kind LLLexer::LexIdentifier() {
>    KEYWORD(declare); KEYWORD(define);
>    KEYWORD(global);  KEYWORD(constant);
>  
> +  KEYWORD(dso_local);
> +  KEYWORD(dso_preemptable);
> +
>    KEYWORD(private);
>    KEYWORD(internal);
>    KEYWORD(available_externally);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Thu Oct 26 08:00:26 2017
> @@ -483,10 +483,12 @@ bool LLParser::ParseOptionalUnnamedAddr(
>  
>  /// ParseUnnamedGlobal:
>  ///   OptionalVisibility (ALIAS | IFUNC) ...
> -///   OptionalLinkage OptionalVisibility OptionalDLLStorageClass
> +///   OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility
> +///   OptionalDLLStorageClass
>  ///                                                     ...   -> global variable
>  ///   GlobalID '=' OptionalVisibility (ALIAS | IFUNC) ...
> -///   GlobalID '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
> +///   GlobalID '=' OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility
> +///                OptionalDLLStorageClass
>  ///                                                     ...   -> global variable
>  bool LLParser::ParseUnnamedGlobal() {
>    unsigned VarID = NumberedVals.size();
> @@ -506,23 +508,26 @@ bool LLParser::ParseUnnamedGlobal() {
>  
>    bool HasLinkage;
>    unsigned Linkage, Visibility, DLLStorageClass;
> +  bool DSOLocal;
>    GlobalVariable::ThreadLocalMode TLM;
>    GlobalVariable::UnnamedAddr UnnamedAddr;
> -  if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) ||
> +  if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass,
> +                           DSOLocal) ||
>        ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr))
>      return true;
>  
>    if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
>      return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
> -                       DLLStorageClass, TLM, UnnamedAddr);
> +                       DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
>  
>    return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility,
> -                             DLLStorageClass, TLM, UnnamedAddr);
> +                             DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
>  }
>  
>  /// ParseNamedGlobal:
>  ///   GlobalVar '=' OptionalVisibility (ALIAS | IFUNC) ...
> -///   GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
> +///   GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier
> +///                 OptionalVisibility OptionalDLLStorageClass
>  ///                                                     ...   -> global variable
>  bool LLParser::ParseNamedGlobal() {
>    assert(Lex.getKind() == lltok::GlobalVar);
> @@ -532,19 +537,21 @@ bool LLParser::ParseNamedGlobal() {
>  
>    bool HasLinkage;
>    unsigned Linkage, Visibility, DLLStorageClass;
> +  bool DSOLocal;
>    GlobalVariable::ThreadLocalMode TLM;
>    GlobalVariable::UnnamedAddr UnnamedAddr;
>    if (ParseToken(lltok::equal, "expected '=' in global variable") ||
> -      ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) ||
> +      ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass,
> +                           DSOLocal) ||
>        ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr))
>      return true;
>  
>    if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc)
>      return ParseGlobal(Name, NameLoc, Linkage, HasLinkage, Visibility,
> -                       DLLStorageClass, TLM, UnnamedAddr);
> +                       DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
>  
>    return parseIndirectSymbol(Name, NameLoc, Linkage, Visibility,
> -                             DLLStorageClass, TLM, UnnamedAddr);
> +                             DLLStorageClass, DSOLocal, TLM, UnnamedAddr);
>  }
>  
>  bool LLParser::parseComdat() {
> @@ -709,19 +716,21 @@ static bool isValidVisibilityForLinkage(
>  }
>  
>  /// parseIndirectSymbol:
> -///   ::= GlobalVar '=' OptionalLinkage OptionalVisibility
> -///                     OptionalDLLStorageClass OptionalThreadLocal
> -///                     OptionalUnnamedAddr 'alias|ifunc' IndirectSymbol
> +///   ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier 
> +///                     OptionalVisibility OptionalDLLStorageClass
> +///                     OptionalThreadLocal OptionalUnnamedAddr
> +//                      'alias|ifunc' IndirectSymbol
>  ///
>  /// IndirectSymbol
>  ///   ::= TypeAndValue
>  ///
>  /// Everything through OptionalUnnamedAddr has already been parsed.
>  ///
> -bool LLParser::parseIndirectSymbol(
> -    const std::string &Name, LocTy NameLoc, unsigned L, unsigned Visibility,
> -    unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM,
> -    GlobalVariable::UnnamedAddr UnnamedAddr) {
> +bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc,
> +                                   unsigned L, unsigned Visibility,
> +                                   unsigned DLLStorageClass, bool DSOLocal,
> +                                   GlobalVariable::ThreadLocalMode TLM,
> +                                   GlobalVariable::UnnamedAddr UnnamedAddr) {
>    bool IsAlias;
>    if (Lex.getKind() == lltok::kw_alias)
>      IsAlias = true;
> @@ -740,6 +749,11 @@ bool LLParser::parseIndirectSymbol(
>      return Error(NameLoc,
>                   "symbol with local linkage must have default visibility");
>  
> +  if (DSOLocal && !IsAlias) {
> +    return Error(NameLoc,
> +                 "dso_local is invalid on ifunc");
> +  }
> +
>    Type *Ty;
>    LocTy ExplicitTypeLoc = Lex.getLoc();
>    if (ParseType(Ty) ||
> @@ -812,6 +826,7 @@ bool LLParser::parseIndirectSymbol(
>    GA->setVisibility((GlobalValue::VisibilityTypes)Visibility);
>    GA->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
>    GA->setUnnamedAddr(UnnamedAddr);
> +  GA->setDSOLocal(DSOLocal);
>  
>    if (Name.empty())
>      NumberedVals.push_back(GA.get());
> @@ -843,12 +858,14 @@ bool LLParser::parseIndirectSymbol(
>  }
>  
>  /// ParseGlobal
> -///   ::= GlobalVar '=' OptionalLinkage OptionalVisibility OptionalDLLStorageClass
> -///       OptionalThreadLocal OptionalUnnamedAddr OptionalAddrSpace
> -///       OptionalExternallyInitialized GlobalType Type Const OptionalAttrs
> -///   ::= OptionalLinkage OptionalVisibility OptionalDLLStorageClass
> +///   ::= GlobalVar '=' OptionalLinkage OptionalPreemptionSpecifier
> +///       OptionalVisibility OptionalDLLStorageClass
>  ///       OptionalThreadLocal OptionalUnnamedAddr OptionalAddrSpace
>  ///       OptionalExternallyInitialized GlobalType Type Const OptionalAttrs
> +///   ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility
> +///       OptionalDLLStorageClass OptionalThreadLocal OptionalUnnamedAddr
> +///       OptionalAddrSpace OptionalExternallyInitialized GlobalType Type
> +///       Const OptionalAttrs
>  ///
>  /// Everything up to and including OptionalUnnamedAddr has been parsed
>  /// already.
> @@ -856,7 +873,7 @@ bool LLParser::parseIndirectSymbol(
>  bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
>                             unsigned Linkage, bool HasLinkage,
>                             unsigned Visibility, unsigned DLLStorageClass,
> -                           GlobalVariable::ThreadLocalMode TLM,
> +                           bool DSOLocal, GlobalVariable::ThreadLocalMode TLM,
>                             GlobalVariable::UnnamedAddr UnnamedAddr) {
>    if (!isValidVisibilityForLinkage(Visibility, Linkage))
>      return Error(NameLoc,
> @@ -930,6 +947,7 @@ bool LLParser::ParseGlobal(const std::st
>      GV->setInitializer(Init);
>    GV->setConstant(IsConstant);
>    GV->setLinkage((GlobalValue::LinkageTypes)Linkage);
> +  GV->setDSOLocal(DSOLocal);
>    GV->setVisibility((GlobalValue::VisibilityTypes)Visibility);
>    GV->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
>    GV->setExternallyInitialized(IsExternallyInitialized);
> @@ -1608,15 +1626,38 @@ static unsigned parseOptionalLinkageAux(
>  ///   ::= 'external'
>  bool LLParser::ParseOptionalLinkage(unsigned &Res, bool &HasLinkage,
>                                      unsigned &Visibility,
> -                                    unsigned &DLLStorageClass) {
> +                                    unsigned &DLLStorageClass,
> +                                    bool &DSOLocal) {
>    Res = parseOptionalLinkageAux(Lex.getKind(), HasLinkage);
>    if (HasLinkage)
>      Lex.Lex();
> +  ParseOptionalDSOLocal(DSOLocal);
>    ParseOptionalVisibility(Visibility);
>    ParseOptionalDLLStorageClass(DLLStorageClass);
> +
> +  if (DSOLocal && DLLStorageClass == GlobalValue::DLLImportStorageClass) {
> +    return Error(Lex.getLoc(), "dso_location and DLL-StorageClass mismatch");
> +  }
> +
>    return false;
>  }
>  
> +void LLParser::ParseOptionalDSOLocal(bool &DSOLocal) {
> +  switch (Lex.getKind()) {
> +  default:
> +    DSOLocal = false;
> +    break;
> +  case lltok::kw_dso_local:
> +    DSOLocal = true;
> +    Lex.Lex();
> +    break;
> +  case lltok::kw_dso_preemptable:
> +    DSOLocal = false;
> +    Lex.Lex();
> +    break;
> +  }
> +}
> +
>  /// ParseOptionalVisibility
>  ///   ::= /*empty*/
>  ///   ::= 'default'
> @@ -4699,22 +4740,24 @@ bool LLParser::ParseTypeAndBasicBlock(Ba
>  }
>  
>  /// FunctionHeader
> -///   ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs
> -///       OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs OptSection
> -///       OptionalAlign OptGC OptionalPrefix OptionalPrologue OptPersonalityFn
> +///   ::= OptionalLinkage OptionalPreemptionSpecifier OptionalVisibility
> +///       OptionalCallingConv OptRetAttrs OptUnnamedAddr Type GlobalName
> +///       '(' ArgList ')' OptFuncAttrs OptSection OptionalAlign OptGC
> +///       OptionalPrefix OptionalPrologue OptPersonalityFn
>  bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
>    // Parse the linkage.
>    LocTy LinkageLoc = Lex.getLoc();
>    unsigned Linkage;
> -
>    unsigned Visibility;
>    unsigned DLLStorageClass;
> +  bool DSOLocal;
>    AttrBuilder RetAttrs;
>    unsigned CC;
>    bool HasLinkage;
>    Type *RetType = nullptr;
>    LocTy RetTypeLoc = Lex.getLoc();
> -  if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) ||
> +  if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass,
> +                           DSOLocal) ||
>        ParseOptionalCallingConv(CC) || ParseOptionalReturnAttrs(RetAttrs) ||
>        ParseType(RetType, RetTypeLoc, true /*void allowed*/))
>      return true;
> @@ -4876,6 +4919,7 @@ bool LLParser::ParseFunctionHeader(Funct
>      NumberedVals.push_back(Fn);
>  
>    Fn->setLinkage((GlobalValue::LinkageTypes)Linkage);
> +  Fn->setDSOLocal(DSOLocal);
>    Fn->setVisibility((GlobalValue::VisibilityTypes)Visibility);
>    Fn->setDLLStorageClass((GlobalValue::DLLStorageClassTypes)DLLStorageClass);
>    Fn->setCallingConv(CC);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.h (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.h Thu Oct 26 08:00:26 2017
> @@ -240,7 +240,9 @@ namespace llvm {
>      bool ParseOptionalParamAttrs(AttrBuilder &B);
>      bool ParseOptionalReturnAttrs(AttrBuilder &B);
>      bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage,
> -                              unsigned &Visibility, unsigned &DLLStorageClass);
> +                              unsigned &Visibility, unsigned &DLLStorageClass,
> +                              bool &DSOLocal);
> +    void ParseOptionalDSOLocal(bool &DSOLocal);
>      void ParseOptionalVisibility(unsigned &Visibility);
>      void ParseOptionalDLLStorageClass(unsigned &DLLStorageClass);
>      bool ParseOptionalCallingConv(unsigned &CC);
> @@ -284,12 +286,12 @@ namespace llvm {
>      bool ParseNamedGlobal();
>      bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage,
>                       bool HasLinkage, unsigned Visibility,
> -                     unsigned DLLStorageClass,
> +                     unsigned DLLStorageClass, bool DSOLocal,
>                       GlobalVariable::ThreadLocalMode TLM,
>                       GlobalVariable::UnnamedAddr UnnamedAddr);
>      bool parseIndirectSymbol(const std::string &Name, LocTy Loc,
>                               unsigned Linkage, unsigned Visibility,
> -                             unsigned DLLStorageClass,
> +                             unsigned DLLStorageClass, bool DSOLocal,
>                               GlobalVariable::ThreadLocalMode TLM,
>                               GlobalVariable::UnnamedAddr UnnamedAddr);
>      bool parseComdat();
>
> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> +++ llvm/trunk/lib/AsmParser/LLToken.h Thu Oct 26 08:00:26 2017
> @@ -45,6 +45,9 @@ enum Kind {
>    kw_global,
>    kw_constant,
>  
> +  kw_dso_local,
> +  kw_dso_preemptable,
> +
>    kw_private,
>    kw_internal,
>    kw_linkonce,
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Thu Oct 26 08:00:26 2017
> @@ -911,6 +911,14 @@ getDecodedDLLStorageClass(unsigned Val)
>    }
>  }
>  
> +static bool getDecodedDSOLocal(unsigned Val) {
> +  switch(Val) {
> +  default: // Map unknown values to preemptable.
> +  case 0:  return false;
> +  case 1:  return true;
> +  }
> +}
> +
>  static GlobalVariable::ThreadLocalMode getDecodedThreadLocalMode(unsigned Val) {
>    switch (Val) {
>      case 0: return GlobalVariable::NotThreadLocal;
> @@ -2803,7 +2811,7 @@ Error BitcodeReader::parseComdatRecord(A
>  Error BitcodeReader::parseGlobalVarRecord(ArrayRef<uint64_t> Record) {
>    // v1: [pointer type, isconst, initid, linkage, alignment, section,
>    // visibility, threadlocal, unnamed_addr, externally_initialized,
> -  // dllstorageclass, comdat, attributes] (name in VST)
> +  // dllstorageclass, comdat, attributes, preemption specifier] (name in VST)
>    // v2: [strtab_offset, strtab_size, v1]
>    StringRef Name;
>    std::tie(Name, Record) = readNameFromStrtab(Record);
> @@ -2888,13 +2896,18 @@ Error BitcodeReader::parseGlobalVarRecor
>      auto AS = getAttributes(Record[12]).getFnAttributes();
>      NewGV->setAttributes(AS);
>    }
> +
> +  if (Record.size() > 13) {
> +    NewGV->setDSOLocal(getDecodedDSOLocal(Record[13]));
> +  }
> +
>    return Error::success();
>  }
>  
>  Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
>    // v1: [type, callingconv, isproto, linkage, paramattr, alignment, section,
>    // visibility, gc, unnamed_addr, prologuedata, dllstorageclass, comdat,
> -  // prefixdata] (name in VST)
> +  // prefixdata,  personalityfn, preemption specifier] (name in VST)
>    // v2: [strtab_offset, strtab_size, v1]
>    StringRef Name;
>    std::tie(Name, Record) = readNameFromStrtab(Record);
> @@ -2968,6 +2981,10 @@ Error BitcodeReader::parseFunctionRecord
>    if (Record.size() > 14 && Record[14] != 0)
>      FunctionPersonalityFns.push_back(std::make_pair(Func, Record[14] - 1));
>  
> +  if (Record.size() > 15) {
> +    Func->setDSOLocal(getDecodedDSOLocal(Record[15]));
> +  }
> +
>    ValueList.push_back(Func);
>  
>    // If this is a function with a body, remember the prototype we are
> @@ -2984,9 +3001,11 @@ Error BitcodeReader::parseGlobalIndirect
>      unsigned BitCode, ArrayRef<uint64_t> Record) {
>    // v1 ALIAS_OLD: [alias type, aliasee val#, linkage] (name in VST)
>    // v1 ALIAS: [alias type, addrspace, aliasee val#, linkage, visibility,
> -  // dllstorageclass] (name in VST)
> +  // dllstorageclass, threadlocal, unnamed_addr,
> +  // preemption specifier] (name in VST)
>    // v1 IFUNC: [alias type, addrspace, aliasee val#, linkage,
> -  // visibility, dllstorageclass] (name in VST)
> +  // visibility, dllstorageclass, threadlocal, unnamed_addr,
> +  // preemption specifier] (name in VST)
>    // v2: [strtab_offset, strtab_size, v1]
>    StringRef Name;
>    std::tie(Name, Record) = readNameFromStrtab(Record);
> @@ -3036,6 +3055,8 @@ Error BitcodeReader::parseGlobalIndirect
>      NewGA->setThreadLocalMode(getDecodedThreadLocalMode(Record[OpNum++]));
>    if (OpNum != Record.size())
>      NewGA->setUnnamedAddr(getDecodedUnnamedAddrType(Record[OpNum++]));
> +  if (OpNum != Record.size())
> +    NewGA->setDSOLocal(getDecodedDSOLocal(Record[OpNum++]));
>    ValueList.push_back(NewGA);
>    IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
>    return Error::success();
>
> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Thu Oct 26 08:00:26 2017
> @@ -1197,7 +1197,7 @@ void ModuleBitcodeWriter::writeModuleInf
>      // GLOBALVAR: [strtab offset, strtab size, type, isconst, initid,
>      //             linkage, alignment, section, visibility, threadlocal,
>      //             unnamed_addr, externally_initialized, dllstorageclass,
> -    //             comdat, attributes]
> +    //             comdat, attributes, DSO_Local]
>      Vals.push_back(addToStrtab(GV.getName()));
>      Vals.push_back(GV.getName().size());
>      Vals.push_back(VE.getTypeID(GV.getValueType()));
> @@ -1213,7 +1213,8 @@ void ModuleBitcodeWriter::writeModuleInf
>          GV.isExternallyInitialized() ||
>          GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass ||
>          GV.hasComdat() ||
> -        GV.hasAttributes()) {
> +        GV.hasAttributes() ||
> +        GV.isDSOLocal()) {
>        Vals.push_back(getEncodedVisibility(GV));
>        Vals.push_back(getEncodedThreadLocalMode(GV));
>        Vals.push_back(getEncodedUnnamedAddr(GV));
> @@ -1223,6 +1224,8 @@ void ModuleBitcodeWriter::writeModuleInf
>  
>        auto AL = GV.getAttributesAsList(AttributeList::FunctionIndex);
>        Vals.push_back(VE.getAttributeListID(AL));
> +
> +      Vals.push_back(GV.isDSOLocal());
>      } else {
>        AbbrevToUse = SimpleGVarAbbrev;
>      }
> @@ -1236,7 +1239,7 @@ void ModuleBitcodeWriter::writeModuleInf
>      // FUNCTION:  [strtab offset, strtab size, type, callingconv, isproto,
>      //             linkage, paramattrs, alignment, section, visibility, gc,
>      //             unnamed_addr, prologuedata, dllstorageclass, comdat,
> -    //             prefixdata, personalityfn]
> +    //             prefixdata, personalityfn, DSO_Local]
>      Vals.push_back(addToStrtab(F.getName()));
>      Vals.push_back(F.getName().size());
>      Vals.push_back(VE.getTypeID(F.getFunctionType()));
> @@ -1258,6 +1261,7 @@ void ModuleBitcodeWriter::writeModuleInf
>      Vals.push_back(
>          F.hasPersonalityFn() ? (VE.getValueID(F.getPersonalityFn()) + 1) : 0);
>  
> +    Vals.push_back(F.isDSOLocal());
>      unsigned AbbrevToUse = 0;
>      Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
>      Vals.clear();
> @@ -1266,7 +1270,8 @@ void ModuleBitcodeWriter::writeModuleInf
>    // Emit the alias information.
>    for (const GlobalAlias &A : M.aliases()) {
>      // ALIAS: [strtab offset, strtab size, alias type, aliasee val#, linkage,
> -    //         visibility, dllstorageclass, threadlocal, unnamed_addr]
> +    //         visibility, dllstorageclass, threadlocal, unnamed_addr,
> +    //         DSO_Local]
>      Vals.push_back(addToStrtab(A.getName()));
>      Vals.push_back(A.getName().size());
>      Vals.push_back(VE.getTypeID(A.getValueType()));
> @@ -1277,6 +1282,8 @@ void ModuleBitcodeWriter::writeModuleInf
>      Vals.push_back(getEncodedDLLStorageClass(A));
>      Vals.push_back(getEncodedThreadLocalMode(A));
>      Vals.push_back(getEncodedUnnamedAddr(A));
> +    Vals.push_back(A.isDSOLocal());
> +
>      unsigned AbbrevToUse = 0;
>      Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
>      Vals.clear();
>
> Modified: llvm/trunk/lib/IR/AsmWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/AsmWriter.cpp (original)
> +++ llvm/trunk/lib/IR/AsmWriter.cpp Thu Oct 26 08:00:26 2017
> @@ -2493,6 +2493,11 @@ static void PrintVisibility(GlobalValue:
>    }
>  }
>  
> +static void PrintDSOLocation(bool IsDSOLocal, formatted_raw_ostream &Out){
> +  if (IsDSOLocal)
> +    Out << "dso_local ";
> +}
> +
>  static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,
>                                   formatted_raw_ostream &Out) {
>    switch (SCT) {
> @@ -2563,6 +2568,7 @@ void AssemblyWriter::printGlobal(const G
>      Out << "external ";
>  
>    Out << getLinkagePrintName(GV->getLinkage());
> +  PrintDSOLocation(GV->isDSOLocal(), Out);
>    PrintVisibility(GV->getVisibility(), Out);
>    PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
>    PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
> @@ -2609,6 +2615,7 @@ void AssemblyWriter::printIndirectSymbol
>    Out << " = ";
>  
>    Out << getLinkagePrintName(GIS->getLinkage());
> +  PrintDSOLocation(GIS->isDSOLocal(), Out);
>    PrintVisibility(GIS->getVisibility(), Out);
>    PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);
>    PrintThreadLocalModel(GIS->getThreadLocalMode(), Out);
> @@ -2720,6 +2727,7 @@ void AssemblyWriter::printFunction(const
>      Out << "define ";
>  
>    Out << getLinkagePrintName(F->getLinkage());
> +  PrintDSOLocation(F->isDSOLocal(), Out);
>    PrintVisibility(F->getVisibility(), Out);
>    PrintDLLStorageClass(F->getDLLStorageClass(), Out);
>  
>
> Modified: llvm/trunk/lib/IR/Globals.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Globals.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Globals.cpp (original)
> +++ llvm/trunk/lib/IR/Globals.cpp Thu Oct 26 08:00:26 2017
> @@ -67,6 +67,7 @@ void GlobalValue::copyAttributesFrom(con
>    setVisibility(Src->getVisibility());
>    setUnnamedAddr(Src->getUnnamedAddr());
>    setDLLStorageClass(Src->getDLLStorageClass());
> +  setDSOLocal(Src->isDSOLocal());
>  }
>  
>  void GlobalValue::removeFromParent() {
>
> Modified: llvm/trunk/lib/IR/Verifier.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Verifier.cpp (original)
> +++ llvm/trunk/lib/IR/Verifier.cpp Thu Oct 26 08:00:26 2017
> @@ -568,6 +568,10 @@ void Verifier::visitGlobalValue(const Gl
>    if (GV.isDeclarationForLinker())
>      Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV);
>  
> +  if (GV.hasDLLImportStorageClass())
> +    Assert(!GV.isDSOLocal(),
> +           "GlobalValue with DLLImport Storage is dso_local!", &GV);
> +
>    forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {
>      if (const Instruction *I = dyn_cast<Instruction>(V)) {
>        if (!I->getParent() || !I->getParent()->getParent())
>
> Modified: llvm/trunk/lib/Target/TargetMachine.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetMachine.cpp?rev=316668&r1=316667&r2=316668&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/TargetMachine.cpp (original)
> +++ llvm/trunk/lib/Target/TargetMachine.cpp Thu Oct 26 08:00:26 2017
> @@ -128,7 +128,8 @@ bool TargetMachine::shouldAssumeDSOLocal
>    if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO()))
>      return true;
>  
> -  if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility()))
> +  if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility() ||
> +              GV->isDSOLocal()))
>      return true;
>  
>    if (TT.isOSBinFormatMachO()) {
>
> Added: llvm/trunk/test/Assembler/dllimport-dsolocal-diag.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/dllimport-dsolocal-diag.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/Assembler/dllimport-dsolocal-diag.ll (added)
> +++ llvm/trunk/test/Assembler/dllimport-dsolocal-diag.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,4 @@
> +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
> +
> +declare dso_local dllimport void @fun()
> +; CHECK: error: dso_location and DLL-StorageClass mismatch
>
> Added: llvm/trunk/test/Assembler/ifunc-dsolocal-daig.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/ifunc-dsolocal-daig.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/Assembler/ifunc-dsolocal-daig.ll (added)
> +++ llvm/trunk/test/Assembler/ifunc-dsolocal-daig.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,9 @@
> +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
> +
> + at foo = dso_local ifunc i32 (i32), i64 ()* @foo_ifunc
> +; CHECK: error: dso_local is invalid on ifunc
> +
> +define internal i64 @foo_ifunc() {
> +entry:
> +  ret i64 0
> +}
>
> Added: llvm/trunk/test/Bitcode/dso_location.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/dso_location.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/Bitcode/dso_location.ll (added)
> +++ llvm/trunk/test/Bitcode/dso_location.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,47 @@
> +; RUN: llvm-as < %s | llvm-dis | FileCheck %s
> +
> +; Tests parsing for the dso_local keyword as well as the serialization/
> +; deserialization of the dso_local value on GlobalValues.
> +
> + at local_global = dso_local global i32 0
> +; CHECK: @local_global = dso_local global i32 0
> +
> + at weak_local_global = weak dso_local global i32 0
> +; CHECK: @weak_local_global = weak dso_local global i32 0
> +
> + at external_local_global = external dso_local global i32
> +; CHECK: @external_local_global = external dso_local global i32
> +
> + at default_local_global = dso_local default global i32 0
> +; CHECK: @default_local_global = dso_local global i32 0
> +
> + at hidden_local_global = dso_local hidden global i32 0
> +; CHECK: @hidden_local_global = dso_local hidden global i32 0
> +
> + at protected_local_global = dso_local protected global i32 0
> +; CHECK: @protected_local_global = dso_local protected global i32 0
> +
> + at local_alias = dso_local alias i32, i32* @local_global
> +; CHECK-DAG: @local_alias = dso_local alias i32, i32* @local_global
> +
> + at preemptable_alias = dso_preemptable alias i32, i32* @hidden_local_global
> +; CHECK-DAG: @preemptable_alias = alias i32, i32* @hidden_local_global
> +
> + at preemptable_ifunc = dso_preemptable ifunc void (), i8* ()* @ifunc_resolver
> +; CHECK-DAG: @preemptable_ifunc = ifunc void (), i8* ()* @ifunc_resolver
> +declare dso_local default void @default_local()
> +; CHECK: declare dso_local void @default_local()
> +
> +declare dso_local hidden void @hidden_local()
> +; CHECK: declare dso_local hidden void @hidden_local()
> +
> +define dso_local protected void @protected_local() {
> +; CHECK: define dso_local protected void @protected_local()
> +entry:
> +  ret void
> +}
> +
> +define i8* @ifunc_resolver() {
> +entry:
> +  ret i8* null
> +}
>
> Added: llvm/trunk/test/CodeGen/PowerPC/preemption.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/preemption.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/PowerPC/preemption.ll (added)
> +++ llvm/trunk/test/CodeGen/PowerPC/preemption.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,301 @@
> +; RUN: llc -mtriple powerpc64le-unkown-gnu-linux  < %s |  FileCheck %s
> +; RUN: llc -mtriple powerpc64le-unkown-gnu-linux -relocation-model=static \
> +; RUN: < %s |  FileCheck --check-prefix=STATIC %s
> +; RUN: llc -mtriple powerpc64le-unkown-gnu-linux -relocation-model=pic \
> +; RUN: < %s |  FileCheck %s
> +
> +; globals
> +
> + at strong_default = global i32 55
> +define i32* @get_strong_default() #0 {
> +  ret i32* @strong_default
> +
> +; STATIC-LABEL: @get_strong_default
> +; STATIC: addis 3, 2, strong_default at toc@ha
> +; STATIC: addi 3, 3, strong_default at toc@l
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_strong_default
> +; CHECK: addis 3, 2, .LC0 at toc@ha
> +; CHECK: ld 3, .LC0 at toc@l(3)
> +; CHECK: blr
> +}
> +
> + at weak_default = weak global i32 55
> +define i32* @get_weak_default() #0 {
> +  ret i32* @weak_default
> +
> +; STATIC-LABEL: @get_weak_default
> +; STATIC: addis 3, 2, weak_default at toc@ha
> +; STATIC: addi 3, 3, weak_default at toc@l
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_weak_default
> +; CHECK: addis 3, 2, .LC1 at toc@ha
> +; CHECK: ld 3, .LC1 at toc@l(3)
> +; CHECK: blr
> +}
> +
> + at external_default_global = external global i32
> +define i32* @get_external_default_global() {
> +  ret i32* @external_default_global
> +
> +; STATIC-LABEL: @get_external_default_global
> +; STATIC: addis 3, 2, .LC0 at toc@ha
> +; STATIC: ld 3, .LC0 at toc@l(3)
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_external_default_global
> +; CHECK: addis 3, 2, .LC2 at toc@ha
> +; CHECK: ld 3, .LC2 at toc@l(3)
> +; CHECK: blr
> +}
> +
> +
> + at strong_local_global = dso_local global i32 55
> +define i32* @get_strong_local_global() {
> +  ret i32* @strong_local_global
> +
> +; STATIC-LABEL: @get_strong_local_global
> +; STATIC:       addis 3, 2, strong_local_global at toc@ha
> +; STATIC:       addi 3, 3, strong_local_global at toc@l
> +; STATIC:       blr
> +
> +; CHECK-LABEL: @get_strong_local_global
> +; CHECK:       addis 3, 2, strong_local_global at toc@ha
> +; CHECK:       addi 3, 3, strong_local_global at toc@l
> +; CHECK:       blr
> +}
> +
> + at weak_local_global = weak dso_local global i32 42
> +define i32* @get_weak_local_global() {
> +  ret i32* @weak_local_global
> +
> +; STATIC-LABEL: @get_weak_local_global
> +; STATIC:       addis 3, 2, weak_local_global at toc@ha
> +; STATIC:       addi 3, 3, weak_local_global at toc@l
> +; STATIC:       blr
> +
> +; CHECK-LABEL: @get_weak_local_global
> +; CHECK:       addis 3, 2, weak_local_global at toc@ha
> +; CHECK:       addi 3, 3, weak_local_global at toc@l
> +; CHECK:       blr
> +}
> +
> + at external_local_global = external dso_local global i32
> +define i32* @get_external_local_global() {
> +  ret i32* @external_local_global
> +; STATIC-LABEL: @get_external_local_global
> +; STATIC:       addis 3, 2, external_local_global at toc@ha
> +; STATIC:       addi 3, 3, external_local_global at toc@l
> +; STATIC:       blr
> +
> +; CHECK-LABEL: @get_external_local_global
> +; CHECK:       addis 3, 2, external_local_global at toc@ha
> +; CHECK:       addi 3, 3, external_local_global at toc@l
> +; CHECK:       blr
> +}
> +
> + at strong_preemptable_global = dso_preemptable global i32 42
> +define i32* @get_strong_preemptable_global() {
> +  ret i32* @strong_preemptable_global
> +
> +; STATIC-LABEL: @get_strong_preemptable_global
> +; STATIC: addis 3, 2, strong_preemptable_global at toc@ha
> +; STATIC: addi 3, 3, strong_preemptable_global at toc@l
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_strong_preemptable_global
> +; CHECK: addis 3, 2, .LC3 at toc@ha
> +; CHECK: ld 3, .LC3 at toc@l(3)
> +; CHECK: blr
> +}
> +
> + at weak_preemptable_global = weak dso_preemptable global i32 42
> +define i32* @get_weak_preemptable_global() {
> +  ret i32* @weak_preemptable_global
> +
> +; STATIC-LABEL: @get_weak_preemptable_global
> +; STATIC: addis 3, 2, weak_preemptable_global at toc@ha
> +; STATIC: addi 3, 3, weak_preemptable_global at toc@l
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_weak_preemptable_global
> +; CHECK: addis 3, 2, .LC4 at toc@ha
> +; CHECK: ld 3, .LC4 at toc@l(3)
> +; CHECK: blr
> +}
> +
> + at external_preemptable_global = external dso_preemptable global i32
> +define i32* @get_external_preemptable_global() {
> +  ret i32* @external_preemptable_global
> +
> +; STATIC-LABEL: @get_external_preemptable_global
> +; STATIC: addis 3, 2, .LC1 at toc@ha
> +; STATIC: ld 3, .LC1 at toc@l(3)
> +; STATIC: blr
> +
> +; CHECK-LABEL: @get_external_preemptable_global
> +; CHECK: addis 3, 2, .LC5 at toc@ha
> +; CHECK: ld 3, .LC5 at toc@l(3)
> +; CHECK: blr
> +}
> +
> +; functions
> +define signext i32 @strong_default_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @strong_default_function_caller(i32 %i) {
> +  %call = notail call signext i32 @strong_default_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @strong_default_function_caller
> +; STATIC:       bl strong_default_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @strong_default_function_caller
> +; CHECK:        bl strong_default_function
> +; CHECK-NEXT:   nop
> +; CHECK:        blr
> +}
> +
> +define weak signext i32 @weak_default_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @weak_default_function_caller(i32 %i) {
> +  %call = notail call signext i32 @weak_default_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @weak_default_function_caller
> +; STATIC:       bl weak_default_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @weak_default_function_caller
> +; CHECK:        bl weak_default_function
> +; CHECK-NEXT:   nop
> +; CHECK:        blr
> +}
> +
> +
> +declare i32 @external_default_function(i32 %i)
> +define i32 @external_default_function_caller(i32 %i) {
> +  %call = notail call signext i32  @external_default_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @external_default_function_caller
> +; STATIC:       bl external_default_function
> +; STATIC-NEXT:  nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @external_default_function_caller
> +; CHECK:        bl external_default_function
> +; CHECK-NEXT:   nop
> +; CHECK:        blr
> +}
> +
> +define dso_local signext i32 @strong_local_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @strong_local_function_caller(i32 %i) {
> +  %call = notail call signext i32 @strong_local_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @strong_local_function_caller
> +; STATIC:       bl strong_local_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @strong_local_function_caller
> +; CHECK:        bl strong_local_function
> +; CHECK-NOT:    nop
> +; CHECK:        blr
> +}
> +
> +define weak dso_local signext i32 @weak_local_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @weak_local_function_caller(i32 %i) {
> +  %call = notail call signext i32 @weak_local_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @weak_local_function_caller
> +; STATIC:       bl weak_local_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @weak_local_function_caller
> +; CHECK:        bl weak_local_function
> +; CHECK-NOT:    nop
> +; CHECK:        blr
> +}
> +
> +declare dso_local i32 @external_local_function(i32 %i)
> +define i32 @external_local_function_caller(i32 %i) {
> +  %call = notail call signext i32  @external_local_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @external_local_function_caller
> +; STATIC:       bl external_local_function
> +; STATIC-NOT:  nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @external_local_function_caller
> +; CHECK:        bl external_local_function
> +; CHECK-NOT:    nop
> +; CHECK:        blr
> +}
> +
> +define dso_preemptable signext i32 @strong_preemptable_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @strong_preemptable_function_caller(i32 %i) {
> +  %call = notail call signext i32 @strong_preemptable_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @strong_preemptable_function_caller
> +; STATIC:       bl strong_preemptable_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @strong_preemptable_function_caller
> +; CHECK:        bl strong_preemptable_function
> +; CHECK-NEXT:   nop
> +; CHECK:        blr
> +}
> +
> +define weak dso_preemptable signext i32 @weak_preemptable_function(i32 %i) {
> +  ret i32 %i
> +}
> +define signext i32 @weak_preemptable_function_caller(i32 %i) {
> +  %call = notail call signext i32 @weak_preemptable_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @weak_preemptable_function_caller
> +; STATIC:       bl weak_preemptable_function
> +; STATIC-NOT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @weak_preemptable_function_caller
> +; CHECK:        bl weak_preemptable_function
> +; CHECK-NEXT:   nop
> +; CHECK:        blr
> +}
> +
> +declare dso_preemptable i32 @external_preemptable_function(i32 %i)
> +define i32 @external_preemptable_function_caller(i32 %i) {
> +  %call = notail call signext i32  @external_preemptable_function(i32 signext %i)
> +  ret i32 %call
> +
> +; STATIC-LABEL: @external_preemptable_function_caller
> +; STATIC:       bl external_preemptable_function
> +; STATIC-NEXT:   nop
> +; STATIC:       blr
> +
> +; CHECK-LABEL:  @external_preemptable_function_caller
> +; CHECK:        bl external_preemptable_function
> +; CHECK-NEXT:    nop
> +; CHECK:        blr
> +}
> +
>
> Added: llvm/trunk/test/CodeGen/X86/darwin-preemption.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/darwin-preemption.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/darwin-preemption.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/darwin-preemption.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,251 @@
> +; RUN: llc -mtriple x86_64-apple-darwin \
> +; RUN:     -relocation-model=static          < %s | FileCheck %s
> +; RUN: llc -mtriple x86_64-apple-darwin \
> +; RUN:     -relocation-model=pic             < %s | FileCheck %s
> +; RUN: llc -mtriple x86_64-apple-darwin \
> +; RUN:     -relocation-model=dynamic-no-pic  < %s | FileCheck %s
> +
> +; 32 bits
> +
> +; RUN: llc -mtriple i386-apple-darwin \
> +; RUN:    -relocation-model=static < %s | FileCheck --check-prefix=DARWIN32_S %s
> +; RUN: llc -mtriple i386-apple-darwin \
> +; RUN:     -relocation-model=pic     < %s | FileCheck --check-prefix=DARWIN32 %s
> +; RUN: llc -mtriple i386-apple-darwin \
> +; RUN:   -relocation-model=dynamic-no-pic < %s | \
> +; RUN:   FileCheck --check-prefix=DARWIN32_DNP %s
> +
> +; globals
> +
> + at strong_default_global = global i32 42
> +define i32* @get_strong_default_global() {
> +  ret i32* @strong_default_global
> +}
> +; CHECK: leaq _strong_default_global(%rip), %rax
> +; DARWIN32: leal _strong_default_global-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_default_global, %eax
> +; DARWIN32_DNP: movl $_strong_default_global, %eax
> +
> + at weak_default_global = weak global i32 42
> +define i32* @get_weak_default_global() {
> +  ret i32* @weak_default_global
> +}
> +; CHECK: movq _weak_default_global at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_default_global$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_default_global, %eax
> +; DARWIN32_DNP: movl L_weak_default_global$non_lazy_ptr, %eax
> +
> + at external_default_global = external global i32
> +define i32* @get_external_default_global() {
> +  ret i32* @external_default_global
> +}
> +; CHECK: movq _external_default_global at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_external_default_global$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_default_global, %eax
> +; DARWIN32_DNP: movl L_external_default_global$non_lazy_ptr, %eax
> +
> + at strong_local_global = dso_local global i32 42
> +define i32* @get_strong_local_global() {
> +  ret i32* @strong_local_global
> +}
> +; CHECK: leaq _strong_local_global(%rip), %rax
> +; DARWIN32: leal _strong_local_global-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_local_global, %eax
> +; DARWIN32_DNP: movl $_strong_local_global, %eax
> +
> + at weak_local_global = weak dso_local global i32 42
> +define i32* @get_weak_local_global() {
> +  ret i32* @weak_local_global
> +}
> +; CHECK: leaq _weak_local_global(%rip), %rax
> +; DARWIN32: leal _weak_local_global-L{{.}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_local_global, %eax
> +; DARWIN32_DNP: movl $_weak_local_global, %eax
> +
> + at external_local_global = external dso_local global i32
> +define i32* @get_external_local_global() {
> +  ret i32* @external_local_global
> +}
> +; CHECK: leaq _external_local_global(%rip), %rax
> +; DARWIN32: movl L_external_local_global$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_local_global, %eax
> +; DARWIN32_DNP: movl $_external_local_global, %eax
> +
> + at strong_preemptable_global = dso_preemptable global i32 42
> +define i32* @get_strong_preemptable_global() {
> +  ret i32* @strong_preemptable_global
> +}
> +; CHECK: leaq _strong_preemptable_global(%rip), %rax
> +; DARWIN32: leal _strong_preemptable_global-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_preemptable_global, %eax
> +; DARWIN32_DNP: movl $_strong_preemptable_global, %eax
> +
> + at weak_preemptable_global = weak dso_preemptable global i32 42
> +define i32* @get_weak_preemptable_global() {
> +  ret i32* @weak_preemptable_global
> +}
> +; CHECK: movq _weak_preemptable_global at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_preemptable_global$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_preemptable_global, %eax
> +; DARWIN32_DNP: movl L_weak_preemptable_global$non_lazy_ptr, %eax
> +
> + at external_preemptable_global = external dso_preemptable global i32
> +define i32* @get_external_preemptable_global() {
> +  ret i32* @external_preemptable_global
> +}
> +; CHECK: movq _external_preemptable_global at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_external_preemptable_global$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_preemptable_global, %eax
> +; DARWIN32_DNP: movl L_external_preemptable_global$non_lazy_ptr, %eax
> +
> +; aliases
> + at aliasee = global i32 42
> +
> + at strong_default_alias = alias i32, i32* @aliasee
> +define i32* @get_strong_default_alias() {
> +  ret i32* @strong_default_alias
> +}
> +; CHECK: leaq _strong_default_alias(%rip), %rax
> +; DARWIN32: leal _strong_default_alias-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_default_alias, %eax
> +; DARWIN32_DNP: movl $_strong_default_alias, %eax
> +
> + at weak_default_alias = weak alias i32, i32* @aliasee
> +define i32* @get_weak_default_alias() {
> +  ret i32* @weak_default_alias
> +}
> +; CHECK: movq _weak_default_alias at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_default_alias$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_default_alias, %eax
> +; DARWIN32_DNP: movl L_weak_default_alias$non_lazy_ptr, %eax
> +
> + at strong_local_alias = dso_local alias i32, i32* @aliasee
> +define i32* @get_strong_local_alias() {
> +  ret i32* @strong_local_alias
> +}
> +; CHECK: leaq _strong_local_alias(%rip), %rax
> +; DARWIN32: leal _strong_local_alias-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_local_alias, %eax
> +; DARWIN32_DNP: movl $_strong_local_alias, %eax
> +
> + at weak_local_alias = weak dso_local alias i32, i32* @aliasee
> +define i32* @get_weak_local_alias() {
> +  ret i32* @weak_local_alias
> +}
> +; CHECK: leaq _weak_local_alias(%rip), %rax
> +; DARWIN32: leal _weak_local_alias-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_local_alias, %eax
> +; DARWIN32_DNP: movl $_weak_local_alias, %eax
> +
> + at strong_preemptable_alias = dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_strong_preemptable_alias() {
> +  ret i32* @strong_preemptable_alias
> +}
> +; CHECK: leaq _strong_preemptable_alias(%rip), %rax
> +; DARWIN32: leal _strong_preemptable_alias-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_preemptable_alias, %eax
> +; DARWIN32_DNP: movl $_strong_preemptable_alias, %eax
> +
> + at weak_preemptable_alias = weak dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_weak_preemptable_alias() {
> +  ret i32* @weak_preemptable_alias
> +}
> +; CHECK: movq _weak_preemptable_alias at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_preemptable_alias$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_preemptable_alias, %eax
> +; DARWIN32_DNP: movl L_weak_preemptable_alias$non_lazy_ptr, %eax
> +
> +; functions
> +
> +define void @strong_default_function() {
> +  ret void
> +}
> +define void()* @get_strong_default_function() {
> +  ret void()* @strong_default_function
> +}
> +; CHECK: leaq _strong_default_function(%rip), %rax
> +; DARWIN32: leal _strong_default_function-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_default_function, %eax
> +; DARWIN32_DNP: movl $_strong_default_function, %eax
> +
> +define weak void @weak_default_function() {
> +  ret void
> +}
> +define void()* @get_weak_default_function() {
> +  ret void()* @weak_default_function
> +}
> +; CHECK: movq _weak_default_function at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_default_function$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_default_function, %eax
> +; DARWIN32_DNP: movl L_weak_default_function$non_lazy_ptr, %eax
> +
> +declare void @external_default_function()
> +define void()* @get_external_default_function() {
> +  ret void()* @external_default_function
> +}
> +; CHECK: movq _external_default_function at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_external_default_function$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_default_function, %eax
> +; DARWIN32_DNP: movl L_external_default_function$non_lazy_ptr, %eax
> +
> +define dso_local void @strong_local_function() {
> +  ret void
> +}
> +define void()* @get_strong_local_function() {
> +  ret void()* @strong_local_function
> +}
> +; CHECK: leaq _strong_local_function(%rip), %rax
> +; DARWIN32: leal _strong_local_function-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_local_function, %eax
> +; DARWIN32_DNP: movl $_strong_local_function, %eax
> +
> +define weak dso_local void @weak_local_function() {
> +  ret void
> +}
> +define void()* @get_weak_local_function() {
> +  ret void()* @weak_local_function
> +}
> +; CHECK: leaq _weak_local_function(%rip), %rax
> +; DARWIN32: leal _weak_local_function-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_local_function, %eax
> +; DARWIN32_DNP: movl $_weak_local_function, %eax
> +
> +declare dso_local void @external_local_function()
> +define void()* @get_external_local_function() {
> +  ret void()* @external_local_function
> +}
> +; CHECK: leaq _external_local_function(%rip), %rax
> +; DARWIN32: movl L_external_local_function$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_local_function, %eax
> +; DARWIN32_DNP: movl $_external_local_function, %eax
> +
> +define dso_preemptable void @strong_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_strong_preemptable_function() {
> +  ret void()* @strong_preemptable_function
> +}
> +; CHECK: leaq _strong_preemptable_function(%rip), %rax
> +; DARWIN32: leal _strong_preemptable_function-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_strong_preemptable_function, %eax
> +; DARWIN32_DNP: movl $_strong_preemptable_function, %eax
> +
> +define weak dso_preemptable void @weak_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_weak_preemptable_function() {
> +  ret void()* @weak_preemptable_function
> +}
> +; CHECK: movq _weak_preemptable_function at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_weak_preemptable_function$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_weak_preemptable_function, %eax
> +; DARWIN32_DNP: movl L_weak_preemptable_function$non_lazy_ptr, %eax
> +
> +declare dso_preemptable void @external_preemptable_function()
> +define void()* @get_external_preemptable_function() {
> +  ret void()* @external_preemptable_function
> +}
> +; CHECK: movq _external_preemptable_function at GOTPCREL(%rip), %rax
> +; DARWIN32: movl L_external_preemptable_function$non_lazy_ptr-L{{.*}}$pb(%eax), %eax
> +; DARWIN32_S: movl $_external_preemptable_function, %eax
> +; DARWIN32_DNP: movl L_external_preemptable_function$non_lazy_ptr, %eax
>
> Added: llvm/trunk/test/CodeGen/X86/linux-preemption.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/linux-preemption.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/linux-preemption.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/linux-preemption.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,225 @@
> +; RUN: llc -mtriple x86_64-pc-linux \
> +; RUN:     -relocation-model=static  < %s | FileCheck --check-prefix=STATIC %s
> +; RUN: llc -mtriple x86_64-pc-linux \
> +; RUN:     -relocation-model=pic             < %s | FileCheck %s
> +; RUN: llc -mtriple x86_64-pc-linux \
> +; RUN:     -relocation-model=dynamic-no-pic  < %s | FileCheck %s
> +
> +; 32 bits
> +
> +; RUN: llc -mtriple i386-pc-linux \
> +; RUN:     -relocation-model=pic     < %s | FileCheck --check-prefix=CHECK32 %s
> +
> +; globals
> +
> + at strong_default_global = global i32 42
> +define i32* @get_strong_default_global() {
> +  ret i32* @strong_default_global
> +}
> +; CHECK: movq strong_default_global at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_default_global, %eax
> +; CHECK32: movl strong_default_global at GOT(%eax), %eax
> +
> + at weak_default_global = weak global i32 42
> +define i32* @get_weak_default_global() {
> +  ret i32* @weak_default_global
> +}
> +; CHECK: movq weak_default_global at GOTPCREL(%rip), %rax
> +; STATIC: movl $weak_default_global, %eax
> +; CHECK32: movl weak_default_global at GOT(%eax), %eax
> +
> + at external_default_global = external global i32
> +define i32* @get_external_default_global() {
> +  ret i32* @external_default_global
> +}
> +; CHECK: movq external_default_global at GOTPCREL(%rip), %rax
> +; STATIC: movl $external_default_global, %eax
> +; CHECK32: movl external_default_global at GOT(%eax), %eax
> +
> + at strong_local_global = dso_local global i32 42
> +define i32* @get_strong_local_global() {
> +  ret i32* @strong_local_global
> +}
> +; CHECK: leaq strong_local_global(%rip), %rax
> +; STATIC: movl $strong_local_global, %eax
> +; CHECK32: leal strong_local_global at GOTOFF(%eax), %eax
> +
> + at weak_local_global = weak dso_local global i32 42
> +define i32* @get_weak_local_global() {
> +  ret i32* @weak_local_global
> +}
> +; CHECK: leaq weak_local_global(%rip), %rax
> +; STATIC: movl $weak_local_global, %eax
> +; CHECK32: leal weak_local_global at GOTOFF(%eax), %eax
> +
> + at external_local_global = external dso_local global i32
> +define i32* @get_external_local_global() {
> +  ret i32* @external_local_global
> +}
> +; CHECK: leaq external_local_global(%rip), %rax
> +; STATIC: movl $external_local_global, %eax
> +; CHECK32: leal external_local_global at GOTOFF(%eax), %eax
> +
> +
> + at strong_preemptable_global = dso_preemptable global i32 42
> +define i32* @get_strong_preemptable_global() {
> +  ret i32* @strong_preemptable_global
> +}
> +; CHECK: movq strong_preemptable_global at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_preemptable_global, %eax
> +; CHECK32: movl strong_preemptable_global at GOT(%eax), %eax
> +
> + at weak_preemptable_global = weak dso_preemptable global i32 42
> +define i32* @get_weak_preemptable_global() {
> +  ret i32* @weak_preemptable_global
> +}
> +; CHECK ;ADD_LABEL_BACK;  movq weak_preemptable_global at GOTPCREL(%rip), %rax
> +; STATIC ;ADD_LABEL_BACK; movq weak_preemptable_global at GOTPCREL, %rax
> +; CHECK32 ;ADD_LABEL_BACK; movl weak_preemptable_global at GOT(%eax), %eax
> +
> + at external_preemptable_global = external dso_preemptable global i32
> +define i32* @get_external_preemptable_global() {
> +  ret i32* @external_preemptable_global
> +}
> +; CHECK: movq external_preemptable_global at GOTPCREL(%rip), %rax
> +; STATIC: movl $external_preemptable_global, %eax
> +; CHECK32: movl external_preemptable_global at GOT(%eax), %eax
> +
> +; aliases
> + at aliasee = global i32 42
> +
> + at strong_default_alias = alias i32, i32* @aliasee
> +define i32* @get_strong_default_alias() {
> +  ret i32* @strong_default_alias
> +}
> +; CHECK: movq strong_default_alias at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_default_alias, %eax
> +; CHECK32: movl strong_default_alias at GOT(%eax), %eax
> +
> + at weak_default_alias = weak alias i32, i32* @aliasee
> +define i32* @get_weak_default_alias() {
> +  ret i32* @weak_default_alias
> +}
> +; CHECK: movq weak_default_alias at GOTPCREL(%rip), %rax
> +; STATIC: movl $weak_default_alias, %eax
> +; CHECK32: movl weak_default_alias at GOT(%eax), %eax
> +
> + at strong_local_alias = dso_local alias i32, i32* @aliasee
> +define i32* @get_strong_local_alias() {
> +  ret i32* @strong_local_alias
> +}
> +; CHECK: leaq strong_local_alias(%rip), %rax
> +; STATIC: movl $strong_local_alias, %eax
> +; CHECK32: leal strong_local_alias at GOTOFF(%eax), %eax
> +
> + at weak_local_alias = weak dso_local alias i32, i32* @aliasee
> +define i32* @get_weak_local_alias() {
> +  ret i32* @weak_local_alias
> +}
> +; CHECK: leaq weak_local_alias(%rip), %rax
> +; STATIC: movl $weak_local_alias, %eax
> +; CHECK32: leal weak_local_alias at GOTOFF(%eax), %eax
> +
> +
> + at strong_preemptable_alias = dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_strong_preemptable_alias() {
> +  ret i32* @strong_preemptable_alias
> +}
> +; CHECK: movq strong_preemptable_alias at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_preemptable_alias, %eax
> +; CHECK32: movl strong_preemptable_alias at GOT(%eax), %eax
> +
> + at weak_preemptable_alias = weak dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_weak_preemptable_alias() {
> +  ret i32* @weak_preemptable_alias
> +}
> +; CHECK: movq weak_preemptable_alias at GOTPCREL(%rip), %rax
> +; STATIC: movl $weak_preemptable_alias, %eax
> +; CHECK32: movl weak_preemptable_alias at GOT(%eax), %eax
> +
> +; functions
> +
> +define void @strong_default_function() {
> +  ret void
> +}
> +define void()* @get_strong_default_function() {
> +  ret void()* @strong_default_function
> +}
> +; CHECK: movq strong_default_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_default_function, %eax
> +; CHECK32: movl strong_default_function at GOT(%eax), %eax
> +
> +define weak void @weak_default_function() {
> +  ret void
> +}
> +define void()* @get_weak_default_function() {
> +  ret void()* @weak_default_function
> +}
> +; CHECK: movq weak_default_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $weak_default_function, %eax
> +; CHECK32: movl weak_default_function at GOT(%eax), %eax
> +
> +declare void @external_default_function()
> +define void()* @get_external_default_function() {
> +  ret void()* @external_default_function
> +}
> +; CHECK: movq external_default_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $external_default_function, %eax
> +; CHECK32: movl external_default_function at GOT(%eax), %eax
> +
> +define dso_local void @strong_local_function() {
> +  ret void
> +}
> +define void()* @get_strong_local_function() {
> +  ret void()* @strong_local_function
> +}
> +; CHECK: leaq strong_local_function(%rip), %rax
> +; STATIC: movl $strong_local_function, %eax
> +; CHECK32: leal strong_local_function at GOTOFF(%eax), %eax
> +
> +define weak dso_local void @weak_local_function() {
> +  ret void
> +}
> +define void()* @get_weak_local_function() {
> +  ret void()* @weak_local_function
> +}
> +; CHECK: leaq weak_local_function(%rip), %rax
> +; STATIC: movl $weak_local_function, %eax
> +; CHECK32: leal weak_local_function at GOTOFF(%eax), %eax
> +
> +declare dso_local void @external_local_function()
> +define void()* @get_external_local_function() {
> +  ret void()* @external_local_function
> +}
> +; CHECK: leaq external_local_function(%rip), %rax
> +; STATIC: movl $external_local_function, %eax
> +; CHECK32: leal external_local_function at GOTOFF(%eax), %eax
> +
> +
> +define dso_preemptable void @strong_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_strong_preemptable_function() {
> +  ret void()* @strong_preemptable_function
> +}
> +; CHECK: movq strong_preemptable_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $strong_preemptable_function, %eax
> +; CHECK32: movl strong_preemptable_function at GOT(%eax), %eax
> +
> +define weak dso_preemptable void @weak_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_weak_preemptable_function() {
> +  ret void()* @weak_preemptable_function
> +}
> +; CHECK: movq weak_preemptable_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $weak_preemptable_function, %eax
> +; CHECK32: movl weak_preemptable_function at GOT(%eax), %eax
> +
> +declare dso_preemptable void @external_preemptable_function()
> +define void()* @get_external_preemptable_function() {
> +  ret void()* @external_preemptable_function
> +}
> +; CHECK: movq external_preemptable_function at GOTPCREL(%rip), %rax
> +; STATIC: movl $external_preemptable_function, %eax
> +; CHECK32: movl external_preemptable_function at GOT(%eax), %eax
>
> Added: llvm/trunk/test/CodeGen/X86/win32-preemption.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-preemption.ll?rev=316668&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/win32-preemption.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/win32-preemption.ll Thu Oct 26 08:00:26 2017
> @@ -0,0 +1,236 @@
> +; RUN: llc -mtriple x86_64-pc-win32 \
> +; RUN:     -relocation-model=static  < %s | FileCheck --check-prefix=COFF_S %s
> +; RUN: llc -mtriple x86_64-pc-win32 \
> +; RUN:     -relocation-model=pic     < %s | FileCheck --check-prefix=COFF %s
> +; RUN: llc -mtriple x86_64-pc-win32 \
> +; RUN:  -relocation-model=dynamic-no-pic < %s | FileCheck --check-prefix=COFF %s
> +
> +
> +; 32 bits
> +
> +; RUN: llc -mtriple i386-pc-win32 \
> +; RUN:    -relocation-model=static  < %s | FileCheck --check-prefix=COFF32 %s
> +; RUN: llc -mtriple i386-pc-win32 \
> +; RUN:     -relocation-model=pic     < %s | FileCheck --check-prefix=COFF32 %s
> +; RUN: llc -mtriple i386-pc-win32 \
> +; RUN:   -relocation-model=dynamic-no-pic < %s | \
> +; RUN:   FileCheck --check-prefix=COFF32 %s
> +
> +; globals
> +
> + at strong_default_global = global i32 42
> +define i32* @get_strong_default_global() {
> +  ret i32* @strong_default_global
> +}
> +; COFF: leaq strong_default_global(%rip), %rax
> +; COFF_S: movl $strong_default_global, %eax
> +; COFF32: movl $_strong_default_global, %eax
> +
> + at weak_default_global = weak global i32 42
> +define i32* @get_weak_default_global() {
> +  ret i32* @weak_default_global
> +}
> +; COFF: leaq weak_default_global(%rip), %rax
> +; COFF_S: movl $weak_default_global, %eax
> +; COFF32: movl $_weak_default_global, %eax
> +
> + at external_default_global = external global i32
> +define i32* @get_external_default_global() {
> +  ret i32* @external_default_global
> +}
> +; COFF: leaq external_default_global(%rip), %rax
> +; COFF_S: movl $external_default_global, %eax
> +; COFF32: movl $_external_default_global, %eax
> +
> +
> + at strong_local_global = dso_local global i32 42
> +define i32* @get_strong_local_global() {
> +  ret i32* @strong_local_global
> +}
> +; COFF: leaq strong_local_global(%rip), %rax
> +; COFF_S: movl $strong_local_global, %eax
> +; COFF32: movl $_strong_local_global, %eax
> +
> + at weak_local_global = weak dso_local global i32 42
> +define i32* @get_weak_local_global() {
> +  ret i32* @weak_local_global
> +}
> +; COFF: leaq weak_local_global(%rip), %rax
> +; COFF_S: movl $weak_local_global, %eax
> +; COFF32: movl $_weak_local_global, %eax
> +
> + at external_local_global = external dso_local global i32
> +define i32* @get_external_local_global() {
> +  ret i32* @external_local_global
> +}
> +; COFF: leaq external_local_global(%rip), %rax
> +; COFF_S: movl $external_local_global, %eax
> +; COFF32: movl $_external_local_global, %eax
> +
> +
> + at strong_preemptable_global = dso_preemptable global i32 42
> +define i32* @get_strong_preemptable_global() {
> +  ret i32* @strong_preemptable_global
> +}
> +; COFF: leaq strong_preemptable_global(%rip), %rax
> +; COFF_S: movl $strong_preemptable_global, %eax
> +; COFF32: movl $_strong_preemptable_global, %eax
> +
> + at weak_preemptable_global = weak dso_preemptable global i32 42
> +define i32* @get_weak_preemptable_global() {
> +  ret i32* @weak_preemptable_global
> +}
> +; COFF: leaq weak_preemptable_global(%rip), %rax
> +; COFF_S: movl $weak_preemptable_global, %eax
> +; COFF32: movl $_weak_preemptable_global, %eax
> +
> + at external_preemptable_global = external dso_preemptable global i32
> +define i32* @get_external_preemptable_global() {
> +  ret i32* @external_preemptable_global
> +}
> +; COFF: leaq external_preemptable_global(%rip), %rax
> +; COFF_S: movl $external_preemptable_global, %eax
> +; COFF32: movl $_external_preemptable_global, %eax
> +
> +
> +; aliases
> + at aliasee = global i32 42
> +
> + at strong_default_alias = alias i32, i32* @aliasee
> +define i32* @get_strong_default_alias() {
> +  ret i32* @strong_default_alias
> +}
> +; COFF: leaq strong_default_alias(%rip), %rax
> +; COFF_S: movl $strong_default_alias, %eax
> +; COFF32: movl $_strong_default_alias, %eax
> +
> + at weak_default_alias = weak alias i32, i32* @aliasee
> +define i32* @get_weak_default_alias() {
> +  ret i32* @weak_default_alias
> +}
> +; COFF: leaq weak_default_alias(%rip), %rax
> +; COFF_S: movl $weak_default_alias, %eax
> +; COFF32: movl $_weak_default_alias, %eax
> +
> +
> + at strong_local_alias = dso_local alias i32, i32* @aliasee
> +define i32* @get_strong_local_alias() {
> +  ret i32* @strong_local_alias
> +}
> +; COFF: leaq strong_local_alias(%rip), %rax
> +; COFF_S: movl $strong_local_alias, %eax
> +; COFF32: movl $_strong_local_alias, %eax
> +
> + at weak_local_alias = weak dso_local alias i32, i32* @aliasee
> +define i32* @get_weak_local_alias() {
> +  ret i32* @weak_local_alias
> +}
> +; COFF: leaq weak_local_alias(%rip), %rax
> +; COFF_S: movl $weak_local_alias, %eax
> +; COFF32: movl $_weak_local_alias, %eax
> +
> +
> + at strong_preemptable_alias = dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_strong_preemptable_alias() {
> +  ret i32* @strong_preemptable_alias
> +}
> +; COFF: leaq strong_preemptable_alias(%rip), %rax
> +; COFF_S: movl $strong_preemptable_alias, %eax
> +; COFF32: movl $_strong_preemptable_alias, %eax
> +
> + at weak_preemptable_alias = weak dso_preemptable alias i32, i32* @aliasee
> +define i32* @get_weak_preemptable_alias() {
> +  ret i32* @weak_preemptable_alias
> +}
> +; COFF: leaq weak_preemptable_alias(%rip), %rax
> +; COFF_S: movl $weak_preemptable_alias, %eax
> +; COFF32: movl $_weak_preemptable_alias, %eax
> +
> +
> +; functions
> +
> +define void @strong_default_function() {
> +  ret void
> +}
> +define void()* @get_strong_default_function() {
> +  ret void()* @strong_default_function
> +}
> +; COFF: leaq strong_default_function(%rip), %rax
> +; COFF_S: movl $strong_default_function, %eax
> +; COFF32: movl $_strong_default_function, %eax
> +
> +define weak void @weak_default_function() {
> +  ret void
> +}
> +define void()* @get_weak_default_function() {
> +  ret void()* @weak_default_function
> +}
> +; COFF: leaq weak_default_function(%rip), %rax
> +; COFF_S: movl $weak_default_function, %eax
> +; COFF32: movl $_weak_default_function, %eax
> +
> +declare void @external_default_function()
> +define void()* @get_external_default_function() {
> +  ret void()* @external_default_function
> +}
> +; COFF: leaq external_default_function(%rip), %rax
> +; COFF_S: movl $external_default_function, %eax
> +; COFF32: movl $_external_default_function, %eax
> +
> +
> +define dso_local void @strong_local_function() {
> +  ret void
> +}
> +define void()* @get_strong_local_function() {
> +  ret void()* @strong_local_function
> +}
> +; COFF: leaq strong_local_function(%rip), %rax
> +; COFF_S: movl $strong_local_function, %eax
> +; COFF32: movl $_strong_local_function, %eax
> +
> +define weak dso_local void @weak_local_function() {
> +  ret void
> +}
> +define void()* @get_weak_local_function() {
> +  ret void()* @weak_local_function
> +}
> +; COFF: leaq weak_local_function(%rip), %rax
> +; COFF_S: movl $weak_local_function, %eax
> +; COFF32: movl $_weak_local_function, %eax
> +
> +declare dso_local void @external_local_function()
> +define void()* @get_external_local_function() {
> +  ret void()* @external_local_function
> +}
> +; COFF: leaq external_local_function(%rip), %rax
> +; COFF_S: movl $external_local_function, %eax
> +; COFF32: movl $_external_local_function, %eax
> +
> +
> +define dso_preemptable void @strong_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_strong_preemptable_function() {
> +  ret void()* @strong_preemptable_function
> +}
> +; COFF: leaq strong_preemptable_function(%rip), %rax
> +; COFF_S: movl $strong_preemptable_function, %eax
> +; COFF32: movl $_strong_preemptable_function, %eax
> +
> +define weak dso_preemptable void @weak_preemptable_function() {
> +  ret void
> +}
> +define void()* @get_weak_preemptable_function() {
> +  ret void()* @weak_preemptable_function
> +}
> +; COFF: leaq weak_preemptable_function(%rip), %rax
> +; COFF_S: movl $weak_preemptable_function, %eax
> +; COFF32: movl $_weak_preemptable_function, %eax
> +
> +declare dso_preemptable void @external_preemptable_function()
> +define void()* @get_external_preemptable_function() {
> +  ret void()* @external_preemptable_function
> +}
> +; COFF: leaq external_preemptable_function(%rip), %rax
> +; COFF_S: movl $external_preemptable_function, %eax
> +; COFF32: movl $_external_preemptable_function, %eax
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list