Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3255,16 +3255,24 @@ } case Intrinsic::experimental_guard: { - Value *IIOperand = 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); + // 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 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: llvm/trunk/test/Transforms/InstCombine/call-guard.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/call-guard.ll +++ llvm/trunk/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 @@ 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 }