]> granicus.if.org Git - llvm/commitdiff
[InstCombine] Allow InstCombine to merge adjacent guards
authorSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 1 Feb 2017 16:34:55 +0000 (16:34 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 1 Feb 2017 16:34:55 +0000 (16:34 +0000)
Summary:
If there are two adjacent guards with different conditions, we can
remove one of them and include its condition into the condition of
another one. This patch allows InstCombine to merge them by the
following pattern:

    guard(a); guard(b) -> guard(a & b).

Reviewers: reames, apilipenko, igor-laevsky, anna, sanjoy

Reviewed By: sanjoy

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D29378

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293778 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCalls.cpp
test/Transforms/InstCombine/call-guard.ll

index 56983dc60360ee66a950b600b7f6326b2b746a1d..f088671c6d7e4ba9a4f9985198746eb31f2ddd63 100644 (file)
@@ -3255,16 +3255,24 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
   }
 
   case Intrinsic::experimental_guard: {
-    Value *IIOperand = II->getArgOperand(0);
+    // Is this guard followed by another guard?
+    Instruction *NextInst = II->getNextNode();
+    Value *NextCond = nullptr;
+    if (match(NextInst,
+              m_Intrinsic<Intrinsic::experimental_guard>(m_Value(NextCond)))) {
+      Value *CurrCond = II->getArgOperand(0);
 
-    // Remove a guard if it is immediately followed by an identical guard.
-    if (match(II->getNextNode(),
-              m_Intrinsic<Intrinsic::experimental_guard>(m_Specific(IIOperand))))
-      return eraseInstFromFunction(*II);
+      // Remove a guard that it is immediately preceeded by an identical guard.
+      if (CurrCond == NextCond)
+        return eraseInstFromFunction(*NextInst);
+
+      // Otherwise canonicalize guard(a); guard(b) -> guard(a & b).
+      II->setArgOperand(0, Builder->CreateAnd(CurrCond, NextCond));
+      return eraseInstFromFunction(*NextInst);
+    }
     break;
   }
   }
-
   return visitCallSite(II);
 }
 
index 18da465e606c593f9cd5b14b80a8a0a1f8fb8f90..9664467f914b42046dd5cc79fdd3393240aae5b9 100644 (file)
@@ -2,8 +2,8 @@
 
 declare void @llvm.experimental.guard(i1, ...)
 
-define void @test_guard_adjacent(i1 %A) {
-; CHECK-LABEL: @test_guard_adjacent(
+define void @test_guard_adjacent_same_cond(i1 %A) {
+; CHECK-LABEL: @test_guard_adjacent_same_cond(
 ; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %A) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
   call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
@@ -19,12 +19,14 @@ define void @test_guard_adjacent(i1 %A) {
   ret void
 }
 
-define void @test_guard_adjacent_neg(i1 %A, i1 %B) {
-; CHECK-LABEL: @test_guard_adjacent_neg(
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %A) [ "deopt"() ]
-; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %B) [ "deopt"() ]
+define void @test_guard_adjacent_diff_cond(i1 %A, i1 %B, i1 %C) {
+; CHECK-LABEL: @test_guard_adjacent_diff_cond(
+; CHECK-NEXT:    %1 = and i1 %A, %B
+; CHECK-NEXT:    %2 = and i1 %1, %C
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
-  call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ]
-  call void(i1, ...) @llvm.experimental.guard( i1 %B )[ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard( i1 %A, i32 123 )[ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard( i1 %B, i32 456 )[ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 789 )[ "deopt"() ]
   ret void
 }