@@ -3247,6 +3247,64 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
3247
3247
return nullptr ;
3248
3248
}
3249
3249
3250
+ Instruction *
3251
+ InstCombinerImpl::foldExtractOfOverflowIntrinsic (ExtractValueInst &EV) {
3252
+ auto *WO = dyn_cast<WithOverflowInst>(EV.getAggregateOperand ());
3253
+ if (!WO)
3254
+ return nullptr ;
3255
+
3256
+ // extractvalue (any_mul_with_overflow X, -1), 0 --> -X
3257
+ Intrinsic::ID OvID = WO->getIntrinsicID ();
3258
+ if (*EV.idx_begin () == 0 &&
3259
+ (OvID == Intrinsic::smul_with_overflow ||
3260
+ OvID == Intrinsic::umul_with_overflow) &&
3261
+ match (WO->getArgOperand (1 ), m_AllOnes ())) {
3262
+ return BinaryOperator::CreateNeg (WO->getArgOperand (0 ));
3263
+ }
3264
+
3265
+ // We're extracting from an overflow intrinsic. See if we're the only user.
3266
+ // That allows us to simplify multiple result intrinsics to simpler things
3267
+ // that just get one value.
3268
+ if (!WO->hasOneUse ())
3269
+ return nullptr ;
3270
+
3271
+ // Check if we're grabbing only the result of a 'with overflow' intrinsic
3272
+ // and replace it with a traditional binary instruction.
3273
+ if (*EV.idx_begin () == 0 ) {
3274
+ Instruction::BinaryOps BinOp = WO->getBinaryOp ();
3275
+ Value *LHS = WO->getLHS (), *RHS = WO->getRHS ();
3276
+ // Replace the old instruction's uses with poison.
3277
+ replaceInstUsesWith (*WO, PoisonValue::get (WO->getType ()));
3278
+ eraseInstFromFunction (*WO);
3279
+ return BinaryOperator::Create (BinOp, LHS, RHS);
3280
+ }
3281
+
3282
+ assert (*EV.idx_begin () == 1 && " Unexpected extract index for overflow inst" );
3283
+
3284
+ // If only the overflow result is used, and the right hand side is a
3285
+ // constant (or constant splat), we can remove the intrinsic by directly
3286
+ // checking for overflow.
3287
+ const APInt *C;
3288
+ if (match (WO->getRHS (), m_APInt (C))) {
3289
+ // Compute the no-wrap range for LHS given RHS=C, then construct an
3290
+ // equivalent icmp, potentially using an offset.
3291
+ ConstantRange NWR = ConstantRange::makeExactNoWrapRegion (
3292
+ WO->getBinaryOp (), *C, WO->getNoWrapKind ());
3293
+
3294
+ CmpInst::Predicate Pred;
3295
+ APInt NewRHSC, Offset;
3296
+ NWR.getEquivalentICmp (Pred, NewRHSC, Offset);
3297
+ auto *OpTy = WO->getRHS ()->getType ();
3298
+ auto *NewLHS = WO->getLHS ();
3299
+ if (Offset != 0 )
3300
+ NewLHS = Builder.CreateAdd (NewLHS, ConstantInt::get (OpTy, Offset));
3301
+ return new ICmpInst (ICmpInst::getInversePredicate (Pred), NewLHS,
3302
+ ConstantInt::get (OpTy, NewRHSC));
3303
+ }
3304
+
3305
+ return nullptr ;
3306
+ }
3307
+
3250
3308
Instruction *InstCombinerImpl::visitExtractValueInst (ExtractValueInst &EV) {
3251
3309
Value *Agg = EV.getAggregateOperand ();
3252
3310
@@ -3308,58 +3366,11 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
3308
3366
return ExtractValueInst::Create (IV->getInsertedValueOperand (),
3309
3367
makeArrayRef (exti, exte));
3310
3368
}
3311
- if (WithOverflowInst *WO = dyn_cast<WithOverflowInst>(Agg)) {
3312
- // extractvalue (any_mul_with_overflow X, -1), 0 --> -X
3313
- Intrinsic::ID OvID = WO->getIntrinsicID ();
3314
- if (*EV.idx_begin () == 0 &&
3315
- (OvID == Intrinsic::smul_with_overflow ||
3316
- OvID == Intrinsic::umul_with_overflow) &&
3317
- match (WO->getArgOperand (1 ), m_AllOnes ())) {
3318
- return BinaryOperator::CreateNeg (WO->getArgOperand (0 ));
3319
- }
3320
3369
3321
- // We're extracting from an overflow intrinsic, see if we're the only user,
3322
- // which allows us to simplify multiple result intrinsics to simpler
3323
- // things that just get one value.
3324
- if (WO->hasOneUse ()) {
3325
- // Check if we're grabbing only the result of a 'with overflow' intrinsic
3326
- // and replace it with a traditional binary instruction.
3327
- if (*EV.idx_begin () == 0 ) {
3328
- Instruction::BinaryOps BinOp = WO->getBinaryOp ();
3329
- Value *LHS = WO->getLHS (), *RHS = WO->getRHS ();
3330
- // Replace the old instruction's uses with poison.
3331
- replaceInstUsesWith (*WO, PoisonValue::get (WO->getType ()));
3332
- eraseInstFromFunction (*WO);
3333
- return BinaryOperator::Create (BinOp, LHS, RHS);
3334
- }
3370
+ if (Instruction *R = foldExtractOfOverflowIntrinsic (EV))
3371
+ return R;
3335
3372
3336
- assert (*EV.idx_begin () == 1 &&
3337
- " unexpected extract index for overflow inst" );
3338
-
3339
- // If only the overflow result is used, and the right hand side is a
3340
- // constant (or constant splat), we can remove the intrinsic by directly
3341
- // checking for overflow.
3342
- const APInt *C;
3343
- if (match (WO->getRHS (), m_APInt (C))) {
3344
- // Compute the no-wrap range for LHS given RHS=C, then construct an
3345
- // equivalent icmp, potentially using an offset.
3346
- ConstantRange NWR =
3347
- ConstantRange::makeExactNoWrapRegion (WO->getBinaryOp (), *C,
3348
- WO->getNoWrapKind ());
3349
-
3350
- CmpInst::Predicate Pred;
3351
- APInt NewRHSC, Offset;
3352
- NWR.getEquivalentICmp (Pred, NewRHSC, Offset);
3353
- auto *OpTy = WO->getRHS ()->getType ();
3354
- auto *NewLHS = WO->getLHS ();
3355
- if (Offset != 0 )
3356
- NewLHS = Builder.CreateAdd (NewLHS, ConstantInt::get (OpTy, Offset));
3357
- return new ICmpInst (ICmpInst::getInversePredicate (Pred), NewLHS,
3358
- ConstantInt::get (OpTy, NewRHSC));
3359
- }
3360
- }
3361
- }
3362
- if (LoadInst *L = dyn_cast<LoadInst>(Agg))
3373
+ if (LoadInst *L = dyn_cast<LoadInst>(Agg)) {
3363
3374
// If the (non-volatile) load only has one use, we can rewrite this to a
3364
3375
// load from a GEP. This reduces the size of the load. If a load is used
3365
3376
// only by extractvalue instructions then this either must have been
@@ -3386,6 +3397,8 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
3386
3397
// the wrong spot, so use replaceInstUsesWith().
3387
3398
return replaceInstUsesWith (EV, NL);
3388
3399
}
3400
+ }
3401
+
3389
3402
// We could simplify extracts from other values. Note that nested extracts may
3390
3403
// already be simplified implicitly by the above: extract (extract (insert) )
3391
3404
// will be translated into extract ( insert ( extract ) ) first and then just
0 commit comments