[llvm] r190773 - Implement function prefix data as an IR feature.

Sean Silva silvas at purdue.edu
Mon Sep 23 12:41:39 PDT 2013


+A trivial example of valid prefix data for the x86 architecture is ``i8
144``,
+which encodes the ``nop`` instruction:
+
+.. code-block:: llvm
+
+    define void @f() prefix i8 144 { ... }
+
+Generally prefix data can be formed by encoding a relative branch
instruction
+which skips the metadata, as in this example of valid prefix data for the
+x86_64 architecture, where the first two bytes encode ``jmp .+10``:
+
+.. code-block:: llvm
+
+    %0 = type <{ i8, i8, i8* }>
+
+    define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... }
+
+A function may have prefix data but no body.  This has similar semantics
+to the ``available_externally`` linkage in that the data may be used by the
+optimizers but will not be emitted in the object file.
+

Can you be a bit more explicit about the endianness/layout of the emitted
data?

-- Sean Silva


On Sun, Sep 15, 2013 at 9:08 PM, Peter Collingbourne <peter at pcc.me.uk>wrote:

> Author: pcc
> Date: Sun Sep 15 20:08:15 2013
> New Revision: 190773
>
> URL: http://llvm.org/viewvc/llvm-project?rev=190773&view=rev
> Log:
> Implement function prefix data as an IR feature.
>
> Previous discussion:
> http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063909.html
>
> Differential Revision: http://llvm-reviews.chandlerc.com/D1191
>
> Added:
>     llvm/trunk/test/CodeGen/X86/prefixdata.ll
>     llvm/trunk/test/Feature/prefixdata.ll
>     llvm/trunk/test/Linker/prefixdata.ll
> Modified:
>     llvm/trunk/docs/BitCodeFormat.rst
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm/IR/Function.h
>     llvm/trunk/lib/AsmParser/LLLexer.cpp
>     llvm/trunk/lib/AsmParser/LLParser.cpp
>     llvm/trunk/lib/AsmParser/LLToken.h
>     llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>     llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
>     llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>     llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
>     llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
>     llvm/trunk/lib/IR/AsmWriter.cpp
>     llvm/trunk/lib/IR/Function.cpp
>     llvm/trunk/lib/IR/LLVMContextImpl.h
>     llvm/trunk/lib/IR/TypeFinder.cpp
>     llvm/trunk/lib/Linker/LinkModules.cpp
>     llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
>
> Modified: llvm/trunk/docs/BitCodeFormat.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/BitCodeFormat.rst (original)
> +++ llvm/trunk/docs/BitCodeFormat.rst Sun Sep 15 20:08:15 2013
> @@ -718,7 +718,7 @@ global variable. The operand fields are:
>  MODULE_CODE_FUNCTION Record
>  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment,
> section, visibility, gc]``
> +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment,
> section, visibility, gc, prefix]``
>
>  The ``FUNCTION`` record (code 8) marks the declaration or definition of a
>  function. The operand fields are:
> @@ -757,6 +757,9 @@ function. The operand fields are:
>  * *unnamed_addr*: If present and non-zero, indicates that the function has
>    ``unnamed_addr``
>
> +* *prefix*: If non-zero, the value index of the prefix data for this
> function,
> +  plus 1.
> +
>  MODULE_CODE_ALIAS Record
>  ^^^^^^^^^^^^^^^^^^^^^^^^
>
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Sun Sep 15 20:08:15 2013
> @@ -552,16 +552,16 @@ an optional ``unnamed_addr`` attribute,
>  name, a (possibly empty) argument list (each with optional :ref:`parameter
>  attributes <paramattrs>`), optional :ref:`function attributes <fnattrs>`,
>  an optional section, an optional alignment, an optional :ref:`garbage
> -collector name <gc>`, an opening curly brace, a list of basic blocks,
> -and a closing curly brace.
> +collector name <gc>`, an optional :ref:`prefix <prefixdata>`, an opening
> +curly brace, a list of basic blocks, and a closing curly brace.
>
>  LLVM function declarations consist of the "``declare``" keyword, an
>  optional :ref:`linkage type <linkage>`, an optional :ref:`visibility
>  style <visibility>`, an optional :ref:`calling convention <callingconv>`,
>  an optional ``unnamed_addr`` attribute, a return type, an optional
>  :ref:`parameter attribute <paramattrs>` for the return type, a function
> -name, a possibly empty list of arguments, an optional alignment, and an
> -optional :ref:`garbage collector name <gc>`.
> +name, a possibly empty list of arguments, an optional alignment, an
> optional
> +:ref:`garbage collector name <gc>` and an optional :ref:`prefix
> <prefixdata>`.
>
>  A function definition contains a list of basic blocks, forming the CFG
>  (Control Flow Graph) for the function. Each basic block may optionally
> @@ -598,7 +598,7 @@ Syntax::
>             [cconv] [ret attrs]
>             <ResultType> @<FunctionName> ([argument list])
>             [fn Attrs] [section "name"] [align N]
> -           [gc] { ... }
> +           [gc] [prefix Constant] { ... }
>
>  .. _langref_aliases:
>
> @@ -757,6 +757,50 @@ The compiler declares the supported valu
>  collector which will cause the compiler to alter its output in order to
>  support the named garbage collection algorithm.
>
> +.. _prefixdata:
> +
> +Prefix Data
> +-----------
> +
> +Prefix data is data associated with a function which the code generator
> +will emit immediately before the function body.  The purpose of this
> feature
> +is to allow frontends to associate language-specific runtime metadata with
> +specific functions and make it available through the function pointer
> while
> +still allowing the function pointer to be called.  To access the data for
> a
> +given function, a program may bitcast the function pointer to a pointer to
> +the constant's type.  This implies that the IR symbol points to the start
> +of the prefix data.
> +
> +To maintain the semantics of ordinary function calls, the prefix data must
> +have a particular format.  Specifically, it must begin with a sequence of
> +bytes which decode to a sequence of machine instructions, valid for the
> +module's target, which transfer control to the point immediately
> succeeding
> +the prefix data, without performing any other visible action.  This allows
> +the inliner and other passes to reason about the semantics of the function
> +definition without needing to reason about the prefix data.  Obviously
> this
> +makes the format of the prefix data highly target dependent.
> +
> +A trivial example of valid prefix data for the x86 architecture is ``i8
> 144``,
> +which encodes the ``nop`` instruction:
> +
> +.. code-block:: llvm
> +
> +    define void @f() prefix i8 144 { ... }
> +
> +Generally prefix data can be formed by encoding a relative branch
> instruction
> +which skips the metadata, as in this example of valid prefix data for the
> +x86_64 architecture, where the first two bytes encode ``jmp .+10``:
> +
> +.. code-block:: llvm
> +
> +    %0 = type <{ i8, i8, i8* }>
> +
> +    define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... }
> +
> +A function may have prefix data but no body.  This has similar semantics
> +to the ``available_externally`` linkage in that the data may be used by
> the
> +optimizers but will not be emitted in the object file.
> +
>  .. _attrgrp:
>
>  Attribute Groups
>
> Modified: llvm/trunk/include/llvm/IR/Function.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Function.h (original)
> +++ llvm/trunk/include/llvm/IR/Function.h Sun Sep 15 20:08:15 2013
> @@ -159,11 +159,11 @@ public:
>    /// calling convention of this function.  The enum values for the known
>    /// calling conventions are defined in CallingConv.h.
>    CallingConv::ID getCallingConv() const {
> -    return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 1);
> +    return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
>    }
>    void setCallingConv(CallingConv::ID CC) {
> -    setValueSubclassData((getSubclassDataFromValue() & 1) |
> -                         (static_cast<unsigned>(CC) << 1));
> +    setValueSubclassData((getSubclassDataFromValue() & 3) |
> +                         (static_cast<unsigned>(CC) << 2));
>    }
>
>    /// @brief Return the attribute list for this Function.
> @@ -427,6 +427,13 @@ public:
>    size_t arg_size() const;
>    bool arg_empty() const;
>
> +  bool hasPrefixData() const {
> +    return getSubclassDataFromValue() & 2;
> +  }
> +
> +  Constant *getPrefixData() const;
> +  void setPrefixData(Constant *PrefixData);
> +
>    /// viewCFG - This function is meant for use from the debugger.  You
> can just
>    /// say 'call F->viewCFG()' and a ghostview window should pop up from
> the
>    /// program, displaying the CFG of the current function with the code
> for each
>
> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Sun Sep 15 20:08:15 2013
> @@ -540,6 +540,7 @@ lltok::Kind LLLexer::LexIdentifier() {
>    KEYWORD(alignstack);
>    KEYWORD(inteldialect);
>    KEYWORD(gc);
> +  KEYWORD(prefix);
>
>    KEYWORD(ccc);
>    KEYWORD(fastcc);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Sun Sep 15 20:08:15 2013
> @@ -2922,7 +2922,7 @@ bool LLParser::ParseTypeAndBasicBlock(Ba
>  /// FunctionHeader
>  ///   ::= OptionalLinkage OptionalVisibility OptionalCallingConv
> OptRetAttrs
>  ///       OptUnnamedAddr Type GlobalName '(' ArgList ')' OptFuncAttrs
> OptSection
> -///       OptionalAlign OptGC
> +///       OptionalAlign OptGC OptionalPrefix
>  bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
>    // Parse the linkage.
>    LocTy LinkageLoc = Lex.getLoc();
> @@ -3001,6 +3001,7 @@ bool LLParser::ParseFunctionHeader(Funct
>    std::string GC;
>    bool UnnamedAddr;
>    LocTy UnnamedAddrLoc;
> +  Constant *Prefix = 0;
>
>    if (ParseArgumentList(ArgList, isVarArg) ||
>        ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
> @@ -3011,7 +3012,9 @@ bool LLParser::ParseFunctionHeader(Funct
>         ParseStringConstant(Section)) ||
>        ParseOptionalAlignment(Alignment) ||
>        (EatIfPresent(lltok::kw_gc) &&
> -       ParseStringConstant(GC)))
> +       ParseStringConstant(GC)) ||
> +      (EatIfPresent(lltok::kw_prefix) &&
> +       ParseGlobalTypeAndValue(Prefix)))
>      return true;
>
>    if (FuncAttrs.contains(Attribute::Builtin))
> @@ -3109,6 +3112,7 @@ bool LLParser::ParseFunctionHeader(Funct
>    Fn->setAlignment(Alignment);
>    Fn->setSection(Section);
>    if (!GC.empty()) Fn->setGC(GC.c_str());
> +  Fn->setPrefixData(Prefix);
>    ForwardRefAttrGroups[Fn] = FwdRefAttrGrps;
>
>    // Add all of the arguments we parsed to the function.
>
> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> +++ llvm/trunk/lib/AsmParser/LLToken.h Sun Sep 15 20:08:15 2013
> @@ -81,6 +81,7 @@ namespace lltok {
>      kw_alignstack,
>      kw_inteldialect,
>      kw_gc,
> +    kw_prefix,
>      kw_c,
>
>      kw_cc, kw_ccc, kw_fastcc, kw_coldcc,
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Sep 15 20:08:15
> 2013
> @@ -1106,9 +1106,11 @@ uint64_t BitcodeReader::decodeSignRotate
>  bool BitcodeReader::ResolveGlobalAndAliasInits() {
>    std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitWorklist;
>    std::vector<std::pair<GlobalAlias*, unsigned> > AliasInitWorklist;
> +  std::vector<std::pair<Function*, unsigned> > FunctionPrefixWorklist;
>
>    GlobalInitWorklist.swap(GlobalInits);
>    AliasInitWorklist.swap(AliasInits);
> +  FunctionPrefixWorklist.swap(FunctionPrefixes);
>
>    while (!GlobalInitWorklist.empty()) {
>      unsigned ValID = GlobalInitWorklist.back().second;
> @@ -1136,6 +1138,20 @@ bool BitcodeReader::ResolveGlobalAndAlia
>      }
>      AliasInitWorklist.pop_back();
>    }
> +
> +  while (!FunctionPrefixWorklist.empty()) {
> +    unsigned ValID = FunctionPrefixWorklist.back().second;
> +    if (ValID >= ValueList.size()) {
> +      FunctionPrefixes.push_back(FunctionPrefixWorklist.back());
> +    } else {
> +      if (Constant *C = dyn_cast<Constant>(ValueList[ValID]))
> +        FunctionPrefixWorklist.back().first->setPrefixData(C);
> +      else
> +        return Error("Function prefix is not a constant!");
> +    }
> +    FunctionPrefixWorklist.pop_back();
> +  }
> +
>    return false;
>  }
>
> @@ -1881,6 +1897,8 @@ bool BitcodeReader::ParseModule(bool Res
>        if (Record.size() > 9)
>          UnnamedAddr = Record[9];
>        Func->setUnnamedAddr(UnnamedAddr);
> +      if (Record.size() > 10 && Record[10] != 0)
> +        FunctionPrefixes.push_back(std::make_pair(Func, Record[10]-1));
>        ValueList.push_back(Func);
>
>        // If this is a function with a body, remember the prototype we are
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Sun Sep 15 20:08:15 2013
> @@ -142,6 +142,7 @@ class BitcodeReader : public GVMateriali
>
>    std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
>    std::vector<std::pair<GlobalAlias*, unsigned> > AliasInits;
> +  std::vector<std::pair<Function*, unsigned> > FunctionPrefixes;
>
>    /// MAttributes - The set of attributes by index.  Index zero in the
>    /// file is for null, and is thus not represented here.  As such all
> indices
>
> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sun Sep 15 20:08:15
> 2013
> @@ -632,7 +632,7 @@ static void WriteModuleInfo(const Module
>    // Emit the function proto information.
>    for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
>      // FUNCTION:  [type, callingconv, isproto, linkage, paramattrs,
> alignment,
> -    //             section, visibility, gc, unnamed_addr]
> +    //             section, visibility, gc, unnamed_addr, prefix]
>      Vals.push_back(VE.getTypeID(F->getType()));
>      Vals.push_back(F->getCallingConv());
>      Vals.push_back(F->isDeclaration());
> @@ -643,6 +643,8 @@ static void WriteModuleInfo(const Module
>      Vals.push_back(getEncodedVisibility(F));
>      Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
>      Vals.push_back(F->hasUnnamedAddr());
> +    Vals.push_back(F->hasPrefixData() ?
> (VE.getValueID(F->getPrefixData()) + 1)
> +                                      : 0);
>
>      unsigned AbbrevToUse = 0;
>      Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
> @@ -1863,6 +1865,8 @@ static void WriteModuleUseLists(const Mo
>      WriteUseList(FI, VE, Stream);
>      if (!FI->isDeclaration())
>        WriteFunctionUseList(FI, VE, Stream);
> +    if (FI->hasPrefixData())
> +      WriteUseList(FI->getPrefixData(), VE, Stream);
>    }
>
>    // Write the aliases.
>
> Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Sun Sep 15 20:08:15
> 2013
> @@ -60,6 +60,11 @@ ValueEnumerator::ValueEnumerator(const M
>         I != E; ++I)
>      EnumerateValue(I->getAliasee());
>
> +  // Enumerate the prefix data constants.
> +  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
> +    if (I->hasPrefixData())
> +      EnumerateValue(I->getPrefixData());
> +
>    // Insert constants and metadata that are named at module level into
> the slot
>    // pool so that the module symbol table can refer to them...
>    EnumerateValueSymbolTable(M->getValueSymbolTable());
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Sun Sep 15 20:08:15
> 2013
> @@ -459,6 +459,10 @@ void AsmPrinter::EmitFunctionHeader() {
>      OutStreamer.EmitLabel(DeadBlockSyms[i]);
>    }
>
> +  // Emit the prefix data.
> +  if (F->hasPrefixData())
> +    EmitGlobalConstant(F->getPrefixData());
> +
>    // Emit pre-function debug and/or EH information.
>    if (DE) {
>      NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
>
> Modified: llvm/trunk/lib/IR/AsmWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/AsmWriter.cpp (original)
> +++ llvm/trunk/lib/IR/AsmWriter.cpp Sun Sep 15 20:08:15 2013
> @@ -1647,6 +1647,10 @@ void AssemblyWriter::printFunction(const
>      Out << " align " << F->getAlignment();
>    if (F->hasGC())
>      Out << " gc \"" << F->getGC() << '"';
> +  if (F->hasPrefixData()) {
> +    Out << " prefix ";
> +    writeOperand(F->getPrefixData(), true);
> +  }
>    if (F->isDeclaration()) {
>      Out << '\n';
>    } else {
>
> Modified: llvm/trunk/lib/IR/Function.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Function.cpp (original)
> +++ llvm/trunk/lib/IR/Function.cpp Sun Sep 15 20:08:15 2013
> @@ -276,6 +276,9 @@ void Function::dropAllReferences() {
>    // blockaddresses, but BasicBlock's destructor takes care of those.
>    while (!BasicBlocks.empty())
>      BasicBlocks.begin()->eraseFromParent();
> +
> +  // Prefix data is stored in a side table.
> +  setPrefixData(0);
>  }
>
>  void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
> @@ -351,6 +354,10 @@ void Function::copyAttributesFrom(const
>      setGC(SrcF->getGC());
>    else
>      clearGC();
> +  if (SrcF->hasPrefixData())
> +    setPrefixData(SrcF->getPrefixData());
> +  else
> +    setPrefixData(0);
>  }
>
>  /// getIntrinsicID - This method returns the ID number of the specified
> @@ -720,3 +727,32 @@ bool Function::callsFunctionThatReturnsT
>
>    return false;
>  }
> +
> +Constant *Function::getPrefixData() const {
> +  assert(hasPrefixData());
> +  const LLVMContextImpl::PrefixDataMapTy &PDMap =
> +      getContext().pImpl->PrefixDataMap;
> +  assert(PDMap.find(this) != PDMap.end());
> +  return cast<Constant>(PDMap.find(this)->second->getReturnValue());
> +}
> +
> +void Function::setPrefixData(Constant *PrefixData) {
> +  if (!PrefixData && !hasPrefixData())
> +    return;
> +
> +  unsigned SCData = getSubclassDataFromValue();
> +  LLVMContextImpl::PrefixDataMapTy &PDMap =
> getContext().pImpl->PrefixDataMap;
> +  ReturnInst *&PDHolder = PDMap[this];
> +  if (PrefixData) {
> +    if (PDHolder)
> +      PDHolder->setOperand(0, PrefixData);
> +    else
> +      PDHolder = ReturnInst::Create(getContext(), PrefixData);
> +    SCData |= 2;
> +  } else {
> +    delete PDHolder;
> +    PDMap.erase(this);
> +    SCData &= ~2;
> +  }
> +  setValueSubclassData(SCData);
> +}
>
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
> +++ llvm/trunk/lib/IR/LLVMContextImpl.h Sun Sep 15 20:08:15 2013
> @@ -355,6 +355,11 @@ public:
>    typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
>    IntrinsicIDCacheTy IntrinsicIDCache;
>
> +  /// \brief Mapping from a function to its prefix data, which is stored
> as the
> +  /// operand of an unparented ReturnInst so that the prefix data has a
> Use.
> +  typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
> +  PrefixDataMapTy PrefixDataMap;
> +
>    int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
>    int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int
> ExistingIdx);
>
>
> Modified: llvm/trunk/lib/IR/TypeFinder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/TypeFinder.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/TypeFinder.cpp (original)
> +++ llvm/trunk/lib/IR/TypeFinder.cpp Sun Sep 15 20:08:15 2013
> @@ -44,6 +44,9 @@ void TypeFinder::run(const Module &M, bo
>    for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI)
> {
>      incorporateType(FI->getType());
>
> +    if (FI->hasPrefixData())
> +      incorporateValue(FI->getPrefixData());
> +
>      // First incorporate the arguments.
>      for (Function::const_arg_iterator AI = FI->arg_begin(),
>             AE = FI->arg_end(); AI != AE; ++AI)
>
> Modified: llvm/trunk/lib/Linker/LinkModules.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Linker/LinkModules.cpp (original)
> +++ llvm/trunk/lib/Linker/LinkModules.cpp Sun Sep 15 20:08:15 2013
> @@ -1260,6 +1260,13 @@ bool ModuleLinker::run() {
>      // Skip if not linking from source.
>      if (DoNotLinkFromSource.count(SF)) continue;
>
> +    Function *DF = cast<Function>(ValueMap[SF]);
> +    if (SF->hasPrefixData()) {
> +      // Link in the prefix data.
> +      DF->setPrefixData(MapValue(
> +          SF->getPrefixData(), ValueMap, RF_None, &TypeMap,
> &ValMaterializer));
> +    }
> +
>      // Skip if no body (function is external) or materialize.
>      if (SF->isDeclaration()) {
>        if (!SF->isMaterializable())
> @@ -1268,7 +1275,7 @@ bool ModuleLinker::run() {
>          return true;
>      }
>
> -    linkFunctionBody(cast<Function>(ValueMap[SF]), SF);
> +    linkFunctionBody(DF, SF);
>      SF->Dematerialize();
>    }
>
> @@ -1296,6 +1303,14 @@ bool ModuleLinker::run() {
>          continue;
>
>        Function *DF = cast<Function>(ValueMap[SF]);
> +      if (SF->hasPrefixData()) {
> +        // Link in the prefix data.
> +        DF->setPrefixData(MapValue(SF->getPrefixData(),
> +                                   ValueMap,
> +                                   RF_None,
> +                                   &TypeMap,
> +                                   &ValMaterializer));
> +      }
>
>        // Materialize if necessary.
>        if (SF->isDeclaration()) {
>
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp?rev=190773&r1=190772&r2=190773&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp Sun Sep 15 20:08:15 2013
> @@ -179,6 +179,9 @@ void GlobalDCE::GlobalIsNeeded(GlobalVal
>      // any globals used will be marked as needed.
>      Function *F = cast<Function>(G);
>
> +    if (F->hasPrefixData())
> +      MarkUsedGlobalsAsNeeded(F->getPrefixData());
> +
>      for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
>        for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;
> ++I)
>          for (User::op_iterator U = I->op_begin(), E = I->op_end(); U !=
> E; ++U)
>
> Added: llvm/trunk/test/CodeGen/X86/prefixdata.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/prefixdata.ll?rev=190773&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/prefixdata.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/prefixdata.ll Sun Sep 15 20:08:15 2013
> @@ -0,0 +1,15 @@
> +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
> +
> + at i = linkonce_odr global i32 1
> +
> +; CHECK: f:
> +; CHECK-NEXT: .long    1
> +define void @f() prefix i32 1 {
> +  ret void
> +}
> +
> +; CHECK: g:
> +; CHECK-NEXT: .quad    i
> +define void @g() prefix i32* @i {
> +  ret void
> +}
>
> Added: llvm/trunk/test/Feature/prefixdata.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/prefixdata.ll?rev=190773&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Feature/prefixdata.ll (added)
> +++ llvm/trunk/test/Feature/prefixdata.ll Sun Sep 15 20:08:15 2013
> @@ -0,0 +1,18 @@
> +; RUN: llvm-as < %s | llvm-dis > %t1.ll
> +; RUN: FileCheck %s < %t1.ll
> +; RUN: llvm-as < %t1.ll | llvm-dis > %t2.ll
> +; RUN: diff %t1.ll %t2.ll
> +; RUN: opt -O3 -S < %t1.ll | FileCheck %s
> +
> +; CHECK: @i
> + at i = linkonce_odr global i32 1
> +
> +; CHECK: f(){{.*}}prefix i32 1
> +define void @f() prefix i32 1 {
> +  ret void
> +}
> +
> +; CHECK: g(){{.*}}prefix i32* @i
> +define void @g() prefix i32* @i {
> +  ret void
> +}
>
> Added: llvm/trunk/test/Linker/prefixdata.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/prefixdata.ll?rev=190773&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Linker/prefixdata.ll (added)
> +++ llvm/trunk/test/Linker/prefixdata.ll Sun Sep 15 20:08:15 2013
> @@ -0,0 +1,9 @@
> +; RUN: echo > %t.ll
> +; RUN: llvm-link %t.ll %s -S -o - | FileCheck %s
> +
> + at i = linkonce_odr global i32 1
> +
> +; CHECK: define void @f() prefix i32* @i
> +define void @f() prefix i32* @i {
> +  ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130923/6f6632f2/attachment.html>


More information about the llvm-commits mailing list