<div dir="ltr">Reverted in r284093. PR30499 still isn't fixed with this change. You might want to check the LLVM IR you used to test for it.</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 12, 2016 at 4:48 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I suspect this causes a crash on valid during the Chromium build:<div><a href="https://build.chromium.org/p/chromium.fyi/builders/ClangToTLinuxLLD/builds/1719/steps/compile/logs/stdio" target="_blank">https://build.chromium.org/p/<wbr>chromium.fyi/builders/<wbr>ClangToTLinuxLLD/builds/1719/<wbr>steps/compile/logs/stdio</a></div><div><br></div><div>The crash is during GVN hoisting:</div><div>3.<span class="m_4465426702782321183gmail-Apple-tab-span" style="white-space:pre-wrap">    </span>Running pass 'Early GVN Hoisting of Expressions' on function '@hb_buffer_deserialize_<wbr>glyphs'</div><div><br></div><div>Your new helper is also on the stack:</div><div>#8 0x0000000001d0a6af llvm::defClobbersUseOrDef(<wbr>llvm::MemoryDef*, llvm::MemoryUseOrDef const*, llvm::AAResults&)<br></div><div><br></div><div>I will try to get a reproducer.</div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Oct 11, 2016 at 7:23 PM, Sebastian Pop via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: spop<br>
Date: Tue Oct 11 21:23:39 2016<br>
New Revision: 283965<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=283965&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=283965&view=rev</a><br>
Log:<br>
GVN-hoist: fix store past load dependence analysis (PR30216, PR30499)<br>
<br>
This is a refreshed version of a patch that was reverted: it fixes<br>
the problems reported in both PR30216 and PR30499, and<br>
contains all the test-cases from both bugs.<br>
<br>
To hoist stores past loads, we used to search for potential<br>
conflicting loads on the hoisting path by following a MemorySSA<br>
def-def link from the store to be hoisted to the previous<br>
defining memory access, and from there we followed the def-use<br>
chains to all the uses that occur on the hoisting path. The<br>
problem is that the def-def link may point to a store that does<br>
not alias with the store to be hoisted, and so the loads that are<br>
walked may not alias with the store to be hoisted, and even as in<br>
the testcase of PR30216, the loads that may alias with the store<br>
to be hoisted are not visited.<br>
<br>
The current patch visits all loads on the path from the store to<br>
be hoisted to the hoisting position and uses the alias analysis<br>
to ask whether the store may alias the load. I was not able to<br>
use the MemorySSA functionality to ask for whether load and<br>
store are clobbered: I'm not sure which function to call, so I<br>
used a call to AA->isNoAlias().<br>
<br>
Store past store is still working as before using a MemorySSA<br>
query: I added an extra test to pr30216.ll to make sure store<br>
past store does not regress.<br>
<br>
Tested on x86_64-linux with check and a test-suite run.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D25476" rel="noreferrer" target="_blank">https://reviews.llvm.org/D2547<wbr>6</a><br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30216.ll<br>
    llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30499.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/Transf<wbr>orms/Utils/MemorySSA.h<br>
    llvm/trunk/lib/Transforms/Scal<wbr>ar/GVNHoist.cpp<br>
    llvm/trunk/lib/Transforms/Util<wbr>s/MemorySSA.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Transf<wbr>orms/Utils/MemorySSA.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/MemorySSA.h?rev=283965&r1=283964&r2=283965&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Transforms/Utils/MemorySSA.h?<wbr>rev=283965&r1=283964&r2=<wbr>283965&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/Transf<wbr>orms/Utils/MemorySSA.h (original)<br>
+++ llvm/trunk/include/llvm/Transf<wbr>orms/Utils/MemorySSA.h Tue Oct 11 21:23:39 2016<br>
@@ -974,6 +974,10 @@ inline upward_defs_iterator upward_defs_<br>
<br>
 inline upward_defs_iterator upward_defs_end() { return upward_defs_iterator(); }<br>
<br>
+bool instructionClobbersQuery(Memor<wbr>yDef *MD,<br>
+                              const MemoryLocation &UseLoc,<br>
+                              const Instruction *UseInst,<br>
+                              AliasAnalysis &AA);<br>
 } // end namespace llvm<br>
<br>
 #endif // LLVM_TRANSFORMS_UTILS_MEMORYSS<wbr>A_H<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scal<wbr>ar/GVNHoist.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVNHoist.cpp?rev=283965&r1=283964&r2=283965&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Scalar/GVNHoist.cpp?rev=<wbr>283965&r1=283964&r2=283965&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Scal<wbr>ar/GVNHoist.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scal<wbr>ar/GVNHoist.cpp Tue Oct 11 21:23:39 2016<br>
@@ -329,31 +329,36 @@ private:<br>
     return I1DFS < I2DFS;<br>
   }<br>
<br>
-  // Return true when there are users of Def in BB.<br>
-  bool hasMemoryUseOnPath(MemoryAcces<wbr>s *Def, const BasicBlock *BB,<br>
-                          const Instruction *OldPt) {<br>
-    const BasicBlock *DefBB = Def->getBlock();<br>
+  // Return true when there are memory uses of Def in BB.<br>
+  bool hasMemoryUse(const Instruction *NewPt, MemoryDef *Def,<br>
+                    const BasicBlock *BB) {<br>
+    const MemorySSA::AccessList *Acc = MSSA->getBlockAccesses(BB);<br>
+    if (!Acc)<br>
+      return false;<br>
+<br>
+    Instruction *OldPt = Def->getMemoryInst();<br>
     const BasicBlock *OldBB = OldPt->getParent();<br>
+    const BasicBlock *NewBB = NewPt->getParent();<br>
+    bool ReachedNewPt = false;<br>
<br>
-    for (User *U : Def->users())<br>
-      if (auto *MU = dyn_cast<MemoryUse>(U)) {<br>
-        // FIXME: MU->getBlock() does not get updated when we move the instruction.<br>
-        BasicBlock *UBB = MU->getMemoryInst()->getParent<wbr>();<br>
-        // Only analyze uses in BB.<br>
-        if (BB != UBB)<br>
-          continue;<br>
-<br>
-        // A use in the same block as the Def is on the path.<br>
-        if (UBB == DefBB) {<br>
-          assert(MSSA->locallyDominates(<wbr>Def, MU) && "def not dominating use");<br>
-          return true;<br>
+    for (const MemoryAccess &MA : *Acc)<br>
+      if (const MemoryUse *MU = dyn_cast<MemoryUse>(&MA)) {<br>
+        Instruction *Insn = MU->getMemoryInst();<br>
+<br>
+        // Do not check whether MU aliases Def when MU occurs after OldPt.<br>
+        if (BB == OldBB && firstInBB(OldPt, Insn))<br>
+          break;<br>
+<br>
+        // Do not check whether MU aliases Def when MU occurs before NewPt.<br>
+        if (BB == NewBB) {<br>
+          if (!ReachedNewPt) {<br>
+            if (firstInBB(Insn, NewPt))<br>
+              continue;<br>
+            ReachedNewPt = true;<br>
+          }<br>
         }<br>
-<br>
-        if (UBB != OldBB)<br>
-          return true;<br>
-<br>
-        // It is only harmful to hoist when the use is before OldPt.<br>
-        if (firstInBB(MU->getMemoryInst()<wbr>, OldPt))<br>
+        if (instructionClobbersQuery(Def, MemoryLocation::get(Insn), Insn,<br>
+                                     *AA))<br>
           return true;<br>
       }<br>
<br>
@@ -361,17 +366,18 @@ private:<br>
   }<br>
<br>
   // Return true when there are exception handling or loads of memory Def<br>
-  // between OldPt and NewPt.<br>
+  // between Def and NewPt.  This function is only called for stores: Def is<br>
+  // the MemoryDef of the store to be hoisted.<br>
<br>
   // Decrement by 1 NBBsOnAllPaths for each block between HoistPt and BB, and<br>
   // return true when the counter NBBsOnAllPaths reaces 0, except when it is<br>
   // initialized to -1 which is unlimited.<br>
-  bool hasEHOrLoadsOnPath(const Instruction *NewPt, const Instruction *OldPt,<br>
-                          MemoryAccess *Def, int &NBBsOnAllPaths) {<br>
+  bool hasEHOrLoadsOnPath(const Instruction *NewPt, MemoryDef *Def,<br>
+                          int &NBBsOnAllPaths) {<br>
     const BasicBlock *NewBB = NewPt->getParent();<br>
-    const BasicBlock *OldBB = OldPt->getParent();<br>
+    const BasicBlock *OldBB = Def->getBlock();<br>
     assert(DT->dominates(NewBB, OldBB) && "invalid path");<br>
-    assert(DT->dominates(Def->getB<wbr>lock(), NewBB) &&<br>
+    assert(DT->dominates(Def->getD<wbr>efiningAccess()->getBlock(), NewBB) &&<br>
            "def does not dominate new hoisting point");<br>
<br>
     // Walk all basic blocks reachable in depth-first iteration on the inverse<br>
@@ -390,7 +396,7 @@ private:<br>
         return true;<br>
<br>
       // Check that we do not move a store past loads.<br>
-      if (hasMemoryUseOnPath(Def, *I, OldPt))<br>
+      if (hasMemoryUse(NewPt, Def, *I))<br>
         return true;<br>
<br>
       // Stop walk once the limit is reached.<br>
@@ -473,7 +479,7 @@ private:<br>
<br>
     // Check for unsafe hoistings due to side effects.<br>
     if (K == InsKind::Store) {<br>
-      if (hasEHOrLoadsOnPath(NewPt, OldPt, D, NBBsOnAllPaths))<br>
+      if (hasEHOrLoadsOnPath(NewPt, dyn_cast<MemoryDef>(U), NBBsOnAllPaths))<br>
         return false;<br>
     } else if (hasEHOnPath(NewBB, OldBB, NBBsOnAllPaths))<br>
       return false;<br>
<br>
Modified: llvm/trunk/lib/Transforms/Util<wbr>s/MemorySSA.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/MemorySSA.cpp?rev=283965&r1=283964&r2=283965&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/MemorySSA.cpp?rev=<wbr>283965&r1=283964&r2=283965&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Util<wbr>s/MemorySSA.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Util<wbr>s/MemorySSA.cpp Tue Oct 11 21:23:39 2016<br>
@@ -169,44 +169,6 @@ template <> struct DenseMapInfo<MemoryLo<br>
     return LHS == RHS;<br>
   }<br>
 };<br>
-}<br>
-<br>
-namespace {<br>
-struct UpwardsMemoryQuery {<br>
-  // True if our original query started off as a call<br>
-  bool IsCall;<br>
-  // The pointer location we started the query with. This will be empty if<br>
-  // IsCall is true.<br>
-  MemoryLocation StartingLoc;<br>
-  // This is the instruction we were querying about.<br>
-  const Instruction *Inst;<br>
-  // The MemoryAccess we actually got called with, used to test local domination<br>
-  const MemoryAccess *OriginalAccess;<br>
-<br>
-  UpwardsMemoryQuery()<br>
-      : IsCall(false), Inst(nullptr), OriginalAccess(nullptr) {}<br>
-<br>
-  UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)<br>
-      : IsCall(ImmutableCallSite(Inst)<wbr>), Inst(Inst), OriginalAccess(Access) {<br>
-    if (!IsCall)<br>
-      StartingLoc = MemoryLocation::get(Inst);<br>
-  }<br>
-};<br>
-<br>
-static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,<br>
-                           AliasAnalysis &AA) {<br>
-  Instruction *Inst = MD->getMemoryInst();<br>
-  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {<br>
-    switch (II->getIntrinsicID()) {<br>
-    case Intrinsic::lifetime_start:<br>
-    case Intrinsic::lifetime_end:<br>
-      return AA.isMustAlias(MemoryLocation(<wbr>II->getArgOperand(1)), Loc);<br>
-    default:<br>
-      return false;<br>
-    }<br>
-  }<br>
-  return false;<br>
-}<br>
<br>
 enum class Reorderability { Always, IfNoAlias, Never };<br>
<br>
@@ -248,21 +210,10 @@ static Reorderability getLoadReorderabil<br>
   return Result;<br>
 }<br>
<br>
-static bool isUseTriviallyOptimizableToLiv<wbr>eOnEntry(AliasAnalysis &AA,<br>
-                                                   const Instruction *I) {<br>
-  // If the memory can't be changed, then loads of the memory can't be<br>
-  // clobbered.<br>
-  //<br>
-  // FIXME: We should handle invariant groups, as well. It's a bit harder,<br>
-  // because we need to pay close attention to invariant group barriers.<br>
-  return isa<LoadInst>(I) && (I->getMetadata(LLVMContext::M<wbr>D_invariant_load) ||<br>
-                              AA.pointsToConstantMemory(I));<br>
-}<br>
-<br>
-static bool instructionClobbersQuery(Memor<wbr>yDef *MD,<br>
-                                     const MemoryLocation &UseLoc,<br>
-                                     const Instruction *UseInst,<br>
-                                     AliasAnalysis &AA) {<br>
+bool instructionClobbersQuery(Memor<wbr>yDef *MD,<br>
+                              const MemoryLocation &UseLoc,<br>
+                              const Instruction *UseInst,<br>
+                              AliasAnalysis &AA) {<br>
   Instruction *DefInst = MD->getMemoryInst();<br>
   assert(DefInst && "Defining instruction not actually an instruction");<br>
<br>
@@ -303,6 +254,56 @@ static bool instructionClobbersQuery(Mem<br>
   return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod;<br>
 }<br>
<br>
+}<br>
+<br>
+namespace {<br>
+struct UpwardsMemoryQuery {<br>
+  // True if our original query started off as a call<br>
+  bool IsCall;<br>
+  // The pointer location we started the query with. This will be empty if<br>
+  // IsCall is true.<br>
+  MemoryLocation StartingLoc;<br>
+  // This is the instruction we were querying about.<br>
+  const Instruction *Inst;<br>
+  // The MemoryAccess we actually got called with, used to test local domination<br>
+  const MemoryAccess *OriginalAccess;<br>
+<br>
+  UpwardsMemoryQuery()<br>
+      : IsCall(false), Inst(nullptr), OriginalAccess(nullptr) {}<br>
+<br>
+  UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)<br>
+      : IsCall(ImmutableCallSite(Inst)<wbr>), Inst(Inst), OriginalAccess(Access) {<br>
+    if (!IsCall)<br>
+      StartingLoc = MemoryLocation::get(Inst);<br>
+  }<br>
+};<br>
+<br>
+static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,<br>
+                           AliasAnalysis &AA) {<br>
+  Instruction *Inst = MD->getMemoryInst();<br>
+  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {<br>
+    switch (II->getIntrinsicID()) {<br>
+    case Intrinsic::lifetime_start:<br>
+    case Intrinsic::lifetime_end:<br>
+      return AA.isMustAlias(MemoryLocation(<wbr>II->getArgOperand(1)), Loc);<br>
+    default:<br>
+      return false;<br>
+    }<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+static bool isUseTriviallyOptimizableToLiv<wbr>eOnEntry(AliasAnalysis &AA,<br>
+                                                   const Instruction *I) {<br>
+  // If the memory can't be changed, then loads of the memory can't be<br>
+  // clobbered.<br>
+  //<br>
+  // FIXME: We should handle invariant groups, as well. It's a bit harder,<br>
+  // because we need to pay close attention to invariant group barriers.<br>
+  return isa<LoadInst>(I) && (I->getMetadata(LLVMContext::M<wbr>D_invariant_load) ||<br>
+                              AA.pointsToConstantMemory(I));<br>
+}<br>
+<br>
 static bool instructionClobbersQuery(Memor<wbr>yDef *MD, MemoryUse *MU,<br>
                                      const MemoryLocOrCall &UseMLOC,<br>
                                      AliasAnalysis &AA) {<br>
<br>
Added: llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30216.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr30216.ll?rev=283965&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/GVNHoist/pr30216.ll?rev=<wbr>283965&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30216.ll (added)<br>
+++ llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30216.ll Tue Oct 11 21:23:39 2016<br>
@@ -0,0 +1,52 @@<br>
+; RUN: opt -S -gvn-hoist < %s | FileCheck %s<br>
+<br>
+; Make sure the two stores @B do not get hoisted past the load @B.<br>
+<br>
+; CHECK-LABEL: define i8* @Foo<br>
+; CHECK: store<br>
+; CHECK: store<br>
+; CHECK: load<br>
+; CHECK: store<br>
+<br>
+@A = external global i8<br>
+@B = external global i8*<br>
+<br>
+define i8* @Foo() {<br>
+  store i8 0, i8* @A<br>
+  br i1 undef, label %if.then, label %if.else<br>
+<br>
+if.then:<br>
+  store i8* null, i8** @B<br>
+  ret i8* null<br>
+<br>
+if.else:<br>
+  %1 = load i8*, i8** @B<br>
+  store i8* null, i8** @B<br>
+  ret i8* %1<br>
+}<br>
+<br>
+; Make sure the two stores @B do not get hoisted past the store @GlobalVar.<br>
+<br>
+; CHECK-LABEL: define i8* @Fun<br>
+; CHECK: store<br>
+; CHECK: store<br>
+; CHECK: store<br>
+; CHECK: store<br>
+; CHECK: load<br>
+<br>
+@GlobalVar = internal global i8 0<br>
+<br>
+define i8* @Fun() {<br>
+  store i8 0, i8* @A<br>
+  br i1 undef, label %if.then, label %if.else<br>
+<br>
+if.then:<br>
+  store i8* null, i8** @B<br>
+  ret i8* null<br>
+<br>
+if.else:<br>
+  store i8 0, i8* @GlobalVar<br>
+  store i8* null, i8** @B<br>
+  %1 = load i8*, i8** @B<br>
+  ret i8* %1<br>
+}<br>
<br>
Added: llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30499.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVNHoist/pr30499.ll?rev=283965&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/test/Transfor<wbr>ms/GVNHoist/pr30499.ll?rev=<wbr>283965&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30499.ll (added)<br>
+++ llvm/trunk/test/Transforms/GVN<wbr>Hoist/pr30499.ll Tue Oct 11 21:23:39 2016<br>
@@ -0,0 +1,30 @@<br>
+; RUN: opt -S -gvn-hoist < %s<br>
+<br>
+define void @_Z3fn2v() #0 {<br>
+entry:<br>
+  %a = alloca i8*, align 8<br>
+  %b = alloca i32, align 4<br>
+  %0 = load i8*, i8** %a, align 8<br>
+  store i8 0, i8* %0, align 1<br>
+  %1 = load i32, i32* %b, align 4<br>
+  %tobool = icmp ne i32 %1, 0<br>
+  br i1 %tobool, label %if.then, label %if.end<br>
+<br>
+if.then:                                          ; preds = %entry<br>
+  %call = call i64 @_Z3fn1v() #2<br>
+  %conv = trunc i64 %call to i32<br>
+  store i32 %conv, i32* %b, align 4<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.then, %entry<br>
+  %2 = load i8*, i8** %a, align 8<br>
+  store i8 0, i8* %2, align 1<br>
+  ret void<br>
+}<br>
+<br>
+; Function Attrs: nounwind readonly<br>
+declare i64 @_Z3fn1v() #1<br>
+<br>
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #1 = { nounwind readonly "correctly-rounded-divide-sqrt<wbr>-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false<wbr>" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="fal<wbr>se" "no-trapping-math"="false" "stack-protector-buffer-size"=<wbr>"8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,<wbr>+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }<br>
+attributes #2 = { nounwind readonly }<br>
<br>
<br>
______________________________<wbr>_________________<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/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>