@@ -6481,6 +6481,73 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) {
6481
6481
Y->getType ()->isIntOrIntVectorTy (1 ) && Pred == ICmpInst::ICMP_ULE)
6482
6482
return BinaryOperator::CreateOr (Builder.CreateIsNull (X), Y);
6483
6483
6484
+ // icmp eq/ne X, (zext/sext (icmp eq/ne X, C))
6485
+ ICmpInst::Predicate Pred1, Pred2;
6486
+ const APInt *C;
6487
+ Instruction *ExtI;
6488
+ if (match (&I, m_c_ICmp (Pred1, m_Value (X),
6489
+ m_CombineAnd (m_Instruction (ExtI),
6490
+ m_ZExtOrSExt (m_ICmp (Pred2, m_Deferred (X),
6491
+ m_APInt (C)))))) &&
6492
+ ICmpInst::isEquality (Pred1) && ICmpInst::isEquality (Pred2)) {
6493
+ bool IsSExt = ExtI->getOpcode () == Instruction::SExt;
6494
+ bool HasOneUse = ExtI->hasOneUse () && ExtI->getOperand (0 )->hasOneUse ();
6495
+ auto CreateRangeCheck = [&] {
6496
+ Value *CmpV1 =
6497
+ Builder.CreateICmp (Pred1, X, Constant::getNullValue (X->getType ()));
6498
+ Value *CmpV2 = Builder.CreateICmp (
6499
+ Pred1, X, ConstantInt::getSigned (X->getType (), IsSExt ? -1 : 1 ));
6500
+ return BinaryOperator::Create (
6501
+ Pred1 == ICmpInst::ICMP_EQ ? Instruction::Or : Instruction::And,
6502
+ CmpV1, CmpV2);
6503
+ };
6504
+ if (C->isZero ()) {
6505
+ if (Pred2 == ICmpInst::ICMP_EQ) {
6506
+ // icmp eq X, (zext/sext (icmp eq X, 0)) --> false
6507
+ // icmp ne X, (zext/sext (icmp eq X, 0)) --> true
6508
+ return replaceInstUsesWith (
6509
+ I, ConstantInt::getBool (I.getType (), Pred1 == ICmpInst::ICMP_NE));
6510
+ } else if (!IsSExt || HasOneUse) {
6511
+ // icmp eq X, (zext (icmp ne X, 0)) --> X == 0 || X == 1
6512
+ // icmp ne X, (zext (icmp ne X, 0)) --> X != 0 && X != 1
6513
+ // icmp eq X, (sext (icmp ne X, 0)) --> X == 0 || X == -1
6514
+ // icmp ne X, (sext (icmp ne X, 0)) --> X != 0 && X == -1
6515
+ return CreateRangeCheck ();
6516
+ }
6517
+ } else if (IsSExt ? C->isAllOnes () : C->isOne ()) {
6518
+ if (Pred2 == ICmpInst::ICMP_NE) {
6519
+ // icmp eq X, (zext (icmp ne X, 1)) --> false
6520
+ // icmp ne X, (zext (icmp ne X, 1)) --> true
6521
+ // icmp eq X, (sext (icmp ne X, -1)) --> false
6522
+ // icmp ne X, (sext (icmp ne X, -1)) --> true
6523
+ return replaceInstUsesWith (
6524
+ I, ConstantInt::getBool (I.getType (), Pred1 == ICmpInst::ICMP_NE));
6525
+ } else if (!IsSExt || HasOneUse) {
6526
+ // icmp eq X, (zext (icmp eq X, 1)) --> X == 0 || X == 1
6527
+ // icmp ne X, (zext (icmp eq X, 1)) --> X != 0 && X != 1
6528
+ // icmp eq X, (sext (icmp eq X, -1)) --> X == 0 || X == -1
6529
+ // icmp ne X, (sext (icmp eq X, -1)) --> X != 0 && X == -1
6530
+ return CreateRangeCheck ();
6531
+ }
6532
+ } else {
6533
+ // when C != 0 && C != 1:
6534
+ // icmp eq X, (zext (icmp eq X, C)) --> icmp eq X, 0
6535
+ // icmp eq X, (zext (icmp ne X, C)) --> icmp eq X, 1
6536
+ // icmp ne X, (zext (icmp eq X, C)) --> icmp ne X, 0
6537
+ // icmp ne X, (zext (icmp ne X, C)) --> icmp ne X, 1
6538
+ // when C != 0 && C != -1:
6539
+ // icmp eq X, (sext (icmp eq X, C)) --> icmp eq X, 0
6540
+ // icmp eq X, (sext (icmp ne X, C)) --> icmp eq X, -1
6541
+ // icmp ne X, (sext (icmp eq X, C)) --> icmp ne X, 0
6542
+ // icmp ne X, (sext (icmp ne X, C)) --> icmp ne X, -1
6543
+ return ICmpInst::Create (
6544
+ Instruction::ICmp, Pred1, X,
6545
+ ConstantInt::getSigned (X->getType (), Pred2 == ICmpInst::ICMP_NE
6546
+ ? (IsSExt ? -1 : 1 )
6547
+ : 0 ));
6548
+ }
6549
+ }
6550
+
6484
6551
return nullptr ;
6485
6552
}
6486
6553
0 commit comments