@@ -270,95 +270,57 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
270
270
bool SimplifyIndvar::strengthenOverflowingOperation (BinaryOperator *BO,
271
271
Value *IVOperand) {
272
272
273
- // Currently we only handle instructions of the form "add <indvar> <value>"
274
- unsigned Op = BO->getOpcode ();
275
- if (Op != Instruction::Add)
273
+ // Fastpath: we don't have any work to do if `BO` is `nuw` and `nsw`.
274
+ if (BO->hasNoUnsignedWrap () && BO->hasNoSignedWrap ())
276
275
return false ;
277
276
278
- // If BO is already both nuw and nsw then there is nothing left to do
279
- if (BO->hasNoUnsignedWrap () && BO->hasNoSignedWrap ())
277
+ const SCEV *(ScalarEvolution::*GetExprForBO)(const SCEV *, const SCEV *,
278
+ SCEV::NoWrapFlags);
279
+
280
+ switch (BO->getOpcode ()) {
281
+ default :
280
282
return false ;
281
283
282
- IntegerType *IT = cast<IntegerType>(IVOperand->getType ());
283
- Value *OtherOperand = nullptr ;
284
- if (BO->getOperand (0 ) == IVOperand) {
285
- OtherOperand = BO->getOperand (1 );
286
- } else {
287
- assert (BO->getOperand (1 ) == IVOperand && " only other use!" );
288
- OtherOperand = BO->getOperand (0 );
284
+ case Instruction::Add:
285
+ GetExprForBO = &ScalarEvolution::getAddExpr;
286
+ break ;
287
+
288
+ case Instruction::Sub:
289
+ GetExprForBO = &ScalarEvolution::getMinusSCEV;
290
+ break ;
291
+
292
+ case Instruction::Mul:
293
+ GetExprForBO = &ScalarEvolution::getMulExpr;
294
+ break ;
289
295
}
290
296
291
- bool Changed = false ;
292
- const SCEV *OtherOpSCEV = SE-> getSCEV (OtherOperand );
293
- if (OtherOpSCEV == SE->getCouldNotCompute ())
294
- return false ;
297
+ unsigned BitWidth = cast<IntegerType>(BO-> getType ())-> getBitWidth () ;
298
+ Type *WideTy = IntegerType::get (BO-> getContext (), BitWidth * 2 );
299
+ const SCEV *LHS = SE->getSCEV (BO-> getOperand ( 0 ));
300
+ const SCEV *RHS = SE-> getSCEV (BO-> getOperand ( 1 )) ;
295
301
296
- const SCEV *IVOpSCEV = SE->getSCEV (IVOperand);
297
- const SCEV *ZeroSCEV = SE->getConstant (IVOpSCEV->getType (), 0 );
302
+ bool Changed = false ;
298
303
299
- if (!BO->hasNoSignedWrap ()) {
300
- // Upgrade the add to an "add nsw" if we can prove that it will never
301
- // sign-overflow or sign-underflow.
302
-
303
- const SCEV *SignedMax =
304
- SE->getConstant (APInt::getSignedMaxValue (IT->getBitWidth ()));
305
- const SCEV *SignedMin =
306
- SE->getConstant (APInt::getSignedMinValue (IT->getBitWidth ()));
307
-
308
- // The addition "IVOperand + OtherOp" does not sign-overflow if the result
309
- // is sign-representable in 2's complement in the given bit-width.
310
- //
311
- // If OtherOp is SLT 0, then for an IVOperand in [SignedMin - OtherOp,
312
- // SignedMax], "IVOperand + OtherOp" is in [SignedMin, SignedMax + OtherOp].
313
- // Everything in [SignedMin, SignedMax + OtherOp] is representable since
314
- // SignedMax + OtherOp is at least -1.
315
- //
316
- // If OtherOp is SGE 0, then for an IVOperand in [SignedMin, SignedMax -
317
- // OtherOp], "IVOperand + OtherOp" is in [SignedMin + OtherOp, SignedMax].
318
- // Everything in [SignedMin + OtherOp, SignedMax] is representable since
319
- // SignedMin + OtherOp is at most -1.
320
- //
321
- // It follows that for all values of IVOperand in [SignedMin - smin(0,
322
- // OtherOp), SignedMax - smax(0, OtherOp)] the result of the add is
323
- // representable (i.e. there is no sign-overflow).
324
-
325
- const SCEV *UpperDelta = SE->getSMaxExpr (ZeroSCEV, OtherOpSCEV);
326
- const SCEV *UpperLimit = SE->getMinusSCEV (SignedMax, UpperDelta);
327
-
328
- bool NeverSignedOverflows =
329
- SE->isKnownPredicate (ICmpInst::ICMP_SLE, IVOpSCEV, UpperLimit);
330
-
331
- if (NeverSignedOverflows) {
332
- const SCEV *LowerDelta = SE->getSMinExpr (ZeroSCEV, OtherOpSCEV);
333
- const SCEV *LowerLimit = SE->getMinusSCEV (SignedMin, LowerDelta);
334
-
335
- bool NeverSignedUnderflows =
336
- SE->isKnownPredicate (ICmpInst::ICMP_SGE, IVOpSCEV, LowerLimit);
337
- if (NeverSignedUnderflows) {
338
- BO->setHasNoSignedWrap (true );
339
- Changed = true ;
340
- }
304
+ if (!BO->hasNoUnsignedWrap ()) {
305
+ const SCEV *ExtendAfterOp = SE->getZeroExtendExpr (SE->getSCEV (BO), WideTy);
306
+ const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
307
+ SE->getZeroExtendExpr (LHS, WideTy), SE->getZeroExtendExpr (RHS, WideTy),
308
+ SCEV::FlagAnyWrap);
309
+ if (ExtendAfterOp == OpAfterExtend) {
310
+ BO->setHasNoUnsignedWrap ();
311
+ SE->forgetValue (BO);
312
+ Changed = true ;
341
313
}
342
314
}
343
315
344
- if (!BO->hasNoUnsignedWrap ()) {
345
- // Upgrade the add computing "IVOperand + OtherOp" to an "add nuw" if we can
346
- // prove that it will never unsigned-overflow (i.e. the result will always
347
- // be representable in the given bit-width).
348
- //
349
- // "IVOperand + OtherOp" is unsigned-representable in 2's complement iff it
350
- // does not produce a carry. "IVOperand + OtherOp" produces no carry iff
351
- // IVOperand ULE (UnsignedMax - OtherOp).
352
-
353
- const SCEV *UnsignedMax =
354
- SE->getConstant (APInt::getMaxValue (IT->getBitWidth ()));
355
- const SCEV *UpperLimit = SE->getMinusSCEV (UnsignedMax, OtherOpSCEV);
356
-
357
- bool NeverUnsignedOverflows =
358
- SE->isKnownPredicate (ICmpInst::ICMP_ULE, IVOpSCEV, UpperLimit);
359
-
360
- if (NeverUnsignedOverflows) {
361
- BO->setHasNoUnsignedWrap (true );
316
+ if (!BO->hasNoSignedWrap ()) {
317
+ const SCEV *ExtendAfterOp = SE->getSignExtendExpr (SE->getSCEV (BO), WideTy);
318
+ const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
319
+ SE->getSignExtendExpr (LHS, WideTy), SE->getSignExtendExpr (RHS, WideTy),
320
+ SCEV::FlagAnyWrap);
321
+ if (ExtendAfterOp == OpAfterExtend) {
322
+ BO->setHasNoSignedWrap ();
323
+ SE->forgetValue (BO);
362
324
Changed = true ;
363
325
}
364
326
}
0 commit comments