Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2022-11-13 20:38:39 +0300
committerFlorian Hahn <flo@fhahn.com>2022-11-13 20:38:39 +0300
commit7854a1abfd9a52dec0fe5d668e26de19614faefb (patch)
treed1d0c40bcafe54b216776b0c3c1d7ec80942fa15
parentae461d8b99e63e26726ce3047f00b78180d427d8 (diff)
[SimpleLoopUnswitch] Forget SCEVs for replaced phis.
Forget SCEVs based on exit phis in case SCEV looked through the phi. After unswitching, it may not be possible to look through the phi due to it having multiple incoming values, so it needs to be re-computed. Fixes #58868
-rw-r--r--llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp9
-rw-r--r--llvm/test/Transforms/SimpleLoopUnswitch/pr58868-scev-invalidation-for-phis.ll73
2 files changed, 80 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index f7ecc4794715..f6f3c8fffb8b 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -1114,7 +1114,8 @@ static BasicBlock *buildClonedLoopBlocks(
const SmallDenseMap<BasicBlock *, BasicBlock *, 16> &DominatingSucc,
ValueToValueMapTy &VMap,
SmallVectorImpl<DominatorTree::UpdateType> &DTUpdates, AssumptionCache &AC,
- DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU) {
+ DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU,
+ ScalarEvolution *SE) {
SmallVector<BasicBlock *, 4> NewBlocks;
NewBlocks.reserve(L.getNumBlocks() + ExitBlocks.size());
@@ -1190,6 +1191,10 @@ static BasicBlock *buildClonedLoopBlocks(
// We should have a value map between the instruction and its clone.
assert(VMap.lookup(&I) == &ClonedI && "Mismatch in the value map!");
+ // Forget SCEVs based on exit phis in case SCEV looked through the phi.
+ if (SE && isa<PHINode>(I))
+ SE->forgetValue(&I);
+
auto *MergePN =
PHINode::Create(I.getType(), /*NumReservedValues*/ 2, ".us-phi",
&*MergeBB->getFirstInsertionPt());
@@ -2218,7 +2223,7 @@ static void unswitchNontrivialInvariants(
VMaps.emplace_back(new ValueToValueMapTy());
ClonedPHs[SuccBB] = buildClonedLoopBlocks(
L, LoopPH, SplitBB, ExitBlocks, ParentBB, SuccBB, RetainedSuccBB,
- DominatingSucc, *VMaps.back(), DTUpdates, AC, DT, LI, MSSAU);
+ DominatingSucc, *VMaps.back(), DTUpdates, AC, DT, LI, MSSAU, SE);
}
// Drop metadata if we may break its semantics by moving this instr into the
diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/pr58868-scev-invalidation-for-phis.ll b/llvm/test/Transforms/SimpleLoopUnswitch/pr58868-scev-invalidation-for-phis.ll
new file mode 100644
index 000000000000..2a8553c69c40
--- /dev/null
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/pr58868-scev-invalidation-for-phis.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes="loop-mssa(loop-deletion,simple-loop-unswitch<nontrivial;trivial>),loop(indvars)" -verify-scev -S %s | FileCheck %s
+
+define void @pr58868(i1 %c.1, ptr %src, ptr %dst) {
+; CHECK-LABEL: @pr58868(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[C_1:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
+; CHECK: entry.split.us:
+; CHECK-NEXT: br label [[OUTER_HEADER_US:%.*]]
+; CHECK: outer.header.us:
+; CHECK-NEXT: br label [[OUTER_BB1_US:%.*]]
+; CHECK: outer.bb1.us:
+; CHECK-NEXT: br label [[OUTER_BB2_US:%.*]]
+; CHECK: outer.bb2.us:
+; CHECK-NEXT: [[LV_US:%.*]] = load i16, ptr [[SRC:%.*]], align 1
+; CHECK-NEXT: br i1 true, label [[OUTER_HEADER_LOOPEXIT_US:%.*]], label [[OUTER_BB2_SPLIT_SPLIT_US:%.*]]
+; CHECK: outer.header.loopexit.us:
+; CHECK-NEXT: br label [[OUTER_HEADER_US]]
+; CHECK: outer.bb2.split.split.us:
+; CHECK-NEXT: [[LV_LCSSA_US:%.*]] = phi i16 [ [[LV_US]], [[OUTER_BB2_US]] ]
+; CHECK-NEXT: br label [[OUTER_BB2_SPLIT:%.*]]
+; CHECK: entry.split:
+; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
+; CHECK: outer.header.loopexit:
+; CHECK-NEXT: unreachable
+; CHECK: outer.header:
+; CHECK-NEXT: br label [[OUTER_BB2:%.*]]
+; CHECK: outer.bb2:
+; CHECK-NEXT: [[LV:%.*]] = load i16, ptr [[SRC]], align 1
+; CHECK-NEXT: br i1 false, label [[OUTER_HEADER_LOOPEXIT:%.*]], label [[OUTER_BB2_SPLIT_SPLIT:%.*]]
+; CHECK: outer.bb2.split.split:
+; CHECK-NEXT: [[LV_LCSSA:%.*]] = phi i16 [ [[LV]], [[OUTER_BB2]] ]
+; CHECK-NEXT: br label [[OUTER_BB2_SPLIT]]
+; CHECK: outer.bb2.split:
+; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i16 [ [[LV_LCSSA]], [[OUTER_BB2_SPLIT_SPLIT]] ], [ [[LV_LCSSA_US]], [[OUTER_BB2_SPLIT_SPLIT_US]] ]
+; CHECK-NEXT: br label [[INNER_HEADER:%.*]]
+; CHECK: inner.header:
+; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[DOTUS_PHI]], [[OUTER_BB2_SPLIT]] ], [ [[IV_NEXT:%.*]], [[INNER_LATCH:%.*]] ]
+; CHECK-NEXT: br label [[INNER_LATCH]]
+; CHECK: inner.latch:
+; CHECK-NEXT: [[IV_NEXT]] = add nsw i16 [[IV]], 1
+; CHECK-NEXT: store i16 0, ptr [[DST:%.*]], align 1
+; CHECK-NEXT: [[C_2:%.*]] = icmp ne i16 [[IV]], 0
+; CHECK-NEXT: br i1 [[C_2]], label [[INNER_HEADER]], label [[EXIT:%.*]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %outer.header
+
+outer.header:
+ br i1 %c.1, label %outer.bb1, label %outer.bb2
+
+outer.bb1:
+ br label %outer.bb2
+
+outer.bb2:
+ %lv = load i16, ptr %src, align 1
+ br label %inner.header
+
+inner.header:
+ %iv = phi i16 [ %lv, %outer.bb2 ], [ %iv.next, %inner.latch ]
+ br i1 %c.1, label %outer.header, label %inner.latch
+
+inner.latch:
+ %iv.next = add nsw i16 %iv, 1
+ store i16 0, ptr %dst, align 1
+ %c.2 = icmp ne i16 %iv, 0
+ br i1 %c.2, label %inner.header, label %exit
+
+exit:
+ ret void
+}