<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">
<div class="">There’s a similar thing in InitLibcallNames() within CodeGen/TargetLoweringBase.cpp that would be good to roll into this if it can be made to work.</div>
<div class=""><br class="">
</div>
<div class="">-Daniel</div>
<br class="">
<div>
<blockquote type="cite" class="">
<div class="">On Jul 17, 2017, at 9:45 AM, Derek Schuff <<a href="mailto:dschuff@google.com" class="">dschuff@google.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">Hi Daniel, David,
<div class=""><br class="">
</div>
<div class="">Thanks for fixing this up!</div>
<div class="">I also agree that this current system is too brittle and we should fix it.</div>
<div class="">Fundamentally what we need is to keep information about each libcall (its signature) in order to generate the wasm type declarations for generated calls. I would guess that the current system attempted to avoid making changes to the shared RuntimeLibCalls
 code, but I think it might make more sense to turn the enum in RuntimeLibCalls.h into a .def file similar to what we have in other places (instructions, etc). Then we can reuse it to define the RTLIB::Libcall enumeration and also the wasm signatures.</div>
<div class=""><br class="">
</div>
<div class="">I can volunteer to do this if that seems like a good idea (or we can figure something else out).</div>
<div class=""><br class="">
</div>
<div class="">thanks,</div>
<div class="">-Derek</div>
</div>
<br class="">
<div class="gmail_quote">
<div dir="ltr" class="">On Wed, Jul 12, 2017 at 12:32 PM David Blaikie via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:<br class="">
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr" class="">
<div class="gmail_quote">
<div dir="ltr" class="">On Wed, Jul 12, 2017 at 12:05 PM Daniel Neilson <<a href="mailto:dneilson@azul.com" target="_blank" class="">dneilson@azul.com</a>> wrote:<br class="">
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class="">The problem is in lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp. There’s an array declared:</div>
<div class="">545 static const char *<br class="">
546 RuntimeLibcallNames[RTLIB::UNKNOWN_LIBCALL] = {<br class="">
<br class="">
</div>
<div class=""> That is defining a runtime lib call name for each entry in the enum RTLIB:Libcall from include/llvm/CodeGen/RuntimeLibcalls.h.</div>
<div class=""><br class="">
</div>
<div class="">This patch added entries to the enum, but didn’t add entries to the RuntimeLibcallNames array. In fact, it looks like there are a couple of arrays in that WebAssembly file that are expecting to be changed/updated whenever the RTLIB::Libcall enum
 has been changed/updated. Mirrored structures like this are kind of dangerous for exactly this reason, aren’t they?</div>
<div class=""><br class="">
</div>
<div class=""> What’s the suggested way forward? (Still kind of new to LLVM) Should I try to add the corresponding entries to the WebAssembly arrays? Does someone with some familiarity with those tables want to tackle it?</div>
</div>
</blockquote>
</div>
</div>
<div dir="ltr" class="">
<div class="gmail_quote">
<div class=""><br class="">
Thanks for committing a fix - and I agree with you that this representation sounds problematic.<br class="">
<br class="">
Adding a couple of WebAssembly developers to this thread to bnring this to their attention, see if they have some ideas about how to make this code less brittle.<br class="">
 </div>
</div>
</div>
<div dir="ltr" class="">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class=""><br class="">
</div>
<div class="">-Daniel</div>
</div>
<div style="word-wrap:break-word" class="">
<div class=""><br class="">
</div>
<div class="">
<blockquote type="cite" class="">
<div class="">On Jul 12, 2017, at 11:37 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank" class="">dblaikie@gmail.com</a>> wrote:</div>
<br class="m_3161077768360514121m_1278730238680722948Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">Reverting the patch locally does seem to remove the failure.<br class="">
<br class="">
Here's the crash dump from one of the failing tests:<br class="">
<br class="">
<div class="">/usr/local/google/home/blaikie/dev/llvm/build/default/./bin/llc < /usr/local/google/home/blaikie/dev/llvm/src/test/CodeGen/WebAssembly/global.ll -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | /usr/local/google/home/blaikie/dev/llvm/build/default/./bin/FileCheck
 /usr/local/google/home/blaikie/dev/llvm/src/test/CodeGen/WebAssembly/global.ll</div>
<div class="">--</div>
<div class="">Exit Code: 2</div>
<div class=""><br class="">
</div>
<div class="">Command Output (stderr):</div>
<div class="">--</div>
<div class="">#0 0x000000000471fcb9 llvm::sys::PrintStackTrace(llvm::raw_ostream&) src/lib/Support/Unix/Signals.inc:398:11</div>
<div class="">#1 0x000000000471fe69 PrintStackTraceSignalHandler(void*) src/lib/Support/Unix/Signals.inc:462:1</div>
<div class="">#2 0x000000000471e4c3 llvm::sys::RunSignalHandlers() src/lib/Support/Signals.cpp:0:5</div>
<div class="">#3 0x00000000047201c4 SignalHandler(int) src/lib/Support/Unix/Signals.inc:252:1</div>
<div class="">#4 0x00007f770219a330 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)</div>
<div class="">#5 0x00007f7700d7079a /build/eglibc-SvCtMH/eglibc-2.19/string/../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:29:0</div>
<div class="">#6 0x000000000350622b llvm::GetSignature(llvm::WebAssemblySubtarget const&, char const*, llvm::SmallVectorImpl<llvm::wasm::ValType>&, llvm::SmallVectorImpl<llvm::wasm::ValType>&) src/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp:1294:3</div>
<div class="">#7 0x0000000003501337 llvm::WebAssemblyMCInstLower::GetExternalSymbolSymbol(llvm::MachineOperand const&) const src/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp:100:3</div>
<div class="">#8 0x0000000003501ce5 llvm::WebAssemblyMCInstLower::Lower(llvm::MachineInstr const*, llvm::MCInst&) const src/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp:229:33</div>
<div class="">#9 0x00000000034fee64 llvm::WebAssemblyAsmPrinter::EmitInstruction(llvm::MachineInstr const*) src/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp:208:5</div>
<div class="">#10 0x00000000037a9dd5 llvm::AsmPrinter::EmitFunctionBody() src/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:1037:11</div>
<div class="">#11 0x00000000021225e8 llvm::AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) src/include/llvm/CodeGen/AsmPrinter.h:277:5</div>
<div class="">#12 0x00000000034ff8d3 llvm::WebAssemblyAsmPrinter::runOnMachineFunction(llvm::MachineFunction&) src/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h:49:5</div>
<div class="">#13 0x0000000003a21f61 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) src/lib/CodeGen/MachineFunctionPass.cpp:62:8</div>
<div class="">#14 0x0000000003e5d92f llvm::FPPassManager::runOnFunction(llvm::Function&) src/lib/IR/LegacyPassManager.cpp:1519:27</div>
<div class="">#15 0x0000000003e5dc45 llvm::FPPassManager::runOnModule(llvm::Module&) src/lib/IR/LegacyPassManager.cpp:1540:16</div>
<div class="">#16 0x0000000003e5e3da (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) src/lib/IR/LegacyPassManager.cpp:1596:27</div>
<div class="">#17 0x0000000003e5df06 llvm::legacy::PassManagerImpl::run(llvm::Module&) src/lib/IR/LegacyPassManager.cpp:1699:16</div>
<div class="">#18 0x0000000003e5e8f1 llvm::legacy::PassManager::run(llvm::Module&) src/lib/IR/LegacyPassManager.cpp:1730:3</div>
<div class="">#19 0x00000000020ea715 compileModule(char**, llvm::LLVMContext&) src/tools/llc/llc.cpp:619:42</div>
<div class="">#20 0x00000000020e883c main src/tools/llc/llc.cpp:358:13</div>
<div class="">#21 0x00007f7700cf7f45 __libc_start_main build/eglibc-SvCtMH/eglibc-2.19/csu/libc-start.c:321:0</div>
<div class="">#22 0x00000000020e8029 _start (build/default/./bin/llc+0x20e8029)</div>
<div class="">Stack dump:</div>
<div class="">0.      Program arguments: build/default/./bin/llc -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals</div>
<div class="">1.      Running pass 'Function Pass Manager' on module '<stdin>'.</div>
<div class="">2.      Running pass 'WebAssembly Assembly Printer' on function '@call_memcpy'</div>
<div class="">FileCheck error: '-' is empty.</div>
<div class="">FileCheck command line:  build/default/./bin/FileCheck src/test/CodeGen/WebAssembly/global.ll</div>
<br class="">
<div class="gmail_quote">
<div dir="ltr" class="">On Wed, Jul 12, 2017 at 11:31 AM Daniel Neilson <<a href="mailto:dneilson@azul.com" target="_blank" class="">dneilson@azul.com</a>> wrote:<br class="">
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class="">That’s surprising to me; this should basically be NFC since nothing is actually using the introduced intrinsic. Any information that you can share would be appreciated.</div>
</div>
<div style="word-wrap:break-word" class="">
<div class=""><br class="">
</div>
<div class="">-Daniel</div>
</div>
<div style="word-wrap:break-word" class=""><br class="">
<div class="">
<blockquote type="cite" class="">
<div class="">On Jul 12, 2017, at 11:26 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" target="_blank" class="">dblaikie@gmail.com</a>> wrote:</div>
<br class="m_3161077768360514121m_1278730238680722948m_-6007959335525949403Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">This seems to be breaking internal buildbots on WebAssembly tests (test/CodeGen/WebAssembli/{byval,f16,f32,f64,frem,global,i128,legalize,mem-intrinsics}.ll<br class="">
<br class="">
I've not reproduced this myself, but working on that now to get more info, including stack traces, etc.</div>
<br class="">
<div class="gmail_quote">
<div dir="ltr" class="">On Wed, Jul 12, 2017 at 8:25 AM Daniel Neilson via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="">llvm-commits@lists.llvm.org</a>> wrote:<br class="">
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: dneilson<br class="">
Date: Wed Jul 12 08:25:26 2017<br class="">
New Revision: 307796<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=307796&view=rev" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project?rev=307796&view=rev</a><br class="">
Log:<br class="">
Add element atomic memmove intrinsic<br class="">
<br class="">
Summary: Continuing the work from <a href="https://reviews.llvm.org/D33240" rel="noreferrer" target="_blank" class="">
https://reviews.llvm.org/D33240</a>, this change introduces an element unordered-atomic memmove intrinsic. This intrinsic is essentially memmove with the implementation requirement that all loads/stores used for the copy are done with unordered-atomic loads/stores
 of a given element size.<br class="">
<br class="">
Reviewers: eli.friedman, reames, mkazantsev, skatkov<br class="">
<br class="">
Reviewed By: reames<br class="">
<br class="">
Subscribers: llvm-commits<br class="">
<br class="">
Differential Revision: <a href="https://reviews.llvm.org/D34884" rel="noreferrer" target="_blank" class="">
https://reviews.llvm.org/D34884</a><br class="">
<br class="">
Modified:<br class="">
    llvm/trunk/docs/LangRef.rst<br class="">
    llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h<br class="">
    llvm/trunk/include/llvm/IR/IntrinsicInst.h<br class="">
    llvm/trunk/include/llvm/IR/Intrinsics.td<br class="">
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br class="">
    llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp<br class="">
    llvm/trunk/lib/IR/Verifier.cpp<br class="">
    llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll<br class="">
    llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll<br class="">
<br class="">
Modified: llvm/trunk/docs/LangRef.rst<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/docs/LangRef.rst (original)<br class="">
+++ llvm/trunk/docs/LangRef.rst Wed Jul 12 08:25:26 2017<br class="">
@@ -10282,6 +10282,8 @@ overlap. It copies "len" bytes of memory<br class="">
 to be aligned to some boundary, this can be specified as the fourth<br class="">
 argument, otherwise it should be set to 0 or 1 (both meaning no alignment).<br class="">
<br class="">
+.. _int_memmove:<br class="">
+<br class="">
 '``llvm.memmove``' Intrinsic<br class="">
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br class="">
<br class="">
@@ -14178,4 +14180,81 @@ In the most general case call to the '``<br class="">
 lowered to a call to the symbol ``__llvm_memcpy_element_unordered_atomic_*``. Where '*'<br class="">
 is replaced with an actual element size.<br class="">
<br class="">
+Optimizer is allowed to inline memory copy when it's profitable to do so.<br class="">
+<br class="">
+'``llvm.memmove.element.unordered.atomic``' Intrinsic<br class="">
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br class="">
+<br class="">
+Syntax:<br class="">
+"""""""<br class="">
+<br class="">
+This is an overloaded intrinsic. You can use<br class="">
+``llvm.memmove.element.unordered.atomic`` on any integer bit width and for<br class="">
+different address spaces. Not all targets support all bit widths however.<br class="">
+<br class="">
+::<br class="">
+<br class="">
+      declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* <dest>,<br class="">
+                                                                        i8* <src>,<br class="">
+                                                                        i32 <len>,<br class="">
+                                                                        i32 <element_size>)<br class="">
+      declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* <dest>,<br class="">
+                                                                        i8* <src>,<br class="">
+                                                                        i64 <len>,<br class="">
+                                                                        i32 <element_size>)<br class="">
+<br class="">
+Overview:<br class="">
+"""""""""<br class="">
+<br class="">
+The '``llvm.memmove.element.unordered.atomic.*``' intrinsic is a specialization<br class="">
+of the '``llvm.memmove.*``' intrinsic. It differs in that the ``dest`` and<br class="">
+``src`` are treated as arrays with elements that are exactly ``element_size``<br class="">
+bytes, and the copy between buffers uses a sequence of<br class="">
+:ref:`unordered atomic <ordering>` load/store operations that are a positive<br class="">
+integer multiple of the ``element_size`` in size.<br class="">
+<br class="">
+Arguments:<br class="">
+""""""""""<br class="">
+<br class="">
+The first three arguments are the same as they are in the<br class="">
+:ref:`@llvm.memmove <int_memmove>` intrinsic, with the added constraint that<br class="">
+``len`` is required to be a positive integer multiple of the ``element_size``.<br class="">
+If ``len`` is not a positive integer multiple of ``element_size``, then the<br class="">
+behaviour of the intrinsic is undefined.<br class="">
+<br class="">
+``element_size`` must be a compile-time constant positive power of two no<br class="">
+greater than a target-specific atomic access size limit.<br class="">
+<br class="">
+For each of the input pointers the ``align`` parameter attribute must be<br class="">
+specified. It must be a power of two no less than the ``element_size``. Caller<br class="">
+guarantees that both the source and destination pointers are aligned to that<br class="">
+boundary.<br class="">
+<br class="">
+Semantics:<br class="">
+""""""""""<br class="">
+<br class="">
+The '``llvm.memmove.element.unordered.atomic.*``' intrinsic copies ``len`` bytes<br class="">
+of memory from the source location to the destination location. These locations<br class="">
+are allowed to overlap. The memory copy is performed as a sequence of load/store<br class="">
+operations where each access is guaranteed to be a multiple of ``element_size``<br class="">
+bytes wide and aligned at an ``element_size`` boundary.<br class="">
+<br class="">
+The order of the copy is unspecified. The same value may be read from the source<br class="">
+buffer many times, but only one write is issued to the destination buffer per<br class="">
+element. It is well defined to have concurrent reads and writes to both source<br class="">
+and destination provided those reads and writes are unordered atomic when<br class="">
+specified.<br class="">
+<br class="">
+This intrinsic does not provide any additional ordering guarantees over those<br class="">
+provided by a set of unordered loads from the source location and stores to the<br class="">
+destination.<br class="">
+<br class="">
+Lowering:<br class="">
+"""""""""<br class="">
+<br class="">
+In the most general case call to the<br class="">
+'``llvm.memmove.element.unordered.atomic.*``' is lowered to a call to the symbol<br class="">
+``__llvm_memmove_element_unordered_atomic_*``. Where '*' is replaced with an<br class="">
+actual element size.<br class="">
+<br class="">
 The optimizer is allowed to inline the memory copy when it's profitable to do so.<br class="">
<br class="">
Modified: llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h (original)<br class="">
+++ llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.h Wed Jul 12 08:25:26 2017<br class="">
@@ -340,6 +340,12 @@ namespace RTLIB {<br class="">
     MEMCPY_ELEMENT_UNORDERED_ATOMIC_8,<br class="">
     MEMCPY_ELEMENT_UNORDERED_ATOMIC_16,<br class="">
<br class="">
+    MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1,<br class="">
+    MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2,<br class="">
+    MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4,<br class="">
+    MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8,<br class="">
+    MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16,<br class="">
+<br class="">
     // EXCEPTION HANDLING<br class="">
     UNWIND_RESUME,<br class="">
<br class="">
@@ -515,6 +521,11 @@ namespace RTLIB {<br class="">
   /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or<br class="">
   /// UNKNOW_LIBCALL if there is none.<br class="">
   Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);<br class="">
+<br class="">
+  /// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return<br class="">
+  /// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or<br class="">
+  /// UNKNOW_LIBCALL if there is none.<br class="">
+  Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);<br class="">
 }<br class="">
 }<br class="">
<br class="">
<br class="">
Modified: llvm/trunk/include/llvm/IR/IntrinsicInst.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicInst.h?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicInst.h?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/include/llvm/IR/IntrinsicInst.h (original)<br class="">
+++ llvm/trunk/include/llvm/IR/IntrinsicInst.h Wed Jul 12 08:25:26 2017<br class="">
@@ -296,6 +296,95 @@ namespace llvm {<br class="">
     }<br class="">
   };<br class="">
<br class="">
+  class ElementUnorderedAtomicMemMoveInst : public IntrinsicInst {<br class="">
+  private:<br class="">
+    enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };<br class="">
+<br class="">
+  public:<br class="">
+    Value *getRawDest() const {<br class="">
+      return const_cast<Value *>(getArgOperand(ARG_DEST));<br class="">
+    }<br class="">
+    const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }<br class="">
+    Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }<br class="">
+<br class="">
+    /// Return the arguments to the instruction.<br class="">
+    Value *getRawSource() const {<br class="">
+      return const_cast<Value *>(getArgOperand(ARG_SOURCE));<br class="">
+    }<br class="">
+    const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }<br class="">
+    Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }<br class="">
+<br class="">
+    Value *getLength() const {<br class="">
+      return const_cast<Value *>(getArgOperand(ARG_LENGTH));<br class="">
+    }<br class="">
+    const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }<br class="">
+    Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }<br class="">
+<br class="">
+    bool isVolatile() const { return false; }<br class="">
+<br class="">
+    Value *getRawElementSizeInBytes() const {<br class="">
+      return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));<br class="">
+    }<br class="">
+<br class="">
+    ConstantInt *getElementSizeInBytesCst() const {<br class="">
+      return cast<ConstantInt>(getRawElementSizeInBytes());<br class="">
+    }<br class="">
+<br class="">
+    uint32_t getElementSizeInBytes() const {<br class="">
+      return getElementSizeInBytesCst()->getZExtValue();<br class="">
+    }<br class="">
+<br class="">
+    /// This is just like getRawDest, but it strips off any cast<br class="">
+    /// instructions that feed it, giving the original input.  The returned<br class="">
+    /// value is guaranteed to be a pointer.<br class="">
+    Value *getDest() const { return getRawDest()->stripPointerCasts(); }<br class="">
+<br class="">
+    /// This is just like getRawSource, but it strips off any cast<br class="">
+    /// instructions that feed it, giving the original input.  The returned<br class="">
+    /// value is guaranteed to be a pointer.<br class="">
+    Value *getSource() const { return getRawSource()->stripPointerCasts(); }<br class="">
+<br class="">
+    unsigned getDestAddressSpace() const {<br class="">
+      return cast<PointerType>(getRawDest()->getType())->getAddressSpace();<br class="">
+    }<br class="">
+<br class="">
+    unsigned getSourceAddressSpace() const {<br class="">
+      return cast<PointerType>(getRawSource()->getType())->getAddressSpace();<br class="">
+    }<br class="">
+<br class="">
+    /// Set the specified arguments of the instruction.<br class="">
+    void setDest(Value *Ptr) {<br class="">
+      assert(getRawDest()->getType() == Ptr->getType() &&<br class="">
+             "setDest called with pointer of wrong type!");<br class="">
+      setArgOperand(ARG_DEST, Ptr);<br class="">
+    }<br class="">
+<br class="">
+    void setSource(Value *Ptr) {<br class="">
+      assert(getRawSource()->getType() == Ptr->getType() &&<br class="">
+             "setSource called with pointer of wrong type!");<br class="">
+      setArgOperand(ARG_SOURCE, Ptr);<br class="">
+    }<br class="">
+<br class="">
+    void setLength(Value *L) {<br class="">
+      assert(getLength()->getType() == L->getType() &&<br class="">
+             "setLength called with value of wrong type!");<br class="">
+      setArgOperand(ARG_LENGTH, L);<br class="">
+    }<br class="">
+<br class="">
+    void setElementSizeInBytes(Constant *V) {<br class="">
+      assert(V->getType() == Type::getInt8Ty(getContext()) &&<br class="">
+             "setElementSizeInBytes called with value of wrong type!");<br class="">
+      setArgOperand(ARG_ELEMENTSIZE, V);<br class="">
+    }<br class="">
+<br class="">
+    static inline bool classof(const IntrinsicInst *I) {<br class="">
+      return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic;<br class="">
+    }<br class="">
+    static inline bool classof(const Value *V) {<br class="">
+      return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));<br class="">
+    }<br class="">
+  };<br class="">
+<br class="">
   /// This is the common base class for memset/memcpy/memmove.<br class="">
   class MemIntrinsic : public IntrinsicInst {<br class="">
   public:<br class="">
<br class="">
Modified: llvm/trunk/include/llvm/IR/Intrinsics.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/include/llvm/IR/Intrinsics.td (original)<br class="">
+++ llvm/trunk/include/llvm/IR/Intrinsics.td Wed Jul 12 08:25:26 2017<br class="">
@@ -873,6 +873,18 @@ def int_memcpy_element_unordered_atomic<br class="">
                   ReadOnly<1><br class="">
                 ]>;<br class="">
<br class="">
+// @llvm.memmove.element.unordered.atomic.*(dest, src, length, elementsize)<br class="">
+def int_memmove_element_unordered_atomic<br class="">
+    : Intrinsic<[],<br class="">
+                [<br class="">
+                  llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty<br class="">
+                ],<br class="">
+                [<br class="">
+                  IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>,<br class="">
+                  ReadOnly<1><br class="">
+                ]>;<br class="">
+<br class="">
+<br class="">
 //===------------------------ Reduction Intrinsics ------------------------===//<br class="">
 //<br class="">
 def int_experimental_vector_reduce_fadd : Intrinsic<[llvm_anyfloat_ty],<br class="">
<br class="">
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)<br class="">
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Jul 12 08:25:26 2017<br class="">
@@ -4994,6 +4994,44 @@ SelectionDAGBuilder::visitIntrinsicCall(<br class="">
     DAG.setRoot(CallResult.second);<br class="">
     return nullptr;<br class="">
   }<br class="">
+  case Intrinsic::memmove_element_unordered_atomic: {<br class="">
+    auto &MI = cast<ElementUnorderedAtomicMemMoveInst>(I);<br class="">
+    SDValue Dst = getValue(MI.getRawDest());<br class="">
+    SDValue Src = getValue(MI.getRawSource());<br class="">
+    SDValue Length = getValue(MI.getLength());<br class="">
+<br class="">
+    // Emit a library call.<br class="">
+    TargetLowering::ArgListTy Args;<br class="">
+    TargetLowering::ArgListEntry Entry;<br class="">
+    Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext());<br class="">
+    Entry.Node = Dst;<br class="">
+    Args.push_back(Entry);<br class="">
+<br class="">
+    Entry.Node = Src;<br class="">
+    Args.push_back(Entry);<br class="">
+<br class="">
+    Entry.Ty = MI.getLength()->getType();<br class="">
+    Entry.Node = Length;<br class="">
+    Args.push_back(Entry);<br class="">
+<br class="">
+    uint64_t ElementSizeConstant = MI.getElementSizeInBytes();<br class="">
+    RTLIB::Libcall LibraryCall =<br class="">
+        RTLIB::getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(ElementSizeConstant);<br class="">
+    if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)<br class="">
+      report_fatal_error("Unsupported element size");<br class="">
+<br class="">
+    TargetLowering::CallLoweringInfo CLI(DAG);<br class="">
+    CLI.setDebugLoc(sdl).setChain(getRoot()).setLibCallee(<br class="">
+        TLI.getLibcallCallingConv(LibraryCall),<br class="">
+        Type::getVoidTy(*DAG.getContext()),<br class="">
+        DAG.getExternalSymbol(TLI.getLibcallName(LibraryCall),<br class="">
+                              TLI.getPointerTy(DAG.getDataLayout())),<br class="">
+        std::move(Args));<br class="">
+<br class="">
+    std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);<br class="">
+    DAG.setRoot(CallResult.second);<br class="">
+    return nullptr;<br class="">
+  }<br class="">
   case Intrinsic::dbg_declare: {<br class="">
     const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);<br class="">
     DILocalVariable *Variable = DI.getVariable();<br class="">
<br class="">
Modified: llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp (original)<br class="">
+++ llvm/trunk/lib/CodeGen/TargetLoweringBase.cpp Wed Jul 12 08:25:26 2017<br class="">
@@ -384,6 +384,16 @@ static void InitLibcallNames(const char<br class="">
       "__llvm_memcpy_element_unordered_atomic_8";<br class="">
   Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_16] =<br class="">
       "__llvm_memcpy_element_unordered_atomic_16";<br class="">
+  Names[RTLIB::MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1] =<br class="">
+      "__llvm_memmove_element_unordered_atomic_1";<br class="">
+  Names[RTLIB::MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2] =<br class="">
+      "__llvm_memmove_element_unordered_atomic_2";<br class="">
+  Names[RTLIB::MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4] =<br class="">
+      "__llvm_memmove_element_unordered_atomic_4";<br class="">
+  Names[RTLIB::MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8] =<br class="">
+      "__llvm_memmove_element_unordered_atomic_8";<br class="">
+  Names[RTLIB::MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16] =<br class="">
+      "__llvm_memmove_element_unordered_atomic_16";<br class="">
   Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume";<br class="">
   Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1] = "__sync_val_compare_and_swap_1";<br class="">
   Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2] = "__sync_val_compare_and_swap_2";<br class="">
@@ -801,6 +811,23 @@ RTLIB::Libcall RTLIB::getMEMCPY_ELEMENT_<br class="">
   default:<br class="">
     return UNKNOWN_LIBCALL;<br class="">
   }<br class="">
+}<br class="">
+<br class="">
+RTLIB::Libcall RTLIB::getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize) {<br class="">
+  switch (ElementSize) {<br class="">
+  case 1:<br class="">
+    return MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1;<br class="">
+  case 2:<br class="">
+    return MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2;<br class="">
+  case 4:<br class="">
+    return MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4;<br class="">
+  case 8:<br class="">
+    return MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8;<br class="">
+  case 16:<br class="">
+    return MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16;<br class="">
+  default:<br class="">
+    return UNKNOWN_LIBCALL;<br class="">
+  }<br class="">
 }<br class="">
<br class="">
 /// InitCmpLibcallCCs - Set default comparison libcall CC.<br class="">
<br class="">
Modified: llvm/trunk/lib/IR/Verifier.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/lib/IR/Verifier.cpp (original)<br class="">
+++ llvm/trunk/lib/IR/Verifier.cpp Wed Jul 12 08:25:26 2017<br class="">
@@ -4044,6 +4044,42 @@ void Verifier::visitIntrinsicCallSite(In<br class="">
            "incorrect alignment of the source argument", CS);<br class="">
     break;<br class="">
   }<br class="">
+  case Intrinsic::memmove_element_unordered_atomic: {<br class="">
+    auto *MI = cast<ElementUnorderedAtomicMemMoveInst>(CS.getInstruction());<br class="">
+<br class="">
+    ConstantInt *ElementSizeCI =<br class="">
+        dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());<br class="">
+    Assert(ElementSizeCI,<br class="">
+           "element size of the element-wise unordered atomic memory "<br class="">
+           "intrinsic must be a constant int",<br class="">
+           CS);<br class="">
+    const APInt &ElementSizeVal = ElementSizeCI->getValue();<br class="">
+    Assert(ElementSizeVal.isPowerOf2(),<br class="">
+           "element size of the element-wise atomic memory intrinsic "<br class="">
+           "must be a power of 2",<br class="">
+           CS);<br class="">
+<br class="">
+    if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {<br class="">
+      uint64_t Length = LengthCI->getZExtValue();<br class="">
+      uint64_t ElementSize = MI->getElementSizeInBytes();<br class="">
+      Assert((Length % ElementSize) == 0,<br class="">
+             "constant length must be a multiple of the element size in the "<br class="">
+             "element-wise atomic memory intrinsic",<br class="">
+             CS);<br class="">
+    }<br class="">
+<br class="">
+    auto IsValidAlignment = [&](uint64_t Alignment) {<br class="">
+      return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);<br class="">
+    };<br class="">
+    uint64_t DstAlignment = CS.getParamAlignment(0),<br class="">
+             SrcAlignment = CS.getParamAlignment(1);<br class="">
+    Assert(IsValidAlignment(DstAlignment),<br class="">
+           "incorrect alignment of the destination argument", CS);<br class="">
+    Assert(IsValidAlignment(SrcAlignment),<br class="">
+           "incorrect alignment of the source argument", CS);<br class="">
+<br class="">
+    break;<br class="">
+  }<br class="">
   case Intrinsic::gcroot:<br class="">
   case Intrinsic::gcwrite:<br class="">
   case Intrinsic::gcread:<br class="">
<br class="">
Modified: llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll (original)<br class="">
+++ llvm/trunk/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll Wed Jul 12 08:25:26 2017<br class="">
@@ -62,4 +62,67 @@ define void @test_memcpy_args(i8** %Stor<br class="">
   call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %Dst, i8* align 4 %Src, i32 4, i32 4)  ret void<br class="">
 }<br class="">
<br class="">
+define i8* @test_memmove1(i8* %P, i8* %Q) {<br class="">
+  ; CHECK: test_memmove<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 1)<br class="">
+  ret i8* %P<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $1, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_1<br class="">
+}<br class="">
+<br class="">
+define i8* @test_memmove2(i8* %P, i8* %Q) {<br class="">
+  ; CHECK: test_memmove2<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 2, i32 2)<br class="">
+  ret i8* %P<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $2, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_2<br class="">
+}<br class="">
+<br class="">
+define i8* @test_memmove4(i8* %P, i8* %Q) {<br class="">
+  ; CHECK: test_memmove4<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 4, i32 4)<br class="">
+  ret i8* %P<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $4, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_4<br class="">
+}<br class="">
+<br class="">
+define i8* @test_memmove8(i8* %P, i8* %Q) {<br class="">
+  ; CHECK: test_memmove8<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %P, i8* align 8 %Q, i32 8, i32 8)<br class="">
+  ret i8* %P<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $8, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_8<br class="">
+}<br class="">
+<br class="">
+define i8* @test_memmove16(i8* %P, i8* %Q) {<br class="">
+  ; CHECK: test_memmove16<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 16 %P, i8* align 16 %Q, i32 16, i32 16)<br class="">
+  ret i8* %P<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $16, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_16<br class="">
+}<br class="">
+<br class="">
+define void @test_memmove_args(i8** %Storage) {<br class="">
+  ; CHECK: test_memmove_args<br class="">
+  %Dst = load i8*, i8** %Storage<br class="">
+  %Src.addr = getelementptr i8*, i8** %Storage, i64 1<br class="">
+  %Src = load i8*, i8** %Src.addr<br class="">
+<br class="">
+  ; 1st arg (%rdi)<br class="">
+  ; CHECK-DAG: movq (%rdi), [[REG1:%r.+]]<br class="">
+  ; CHECK-DAG: movq [[REG1]], %rdi<br class="">
+  ; 2nd arg (%rsi)<br class="">
+  ; CHECK-DAG: movq 8(%rdi), %rsi<br class="">
+  ; 3rd arg (%edx) -- length<br class="">
+  ; CHECK-DAG: movl $4, %edx<br class="">
+  ; CHECK: __llvm_memmove_element_unordered_atomic_4<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %Dst, i8* align 4 %Src, i32 4, i32 4)  ret void<br class="">
+}<br class="">
+<br class="">
 declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind<br class="">
+declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind<br class="">
<br class="">
Modified: llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll?rev=307796&r1=307795&r2=307796&view=diff" rel="noreferrer" target="_blank" class="">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll?rev=307796&r1=307795&r2=307796&view=diff</a><br class="">
==============================================================================<br class="">
--- llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll (original)<br class="">
+++ llvm/trunk/test/Verifier/element-wise-atomic-memory-intrinsics.ll Wed Jul 12 08:25:26 2017<br class="">
@@ -22,4 +22,28 @@ define void @test_memcpy(i8* %P, i8* %Q,<br class="">
   ret void<br class="">
 }<br class="">
 declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind<br class="">
+<br class="">
+define void @test_memmove(i8* %P, i8* %Q, i32 %A, i32 %E) {<br class="">
+  ; CHECK: element size of the element-wise unordered atomic memory intrinsic must be a constant int<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 %E)<br class="">
+  ; CHECK: element size of the element-wise atomic memory intrinsic must be a power of 2<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 3)<br class="">
+<br class="">
+  ; CHECK: constant length must be a multiple of the element size in the element-wise atomic memory intrinsic<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 7, i32 4)<br class="">
+<br class="">
+  ; CHECK: incorrect alignment of the destination argument<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* %P, i8* align 4 %Q, i32 1, i32 1)<br class="">
+  ; CHECK: incorrect alignment of the destination argument<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 1 %P, i8* align 4 %Q, i32 4, i32 4)<br class="">
+<br class="">
+  ; CHECK: incorrect alignment of the source argument<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* %Q, i32 1, i32 1)<br class="">
+  ; CHECK: incorrect alignment of the source argument<br class="">
+  call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 1 %Q, i32 4, i32 4)<br class="">
+<br class="">
+  ret void<br class="">
+}<br class="">
+declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind<br class="">
+<br class="">
 ; CHECK: input module is broken!<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
llvm-commits mailing list<br class="">
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="">llvm-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="">
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</blockquote>
</div>
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</blockquote>
</div>
</div>
_______________________________________________<br class="">
llvm-commits mailing list<br class="">
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="">llvm-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br class="">
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">
</body>
</html>