[llvm] r274485 - Add writeonly IR attribute

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 4 01:15:26 PDT 2016


Hi,

Did this get an LGTM?  I can't seem to find one in
http://reviews.llvm.org/D18714

Please revert this revision if it has not received an LGTM.

On Mon, Jul 4, 2016 at 1:01 AM, Nicolai Haehnle via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: nha
> Date: Mon Jul  4 03:01:29 2016
> New Revision: 274485
>
> URL: http://llvm.org/viewvc/llvm-project?rev=274485&view=rev
> Log:
> Add writeonly IR attribute
>
> Summary:
> This complements the earlier addition of IntrWriteMem and IntrWriteArgMem
> LLVM intrinsic properties, see D18291.
>
> Also start using the attribute for memset, memcpy, and memmove intrinsics,
> and remove their special-casing in BasicAliasAnalysis.
>
> Reviewers: reames, joker.eph
>
> Subscribers: joker.eph, llvm-commits
>
> Differential Revision: http://reviews.llvm.org/D18714
>
> Added:
>     llvm/trunk/test/Verifier/writeonly.ll
> Modified:
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
>     llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
>     llvm/trunk/include/llvm/IR/Attributes.td
>     llvm/trunk/include/llvm/IR/CallSite.h
>     llvm/trunk/include/llvm/IR/Function.h
>     llvm/trunk/include/llvm/IR/Instructions.h
>     llvm/trunk/include/llvm/IR/Intrinsics.td
>     llvm/trunk/lib/Analysis/AliasAnalysis.cpp
>     llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
>     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/Writer/BitcodeWriter.cpp
>     llvm/trunk/lib/IR/Attributes.cpp
>     llvm/trunk/lib/IR/Verifier.cpp
>     llvm/trunk/test/Analysis/BasicAA/cs-cs.ll
>     llvm/trunk/test/Bindings/llvm-c/Inputs/invalid.ll.bc
>     llvm/trunk/test/Bindings/llvm-c/invalid-bitcode.test
>     llvm/trunk/test/Bitcode/attributes.ll
>     llvm/trunk/test/Bitcode/compatibility.ll
>     llvm/trunk/test/Bitcode/invalid.ll
>     llvm/trunk/test/Bitcode/invalid.ll.bc
>     llvm/trunk/test/LTO/X86/Inputs/invalid.ll.bc
>     llvm/trunk/test/LTO/X86/invalid.ll
>     llvm/trunk/utils/TableGen/CodeGenIntrinsics.h
>     llvm/trunk/utils/TableGen/CodeGenTarget.cpp
>     llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Mon Jul  4 03:01:29 2016
> @@ -1474,6 +1474,13 @@ example:
>      On an argument, this attribute indicates that the function does not
> write
>      through this pointer argument, even though it may write to the memory
> that
>      the pointer points to.
> +``writeonly``
> +    On a function, this attribute indicates that the function may write
> to but
> +    does not read from memory.
> +
> +    On an argument, this attribute indicates that the function may write
> to but
> +    does not read through this pointer argument (even though it may read
> from
> +    the memory that the pointer points to).
>  ``argmemonly``
>      This attribute indicates that the only memory accesses inside
> function are
>      loads and stores from objects pointed to by its pointer-typed
> arguments,
>
> Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)
> +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Mon Jul  4 03:01:29
> 2016
> @@ -151,6 +151,13 @@ enum FunctionModRefBehavior {
>    /// This property corresponds to the IntrReadMem LLVM intrinsic flag.
>    FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
>
> +  // This function does not read from memory anywhere, but may write to
> any
> +  // memory location.
> +  //
> +  // This property corresponds to the LLVM IR 'writeonly' attribute.
> +  // This property corresponds to the IntrWriteMem LLVM intrinsic flag.
> +  FMRB_DoesNotReadMemory = FMRL_Anywhere | MRI_Mod,
> +
>    /// This indicates that the function could not be classified into one
> of the
>    /// behaviors above.
>    FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
> @@ -312,6 +319,12 @@ public:
>      return !(MRB & MRI_Mod);
>    }
>
> +  /// Checks if functions with the specified behavior are known to only
> write
> +  /// memory (or not access memory at all).
> +  static bool doesNotReadMemory(FunctionModRefBehavior MRB) {
> +    return !(MRB & MRI_Ref);
> +  }
> +
>    /// Checks if functions with the specified behavior are known to read
> and
>    /// write at most from objects pointed to by their pointer-typed
> arguments
>    /// (with arbitrary offsets).
>
> Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
> +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Mon Jul  4 03:01:29 2016
> @@ -521,7 +521,8 @@ enum AttributeKindCodes {
>    ATTR_KIND_NO_RECURSE = 48,
>    ATTR_KIND_INACCESSIBLEMEM_ONLY = 49,
>    ATTR_KIND_INACCESSIBLEMEM_OR_ARGMEMONLY = 50,
> -  ATTR_KIND_ALLOC_SIZE = 51
> +  ATTR_KIND_ALLOC_SIZE = 51,
> +  ATTR_KIND_WRITEONLY = 52
>  };
>
>  enum ComdatSelectionKindCodes {
>
> Modified: llvm/trunk/include/llvm/IR/Attributes.td
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.td?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Attributes.td (original)
> +++ llvm/trunk/include/llvm/IR/Attributes.td Mon Jul  4 03:01:29 2016
> @@ -167,6 +167,9 @@ def SwiftSelf : EnumAttr<"swiftself">;
>  /// Function must be in a unwind table.
>  def UWTable : EnumAttr<"uwtable">;
>
> +/// Function only writes to memory.
> +def WriteOnly : EnumAttr<"writeonly">;
> +
>  /// Zero extended before/after call.
>  def ZExt : EnumAttr<"zeroext">;
>
>
> Modified: llvm/trunk/include/llvm/IR/CallSite.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/CallSite.h (original)
> +++ llvm/trunk/include/llvm/IR/CallSite.h Mon Jul  4 03:01:29 2016
> @@ -417,6 +417,14 @@ public:
>      CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory());
>    }
>
> +  /// @brief Determine if the call does not access or only writes memory.
> +  bool doesNotReadMemory() const {
> +    CALLSITE_DELEGATE_GETTER(doesNotReadMemory());
> +  }
> +  void setDoesNotReadMemory() {
> +    CALLSITE_DELEGATE_SETTER(setDoesNotReadMemory());
> +  }
> +
>    /// @brief Determine if the call can access memmory only using pointers
> based
>    /// on its arguments.
>    bool onlyAccessesArgMemory() const {
>
> Modified: llvm/trunk/include/llvm/IR/Function.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Function.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Function.h (original)
> +++ llvm/trunk/include/llvm/IR/Function.h Mon Jul  4 03:01:29 2016
> @@ -298,6 +298,14 @@ public:
>      addFnAttr(Attribute::ReadOnly);
>    }
>
> +  /// @brief Determine if the function does not access or only writes
> memory.
> +  bool doesNotReadMemory() const {
> +    return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly);
> +  }
> +  void setDoesNotReadMemory() {
> +    addFnAttr(Attribute::WriteOnly);
> +  }
> +
>    /// @brief Determine if the call can access memmory only using pointers
> based
>    /// on its arguments.
>    bool onlyAccessesArgMemory() const {
>
> Modified: llvm/trunk/include/llvm/IR/Instructions.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Instructions.h (original)
> +++ llvm/trunk/include/llvm/IR/Instructions.h Mon Jul  4 03:01:29 2016
> @@ -1739,6 +1739,14 @@ public:
>      addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
>    }
>
> +  /// \brief Determine if the call does not access or only writes memory.
> +  bool doesNotReadMemory() const {
> +    return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
> +  }
> +  void setDoesNotReadMemory() {
> +    addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
> +  }
> +
>    /// @brief Determine if the call can access memmory only using pointers
> based
>    /// on its arguments.
>    bool onlyAccessesArgMemory() const {
> @@ -3691,6 +3699,14 @@ public:
>      addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
>    }
>
> +  /// \brief Determine if the call does not access or only writes memory.
> +  bool doesNotReadMemory() const {
> +    return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
> +  }
> +  void setDoesNotReadMemory() {
> +    addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
> +  }
> +
>    /// @brief Determine if the call access memmory only using it's pointer
>    /// arguments.
>    bool onlyAccessesArgMemory() const {
>
> Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
> +++ llvm/trunk/include/llvm/IR/Intrinsics.td Mon Jul  4 03:01:29 2016
> @@ -60,6 +60,12 @@ class ReadOnly<int argNo> : IntrinsicPro
>    int ArgNo = argNo;
>  }
>
> +// WriteOnly - The intrinsic does not read memory through the specified
> +// argument pointer.
> +class WriteOnly<int argNo> : IntrinsicProperty {
> +  int ArgNo = argNo;
> +}
> +
>  // ReadNone - The specified argument pointer is not dereferenced by the
>  // intrinsic.
>  class ReadNone<int argNo> : IntrinsicProperty {
> @@ -349,7 +355,7 @@ def int_memcpy  : Intrinsic<[],
>                               [llvm_anyptr_ty, llvm_anyptr_ty,
> llvm_anyint_ty,
>                                llvm_i32_ty, llvm_i1_ty],
>                              [IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
> -                             ReadOnly<1>]>;
> +                             WriteOnly<0>, ReadOnly<1>]>;
>  def int_memmove : Intrinsic<[],
>                              [llvm_anyptr_ty, llvm_anyptr_ty,
> llvm_anyint_ty,
>                               llvm_i32_ty, llvm_i1_ty],
> @@ -358,7 +364,7 @@ def int_memmove : Intrinsic<[],
>  def int_memset  : Intrinsic<[],
>                              [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty,
>                               llvm_i32_ty, llvm_i1_ty],
> -                            [IntrArgMemOnly, NoCapture<0>]>;
> +                            [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
>
>  let IntrProperties = [IntrNoMem] in {
>    def int_fma  : Intrinsic<[llvm_anyfloat_ty],
>
> Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Mon Jul  4 03:01:29 2016
> @@ -142,6 +142,8 @@ ModRefInfo AAResults::getModRefInfo(Immu
>
>    if (onlyReadsMemory(MRB))
>      Result = ModRefInfo(Result & MRI_Ref);
> +  else if (doesNotReadMemory(MRB))
> +    Result = ModRefInfo(Result & MRI_Mod);
>
>    if (onlyAccessesArgPointees(MRB)) {
>      bool DoesAlias = false;
> @@ -207,6 +209,8 @@ ModRefInfo AAResults::getModRefInfo(Immu
>    // from CS1 reading memory written by CS2.
>    if (onlyReadsMemory(CS1B))
>      Result = ModRefInfo(Result & MRI_Ref);
> +  else if (doesNotReadMemory(CS1B))
> +    Result = ModRefInfo(Result & MRI_Mod);
>
>    // If CS2 only access memory through arguments, accumulate the mod/ref
>    // information from CS1's references to the memory referenced by
>
> Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jul  4 03:01:29 2016
> @@ -563,6 +563,8 @@ FunctionModRefBehavior BasicAAResult::ge
>    // than that.
>    if (CS.onlyReadsMemory())
>      Min = FMRB_OnlyReadsMemory;
> +  else if (CS.doesNotReadMemory())
> +    Min = FMRB_DoesNotReadMemory;
>
>    if (CS.onlyAccessesArgMemory())
>      Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
> @@ -590,6 +592,8 @@ FunctionModRefBehavior BasicAAResult::ge
>    // If the function declares it only reads memory, go with that.
>    if (F->onlyReadsMemory())
>      Min = FMRB_OnlyReadsMemory;
> +  else if (F->doesNotReadMemory())
> +    Min = FMRB_DoesNotReadMemory;
>
>    if (F->onlyAccessesArgMemory())
>      Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
> @@ -597,32 +601,18 @@ FunctionModRefBehavior BasicAAResult::ge
>    return Min;
>  }
>
> -/// Returns true if this is a writeonly (i.e Mod only) parameter.
> Currently,
> -/// we don't have a writeonly attribute, so this only knows about builtin
> -/// intrinsics and target library functions.  We could consider adding a
> -/// writeonly attribute in the future and moving all of these facts to
> either
> -/// Intrinsics.td or InferFunctionAttr.cpp
> +/// Returns true if this is a writeonly (i.e Mod only) parameter.
>  static bool isWriteOnlyParam(ImmutableCallSite CS, unsigned ArgIdx,
>                               const TargetLibraryInfo &TLI) {
> -  if (const IntrinsicInst *II =
> dyn_cast<IntrinsicInst>(CS.getInstruction()))
> -    switch (II->getIntrinsicID()) {
> -    default:
> -      break;
> -    case Intrinsic::memset:
> -    case Intrinsic::memcpy:
> -    case Intrinsic::memmove:
> -      // We don't currently have a writeonly attribute.  All other
> properties
> -      // of these intrinsics are nicely described via attributes in
> -      // Intrinsics.td and handled generically.
> -      if (ArgIdx == 0)
> -        return true;
> -    }
> +  if (CS.paramHasAttr(ArgIdx + 1, Attribute::WriteOnly))
> +    return true;
>
>    // We can bound the aliasing properties of memset_pattern16 just as we
> can
>    // for memcpy/memset.  This is particularly important because the
>    // LoopIdiomRecognizer likes to turn loops into calls to
> memset_pattern16
> -  // whenever possible.  Note that all but the missing writeonly
> attribute are
> -  // handled via InferFunctionAttr.
> +  // whenever possible.
> +  // FIXME Consider handling this in InferFunctionAttr.cpp together with
> other
> +  // attributes.
>    LibFunc::Func F;
>    if (CS.getCalledFunction() && TLI.getLibFunc(*CS.getCalledFunction(),
> F) &&
>        F == LibFunc::memset_pattern16 && TLI.has(F))
> @@ -639,8 +629,7 @@ static bool isWriteOnlyParam(ImmutableCa
>  ModRefInfo BasicAAResult::getArgModRefInfo(ImmutableCallSite CS,
>                                             unsigned ArgIdx) {
>
> -  // Emulate the missing writeonly attribute by checking for known builtin
> -  // intrinsics and target library functions.
> +  // Checking for known builtin intrinsics and target library functions.
>    if (isWriteOnlyParam(CS, ArgIdx, TLI))
>      return MRI_Mod;
>
>
> Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLLexer.cpp Mon Jul  4 03:01:29 2016
> @@ -660,6 +660,7 @@ lltok::Kind LLLexer::LexIdentifier() {
>    KEYWORD(swifterror);
>    KEYWORD(swiftself);
>    KEYWORD(uwtable);
> +  KEYWORD(writeonly);
>    KEYWORD(zeroext);
>
>    KEYWORD(type);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Jul  4 03:01:29 2016
> @@ -1098,6 +1098,7 @@ bool LLParser::ParseFnAttributeValuePair
>      case lltok::kw_sanitize_memory:
>        B.addAttribute(Attribute::SanitizeMemory); break;
>      case lltok::kw_uwtable: B.addAttribute(Attribute::UWTable); break;
> +    case lltok::kw_writeonly: B.addAttribute(Attribute::WriteOnly); break;
>
>      // Error handling.
>      case lltok::kw_inreg:
> @@ -1394,6 +1395,7 @@ bool LLParser::ParseOptionalParamAttrs(A
>      case lltok::kw_sret:            B.addAttribute(Attribute::StructRet);
> break;
>      case lltok::kw_swifterror:
> B.addAttribute(Attribute::SwiftError); break;
>      case lltok::kw_swiftself:       B.addAttribute(Attribute::SwiftSelf);
> break;
> +    case lltok::kw_writeonly:       B.addAttribute(Attribute::WriteOnly);
> break;
>      case lltok::kw_zeroext:         B.addAttribute(Attribute::ZExt);
> break;
>
>      case lltok::kw_alignstack:
>
> Modified: llvm/trunk/lib/AsmParser/LLToken.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLToken.h (original)
> +++ llvm/trunk/lib/AsmParser/LLToken.h Mon Jul  4 03:01:29 2016
> @@ -205,6 +205,7 @@ enum Kind {
>    kw_swifterror,
>    kw_swiftself,
>    kw_uwtable,
> +  kw_writeonly,
>    kw_zeroext,
>
>    kw_type,
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Jul  4 03:01:29
> 2016
> @@ -1464,6 +1464,8 @@ static Attribute::AttrKind getAttrFromCo
>      return Attribute::SwiftSelf;
>    case bitc::ATTR_KIND_UW_TABLE:
>      return Attribute::UWTable;
> +  case bitc::ATTR_KIND_WRITEONLY:
> +    return Attribute::WriteOnly;
>    case bitc::ATTR_KIND_Z_EXT:
>      return Attribute::ZExt;
>    }
>
> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Mon Jul  4 03:01:29
> 2016
> @@ -667,6 +667,8 @@ static uint64_t getAttrKindEncoding(Attr
>      return bitc::ATTR_KIND_SWIFT_SELF;
>    case Attribute::UWTable:
>      return bitc::ATTR_KIND_UW_TABLE;
> +  case Attribute::WriteOnly:
> +    return bitc::ATTR_KIND_WRITEONLY;
>    case Attribute::ZExt:
>      return bitc::ATTR_KIND_Z_EXT;
>    case Attribute::EndAttrKinds:
>
> Modified: llvm/trunk/lib/IR/Attributes.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Attributes.cpp (original)
> +++ llvm/trunk/lib/IR/Attributes.cpp Mon Jul  4 03:01:29 2016
> @@ -292,6 +292,8 @@ std::string Attribute::getAsString(bool
>      return "readnone";
>    if (hasAttribute(Attribute::ReadOnly))
>      return "readonly";
> +  if (hasAttribute(Attribute::WriteOnly))
> +    return "writeonly";
>    if (hasAttribute(Attribute::Returned))
>      return "returned";
>    if (hasAttribute(Attribute::ReturnsTwice))
> @@ -516,6 +518,7 @@ uint64_t AttributeImpl::getAttrMask(Attr
>    case Attribute::InaccessibleMemOrArgMemOnly: return 1ULL << 50;
>    case Attribute::SwiftSelf:       return 1ULL << 51;
>    case Attribute::SwiftError:      return 1ULL << 52;
> +  case Attribute::WriteOnly:       return 1ULL << 53;
>    case Attribute::Dereferenceable:
>      llvm_unreachable("dereferenceable attribute not supported in raw
> format");
>      break;
>
> Modified: llvm/trunk/lib/IR/Verifier.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Verifier.cpp (original)
> +++ llvm/trunk/lib/IR/Verifier.cpp Mon Jul  4 03:01:29 2016
> @@ -1309,6 +1309,7 @@ void Verifier::verifyAttributeTypes(Attr
>          return;
>        }
>      } else if (I->getKindAsEnum() == Attribute::ReadOnly ||
> +               I->getKindAsEnum() == Attribute::WriteOnly ||
>                 I->getKindAsEnum() == Attribute::ReadNone) {
>        if (Idx == 0) {
>          CheckFailed("Attribute '" + I->getAsString() +
> @@ -1382,6 +1383,18 @@ void Verifier::verifyParameterAttrs(Attr
>           "'readnone and readonly' are incompatible!",
>           V);
>
> +  Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadNone) &&
> +           Attrs.hasAttribute(Idx, Attribute::WriteOnly)),
> +         "Attributes "
> +         "'readnone and writeonly' are incompatible!",
> +         V);
> +
> +  Assert(!(Attrs.hasAttribute(Idx, Attribute::ReadOnly) &&
> +           Attrs.hasAttribute(Idx, Attribute::WriteOnly)),
> +         "Attributes "
> +         "'readonly and writeonly' are incompatible!",
> +         V);
> +
>    Assert(!(Attrs.hasAttribute(Idx, Attribute::NoInline) &&
>             Attrs.hasAttribute(Idx, Attribute::AlwaysInline)),
>           "Attributes "
> @@ -1499,6 +1512,16 @@ void Verifier::verifyFunctionAttrs(Funct
>
>    Assert(
>        !(Attrs.hasAttribute(AttributeSet::FunctionIndex,
> Attribute::ReadNone) &&
> +        Attrs.hasAttribute(AttributeSet::FunctionIndex,
> Attribute::WriteOnly)),
> +      "Attributes 'readnone and writeonly' are incompatible!", V);
> +
> +  Assert(
> +      !(Attrs.hasAttribute(AttributeSet::FunctionIndex,
> Attribute::ReadOnly) &&
> +        Attrs.hasAttribute(AttributeSet::FunctionIndex,
> Attribute::WriteOnly)),
> +      "Attributes 'readonly and writeonly' are incompatible!", V);
> +
> +  Assert(
> +      !(Attrs.hasAttribute(AttributeSet::FunctionIndex,
> Attribute::ReadNone) &&
>          Attrs.hasAttribute(AttributeSet::FunctionIndex,
>                             Attribute::InaccessibleMemOrArgMemOnly)),
>        "Attributes 'readnone and inaccessiblemem_or_argmemonly' are
> incompatible!", V);
>
> Modified: llvm/trunk/test/Analysis/BasicAA/cs-cs.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/cs-cs.ll?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Analysis/BasicAA/cs-cs.ll (original)
> +++ llvm/trunk/test/Analysis/BasicAA/cs-cs.ll Mon Jul  4 03:01:29 2016
> @@ -9,6 +9,7 @@ declare void @llvm.memset.p0i8.i64(i8* n
>  declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture,
> i64, i32, i1) nounwind
>
>  declare void @a_readonly_func(i8 *) noinline nounwind readonly
> +declare void @a_writeonly_func(i8 *) noinline nounwind writeonly
>
>  define <8 x i16> @test1(i8* %p, <8 x i16> %y) {
>  entry:
> @@ -22,18 +23,18 @@ entry:
>  ; CHECK-LABEL: Function: test1:
>
>  ; CHECK: NoAlias:      i8* %p, i8* %q
> -; CHECK: Just Ref:  Ptr: i8* %p        <->  %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:  Ptr: i8* %q        <->  %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> +; CHECK: Just Ref:  Ptr: i8* %p        <->  %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:  Ptr: i8* %q        <->  %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
>  ; CHECK: NoModRef:  Ptr: i8* %p        <->  call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
>  ; CHECK: Both ModRef:  Ptr: i8* %q     <->  call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
> -; CHECK: Just Ref:  Ptr: i8* %p        <->  %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:  Ptr: i8* %q        <->  %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <->   call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
> -; CHECK: NoModRef:   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <->   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:   call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8
> x i16> %y, i32 16) <->   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:   call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8
> x i16> %y, i32 16) <->   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <->   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4
> -; CHECK: NoModRef:   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #4 <->   call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
> +; CHECK: Just Ref:  Ptr: i8* %p        <->  %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:  Ptr: i8* %q        <->  %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <->   call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
> +; CHECK: NoModRef:   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <->   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:   call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8
> x i16> %y, i32 16) <->   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:   call void @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8
> x i16> %y, i32 16) <->   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <->   %a = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5
> +; CHECK: NoModRef:   %b = call <8 x i16>
> @llvm.arm.neon.vld1.v8i16.p0i8(i8* %p, i32 16) #5 <->   call void
> @llvm.arm.neon.vst1.p0i8.v8i16(i8* %q, <8 x i16> %y, i32 16)
>  }
>
>  define void @test2(i8* %P, i8* %Q) nounwind ssp {
> @@ -233,9 +234,23 @@ define void @test6(i8* %P) nounwind ssp
>  ; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void
> @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false)
>  }
>
> -attributes #0 = { nounwind readonly argmemonly }
> -attributes #1 = { nounwind argmemonly }
> +define void @test7(i8* %P) nounwind ssp {
> +  call void @a_writeonly_func(i8* %P)
> +  call void @a_readonly_func(i8* %P)
> +  ret void
> +
> +; CHECK-LABEL: Function: test7:
> +
> +; CHECK: Just Mod:  Ptr: i8* %P        <->  call void
> @a_writeonly_func(i8* %P)
> +; CHECK: Just Ref:  Ptr: i8* %P        <->  call void
> @a_readonly_func(i8* %P)
> +; CHECK: Just Mod:   call void @a_writeonly_func(i8* %P) <->   call void
> @a_readonly_func(i8* %P)
> +; CHECK: Just Ref:   call void @a_readonly_func(i8* %P) <->   call void
> @a_writeonly_func(i8* %P)
> +}
> +
> +attributes #0 = { argmemonly nounwind readonly }
> +attributes #1 = { argmemonly nounwind }
>  attributes #2 = { noinline nounwind readonly }
> -attributes #3 = { nounwind ssp }
> -attributes #4 = { nounwind }
> +attributes #3 = { noinline nounwind writeonly }
> +attributes #4 = { nounwind ssp }
> +attributes #5 = { nounwind }
>
>
> Modified: llvm/trunk/test/Bindings/llvm-c/Inputs/invalid.ll.bc
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/llvm-c/Inputs/invalid.ll.bc?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> Binary files llvm/trunk/test/Bindings/llvm-c/Inputs/invalid.ll.bc
> (original) and llvm/trunk/test/Bindings/llvm-c/Inputs/invalid.ll.bc Mon
> Jul  4 03:01:29 2016 differ
>
> Modified: llvm/trunk/test/Bindings/llvm-c/invalid-bitcode.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/llvm-c/invalid-bitcode.test?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Bindings/llvm-c/invalid-bitcode.test (original)
> +++ llvm/trunk/test/Bindings/llvm-c/invalid-bitcode.test Mon Jul  4
> 03:01:29 2016
> @@ -1,13 +1,13 @@
>  ; RUN: not llvm-c-test --module-dump < %S/Inputs/invalid.ll.bc 2>&1 |
> FileCheck %s
>  ; RUN: not llvm-c-test --lazy-module-dump < %S/Inputs/invalid.ll.bc 2>&1
> | FileCheck %s
>
> -CHECK: Error parsing bitcode: Unknown attribute kind (52)
> +CHECK: Error parsing bitcode: Unknown attribute kind (63)
>
>
>  ; RUN: not llvm-c-test --new-module-dump < %S/Inputs/invalid.ll.bc 2>&1 |
> FileCheck --check-prefix=NEW %s
>  ; RUN: not llvm-c-test --lazy-new-module-dump < %S/Inputs/invalid.ll.bc
> 2>&1 | FileCheck --check-prefix=NEW %s
>
> -NEW: Error with new bitcode parser: Unknown attribute kind (52)
> +NEW: Error with new bitcode parser: Unknown attribute kind (63)
>
>  ; RUN: llvm-c-test --test-diagnostic-handler < %S/Inputs/invalid.ll.bc
> 2>&1 | FileCheck --check-prefix=DIAGNOSTIC %s
>
>
> Modified: llvm/trunk/test/Bitcode/attributes.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/attributes.ll?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Bitcode/attributes.ll (original)
> +++ llvm/trunk/test/Bitcode/attributes.ll Mon Jul  4 03:01:29 2016
> @@ -204,7 +204,7 @@ define void @f34()
>  ; CHECK: define void @f34()
>  {
>          call void @nobuiltin() nobuiltin
> -; CHECK: call void @nobuiltin() #32
> +; CHECK: call void @nobuiltin() #33
>          ret void;
>  }
>
> @@ -328,6 +328,12 @@ define i8* @f55(i32, i32) allocsize(0, 1
>    ret i8* null
>  }
>
> +; CHECK: define void @f56() #32
> +define void @f56() writeonly
> +{
> +  ret void
> +}
> +
>  ; CHECK: attributes #0 = { noreturn }
>  ; CHECK: attributes #1 = { nounwind }
>  ; CHECK: attributes #2 = { readnone }
> @@ -360,4 +366,5 @@ define i8* @f55(i32, i32) allocsize(0, 1
>  ; CHECK: attributes #29 = { inaccessiblemem_or_argmemonly }
>  ; CHECK: attributes #30 = { allocsize(0) }
>  ; CHECK: attributes #31 = { allocsize(0,1) }
> -; CHECK: attributes #32 = { nobuiltin }
> +; CHECK: attributes #32 = { writeonly }
> +; CHECK: attributes #33 = { nobuiltin }
>
> Modified: llvm/trunk/test/Bitcode/compatibility.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Bitcode/compatibility.ll (original)
> +++ llvm/trunk/test/Bitcode/compatibility.ll Mon Jul  4 03:01:29 2016
> @@ -1244,7 +1244,7 @@ exit:
>    ; CHECK: select <2 x i1> <i1 true, i1 false>, <2 x i8> <i8 2, i8 3>, <2
> x i8> <i8 3, i8 2>
>
>    call void @f.nobuiltin() builtin
> -  ; CHECK: call void @f.nobuiltin() #39
> +  ; CHECK: call void @f.nobuiltin() #40
>
>    call fastcc noalias i32* @f.noalias() noinline
>    ; CHECK: call fastcc noalias i32* @f.noalias() #12
> @@ -1590,6 +1590,8 @@ normal:
>    ret void
>  }
>
> +declare void @f.writeonly() writeonly
> +; CHECK: declare void @f.writeonly() #39
>
>  ; CHECK: attributes #0 = { alignstack=4 }
>  ; CHECK: attributes #1 = { alignstack=8 }
> @@ -1630,7 +1632,8 @@ normal:
>  ; CHECK: attributes #36 = { argmemonly nounwind readonly }
>  ; CHECK: attributes #37 = { argmemonly nounwind }
>  ; CHECK: attributes #38 = { nounwind readonly }
> -; CHECK: attributes #39 = { builtin }
> +; CHECK: attributes #39 = { writeonly }
> +; CHECK: attributes #40 = { builtin }
>
>  ;; Metadata
>
>
> Modified: llvm/trunk/test/Bitcode/invalid.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/invalid.ll?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Bitcode/invalid.ll (original)
> +++ llvm/trunk/test/Bitcode/invalid.ll Mon Jul  4 03:01:29 2016
> @@ -1,6 +1,6 @@
>  ; RUN:  not llvm-dis < %s.bc 2>&1 | FileCheck %s
>
> -; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (52)
> +; CHECK: llvm-dis{{(\.EXE|\.exe)?}}: error: Unknown attribute kind (63)
>
>  ; invalid.ll.bc has an invalid attribute number.
>  ; The test checks that LLVM reports the error and doesn't access freed
> memory
>
> Modified: llvm/trunk/test/Bitcode/invalid.ll.bc
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/invalid.ll.bc?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> Binary files llvm/trunk/test/Bitcode/invalid.ll.bc (original) and
> llvm/trunk/test/Bitcode/invalid.ll.bc Mon Jul  4 03:01:29 2016 differ
>
> Modified: llvm/trunk/test/LTO/X86/Inputs/invalid.ll.bc
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/X86/Inputs/invalid.ll.bc?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> Binary files - no diff available.
>
> Modified: llvm/trunk/test/LTO/X86/invalid.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/X86/invalid.ll?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/LTO/X86/invalid.ll (original)
> +++ llvm/trunk/test/LTO/X86/invalid.ll Mon Jul  4 03:01:29 2016
> @@ -1,4 +1,4 @@
>  ; RUN: not llvm-lto %S/Inputs/invalid.ll.bc 2>&1 | FileCheck %s
>
>
> -; CHECK: llvm-lto{{.*}}: error loading file
> '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (52)
> +; CHECK: llvm-lto{{.*}}: error loading file
> '{{.*}}/Inputs/invalid.ll.bc': Unknown attribute kind (63)
>
> Added: llvm/trunk/test/Verifier/writeonly.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/writeonly.ll?rev=274485&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Verifier/writeonly.ll (added)
> +++ llvm/trunk/test/Verifier/writeonly.ll Mon Jul  4 03:01:29 2016
> @@ -0,0 +1,13 @@
> +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
> +
> +declare void @a() readnone writeonly
> +; CHECK: Attributes {{.*}} are incompatible
> +
> +declare void @b() readonly writeonly
> +; CHECK: Attributes {{.*}} are incompatible
> +
> +declare void @c(i32* readnone writeonly %p)
> +; CHECK: Attributes {{.*}} are incompatible
> +
> +declare void @d(i32* readonly writeonly %p)
> +; CHECK: Attributes {{.*}} are incompatible
>
> Modified: llvm/trunk/utils/TableGen/CodeGenIntrinsics.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenIntrinsics.h?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/utils/TableGen/CodeGenIntrinsics.h (original)
> +++ llvm/trunk/utils/TableGen/CodeGenIntrinsics.h Mon Jul  4 03:01:29 2016
> @@ -112,6 +112,7 @@ namespace llvm {
>      enum ArgAttribute {
>        NoCapture,
>        ReadOnly,
> +      WriteOnly,
>        ReadNone
>      };
>      std::vector<std::pair<unsigned, ArgAttribute> > ArgumentAttributes;
>
> Modified: llvm/trunk/utils/TableGen/CodeGenTarget.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenTarget.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/utils/TableGen/CodeGenTarget.cpp (original)
> +++ llvm/trunk/utils/TableGen/CodeGenTarget.cpp Mon Jul  4 03:01:29 2016
> @@ -595,6 +595,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Recor
>      } else if (Property->isSubClassOf("ReadOnly")) {
>        unsigned ArgNo = Property->getValueAsInt("ArgNo");
>        ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
> +    } else if (Property->isSubClassOf("WriteOnly")) {
> +      unsigned ArgNo = Property->getValueAsInt("ArgNo");
> +      ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly));
>      } else if (Property->isSubClassOf("ReadNone")) {
>        unsigned ArgNo = Property->getValueAsInt("ArgNo");
>        ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
>
> Modified: llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp?rev=274485&r1=274484&r2=274485&view=diff
>
> ==============================================================================
> --- llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp Mon Jul  4 03:01:29 2016
> @@ -554,6 +554,12 @@ EmitAttributes(const std::vector<CodeGen
>              OS << "Attribute::ReadOnly";
>              addComma = true;
>              break;
> +          case CodeGenIntrinsic::WriteOnly:
> +            if (addComma)
> +              OS << ",";
> +            OS << "Attribute::WriteOnly";
> +            addComma = true;
> +            break;
>            case CodeGenIntrinsic::ReadNone:
>              if (addComma)
>                OS << ",";
> @@ -617,12 +623,21 @@ EmitAttributes(const std::vector<CodeGen
>          OS << "Attribute::ReadOnly";
>          break;
>        case CodeGenIntrinsic::WriteArgMem:
> -      case CodeGenIntrinsic::ReadWriteArgMem:
>          if (addComma)
>            OS << ",";
> +        OS << "Attribute::WriteOnly,";
>          OS << "Attribute::ArgMemOnly";
>          break;
>        case CodeGenIntrinsic::WriteMem:
> +        if (addComma)
> +          OS << ",";
> +        OS << "Attribute::WriteOnly";
> +        break;
> +      case CodeGenIntrinsic::ReadWriteArgMem:
> +        if (addComma)
> +          OS << ",";
> +        OS << "Attribute::ArgMemOnly";
> +        break;
>        case CodeGenIntrinsic::ReadWriteMem:
>          break;
>        }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160704/22096f5d/attachment-0001.html>


More information about the llvm-commits mailing list