[PATCH] D29378: [InstCombine] Allow InstCombine to merge adjacent guards

Max Kazantsev via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 1 00:20:23 PST 2017


mkazantsev created this revision.

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 do this in two cases:

  guard(a); guard(b) -> guard(a & b),
  guard(!a); guard(!b) -> guard(!(a | b)).


https://reviews.llvm.org/D29378

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


Index: test/Transforms/InstCombine/call-guard.ll
===================================================================
--- test/Transforms/InstCombine/call-guard.ll
+++ test/Transforms/InstCombine/call-guard.ll
@@ -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,27 @@
   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 789) [ "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
+}
+
+define void @test_guard_adjacent_not_cond(i1 %A, i1 %B) {
+; CHECK-LABEL: @test_guard_adjacent_not_cond(
+; CHECK-NEXT:    %1 = or i1 %A, %B
+; CHECK-NEXT:    %2 = xor i1 %1, true
+; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 456) [ "deopt"() ]
+; CHECK-NEXT:    ret void
+  %C = xor i1 %A, true
+  %D = xor i1 %B, true
+  call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 123 )[ "deopt"() ]
+  call void(i1, ...) @llvm.experimental.guard( i1 %D, i32 456 )[ "deopt"() ]
   ret void
 }
Index: lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3255,16 +3255,33 @@
   }
 
   case Intrinsic::experimental_guard: {
-    Value *IIOperand = II->getArgOperand(0);
+    // Is this guard followed by another guard?
+    Value *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 (CurrCond == NextCond)
+        return eraseInstFromFunction(*II);
+
+      // Otherwise we try to widen the next guard and remove the current.
+      Value *A, *B, *NewCond;
+      if (match(CurrCond, m_Not(m_Value(A))) &&
+          match(NextCond, m_Not(m_Value(B))))
+        // Canonicalize guard(!a); guard(!b) -> guard(!(a | b)).
+        NewCond = Builder->CreateNot(Builder->CreateOr(A, B));
+      else
+        // Otherwise canonicalize guard(a); guard(b) -> guard(a & b).
+        NewCond = Builder->CreateAnd(CurrCond, NextCond);
 
-    // Remove a guard if it is immediately followed by an identical guard.
-    if (match(II->getNextNode(),
-              m_Intrinsic<Intrinsic::experimental_guard>(m_Specific(IIOperand))))
+      cast<IntrinsicInst>(NextInst)->setArgOperand(0, NewCond);
       return eraseInstFromFunction(*II);
+    }
     break;
   }
   }
-
   return visitCallSite(II);
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D29378.86583.patch
Type: text/x-patch
Size: 3779 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170201/2cb5026f/attachment-0001.bin>


More information about the llvm-commits mailing list