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