Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -3261,6 +3261,49 @@ if (match(II->getNextNode(), m_Intrinsic(m_Specific(IIOperand)))) return eraseInstFromFunction(*II); + + // Canonicalize guard(a && b) -> guard(a); guard(b); + // Note: New guard intrinsics created here are registered by + // the InstCombineIRInserter object. + Function *GuardIntrinsic = II->getCalledFunction(); + Value *A, *B; + OperandBundleDef DeoptOB(*II->getOperandBundle(LLVMContext::OB_deopt)); + if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) { + // Prepare args for guard(a). + SmallVector Args(II->arg_begin(), II->arg_end()); + Args[0] = A; + CallInst *GuardA = + Builder->CreateCall(GuardIntrinsic, Args, {DeoptOB}, II->getName()); + + // Prepare args for guard(b). + Args[0] = B; + CallInst *GuardB = + Builder->CreateCall(GuardIntrinsic, Args, {DeoptOB}, II->getName()); + + auto CC = II->getCallingConv(); + GuardA->setCallingConv(CC); + GuardB->setCallingConv(CC); + return eraseInstFromFunction(*II); + } + + // guard(!(a || b)) -> guard(!a); guard(!b); + if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) { + // Prepare args for guard(!a). + SmallVector Args(II->arg_begin(), II->arg_end()); + Args[0] = Builder->CreateNot(A); + CallInst *GuardA = + Builder->CreateCall(GuardIntrinsic, Args, {DeoptOB}, II->getName()); + + // Prepare args for guard(!b). + Args[0] = Builder->CreateNot(B); + CallInst *GuardB = + Builder->CreateCall(GuardIntrinsic, Args, {DeoptOB}, II->getName()); + + auto CC = II->getCallingConv(); + GuardA->setCallingConv(CC); + GuardB->setCallingConv(CC); + 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,49 @@ call void(i1, ...) @llvm.experimental.guard( i1 %B )[ "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, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %B, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = and i1 %A, %B + call void(i1, ...) @llvm.experimental.guard( i1 %C, i32 123, i32 456, i32 789 )[ "deopt"() ] + ret void +} + +define void @test_guard_and_non_default_cc(i1 %A, i1 %B) { +; CHECK-LABEL: @test_guard_and_non_default_cc( +; CHECK-NEXT: call cc99 void (i1, ...) @llvm.experimental.guard(i1 %A, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: call cc99 void (i1, ...) @llvm.experimental.guard(i1 %B, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = and i1 %A, %B + call cc99 void(i1, ...) @llvm.experimental.guard( i1 %C, i32 123, i32 456, i32 789 )[ "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, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: %2 = xor i1 %B, true +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = or i1 %A, %B + %D = xor i1 %C, true + call void(i1, ...) @llvm.experimental.guard( i1 %D, i32 123, i32 456, i32 789 )[ "deopt"() ] + ret void +} + +define void @test_guard_not_or_non_default_cc(i1 %A, i1 %B) { +; CHECK-LABEL: @test_guard_not_or_non_default_cc( +; CHECK-NEXT: %1 = xor i1 %A, true +; CHECK-NEXT: call cc99 void (i1, ...) @llvm.experimental.guard(i1 %1, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: %2 = xor i1 %B, true +; CHECK-NEXT: call cc99 void (i1, ...) @llvm.experimental.guard(i1 %2, i32 123, i32 456, i32 789) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = or i1 %A, %B + %D = xor i1 %C, true + call cc99 void(i1, ...) @llvm.experimental.guard( i1 %D, i32 123, i32 456, i32 789 )[ "deopt"() ] + ret void +}