llvm-project/llvm/test/Transforms/SimpleLoopUnswitch/invalidate-block-and-loop-dispositions.ll
Florian Hahn a41cb8bf58
[SimpleLoopUnswitch] Forget block & loop dispos during trivial unswitch.
Unswitching adjusts the CFG in ways that may invalidate cached loop
dispositions. Clear all cached block and loop dispositions during
trivial unswitching. The same is already done for non-trivial
unswitching.

Fixes #58751.
2022-11-05 16:56:06 +00:00

141 lines
4.8 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes="loop-mssa(indvars,simple-loop-unswitch<nontrivial>)" -verify-scev -S %s | FileCheck %s
target datalayout = "n16:32"
@glob = external global i16, align 1
; Test case for PR58136.
define void @test_pr58136(i1 %c.1, i1 %c.2) {
; CHECK-LABEL: @test_pr58136(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[SRC1:%.*]] = alloca i16, align 2
; CHECK-NEXT: [[L_3:%.*]] = load i16, ptr [[SRC1]], align 2
; CHECK-NEXT: [[GLOB_PROMOTED:%.*]] = load i16, ptr @glob, align 2
; CHECK-NEXT: [[C_1_FR:%.*]] = freeze i1 [[C_1:%.*]]
; CHECK-NEXT: br i1 [[C_1_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK: entry.split.us:
; CHECK-NEXT: [[C_2_FR:%.*]] = freeze i1 [[C_2:%.*]]
; CHECK-NEXT: br i1 [[C_2_FR]], 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_LATCH_US_US:%.*]] ], [ [[GLOB_PROMOTED]], [[ENTRY_SPLIT_US_SPLIT_US]] ]
; CHECK-NEXT: [[CALL2_US_US:%.*]] = call i16 @foo()
; CHECK-NEXT: br label [[THEN_BB_US_US:%.*]]
; CHECK: then.bb.us.us:
; CHECK-NEXT: br label [[LOOP_LATCH_US_US]]
; CHECK: loop.latch.us.us:
; CHECK-NEXT: [[MUL_US_US]] = mul nsw i16 [[MUL1_US_US]], [[L_3]]
; CHECK-NEXT: store i16 [[MUL_US_US]], ptr @glob, align 2
; 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: [[CALL2_US:%.*]] = call i16 @foo()
; CHECK-NEXT: br label [[THEN_BB_US:%.*]]
; CHECK: then.bb.us:
; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]
; CHECK: exit.split.us:
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
; CHECK: loop.header:
; CHECK-NEXT: [[CALL2:%.*]] = call i16 @foo()
; CHECK-NEXT: br label [[EXIT_SPLIT:%.*]]
; CHECK: exit.split:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;
entry:
%src1 = alloca i16, align 2
%l.3 = load i16, ptr %src1, align 2
%glob.promoted = load i16, ptr @glob, align 2
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%mul1 = phi i16 [ %mul, %loop.latch ], [ %glob.promoted, %entry ]
%call2 = call i16 @foo()
br i1 %c.1, label %then.bb, label %exit
then.bb: ; preds = %loop.header
br i1 %c.2, label %loop.latch, label %exit
loop.latch: ; preds = %then.bb
%mul = mul nsw i16 %mul1, %l.3
store i16 %mul, ptr @glob, align 2
br label %loop.header
exit: ; preds = %then.bb, %loop.header
ret void
}
declare i16 @foo() nounwind readnone
define void @test_pr58158(i1 %c.1) {
; CHECK-LABEL: @test_pr58158(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = tail call i16 @bar()
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK: entry.split.us:
; CHECK-NEXT: br label [[OUTER_US:%.*]]
; CHECK: outer.us:
; CHECK-NEXT: br label [[INNER_PREHEADER_US:%.*]]
; CHECK: inner.us:
; CHECK-NEXT: [[C_2_US:%.*]] = icmp eq i16 0, [[CALL]]
; CHECK-NEXT: br i1 [[C_2_US]], label [[OUTER_LOOPEXIT_US:%.*]], label [[INNER_US:%.*]]
; CHECK: inner.preheader.us:
; CHECK-NEXT: br label [[INNER_US]]
; CHECK: outer.loopexit.us:
; CHECK-NEXT: br label [[OUTER_BACKEDGE_US:%.*]]
; CHECK: outer.backedge.us:
; CHECK-NEXT: br label [[OUTER_US]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[OUTER:%.*]]
; CHECK: outer:
; CHECK-NEXT: br label [[OUTER_BACKEDGE:%.*]]
; CHECK: outer.backedge:
; CHECK-NEXT: br label [[OUTER]]
;
entry:
%call = tail call i16 @bar()
br label %outer
outer:
br i1 %c.1, label %inner, label %outer
inner:
%c.2 = icmp eq i16 0, %call
br i1 %c.2, label %outer, label %inner
}
declare i16 @bar()
define void @pr58751(i16 %a, ptr %dst) {
entry:
%c.1 = icmp eq i16 %a, 0
br label %outer.header
outer.header:
%outer.iv = phi i16 [ %a, %entry ], [ %outer.iv.next, %outer.latch ]
br label %inner.header
inner.header:
%inner.iv = phi i16 [ %outer.iv, %outer.header ], [ %inner.iv.next, %inner.latch ]
br i1 %c.1, label %outer.latch, label %inner.latch
inner.latch:
%inner.iv.next = add nsw i16 %inner.iv, 1
store i16 %inner.iv.next, ptr %dst, align 1
%c.2 = icmp eq i16 %inner.iv.next, 0
br i1 %c.2, label %exit, label %inner.header
outer.latch:
%outer.iv.next = add nsw i16 %outer.iv, 1
br label %outer.header
exit:
ret void
}