@@ -5120,6 +5120,18 @@ static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
5120
5120
return nullptr ;
5121
5121
}
5122
5122
5123
+ // / Return true if X is a multiple of C.
5124
+ // / TODO: Handle non-power-of-2 factors.
5125
+ static bool isMultipleOf (Value *X, const APInt &C, const SimplifyQuery &Q) {
5126
+ if (C.isOne ())
5127
+ return true ;
5128
+
5129
+ if (!C.isPowerOf2 ())
5130
+ return false ;
5131
+
5132
+ return MaskedValueIsZero (X, C - 1 , Q);
5133
+ }
5134
+
5123
5135
// / Try to fold icmp (binop), X or icmp X, (binop).
5124
5136
// / TODO: A large part of this logic is duplicated in InstSimplify's
5125
5137
// / simplifyICmpWithBinOp(). We should be able to share that and avoid the code
@@ -5278,66 +5290,62 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
5278
5290
return new ICmpInst (Pred, Y, Z);
5279
5291
}
5280
5292
5281
- // icmp slt (A + -1), Op1 -> icmp sle A, Op1
5282
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_SLT &&
5283
- match (B, m_AllOnes ()))
5284
- return new ICmpInst (CmpInst::ICMP_SLE, A, Op1);
5285
-
5286
- // icmp sge (A + -1), Op1 -> icmp sgt A, Op1
5287
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_SGE &&
5288
- match (B, m_AllOnes ()))
5289
- return new ICmpInst (CmpInst::ICMP_SGT, A, Op1);
5290
-
5291
- // icmp sle (A + 1), Op1 -> icmp slt A, Op1
5292
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_SLE && match (B, m_One ()))
5293
- return new ICmpInst (CmpInst::ICMP_SLT, A, Op1);
5294
-
5295
- // icmp sgt (A + 1), Op1 -> icmp sge A, Op1
5296
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_SGT && match (B, m_One ()))
5297
- return new ICmpInst (CmpInst::ICMP_SGE, A, Op1);
5293
+ if (ICmpInst::isRelational (Pred)) {
5294
+ // Return if both X and Y is divisible by Z/-Z.
5295
+ // TODO: Generalize to check if (X - Y) is divisible by Z/-Z.
5296
+ auto ShareCommonDivisor = [&Q](Value *X, Value *Y, Value *Z,
5297
+ bool IsNegative) -> bool {
5298
+ const APInt *OffsetC;
5299
+ if (!match (Z, m_APInt (OffsetC)))
5300
+ return false ;
5298
5301
5299
- // icmp sgt Op0, (C + -1) -> icmp sge Op0, C
5300
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SGT &&
5301
- match (D, m_AllOnes ()))
5302
- return new ICmpInst (CmpInst::ICMP_SGE, Op0, C);
5302
+ // Fast path for Z == 1/-1.
5303
+ if (IsNegative ? OffsetC->isAllOnes () : OffsetC->isOne ())
5304
+ return true ;
5303
5305
5304
- // icmp sle Op0, (C + -1) -> icmp slt Op0, C
5305
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SLE &&
5306
- match (D, m_AllOnes ()))
5307
- return new ICmpInst (CmpInst::ICMP_SLT, Op0, C);
5306
+ APInt C = *OffsetC;
5307
+ if (IsNegative)
5308
+ C.negate ();
5309
+ // Note: -INT_MIN is also negative.
5310
+ if (!C.isStrictlyPositive ())
5311
+ return false ;
5308
5312
5309
- // icmp sge Op0, (C + 1) -> icmp sgt Op0, C
5310
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SGE && match (D, m_One ()))
5311
- return new ICmpInst (CmpInst::ICMP_SGT, Op0, C);
5313
+ return isMultipleOf (X, C, Q) && isMultipleOf (Y, C, Q);
5314
+ };
5312
5315
5313
- // icmp slt Op0, (C + 1) -> icmp sle Op0, C
5314
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SLT && match (D, m_One ()))
5315
- return new ICmpInst (CmpInst::ICMP_SLE, Op0, C);
5316
+ // TODO: The subtraction-related identities shown below also hold, but
5317
+ // canonicalization from (X -nuw 1) to (X + -1) means that the combinations
5318
+ // wouldn't happen even if they were implemented.
5319
+ //
5320
+ // icmp ult (A - 1), Op1 -> icmp ule A, Op1
5321
+ // icmp uge (A - 1), Op1 -> icmp ugt A, Op1
5322
+ // icmp ugt Op0, (C - 1) -> icmp uge Op0, C
5323
+ // icmp ule Op0, (C - 1) -> icmp ult Op0, C
5324
+
5325
+ // icmp slt (A + -1), Op1 -> icmp sle A, Op1
5326
+ // icmp sge (A + -1), Op1 -> icmp sgt A, Op1
5327
+ // icmp sle (A + 1), Op1 -> icmp slt A, Op1
5328
+ // icmp sgt (A + 1), Op1 -> icmp sge A, Op1
5329
+ // icmp ule (A + 1), Op0 -> icmp ult A, Op1
5330
+ // icmp ugt (A + 1), Op0 -> icmp uge A, Op1
5331
+ if (A && NoOp0WrapProblem &&
5332
+ ShareCommonDivisor (A, Op1, B,
5333
+ ICmpInst::isLT (Pred) || ICmpInst::isGE (Pred)))
5334
+ return new ICmpInst (ICmpInst::getFlippedStrictnessPredicate (Pred), A,
5335
+ Op1);
5316
5336
5317
- // TODO: The subtraction-related identities shown below also hold, but
5318
- // canonicalization from (X -nuw 1) to (X + -1) means that the combinations
5319
- // wouldn't happen even if they were implemented.
5320
- //
5321
- // icmp ult (A - 1), Op1 -> icmp ule A, Op1
5322
- // icmp uge (A - 1), Op1 -> icmp ugt A, Op1
5323
- // icmp ugt Op0, (C - 1) -> icmp uge Op0, C
5324
- // icmp ule Op0, (C - 1) -> icmp ult Op0, C
5325
-
5326
- // icmp ule (A + 1), Op0 -> icmp ult A, Op1
5327
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_ULE && match (B, m_One ()))
5328
- return new ICmpInst (CmpInst::ICMP_ULT, A, Op1);
5329
-
5330
- // icmp ugt (A + 1), Op0 -> icmp uge A, Op1
5331
- if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_UGT && match (B, m_One ()))
5332
- return new ICmpInst (CmpInst::ICMP_UGE, A, Op1);
5333
-
5334
- // icmp uge Op0, (C + 1) -> icmp ugt Op0, C
5335
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_UGE && match (D, m_One ()))
5336
- return new ICmpInst (CmpInst::ICMP_UGT, Op0, C);
5337
-
5338
- // icmp ult Op0, (C + 1) -> icmp ule Op0, C
5339
- if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_ULT && match (D, m_One ()))
5340
- return new ICmpInst (CmpInst::ICMP_ULE, Op0, C);
5337
+ // icmp sgt Op0, (C + -1) -> icmp sge Op0, C
5338
+ // icmp sle Op0, (C + -1) -> icmp slt Op0, C
5339
+ // icmp sge Op0, (C + 1) -> icmp sgt Op0, C
5340
+ // icmp slt Op0, (C + 1) -> icmp sle Op0, C
5341
+ // icmp uge Op0, (C + 1) -> icmp ugt Op0, C
5342
+ // icmp ult Op0, (C + 1) -> icmp ule Op0, C
5343
+ if (C && NoOp1WrapProblem &&
5344
+ ShareCommonDivisor (Op0, C, D,
5345
+ ICmpInst::isGT (Pred) || ICmpInst::isLE (Pred)))
5346
+ return new ICmpInst (ICmpInst::getFlippedStrictnessPredicate (Pred), Op0,
5347
+ C);
5348
+ }
5341
5349
5342
5350
// if C1 has greater magnitude than C2:
5343
5351
// icmp (A + C1), (C + C2) -> icmp (A + C3), C
0 commit comments