<div dir="ltr">Breaks WERROR, <div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/11432/steps/bootstrap%20clang/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux/builds/11432/steps/bootstrap%20clang/logs/stdio</a><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 9, 2018 at 3:56 PM, Philip Reames 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: reames<br>
Date: Wed May  9 15:56:32 2018<br>
New Revision: 331935<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=331935&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=331935&view=rev</a><br>
Log:<br>
[InstCombine] Widen guards with conditions between<br>
<br>
The previous handling for guard widening in InstCombine was extremely restrictive. In particular, it didn't handle the common case where we had two guards separated by a single icmp. Handle this by scanning through a small fixed window of instructions to find the next guard if needed.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D46203" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D46203</a><br>
<br>
<br>
Modified:<br>
    llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineCalls.<wbr>cpp<br>
    llvm/trunk/test/Transforms/<wbr>InstCombine/call-guard.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineCalls.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=331935&r1=331934&r2=331935&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/lib/<wbr>Transforms/InstCombine/<wbr>InstCombineCalls.cpp?rev=<wbr>331935&r1=331934&r2=331935&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineCalls.<wbr>cpp (original)<br>
+++ llvm/trunk/lib/Transforms/<wbr>InstCombine/InstCombineCalls.<wbr>cpp Wed May  9 15:56:32 2018<br>
@@ -79,6 +79,13 @@ static cl::opt<unsigned> UnfoldElementAt<br>
     cl::desc("Maximum number of elements in atomic memcpy the optimizer is "<br>
              "allowed to unfold"));<br>
<br>
+static cl::opt<unsigned> GuardWideningWindow(<br>
+    "instcombine-guard-widening-<wbr>window",<br>
+    cl::init(3),<br>
+    cl::desc("How wide an instruction window to bypass looking for "<br>
+             "another guard"));<br>
+<br>
+<br>
 /// Return the specified type promoted as it would be to pass though a va_arg<br>
 /// area.<br>
 static Type *getPromotedType(Type *Ty) {<br>
@@ -3624,8 +3631,16 @@ Instruction *InstCombiner::visitCallInst<br>
   }<br>
<br>
   case Intrinsic::experimental_guard: {<br>
-    // Is this guard followed by another guard?<br>
+    // Is this guard followed by another guard?  We scan forward over a small<br>
+    // fixed window of instructions to handle common cases with conditions<br>
+    // computed between guards.<br>
     Instruction *NextInst = II->getNextNode();<br>
+    for (int i = 0; i < GuardWideningWindow; i++) {<br>
+      // Note: Using context-free form to avoid compile time blow up<br>
+      if (!<wbr>isSafeToSpeculativelyExecute(<wbr>NextInst))<br>
+        break;<br>
+      NextInst = NextInst->getNextNode();<br>
+    }<br>
     Value *NextCond = nullptr;<br>
     if (match(NextInst,<br>
               m_Intrinsic<Intrinsic::<wbr>experimental_guard>(m_Value(<wbr>NextCond)))) {<br>
@@ -3636,6 +3651,12 @@ Instruction *InstCombiner::visitCallInst<br>
         return eraseInstFromFunction(*<wbr>NextInst);<br>
<br>
       // Otherwise canonicalize guard(a); guard(b) -> guard(a & b).<br>
+      Instruction* MoveI = II->getNextNode();<br>
+      while (MoveI != NextInst) {<br>
+        auto *Temp = MoveI;<br>
+        MoveI = MoveI->getNextNode();<br>
+        Temp->moveBefore(II);<br>
+      }<br>
       II->setArgOperand(0, Builder.CreateAnd(CurrCond, NextCond));<br>
       return eraseInstFromFunction(*<wbr>NextInst);<br>
     }<br>
<br>
Modified: llvm/trunk/test/Transforms/<wbr>InstCombine/call-guard.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/call-guard.ll?rev=331935&r1=331934&r2=331935&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/llvm/trunk/test/<wbr>Transforms/InstCombine/call-<wbr>guard.ll?rev=331935&r1=331934&<wbr>r2=331935&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/test/Transforms/<wbr>InstCombine/call-guard.ll (original)<br>
+++ llvm/trunk/test/Transforms/<wbr>InstCombine/call-guard.ll Wed May  9 15:56:32 2018<br>
@@ -30,3 +30,81 @@ define void @test_guard_adjacent_diff_co<br>
   call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]<br>
   ret void<br>
 }<br>
+<br>
+; This version tests for the common form where the conditions are<br>
+; between the guards<br>
+define void @test_guard_adjacent_diff_<wbr>cond2(i32 %V1, i32 %V2) {<br>
+; CHECK-LABEL: @test_guard_adjacent_diff_<wbr>cond2(<br>
+; CHECK-NEXT:    %1 = and i32 %V1, %V2<br>
+; CHECK-NEXT:    %2 = icmp slt i32 %1, 0<br>
+; CHECK-NEXT:    %and = and i32 %V1, 255<br>
+; CHECK-NEXT:    %C = icmp ult i32 %and, 129<br>
+; CHECK-NEXT:    %3 = and i1 %2, %C<br>
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %3, i32 123) [ "deopt"() ]<br>
+; CHECK-NEXT:    ret void<br>
+  %A = icmp slt i32 %V1, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]<br>
+  %B = icmp slt i32 %V2, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]<br>
+  %and = and i32 %V1, 255<br>
+  %C = icmp sle i32 %and, 128<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]<br>
+  ret void<br>
+}<br>
+<br>
+; Might not be legal to hoist the load above the first guard since the<br>
+; guard might control dereferenceability<br>
+define void @negative_load(i32 %V1, i32* %P) {<br>
+; CHECK-LABEL: @negative_load<br>
+; CHECK:    @llvm.experimental.guard<br>
+; CHECK:    @llvm.experimental.guard<br>
+  %A = icmp slt i32 %V1, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]<br>
+  %V2 = load i32, i32* %P<br>
+  %B = icmp slt i32 %V2, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]<br>
+  ret void<br>
+}<br>
+<br>
+define void @deref_load(i32 %V1, i32* dereferenceable(4) %P) {<br>
+; CHECK-LABEL: @deref_load<br>
+; CHECK-NEXT:  %V2 = load i32, i32* %P, align 4<br>
+; CHECK-NEXT:  %1 = and i32 %V2, %V1<br>
+; CHECK-NEXT:  %2 = icmp slt i32 %1, 0<br>
+; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ]<br>
+  %A = icmp slt i32 %V1, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]<br>
+  %V2 = load i32, i32* %P<br>
+  %B = icmp slt i32 %V2, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]<br>
+  ret void<br>
+}<br>
+<br>
+; The divide might fault above the guard<br>
+define void @negative_div(i32 %V1, i32 %D) {<br>
+; CHECK-LABEL: @negative_div<br>
+; CHECK:    @llvm.experimental.guard<br>
+; CHECK:    @llvm.experimental.guard<br>
+  %A = icmp slt i32 %V1, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]<br>
+  %V2 = udiv i32 %V1, %D <br>
+  %B = icmp slt i32 %V2, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]<br>
+  ret void<br>
+}<br>
+<br>
+; Highlight the limit of the window in a case which would otherwise be mergable<br>
+define void @negative_window(i32 %V1, i32 %a, i32 %b, i32 %c, i32 %d) {<br>
+; CHECK-LABEL: @negative_window<br>
+; CHECK:    @llvm.experimental.guard<br>
+; CHECK:    @llvm.experimental.guard<br>
+  %A = icmp slt i32 %V1, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]<br>
+  %V2 = add i32 %a, %b<br>
+  %V3 = add i32 %V2, %c<br>
+  %V4 = add i32 %V3, %d<br>
+  %B = icmp slt i32 %V4, 0<br>
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]<br>
+  ret void<br>
+}<br>
+<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>