[PATCH] D62792: [SimplifyIndVar] Simplify non-overflowing saturating add/sub
Nikita Popov via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 2 02:03:19 PDT 2019
nikic created this revision.
nikic added reviewers: reames, spatel, lebedev.ri.
Herald added subscribers: llvm-commits, sanjoy, javed.absar, hiraditya.
Herald added a project: LLVM.
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 <https://reviews.llvm.org/D62703>, just based on a different underlying analysis (SCEV vs LVI) that catches different cases.
One case this doesn't handle yet is if the IV calculation itself uses a saturating counter.
Repository:
rL LLVM
https://reviews.llvm.org/D62792
Files:
llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
llvm/test/Transforms/IndVarSimplify/eliminate-sat.ll
Index: llvm/test/Transforms/IndVarSimplify/eliminate-sat.ll
===================================================================
--- llvm/test/Transforms/IndVarSimplify/eliminate-sat.ll
+++ llvm/test/Transforms/IndVarSimplify/eliminate-sat.ll
@@ -12,8 +12,8 @@
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[I]], i32 1)
-; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
+; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
+; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
@@ -41,8 +41,8 @@
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[I]], i32 1)
-; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
+; CHECK-NEXT: [[SAT1:%.*]] = add nuw nsw i32 [[I]], 1
+; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
@@ -70,8 +70,8 @@
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[I]], i32 1)
-; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
+; CHECK-NEXT: [[SAT1:%.*]] = sub nuw nsw i32 [[I]], 1
+; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
@@ -99,8 +99,8 @@
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[SAT:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[I]], i32 1)
-; CHECK-NEXT: store volatile i32 [[SAT]], i32* [[P:%.*]]
+; CHECK-NEXT: [[SAT1:%.*]] = sub nsw i32 [[I]], 1
+; CHECK-NEXT: store volatile i32 [[SAT1]], i32* [[P:%.*]]
; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[I_INC]], 100
; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[END:%.*]]
Index: llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
===================================================================
--- llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -81,6 +81,7 @@
bool replaceIVUserWithLoopInvariant(Instruction *UseInst);
bool eliminateOverflowIntrinsic(WithOverflowInst *WO);
+ bool eliminateSaturatingIntrinsic(SaturatingInst *SI);
bool eliminateTrunc(TruncInst *TI);
bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
bool makeIVComparisonInvariant(ICmpInst *ICmp, Value *IVOperand);
@@ -477,6 +478,25 @@
return true;
}
+bool SimplifyIndvar::eliminateSaturatingIntrinsic(SaturatingInst *SI) {
+ const SCEV *LHS = SE->getSCEV(SI->getLHS());
+ const SCEV *RHS = SE->getSCEV(SI->getRHS());
+ if (!willNotOverflow(SE, SI->getBinaryOp(), SI->isSigned(), LHS, RHS))
+ return false;
+
+ BinaryOperator *BO = BinaryOperator::Create(
+ SI->getBinaryOp(), SI->getLHS(), SI->getRHS(), SI->getName(), SI);
+ if (SI->isSigned())
+ BO->setHasNoSignedWrap();
+ else
+ BO->setHasNoUnsignedWrap();
+
+ SI->replaceAllUsesWith(BO);
+ DeadInsts.emplace_back(SI);
+ Changed = true;
+ return true;
+}
+
bool SimplifyIndvar::eliminateTrunc(TruncInst *TI) {
// It is always legal to replace
// icmp <pred> i32 trunc(iv), n
@@ -613,6 +633,10 @@
if (eliminateOverflowIntrinsic(WO))
return true;
+ if (auto *SI = dyn_cast<SaturatingInst>(UseInst))
+ if (eliminateSaturatingIntrinsic(SI))
+ return true;
+
if (auto *TI = dyn_cast<TruncInst>(UseInst))
if (eliminateTrunc(TI))
return true;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D62792.202589.patch
Type: text/x-patch
Size: 4330 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190602/11f06720/attachment.bin>
More information about the llvm-commits
mailing list