From 80a3abf34f71a31840467179b1b07d0216e9d5ed Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 15 Jun 2017 17:55:20 +0000 Subject: [PATCH] [InstCombine] Handle (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2) when the one of the Ands is commuted relative to the other Currently we expect A to be on the same side in both Ands but nothing guarantees that. While there also switch to using matchers for some of the code. Differential Revision: https://reviews.llvm.org/D34230 llvm-svn: 305487 --- .../InstCombine/InstCombineAndOrXor.cpp | 34 ++++++++----------- test/Transforms/InstCombine/onehot_merge.ll | 13 +++---- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 4fe3225a217..28968357400 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1599,31 +1599,25 @@ Value *InstCombiner::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, ConstantInt *LHSC = dyn_cast(LHS->getOperand(1)); ConstantInt *RHSC = dyn_cast(RHS->getOperand(1)); + // TODO support vector splats if (LHS->getPredicate() == ICmpInst::ICMP_EQ && LHSC && LHSC->isZero() && RHS->getPredicate() == ICmpInst::ICMP_EQ && RHSC && RHSC->isZero()) { - BinaryOperator *LAnd = dyn_cast(LHS->getOperand(0)); - BinaryOperator *RAnd = dyn_cast(RHS->getOperand(0)); - if (LAnd && RAnd && LAnd->hasOneUse() && RHS->hasOneUse() && - LAnd->getOpcode() == Instruction::And && - RAnd->getOpcode() == Instruction::And) { + Value *A, *B, *C, *D; + if (match(LHS->getOperand(0), m_And(m_Value(A), m_Value(B))) && + match(RHS->getOperand(0), m_And(m_Value(C), m_Value(D)))) { + if (A == D || B == D) + std::swap(C, D); + if (B == C) + std::swap(A, B); - Value *Mask = nullptr; - Value *Masked = nullptr; - if (LAnd->getOperand(0) == RAnd->getOperand(0) && - isKnownToBeAPowerOfTwo(LAnd->getOperand(1), false, 0, CxtI) && - isKnownToBeAPowerOfTwo(RAnd->getOperand(1), false, 0, CxtI)) { - Mask = Builder->CreateOr(LAnd->getOperand(1), RAnd->getOperand(1)); - Masked = Builder->CreateAnd(LAnd->getOperand(0), Mask); - } else if (LAnd->getOperand(1) == RAnd->getOperand(1) && - isKnownToBeAPowerOfTwo(LAnd->getOperand(0), false, 0, CxtI) && - isKnownToBeAPowerOfTwo(RAnd->getOperand(0), false, 0, CxtI)) { - Mask = Builder->CreateOr(LAnd->getOperand(0), RAnd->getOperand(0)); - Masked = Builder->CreateAnd(LAnd->getOperand(1), Mask); - } - - if (Masked) + if (A == C && + isKnownToBeAPowerOfTwo(B, false, 0, CxtI) && + isKnownToBeAPowerOfTwo(D, false, 0, CxtI)) { + Value *Mask = Builder->CreateOr(B, D); + Value *Masked = Builder->CreateAnd(A, Mask); return Builder->CreateICmp(ICmpInst::ICMP_NE, Masked, Mask); + } } } diff --git a/test/Transforms/InstCombine/onehot_merge.ll b/test/Transforms/InstCombine/onehot_merge.ll index 6fd4fc66a52..c9f0c4d2690 100644 --- a/test/Transforms/InstCombine/onehot_merge.ll +++ b/test/Transforms/InstCombine/onehot_merge.ll @@ -34,21 +34,16 @@ bb: } ; Same as above but with operands commuted one of the ands, but not the other. -; TODO handle this form correctly define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) { ; CHECK-LABEL: @foo1_and_commuted( -; CHECK-NEXT: bb: ; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]] ; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]] ; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K2]], [[TMP]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 -; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], [[K2]] -; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0 -; CHECK-NEXT: [[OR:%.*]] = or i1 [[TMP2]], [[TMP6]] -; CHECK-NEXT: ret i1 [[OR]] +; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[TMP]], [[TMP4]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K2]], [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], [[TMP0]] +; CHECK-NEXT: ret i1 [[TMP2]] ; -bb: %k2 = mul i32 %k, %k ; to trick the complexity sorting %tmp = shl i32 1, %c1 %tmp4 = lshr i32 -2147483648, %c2