From 387f151ad992395897a7e5d859929bbd930bf8be Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Wed, 1 Feb 2017 16:34:55 +0000 Subject: [PATCH] [InstCombine] Allow InstCombine to merge adjacent guards 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 --- .../InstCombine/InstCombineCalls.cpp | 20 +++++++++++++------ test/Transforms/InstCombine/call-guard.ll | 18 +++++++++-------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 56983dc6036..f088671c6d7 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -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(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(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); } diff --git a/test/Transforms/InstCombine/call-guard.ll b/test/Transforms/InstCombine/call-guard.ll index 18da465e606..9664467f914 100644 --- a/test/Transforms/InstCombine/call-guard.ll +++ b/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,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 } -- 2.50.1