Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2878,6 +2878,19 @@ if (match(II->getNextNode(), m_Intrinsic(m_Specific(IIOperand)))) return eraseInstFromFunction(*II); + + // Canonicalize guard(a && b) -> guard(a); guard(b); + // Note: New assumption intrinsics created here are registered by + // the InstCombineIRInserter object. + Value *GuardIntrinsic = II->getCalledValue(), *A, *B; + OperandBundleDef DeoptOB(*II->getOperandBundle(LLVMContext::OB_deopt)); + if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) { + Builder->CreateCall(GuardIntrinsic, A, + {DeoptOB}, II->getName()); + Builder->CreateCall(GuardIntrinsic, B, + {DeoptOB}, II->getName()); + return eraseInstFromFunction(*II); + } break; } } Index: test/Transforms/InstCombine/call-guard.ll =================================================================== --- test/Transforms/InstCombine/call-guard.ll +++ test/Transforms/InstCombine/call-guard.ll @@ -18,3 +18,13 @@ call void(i1, ...) @llvm.experimental.guard( i1 %A )[ "deopt"() ] ret void } + +define void @test_guard_and(i1 %A, i1 %B) { +; CHECK-LABEL: @test_guard_and( +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %A) [ "deopt"() ] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %B) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = and i1 %A, %B + call void(i1, ...) @llvm.experimental.guard( i1 %C )[ "deopt"() ] + ret void +}