Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2891,6 +2891,15 @@ {DeoptOB}, II->getName()); return eraseInstFromFunction(*II); } + + // guard(!(a || b)) -> guard(!a); guard(!b); + if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) { + Builder->CreateCall(GuardIntrinsic, Builder->CreateNot(A), + {DeoptOB}, II->getName()); + Builder->CreateCall(GuardIntrinsic, Builder->CreateNot(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 @@ -28,3 +28,16 @@ call void(i1, ...) @llvm.experimental.guard( i1 %C )[ "deopt"() ] ret void } + +define void @test_guard_not_or(i1 %A, i1 %B) { +; CHECK-LABEL: @test_guard_not_or( +; CHECK-NEXT: %1 = xor i1 %A, true +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %1) [ "deopt"() ] +; CHECK-NEXT: %2 = xor i1 %B, true +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %2) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = or i1 %A, %B + %D = xor i1 %C, true + call void(i1, ...) @llvm.experimental.guard( i1 %D )[ "deopt"() ] + ret void +}