aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/LoopUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopUtils.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/LoopUtils.cpp78
1 files changed, 71 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 7df8651ede15..7d6662c44f07 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -466,6 +466,19 @@ llvm::collectChildrenInLoop(DomTreeNode *N, const Loop *CurLoop) {
return Worklist;
}
+bool llvm::isAlmostDeadIV(PHINode *PN, BasicBlock *LatchBlock, Value *Cond) {
+ int LatchIdx = PN->getBasicBlockIndex(LatchBlock);
+ Value *IncV = PN->getIncomingValue(LatchIdx);
+
+ for (User *U : PN->users())
+ if (U != Cond && U != IncV) return false;
+
+ for (User *U : IncV->users())
+ if (U != Cond && U != PN) return false;
+ return true;
+}
+
+
void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
LoopInfo *LI, MemorySSA *MSSA) {
assert((!DT || L->isLCSSAForm(*DT)) && "Expected LCSSA!");
@@ -628,18 +641,17 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
}
// After the loop has been deleted all the values defined and modified
- // inside the loop are going to be unavailable.
- // Since debug values in the loop have been deleted, inserting an undef
- // dbg.value truncates the range of any dbg.value before the loop where the
- // loop used to be. This is particularly important for constant values.
+ // inside the loop are going to be unavailable. Values computed in the
+ // loop will have been deleted, automatically causing their debug uses
+ // be be replaced with undef. Loop invariant values will still be available.
+ // Move dbg.values out the loop so that earlier location ranges are still
+ // terminated and loop invariant assignments are preserved.
Instruction *InsertDbgValueBefore = ExitBlock->getFirstNonPHI();
assert(InsertDbgValueBefore &&
"There should be a non-PHI instruction in exit block, else these "
"instructions will have no parent.");
- for (auto *DVI : DeadDebugInst) {
- DVI->setKillLocation();
+ for (auto *DVI : DeadDebugInst)
DVI->moveBefore(InsertDbgValueBefore);
- }
}
// Remove the block from the reference counting scheme, so that we can
@@ -880,6 +892,29 @@ bool llvm::hasIterationCountInvariantInParent(Loop *InnerLoop,
return true;
}
+Intrinsic::ID llvm::getMinMaxReductionIntrinsicOp(RecurKind RK) {
+ switch (RK) {
+ default:
+ llvm_unreachable("Unknown min/max recurrence kind");
+ case RecurKind::UMin:
+ return Intrinsic::umin;
+ case RecurKind::UMax:
+ return Intrinsic::umax;
+ case RecurKind::SMin:
+ return Intrinsic::smin;
+ case RecurKind::SMax:
+ return Intrinsic::smax;
+ case RecurKind::FMin:
+ return Intrinsic::minnum;
+ case RecurKind::FMax:
+ return Intrinsic::maxnum;
+ case RecurKind::FMinimum:
+ return Intrinsic::minimum;
+ case RecurKind::FMaximum:
+ return Intrinsic::maximum;
+ }
+}
+
CmpInst::Predicate llvm::getMinMaxReductionPredicate(RecurKind RK) {
switch (RK) {
default:
@@ -896,6 +931,9 @@ CmpInst::Predicate llvm::getMinMaxReductionPredicate(RecurKind RK) {
return CmpInst::FCMP_OLT;
case RecurKind::FMax:
return CmpInst::FCMP_OGT;
+ // We do not add FMinimum/FMaximum recurrence kind here since there is no
+ // equivalent predicate which compares signed zeroes according to the
+ // semantics of the intrinsics (llvm.minimum/maximum).
}
}
@@ -910,6 +948,14 @@ Value *llvm::createSelectCmpOp(IRBuilderBase &Builder, Value *StartVal,
Value *llvm::createMinMaxOp(IRBuilderBase &Builder, RecurKind RK, Value *Left,
Value *Right) {
+ Type *Ty = Left->getType();
+ if (Ty->isIntOrIntVectorTy() ||
+ (RK == RecurKind::FMinimum || RK == RecurKind::FMaximum)) {
+ // TODO: Add float minnum/maxnum support when FMF nnan is set.
+ Intrinsic::ID Id = getMinMaxReductionIntrinsicOp(RK);
+ return Builder.CreateIntrinsic(Ty, Id, {Left, Right}, nullptr,
+ "rdx.minmax");
+ }
CmpInst::Predicate Pred = getMinMaxReductionPredicate(RK);
Value *Cmp = Builder.CreateCmp(Pred, Left, Right, "rdx.minmax.cmp");
Value *Select = Builder.CreateSelect(Cmp, Left, Right, "rdx.minmax.select");
@@ -1055,6 +1101,10 @@ Value *llvm::createSimpleTargetReduction(IRBuilderBase &Builder,
return Builder.CreateFPMaxReduce(Src);
case RecurKind::FMin:
return Builder.CreateFPMinReduce(Src);
+ case RecurKind::FMinimum:
+ return Builder.CreateFPMinimumReduce(Src);
+ case RecurKind::FMaximum:
+ return Builder.CreateFPMaximumReduce(Src);
default:
llvm_unreachable("Unhandled opcode");
}
@@ -1123,6 +1173,20 @@ bool llvm::isKnownNonNegativeInLoop(const SCEV *S, const Loop *L,
SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGE, S, Zero);
}
+bool llvm::isKnownPositiveInLoop(const SCEV *S, const Loop *L,
+ ScalarEvolution &SE) {
+ const SCEV *Zero = SE.getZero(S->getType());
+ return SE.isAvailableAtLoopEntry(S, L) &&
+ SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SGT, S, Zero);
+}
+
+bool llvm::isKnownNonPositiveInLoop(const SCEV *S, const Loop *L,
+ ScalarEvolution &SE) {
+ const SCEV *Zero = SE.getZero(S->getType());
+ return SE.isAvailableAtLoopEntry(S, L) &&
+ SE.isLoopEntryGuardedByCond(L, ICmpInst::ICMP_SLE, S, Zero);
+}
+
bool llvm::cannotBeMinInLoop(const SCEV *S, const Loop *L, ScalarEvolution &SE,
bool Signed) {
unsigned BitWidth = cast<IntegerType>(S->getType())->getBitWidth();