From dcf39d2586da38fe4410d8406a0abe4e3c7860c1 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 27 Nov 2014 07:25:21 +0000 Subject: [PATCH] InstCombine: Restore optimizations lost in r210006 This restores our ability to optimize: (X & C) == 0 ? X ^ C : X into X | C (X & C) != 0 ? X ^ C : X into X & ~C git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222871 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineSelect.cpp | 28 ++++++++++ test/Transforms/InstCombine/select.ll | 53 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 8e2a7d5ce65..83a2f2c563f 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -617,6 +617,34 @@ Instruction *InstCombiner::visitSelectInstWithICmp(SelectInst &SI, } } + { + Value *X; + const APInt *Y, *C; + if (match(CmpLHS, m_And(m_Value(X), m_Power2(Y))) && + match(CmpRHS, m_Zero())) { + Value *V = nullptr; + // (X & Y) == 0 ? X : X ^ Y --> X & ~Y + if (Pred == ICmpInst::ICMP_EQ && TrueVal == X && + match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) + V = Builder->CreateAnd(X, ~(*Y)); + // (X & Y) != 0 ? X ^ Y : X --> X & ~Y + else if (Pred == ICmpInst::ICMP_NE && FalseVal == X && + match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) + V = Builder->CreateAnd(X, ~(*Y)); + // (X & Y) == 0 ? X ^ Y : X --> X | Y + else if (Pred == ICmpInst::ICMP_EQ && FalseVal == X && + match(TrueVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) + V = Builder->CreateOr(X, *Y); + // (X & Y) != 0 ? X : X ^ Y --> X | Y + else if (Pred == ICmpInst::ICMP_NE && TrueVal == X && + match(FalseVal, m_Xor(m_Specific(X), m_APInt(C))) && *Y == *C) + V = Builder->CreateOr(X, *Y); + + if (V) + return ReplaceInstUsesWith(SI, V); + } + } + if (Value *V = foldSelectICmpAndOr(SI, TrueVal, FalseVal, Builder)) return ReplaceInstUsesWith(SI, V); diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index bdf48e40fd7..db3d77aedea 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -997,6 +997,59 @@ define <2 x i32> @select_icmp_eq_and_1_0_or_vector_of_2s(i32 %x, <2 x i32> %y) { ret <2 x i32> %select } +; CHECK-LABEL: @select_icmp_and_8_ne_0_xor_8( +; CHECK-NEXT: [[AND:%[a-z0-9]+]] = and i32 %x, -9 +; CHECK-NEXT: ret i32 [[AND]] +define i32 @select_icmp_and_8_ne_0_xor_8(i32 %x) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %xor = xor i32 %x, 8 + %x.xor = select i1 %cmp, i32 %x, i32 %xor + ret i32 %x.xor +} + +; CHECK-LABEL: @select_icmp_and_8_eq_0_xor_8( +; CHECK-NEXT: [[OR:%[a-z0-9]+]] = or i32 %x, 8 +; CHECK-NEXT: ret i32 [[OR]] +define i32 @select_icmp_and_8_eq_0_xor_8(i32 %x) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %xor = xor i32 %x, 8 + %xor.x = select i1 %cmp, i32 %xor, i32 %x + ret i32 %xor.x +} + +; CHECK-LABEL: @select_icmp_x_and_8_eq_0_y_xor_8( +; CHECK: select i1 %cmp, i64 %y, i64 %xor +define i64 @select_icmp_x_and_8_eq_0_y_xor_8(i32 %x, i64 %y) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %xor = xor i64 %y, 8 + %y.xor = select i1 %cmp, i64 %y, i64 %xor + ret i64 %y.xor +} + +; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_xor_8( +; CHECK: select i1 %cmp, i64 %xor, i64 %y +define i64 @select_icmp_x_and_8_ne_0_y_xor_8(i32 %x, i64 %y) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %xor = xor i64 %y, 8 + %xor.y = select i1 %cmp, i64 %xor, i64 %y + ret i64 %xor.y +} + +; CHECK-LABEL: @select_icmp_x_and_8_ne_0_y_or_8( +; CHECK: xor i64 %1, 8 +; CHECK: or i64 %2, %y +define i64 @select_icmp_x_and_8_ne_0_y_or_8(i32 %x, i64 %y) { + %and = and i32 %x, 8 + %cmp = icmp eq i32 %and, 0 + %or = or i64 %y, 8 + %or.y = select i1 %cmp, i64 %or, i64 %y + ret i64 %or.y +} + define i32 @test65(i64 %x) { %1 = and i64 %x, 16 %2 = icmp ne i64 %1, 0 -- 2.34.1