[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