From: Benjamin Kramer Date: Sun, 8 Jan 2012 18:32:24 +0000 (+0000) Subject: InstCombine: If we have a bit test and a sign test anded/ored together, merge the... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=dfb806f6ba53b792171b928b57def9d0182d2f5f;p=oota-llvm.git InstCombine: If we have a bit test and a sign test anded/ored together, merge the sign bit into the bit test. This is common in bit field code, e.g. checking if the first or the last bit of a bit field is set. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147749 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 4b1e7feef07..96ca40a3cf9 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -743,6 +743,22 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { } } } + + // (X & C) == 0 & X > -1 -> (X & (C | SignBit)) == 0 + if (LHS->hasOneUse() && RHS->hasOneUse() && + ((LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero() && + RHSCC == ICmpInst::ICMP_SGT && RHSCst->isAllOnesValue()) || + (RHSCC == ICmpInst::ICMP_EQ && RHSCst->isZero() && + LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()))) { + BinaryOperator *BO = + dyn_cast(LHSCC == ICmpInst::ICMP_EQ ? Val : Val2); + ConstantInt *AndCst; + if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) { + APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth()); + BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New)); + return BO == Val ? LHS : RHS; + } + } // From here on, we only handle: // (icmp1 A, C1) & (icmp2 A, C2) --> something simpler. @@ -1442,6 +1458,22 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) { } } + // (X & C) != 0 & X < 0 -> (X & (C | SignBit)) != 0 + if (LHS->hasOneUse() && RHS->hasOneUse() && + ((LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero() && + RHSCC == ICmpInst::ICMP_SLT && RHSCst->isZero()) || + (RHSCC == ICmpInst::ICMP_NE && RHSCst->isZero() && + LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()))) { + BinaryOperator *BO = + dyn_cast(LHSCC == ICmpInst::ICMP_NE ? Val : Val2); + ConstantInt *AndCst; + if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) { + APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth()); + BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New)); + return BO == Val ? LHS : RHS; + } + } + // (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1) // iff C2 + CA == C1. if (LHSCC == ICmpInst::ICMP_ULT && RHSCC == ICmpInst::ICMP_EQ) { diff --git a/test/Transforms/InstCombine/sign-test-and-or.ll b/test/Transforms/InstCombine/sign-test-and-or.ll index 47f5f3051e4..2a5f7725066 100644 --- a/test/Transforms/InstCombine/sign-test-and-or.ll +++ b/test/Transforms/InstCombine/sign-test-and-or.ll @@ -77,3 +77,83 @@ if.then: if.end: ret void } + +define void @test5(i32 %a) nounwind { + %and = and i32 %a, 134217728 + %1 = icmp eq i32 %and, 0 + %2 = icmp sgt i32 %a, -1 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test5 +; CHECK-NEXT: %and = and i32 %a, -2013265920 +; CHECK-NEXT: %1 = icmp eq i32 %and, 0 +; CHECK-NEXT: br i1 %1, label %if.then, label %if.end + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test6(i32 %a) nounwind { + %1 = icmp sgt i32 %a, -1 + %and = and i32 %a, 134217728 + %2 = icmp eq i32 %and, 0 + %or.cond = and i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test6 +; CHECK-NEXT: %and = and i32 %a, -2013265920 +; CHECK-NEXT: %1 = icmp eq i32 %and, 0 +; CHECK-NEXT: br i1 %1, label %if.then, label %if.end + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test7(i32 %a) nounwind { + %and = and i32 %a, 134217728 + %1 = icmp ne i32 %and, 0 + %2 = icmp slt i32 %a, 0 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test7 +; CHECK-NEXT: %and = and i32 %a, -2013265920 +; CHECK-NEXT: %1 = icmp eq i32 %and, 0 +; CHECK-NEXT: br i1 %1, label %if.end, label %if.the + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +} + +define void @test8(i32 %a) nounwind { + %1 = icmp slt i32 %a, 0 + %and = and i32 %a, 134217728 + %2 = icmp ne i32 %and, 0 + %or.cond = or i1 %1, %2 + br i1 %or.cond, label %if.then, label %if.end + +; CHECK: @test8 +; CHECK-NEXT: %and = and i32 %a, -2013265920 +; CHECK-NEXT: %1 = icmp eq i32 %and, 0 +; CHECK-NEXT: br i1 %1, label %if.end, label %if.the + +if.then: + tail call void @foo() nounwind + ret void + +if.end: + ret void +}