@@ -3217,18 +3217,26 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
3217
3217
}
3218
3218
3219
3219
// Try to fold (C1 * D /u C2) -> C1/C2 * D, if C1 and C2 are powers-of-2,
3220
- // D is a multiple of C2, and C1 is a multiple of C2.
3220
+ // D is a multiple of C2, and C1 is a multiple of C2. If C2 is a multiple
3221
+ // of C1, fold to (D /u (C2 /u C1)).
3221
3222
const SCEV *D;
3222
3223
APInt C1V = LHSC->getAPInt();
3223
- // (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN.
3224
- if (C1V.isNegative() && !C1V.isMinSignedValue())
3224
+ // (C1 * D /u C2) == -1 * -C1 * D /u C2 when C1 != INT_MIN. Don't treat -1
3225
+ // as -1 * 1, as it won't enable additional folds.
3226
+ if (C1V.isNegative() && !C1V.isMinSignedValue() && !C1V.isAllOnes())
3225
3227
C1V = C1V.abs();
3226
3228
const SCEVConstant *C2;
3227
3229
if (C1V.isPowerOf2() &&
3228
3230
match(Ops[1], m_scev_UDiv(m_SCEV(D), m_SCEVConstant(C2))) &&
3229
- C2->getAPInt().isPowerOf2() && C1V.uge(C2->getAPInt()) &&
3231
+ C2->getAPInt().isPowerOf2() &&
3230
3232
C1V.logBase2() <= getMinTrailingZeros(D)) {
3231
- const SCEV *NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
3233
+ const SCEV *NewMul;
3234
+ if (C1V.uge(C2->getAPInt())) {
3235
+ NewMul = getMulExpr(getUDivExpr(getConstant(C1V), C2), D);
3236
+ } else {
3237
+ assert(C1V.ugt(1) && "C1 <= 1 should have been folded earlier");
3238
+ NewMul = getUDivExpr(D, getUDivExpr(C2, getConstant(C1V)));
3239
+ }
3232
3240
return C1V == LHSC->getAPInt() ? NewMul : getNegativeSCEV(NewMul);
3233
3241
}
3234
3242
}
0 commit comments