From c6141d3748e389b85a384a86f374a34c2bf5ea70 Mon Sep 17 00:00:00 2001 From: Artur Pilipenko Date: Wed, 25 Jan 2017 14:45:12 +0000 Subject: [PATCH] [InstCombine] Canonicalize guards for NOT OR condition This is a partial fix for Bug 31520 - [guards] canonicalize guards in instcombine Reviewed By: apilipenko Differential Revision: https://reviews.llvm.org/D29075 Patch by Maxim Kazantsev. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@293061 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineCalls.cpp | 12 +++++++++ test/Transforms/InstCombine/call-guard.ll | 26 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 64117f5a85b..5be321b7b47 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2989,6 +2989,18 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { 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))))) { + CallInst *GuardA = Builder->CreateCall( + GuardIntrinsic, Builder->CreateNot(A), {DeoptOB}, II->getName()); + CallInst *GuardB = Builder->CreateCall( + GuardIntrinsic, Builder->CreateNot(B), {DeoptOB}, II->getName()); + auto CC = II->getCallingConv(); + GuardA->setCallingConv(CC); + GuardB->setCallingConv(CC); + return eraseInstFromFunction(*II); + } break; } } diff --git a/test/Transforms/InstCombine/call-guard.ll b/test/Transforms/InstCombine/call-guard.ll index d392ede574f..1b59878f25c 100644 --- a/test/Transforms/InstCombine/call-guard.ll +++ b/test/Transforms/InstCombine/call-guard.ll @@ -48,3 +48,29 @@ define void @test_guard_and_non_default_cc(i1 %A, i1 %B) { call cc99 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 +} + +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) [ "deopt"() ] +; CHECK-NEXT: %2 = xor i1 %B, true +; CHECK-NEXT: call cc99 void (i1, ...) @llvm.experimental.guard(i1 %2) [ "deopt"() ] +; CHECK-NEXT: ret void + %C = or i1 %A, %B + %D = xor i1 %C, true + call cc99 void(i1, ...) @llvm.experimental.guard( i1 %D )[ "deopt"() ] + ret void +} -- 2.50.1