}
}
}
+
+ // (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<BinaryOperator>(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.
}
}
+ // (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<BinaryOperator>(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) {
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
+}