From e399dd601f439ada0e505f380adf83d85d522f5a Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 4 Oct 2022 10:27:52 +0100 Subject: [PATCH] [SimpleLoopUnswitch] Clear block and loop dispos after destroying loop. SimpleLoopUnswitch may remove loops. Clear block and loop dispositions, to clean up invalid entries in the cache. Fixes #58136. --- llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp | 8 +- .../invalidate-block-and-loop-dispositions.ll | 85 ++++++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/SimpleLoopUnswitch/invalidate-block-and-loop-dispositions.ll diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index e1d5bb5..c1e67af 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -1820,7 +1820,8 @@ static SmallPtrSet recomputeLoopBlockSet(Loop &L, /// referenced). static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef ExitBlocks, LoopInfo &LI, - SmallVectorImpl &HoistedLoops) { + SmallVectorImpl &HoistedLoops, + ScalarEvolution *SE) { auto *PH = L.getLoopPreheader(); // Compute the actual parent loop from the exit blocks. Because we may have @@ -2013,6 +2014,8 @@ static bool rebuildLoopAfterUnswitch(Loop &L, ArrayRef ExitBlocks, LI.removeLoop(llvm::find(LI, &L)); // markLoopAsDeleted for L should be triggered by the caller (it is typically // done by using the UnswitchCB callback). + if (SE) + SE->forgetBlockAndLoopDispositions(); LI.destroy(&L); return false; } @@ -2380,7 +2383,8 @@ static void unswitchNontrivialInvariants( MSSAU->getMemorySSA()->verifyMemorySSA(); SmallVector HoistedLoops; - bool IsStillLoop = rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops); + bool IsStillLoop = + rebuildLoopAfterUnswitch(L, ExitBlocks, LI, HoistedLoops, SE); if (MSSAU && VerifyMemorySSA) MSSAU->getMemorySSA()->verifyMemorySSA(); diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/invalidate-block-and-loop-dispositions.ll b/llvm/test/Transforms/SimpleLoopUnswitch/invalidate-block-and-loop-dispositions.ll new file mode 100644 index 0000000..b50611c --- /dev/null +++ b/llvm/test/Transforms/SimpleLoopUnswitch/invalidate-block-and-loop-dispositions.ll @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes="loop-mssa(loop-simplifycfg,require,licm,simple-loop-unswitch)" -verify-scev -S %s | FileCheck %s +target datalayout = "n16:32" + +@glob = external global i16, align 1 + +; Test case for PR58136. +define void @test() { +; CHECK-LABEL: @test( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SRC:%.*]] = alloca i16, align 1 +; CHECK-NEXT: [[DST:%.*]] = alloca float, align 1 +; CHECK-NEXT: [[CALL:%.*]] = call i16 @foo() +; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i16 8509, [[CALL]] +; CHECK-NEXT: [[L_1:%.*]] = load i16, ptr [[SRC]], align 1 +; CHECK-NEXT: [[C_2:%.*]] = icmp slt i16 [[L_1]], 10 +; CHECK-NEXT: [[L_3:%.*]] = load i16, ptr [[SRC]], align 1 +; CHECK-NEXT: [[GLOB_PROMOTED:%.*]] = load i16, ptr @glob, align 1 +; CHECK-NEXT: [[DST_PROMOTED:%.*]] = load float, ptr [[DST]], align 1 +; CHECK-NEXT: br i1 [[C_1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]] +; CHECK: entry.split.us: +; CHECK-NEXT: br i1 [[C_2]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]], label [[ENTRY_SPLIT_US_SPLIT:%.*]] +; CHECK: entry.split.us.split.us: +; CHECK-NEXT: br label [[LOOP_HEADER_US_US:%.*]] +; CHECK: loop.header.us.us: +; CHECK-NEXT: [[MUL1_US_US:%.*]] = phi i16 [ [[MUL_US_US:%.*]], [[LOOP_HEADER_US_US]] ], [ [[GLOB_PROMOTED]], [[ENTRY_SPLIT_US_SPLIT_US]] ] +; CHECK-NEXT: [[MUL_US_US]] = mul nsw i16 [[MUL1_US_US]], [[L_3]] +; CHECK-NEXT: br label [[LOOP_HEADER_US_US]] +; CHECK: entry.split.us.split: +; CHECK-NEXT: br label [[LOOP_HEADER_US:%.*]] +; CHECK: loop.header.us: +; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]] +; CHECK: exit.split.us: +; CHECK-NEXT: [[DOTLCSSA_US:%.*]] = phi float [ [[DST_PROMOTED]], [[LOOP_HEADER_US]] ] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: entry.split: +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[TMP0:%.*]] = phi float [ 1.000000e+01, [[LOOP_LATCH:%.*]] ], [ [[DST_PROMOTED]], [[ENTRY_SPLIT]] ] +; CHECK-NEXT: [[MUL1:%.*]] = phi i16 [ [[MUL:%.*]], [[LOOP_LATCH]] ], [ [[GLOB_PROMOTED]], [[ENTRY_SPLIT]] ] +; CHECK-NEXT: br i1 false, label [[LOOP_LATCH]], label [[EXIT_SPLIT:%.*]] +; CHECK: loop.latch: +; CHECK-NEXT: [[MUL]] = mul nsw i16 [[MUL1]], [[L_3]] +; CHECK-NEXT: store i16 [[MUL]], ptr @glob, align 1 +; CHECK-NEXT: br label [[LOOP_HEADER]] +; CHECK: exit.split: +; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi float [ [[TMP0]], [[LOOP_HEADER]] ] +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi float [ [[DOTLCSSA]], [[EXIT_SPLIT]] ], [ [[DOTLCSSA_US]], [[EXIT_SPLIT_US]] ] +; CHECK-NEXT: store float [[DOTUS_PHI]], ptr [[DST]], align 1 +; CHECK-NEXT: ret void +; +entry: + %src = alloca i16, align 1 + %dst = alloca float, align 1 + br label %loop.header + +loop.header: + %call = call i16 @foo() + %c.1 = icmp ugt i16 8509, %call + br i1 %c.1, label %then.bb, label %merge.bb + +then.bb: + %l.1 = load i16, ptr %src, align 1 + %c.2 = icmp slt i16 %l.1, 10 + br label %merge.bb + +merge.bb: + %p = phi i1 [ false, %loop.header ], [ %c.2, %then.bb ] + br i1 %p, label %loop.latch, label %exit + +loop.latch: + %l.2 = load i16, ptr @glob, align 1 + %l.3 = load i16, ptr %src, align 1 + %mul = mul nsw i16 %l.2, %l.3 + store i16 %mul, ptr @glob, align 1 + store float 10.0, ptr %dst, align 1 + br label %loop.header + +exit: + ret void +} + +declare i16 @foo() nounwind readnone -- 2.7.4