<div dir="ltr">In the meantime, I think it's fine if we XFAIL this for now on powerpc, while Tim has a look.<div><br></div><div>Cheers</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, May 5, 2017 at 9:36 AM Dean Michael Berris <<a href="mailto:dberris@google.com">dberris@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Huh. <a class="m_-8099157572313735759GWVZpf m_-8099157572313735759gW" id="m_-8099157572313735759IloFPc-0" href="mailto:timshen@google.com" target="_blank">+Tim Shen</a> -- any ideas why the recursion guard in the example wouldn't work?<div><br></div><div>Bill, do you think the fact that the set is a global, that we're running into weird init/destruction issues on ppc?</div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, May 5, 2017 at 2:18 AM Bill Seurer <<a href="mailto:seurer@linux.vnet.ibm.com" target="_blank">seurer@linux.vnet.ibm.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The new test case doesn't work on powerpc64le:<br>
<br>
<a href="http://lab.llvm.org:8011/builders/clang-ppc64le-linux/builds/6031/steps/ninja%20check%201/logs/FAIL%3A%20XRay-powerpc64le-linux%3A%3Acoverage-sample.cc" rel="noreferrer" target="_blank">http://lab.llvm.org:8011/builders/clang-ppc64le-linux/builds/6031/steps/ninja%20check%201/logs/FAIL%3A%20XRay-powerpc64le-linux%3A%3Acoverage-sample.cc</a><br>
<br>
When I run it locally it segfaults.<br>
<br>
Program received signal SIGSEGV, Segmentation fault.<br>
0x00003fffb7e39868 in std::_Rb_tree_insert_and_rebalance<br>
(__insert_left=<optimized out>, __x=<optimized out>, __p=<optimized<br>
out>, __header=...)<br>
     at /home/seurer/gcc/gcc-6.2.0/libstdc++-v3/src/c++98/tree.cc:282<br>
282         __root->_M_color = _S_black;<br>
(gdb) where<br>
#0  0x00003fffb7e39868 in std::_Rb_tree_insert_and_rebalance<br>
(__insert_left=<optimized out>, __x=<optimized out>, __p=<optimized<br>
out>, __header=...)<br>
     at /home/seurer/gcc/gcc-6.2.0/libstdc++-v3/src/c++98/tree.cc:282<br>
#1  0x000000001003644c in std::_Rb_tree<int, int, std::_Identity<int>,<br>
std::less<int>, std::allocator<int> >::_M_insert_<int const&,<br>
std::_Rb_tree<int, int, std::_Identity<int>, std::less<int>,<br>
std::allocator<int> >::_Alloc_node> (this=0x10ab48a0 <function_ids>,<br>
__x=0x0, __p=0x3fffffffef60, __v=@0x3ffffffff104: 3, __node_gen=...)<br>
     at<br>
/home/seurer/gcc/install/gcc-6.2.0/lib/gcc/powerpc64le-unknown-linux-gnu/6.1.1/../../../../include/c++/6.1.1/bits/stl_tree.h:1512<br>
#2  0x0000000010035f4c in std::_Rb_tree<int, int, std::_Identity<int>,<br>
std::less<int>, std::allocator<int> >::_M_insert_unique<int const&><br>
(this=0x10ab48a0 <function_ids>,<br>
     __v=@0x3ffffffff104: 3) at<br>
/home/seurer/gcc/install/gcc-6.2.0/lib/gcc/powerpc64le-unknown-linux-gnu/6.1.1/../../../../include/c++/6.1.1/bits/stl_tree.h:1869<br>
#3  0x00000000100353dc in std::set<int, std::less<int>,<br>
std::allocator<int> >::insert (this=0x10ab48a0 <function_ids>,<br>
__x=@0x3ffffffff104: 3)<br>
     at<br>
/home/seurer/gcc/install/gcc-6.2.0/lib/gcc/powerpc64le-unknown-linux-gnu/6.1.1/../../../../include/c++/6.1.1/bits/stl_set.h:483<br>
#4  0x0000000010034d50 in coverage_handler (fid=3) at<br>
/home/seurer/llvm/llvm-test/projects/compiler-rt/test/xray/TestCases/Linux/coverage-sample.cc:18<br>
#5  0x000000001002db78 in __xray::CallXRayPatchedFunction<br>
(FuncId=<optimized out>, Type=<optimized out>)<br>
     at<br>
/home/seurer/llvm/llvm-test/projects/compiler-rt/lib/xray/xray_trampoline_powerpc64.cc:12<br>
#6  0x000000001002dca8 in __xray_FunctionEntry () at<br>
/home/seurer/llvm/llvm-test/projects/compiler-rt/lib/xray/xray_trampoline_powerpc64_asm.S:75<br>
<br>
<br>
On 05/03/2017 11:59 PM, Dean Michael Berris via llvm-commits wrote:<br>
> Author: dberris<br>
> Date: Wed May  3 23:59:20 2017<br>
> New Revision: 302112<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=302112&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=302112&view=rev</a><br>
> Log:<br>
> [XRay][compiler-rt] Support patching/unpatching specific functions<br>
><br>
> Summary:<br>
> This change allows us to patch/unpatch specific functions using the<br>
> function ID. This is useful in cases where implementations might want to<br>
> do coverage-style, or more fine-grained control of which functions to<br>
> patch or un-patch at runtime.<br>
><br>
> Depends on D32693.<br>
><br>
> Reviewers: dblaikie, echristo, kpw<br>
><br>
> Subscribers: llvm-commits<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D32695" rel="noreferrer" target="_blank">https://reviews.llvm.org/D32695</a><br>
><br>
> Added:<br>
>     compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc<br>
> Modified:<br>
>     compiler-rt/trunk/include/xray/xray_interface.h<br>
>     compiler-rt/trunk/lib/xray/xray_init.cc<br>
>     compiler-rt/trunk/lib/xray/xray_interface.cc<br>
>     compiler-rt/trunk/lib/xray/xray_interface_internal.h<br>
><br>
> Modified: compiler-rt/trunk/include/xray/xray_interface.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=302112&r1=302111&r2=302112&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=302112&r1=302111&r2=302112&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/include/xray/xray_interface.h (original)<br>
> +++ compiler-rt/trunk/include/xray/xray_interface.h Wed May  3 23:59:20 2017<br>
> @@ -67,6 +67,14 @@ extern XRayPatchingStatus __xray_patch()<br>
>  // result values.<br>
>  extern XRayPatchingStatus __xray_unpatch();<br>
><br>
> +// This patches a specific function id. See XRayPatchingStatus for possible<br>
> +// result values.<br>
> +extern XRayPatchingStatus __xray_patch_function(int32_t FuncId);<br>
> +<br>
> +// This unpatches a specific function id. See XRayPatchingStatus for possible<br>
> +// result values.<br>
> +extern XRayPatchingStatus __xray_unpatch_function(int32_t FuncId);<br>
> +<br>
>  // Use XRay to log the first argument of each (instrumented) function call.<br>
>  // When this function exits, all threads will have observed the effect and<br>
>  // start logging their subsequent affected function calls (if patched).<br>
><br>
> Modified: compiler-rt/trunk/lib/xray/xray_init.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_init.cc?rev=302112&r1=302111&r2=302112&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_init.cc?rev=302112&r1=302111&r2=302112&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/xray/xray_init.cc (original)<br>
> +++ compiler-rt/trunk/lib/xray/xray_init.cc Wed May  3 23:59:20 2017<br>
> @@ -25,6 +25,8 @@ extern "C" {<br>
>  void __xray_init();<br>
>  extern const XRaySledEntry __start_xray_instr_map[] __attribute__((weak));<br>
>  extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));<br>
> +extern const XRayFunctionSledIndex __start_xray_fn_idx[] __attribute__((weak));<br>
> +extern const XRayFunctionSledIndex __stop_xray_fn_idx[] __attribute__((weak));<br>
>  }<br>
><br>
>  using namespace __xray;<br>
> @@ -55,6 +57,8 @@ void __xray_init() XRAY_NEVER_INSTRUMENT<br>
>      __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);<br>
>      XRayInstrMap.Sleds = __start_xray_instr_map;<br>
>      XRayInstrMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;<br>
> +    XRayInstrMap.SledsIndex = __start_xray_fn_idx;<br>
> +    XRayInstrMap.Functions = __stop_xray_fn_idx - __start_xray_fn_idx;<br>
>    }<br>
>    __sanitizer::atomic_store(&XRayInitialized, true,<br>
>                              __sanitizer::memory_order_release);<br>
><br>
> Modified: compiler-rt/trunk/lib/xray/xray_interface.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=302112&r1=302111&r2=302112&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=302112&r1=302111&r2=302112&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/xray/xray_interface.cc (original)<br>
> +++ compiler-rt/trunk/lib/xray/xray_interface.cc Wed May  3 23:59:20 2017<br>
> @@ -132,12 +132,48 @@ CleanupInvoker<Function> scopeCleanup(Fu<br>
>    return CleanupInvoker<Function>{Fn};<br>
>  }<br>
><br>
> +inline bool patchSled(const XRaySledEntry &Sled, bool Enable,<br>
> +                      int32_t FuncId) XRAY_NEVER_INSTRUMENT {<br>
> +  // While we're here, we should patch the nop sled. To do that we mprotect<br>
> +  // the page containing the function to be writeable.<br>
> +  const uint64_t PageSize = GetPageSizeCached();<br>
> +  void *PageAlignedAddr =<br>
> +      reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));<br>
> +  std::size_t MProtectLen = (Sled.Address + cSledLength) -<br>
> +                            reinterpret_cast<uint64_t>(PageAlignedAddr);<br>
> +  MProtectHelper Protector(PageAlignedAddr, MProtectLen);<br>
> +  if (Protector.MakeWriteable() == -1) {<br>
> +    printf("Failed mprotect: %d\n", errno);<br>
> +    return XRayPatchingStatus::FAILED;<br>
> +  }<br>
> +<br>
> +  bool Success = false;<br>
> +  switch (Sled.Kind) {<br>
> +  case XRayEntryType::ENTRY:<br>
> +    Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);<br>
> +    break;<br>
> +  case XRayEntryType::EXIT:<br>
> +    Success = patchFunctionExit(Enable, FuncId, Sled);<br>
> +    break;<br>
> +  case XRayEntryType::TAIL:<br>
> +    Success = patchFunctionTailExit(Enable, FuncId, Sled);<br>
> +    break;<br>
> +  case XRayEntryType::LOG_ARGS_ENTRY:<br>
> +    Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);<br>
> +    break;<br>
> +  default:<br>
> +    Report("Unsupported sled kind '%d' @%04x\n", Sled.Address, int(Sled.Kind));<br>
> +    return false;<br>
> +  }<br>
> +  return Success;<br>
> +}<br>
> +<br>
>  // controlPatching implements the common internals of the patching/unpatching<br>
>  // implementation. |Enable| defines whether we're enabling or disabling the<br>
>  // runtime XRay instrumentation.<br>
>  XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT {<br>
>    if (!__sanitizer::atomic_load(&XRayInitialized,<br>
> -                               __sanitizer::memory_order_acquire))<br>
> +                                __sanitizer::memory_order_acquire))<br>
>      return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.<br>
><br>
>    uint8_t NotPatching = false;<br>
> @@ -179,38 +215,7 @@ XRayPatchingStatus controlPatching(bool<br>
>        ++FuncId;<br>
>        CurFun = F;<br>
>      }<br>
> -<br>
> -    // While we're here, we should patch the nop sled. To do that we mprotect<br>
> -    // the page containing the function to be writeable.<br>
> -    void *PageAlignedAddr =<br>
> -        reinterpret_cast<void *>(Sled.Address & ~(PageSize - 1));<br>
> -    std::size_t MProtectLen = (Sled.Address + cSledLength) -<br>
> -                              reinterpret_cast<uint64_t>(PageAlignedAddr);<br>
> -    MProtectHelper Protector(PageAlignedAddr, MProtectLen);<br>
> -    if (Protector.MakeWriteable() == -1) {<br>
> -      printf("Failed mprotect: %d\n", errno);<br>
> -      return XRayPatchingStatus::FAILED;<br>
> -    }<br>
> -<br>
> -    bool Success = false;<br>
> -    switch (Sled.Kind) {<br>
> -    case XRayEntryType::ENTRY:<br>
> -      Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_FunctionEntry);<br>
> -      break;<br>
> -    case XRayEntryType::EXIT:<br>
> -      Success = patchFunctionExit(Enable, FuncId, Sled);<br>
> -      break;<br>
> -    case XRayEntryType::TAIL:<br>
> -      Success = patchFunctionTailExit(Enable, FuncId, Sled);<br>
> -      break;<br>
> -    case XRayEntryType::LOG_ARGS_ENTRY:<br>
> -      Success = patchFunctionEntry(Enable, FuncId, Sled, __xray_ArgLoggerEntry);<br>
> -      break;<br>
> -    default:<br>
> -      Report("Unsupported sled kind: %d\n", int(Sled.Kind));<br>
> -      continue;<br>
> -    }<br>
> -    (void)Success;<br>
> +    patchSled(Sled, Enable, FuncId);<br>
>    }<br>
>    __sanitizer::atomic_store(&XRayPatching, false,<br>
>                              __sanitizer::memory_order_release);<br>
> @@ -226,6 +231,64 @@ XRayPatchingStatus __xray_unpatch() XRAY<br>
>    return controlPatching(false);<br>
>  }<br>
><br>
> +XRayPatchingStatus patchFunction(int32_t FuncId,<br>
> +                                 bool Enable) XRAY_NEVER_INSTRUMENT {<br>
> +  if (!__sanitizer::atomic_load(&XRayInitialized,<br>
> +                                __sanitizer::memory_order_acquire))<br>
> +    return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.<br>
> +<br>
> +  uint8_t NotPatching = false;<br>
> +  if (!__sanitizer::atomic_compare_exchange_strong(<br>
> +          &XRayPatching, &NotPatching, true, __sanitizer::memory_order_acq_rel))<br>
> +    return XRayPatchingStatus::ONGOING; // Already patching.<br>
> +<br>
> +  // Next, we look for the function index.<br>
> +  XRaySledMap InstrMap;<br>
> +  {<br>
> +    __sanitizer::SpinMutexLock Guard(&XRayInstrMapMutex);<br>
> +    InstrMap = XRayInstrMap;<br>
> +  }<br>
> +<br>
> +  // If we don't have an index, we can't patch individual functions.<br>
> +  if (InstrMap.Functions == 0)<br>
> +    return XRayPatchingStatus::NOT_INITIALIZED;<br>
> +<br>
> +  // FuncId must be a positive number, less than the number of functions<br>
> +  // instrumented.<br>
> +  if (FuncId <= 0 || static_cast<size_t>(FuncId) >= InstrMap.Functions) {<br>
> +    Report("Invalid function id provided: %d\n", FuncId);<br>
> +    return XRayPatchingStatus::FAILED;<br>
> +  }<br>
> +<br>
> +  // Now we patch ths sleds for this specific function.<br>
> +  auto SledRange = InstrMap.SledsIndex[FuncId - 1];<br>
> +  auto *f = SledRange.Begin;<br>
> +  auto *e = SledRange.End;<br>
> +<br>
> +  bool SucceedOnce = false;<br>
> +  while (f != e)<br>
> +    SucceedOnce |= patchSled(*f++, Enable, FuncId);<br>
> +<br>
> +  __sanitizer::atomic_store(&XRayPatching, false,<br>
> +                            __sanitizer::memory_order_release);<br>
> +<br>
> +  if (!SucceedOnce) {<br>
> +    Report("Failed patching any sled for function '%d'.", FuncId);<br>
> +    return XRayPatchingStatus::FAILED;<br>
> +  }<br>
> +<br>
> +  return XRayPatchingStatus::SUCCESS;<br>
> +}<br>
> +<br>
> +XRayPatchingStatus __xray_patch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {<br>
> +  return patchFunction(FuncId, true);<br>
> +}<br>
> +<br>
> +XRayPatchingStatus<br>
> +__xray_unpatch_function(int32_t FuncId) XRAY_NEVER_INSTRUMENT {<br>
> +  return patchFunction(FuncId, false);<br>
> +}<br>
> +<br>
>  int __xray_set_handler_arg1(void (*Handler)(int32_t, XRayEntryType, uint64_t)) {<br>
>    if (!__sanitizer::atomic_load(&XRayInitialized,<br>
>                                  __sanitizer::memory_order_acquire))<br>
><br>
> Modified: compiler-rt/trunk/lib/xray/xray_interface_internal.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=302112&r1=302111&r2=302112&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=302112&r1=302111&r2=302112&view=diff</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/lib/xray/xray_interface_internal.h (original)<br>
> +++ compiler-rt/trunk/lib/xray/xray_interface_internal.h Wed May  3 23:59:20 2017<br>
> @@ -39,6 +39,11 @@ struct XRaySledEntry {<br>
>  #error "Unsupported word size."<br>
>  #endif<br>
>  };<br>
> +<br>
> +struct XRayFunctionSledIndex {<br>
> +  const XRaySledEntry* Begin;<br>
> +  const XRaySledEntry* End;<br>
> +};<br>
>  }<br>
><br>
>  namespace __xray {<br>
> @@ -46,6 +51,8 @@ namespace __xray {<br>
>  struct XRaySledMap {<br>
>    const XRaySledEntry *Sleds;<br>
>    size_t Entries;<br>
> +  const XRayFunctionSledIndex *SledsIndex;<br>
> +  size_t Functions;<br>
>  };<br>
><br>
>  bool patchFunctionEntry(bool Enable, uint32_t FuncId,<br>
><br>
> Added: compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc?rev=302112&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc?rev=302112&view=auto</a><br>
> ==============================================================================<br>
> --- compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc (added)<br>
> +++ compiler-rt/trunk/test/xray/TestCases/Linux/coverage-sample.cc Wed May  3 23:59:20 2017<br>
> @@ -0,0 +1,88 @@<br>
> +// Check that we can patch and unpatch specific function ids.<br>
> +//<br>
> +// RUN: %clangxx_xray -std=c++11 %s -o %t<br>
> +// RUN: XRAY_OPTIONS="patch_premain=false xray_naive_log=false" %run %t | FileCheck %s<br>
> +<br>
> +#include "xray/xray_interface.h"<br>
> +<br>
> +#include <set><br>
> +#include <cstdio><br>
> +<br>
> +std::set<int32_t> function_ids;<br>
> +<br>
> +[[clang::xray_never_instrument]] void coverage_handler(int32_t fid,<br>
> +                                                       XRayEntryType) {<br>
> +  thread_local bool patching = false;<br>
> +  if (patching) return;<br>
> +  patching = true;<br>
> +  function_ids.insert(fid);<br>
> +  __xray_unpatch_function(fid);<br>
> +  patching = false;<br>
> +}<br>
> +<br>
> +[[clang::xray_always_instrument]] void baz() {<br>
> +  // do nothing!<br>
> +}<br>
> +<br>
> +[[clang::xray_always_instrument]] void bar() {<br>
> +  baz();<br>
> +}<br>
> +<br>
> +[[clang::xray_always_instrument]] void foo() {<br>
> +  bar();<br>
> +}<br>
> +<br>
> +[[clang::xray_always_instrument]] int main(int argc, char *argv[]) {<br>
> +  __xray_set_handler(coverage_handler);<br>
> +  __xray_patch();<br>
> +  foo();<br>
> +  __xray_unpatch();<br>
> +<br>
> +  // print out the function_ids.<br>
> +  printf("first pass.\n");<br>
> +  for (const auto id : function_ids)<br>
> +    printf("patched: %d\n", id);<br>
> +<br>
> +  // CHECK-LABEL: first pass.<br>
> +  // CHECK-DAG: patched: [[F1:.*]]<br>
> +  // CHECK-DAG: patched: [[F2:.*]]<br>
> +  // CHECK-DAG: patched: [[F3:.*]]<br>
> +<br>
> +  // make a copy of the function_ids, then patch them later.<br>
> +  auto called_fns = function_ids;<br>
> +<br>
> +  // clear the function_ids.<br>
> +  function_ids.clear();<br>
> +<br>
> +  // patch the functions we've called before.<br>
> +  for (const auto id : called_fns)<br>
> +    __xray_patch_function(id);<br>
> +<br>
> +  // then call them again.<br>
> +  foo();<br>
> +  __xray_unpatch();<br>
> +<br>
> +  // confirm that we've seen the same functions again.<br>
> +  printf("second pass.\n");<br>
> +  for (const auto id : function_ids)<br>
> +    printf("patched: %d\n", id);<br>
> +  // CHECK-LABEL: second pass.<br>
> +  // CHECK-DAG: patched: [[F1]]<br>
> +  // CHECK-DAG: patched: [[F2]]<br>
> +  // CHECK-DAG: patched: [[F3]]<br>
> +<br>
> +  // Now we want to make sure that if we unpatch one, that we're only going to<br>
> +  // see two calls of the coverage_handler.<br>
> +  function_ids.clear();<br>
> +  __xray_patch();<br>
> +  __xray_unpatch_function(1);<br>
> +  foo();<br>
> +  __xray_unpatch();<br>
> +<br>
> +  // confirm that we don't see function id one called anymore.<br>
> +  printf("missing 1.\n");<br>
> +  for (const auto id : function_ids)<br>
> +    printf("patched: %d\n", id);<br>
> +  // CHECK-LABEL: missing 1.<br>
> +  // CHECK-NOT: patched: 1<br>
> +}<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">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>
><br>
<br>
<br>
--<br>
<br>
-Bill Seurer<br>
<br>
</blockquote></div></blockquote></div>