llvm.org GIT mirror llvm / bf4a9f7
[SimplifyIndVar] Simplify non-overflowing saturating add/sub If we can detect that saturating math that depends on an IV cannot overflow, replace it with simple math. This is similar to the CVP optimization from D62703, just based on a different underlying analysis (SCEV vs LVI) that catches different cases. Differential Revision: https://reviews.llvm.org/D62792 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363489 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 3 months ago
2 changed file(s) with 32 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
8080 bool replaceIVUserWithLoopInvariant(Instruction *UseInst);
8181
8282 bool eliminateOverflowIntrinsic(WithOverflowInst *WO);
83 bool eliminateSaturatingIntrinsic(SaturatingInst *SI);
8384 bool eliminateTrunc(TruncInst *TI);
8485 bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
8586 bool makeIVComparisonInvariant(ICmpInst *ICmp, Value *IVOperand);
473474 if (WO->use_empty())
474475 WO->eraseFromParent();
475476
477 return true;
478 }
479
480 bool SimplifyIndvar::eliminateSaturatingIntrinsic(SaturatingInst *SI) {
481 const SCEV *LHS = SE->getSCEV(SI->getLHS());
482 const SCEV *RHS = SE->getSCEV(SI->getRHS());
483 if (!willNotOverflow(SE, SI->getBinaryOp(), SI->isSigned(), LHS, RHS))
484 return false;
485
486 BinaryOperator *BO = BinaryOperator::Create(
487 SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI);
488 if (SI->isSigned())
489 BO->setHasNoSignedWrap();
490 else
491 BO->setHasNoUnsignedWrap();
492
493 SI->replaceAllUsesWith(BO);
494 DeadInsts.emplace_back(SI);
495 Changed = true;
476496 return true;
477497 }
478498
613633 if (eliminateOverflowIntrinsic(WO))
614634 return true;
615635
636 if (auto *SI = dyn_cast(UseInst))
637 if (eliminateSaturatingIntrinsic(SI))
638 return true;
639
616640 if (auto *TI = dyn_cast(UseInst))
617641 if (eliminateTrunc(TI))
618642 return true;
1111 ; CHECK-NEXT: br label [[LOOP:%.*]]
1212 ; CHECK: loop:
1313 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
14 ; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[I]], i32 1)
15 ; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
14 ; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
15 ; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
1616 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
1717 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
1818 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
4040 ; CHECK-NEXT: br label [[LOOP:%.*]]
4141 ; CHECK: loop:
4242 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
43 ; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[I]], i32 1)
44 ; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
43 ; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
44 ; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
4545 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
4646 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
4747 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
6969 ; CHECK-NEXT: br label [[LOOP:%.*]]
7070 ; CHECK: loop:
7171 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
72 ; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[I]], i32 1)
73 ; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
72 ; CHECK-NEXT: [[SAT1:%.*]] = sub nuw nsw i32 [[I]], 1
73 ; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
7474 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
7575 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
7676 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
9898 ; CHECK-NEXT: br label [[LOOP:%.*]]
9999 ; CHECK: loop:
100100 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
101 ; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[I]], i32 1)
102 ; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
101 ; CHECK-NEXT: [[SAT1:%.*]] = sub nsw i32 [[I]], 1
102 ; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
103103 ; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
104104 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
105105 ; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]