blob: 8af526198b6c7f7f69b1de7be5d6d16a8bd12829 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes='loop(simple-loop-unswitch),verify<loops>' -S < %s | FileCheck %s
; RUN: opt -verify-memoryssa -passes='loop-mssa(simple-loop-unswitch),verify<loops>' -S < %s | FileCheck %s
; Trivially unswitchable header branch whose exit LCSSA phi uses a header phi.
define i32 @test_unswitch_header_phi(i1 %c) {
; CHECK-LABEL: @test_unswitch_header_phi(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[ENTRY_SPLIT:%.*]], label [[EXIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
br i1 %c, label %latch, label %exit
latch:
%next = add i32 %acc, 1
br label %header
exit:
%r = phi i32 [ %acc, %header ]
ret i32 %r
}
; Header branch whose exit LCSSA phi uses a non-phi header value: not trivially
; unswitchable, so the loop is left unchanged.
define i32 @test_no_unswitch_header_nonphi(i1 %c) {
; CHECK-LABEL: @test_no_unswitch_header_nonphi(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[ACC]], 5
; CHECK-NEXT: br i1 [[C:%.*]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[SUM]], [[HEADER]] ]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
%sum = add i32 %acc, 5
br i1 %c, label %latch, label %exit
latch:
%next = add i32 %acc, 1
br label %header
exit:
%r = phi i32 [ %sum, %header ]
ret i32 %r
}
; Trivially unswitchable header branch whose exit has two LCSSA phis: one with a
; loop-invariant incoming, one with a header phi incoming.
define i32 @test_unswitch_header_phi_mixed(i1 %c, i32 %inv) {
; CHECK-LABEL: @test_unswitch_header_phi_mixed(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[ENTRY_SPLIT:%.*]], label [[EXIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: [[S:%.*]] = phi i32 [ [[INV:%.*]], [[ENTRY]] ]
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[R]], [[S]]
; CHECK-NEXT: ret i32 [[SUM]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
br i1 %c, label %latch, label %exit
latch:
%next = add i32 %acc, 1
br label %header
exit:
%r = phi i32 [ %acc, %header ]
%s = phi i32 [ %inv, %header ]
%sum = add i32 %r, %s
ret i32 %sum
}
; Trivially unswitchable header branch whose exit LCSSA phi uses a header phi
; whose entry value is defined in the preheader, not a constant.
define i32 @test_unswitch_header_phi_nonconst(i1 %c, i32 %x) {
; CHECK-LABEL: @test_unswitch_header_phi_nonconst(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[INIT:%.*]] = add i32 [[X:%.*]], 3
; CHECK-NEXT: br i1 [[C:%.*]], label [[ENTRY_SPLIT:%.*]], label [[EXIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ [[INIT]], [[ENTRY_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[INIT]], [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
%init = add i32 %x, 3
br label %header
header:
%acc = phi i32 [ %init, %entry ], [ %next, %latch ]
br i1 %c, label %latch, label %exit
latch:
%next = add i32 %acc, 1
br label %header
exit:
%r = phi i32 [ %acc, %header ]
ret i32 %r
}
; Trivially unswitchable branch that is not in the header but dominates the
; latch, whose exit LCSSA phi uses a header phi. The header branch unswitches
; first, then %mid is reached and also unswitches.
define i32 @test_unswitch_nonheader_phi(i1 %c1, i1 %c2) {
; CHECK-LABEL: @test_unswitch_nonheader_phi(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C1:%.*]], label [[EXIT1:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT2:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
; CHECK: entry.split.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: br label [[MID:%.*]]
; CHECK: mid:
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit1:
; CHECK-NEXT: ret i32 100
; CHECK: exit2:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
br i1 %c1, label %exit1, label %mid
mid:
br i1 %c2, label %exit2, label %latch
latch:
%next = add i32 %acc, 1
br label %header
exit1:
ret i32 100
exit2:
%r = phi i32 [ %acc, %mid ]
ret i32 %r
}
; Trivially unswitchable header branch whose exit LCSSA reads header phi %acc.
; The exit is also reached from the latch, so it is split on unswitch.
define i32 @test_unswitch_header_phi_split_exit(i1 %c, i32 %n) {
; CHECK-LABEL: @test_unswitch_header_phi_split_exit(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: br label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[NEXT]], [[N:%.*]]
; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[NEXT]], [[LATCH]] ]
; CHECK-NEXT: br label [[EXIT_SPLIT]]
; CHECK: exit.split:
; CHECK-NEXT: [[R_SPLIT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R]], [[EXIT]] ]
; CHECK-NEXT: ret i32 [[R_SPLIT]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
br i1 %c, label %exit, label %latch
latch:
%next = add i32 %acc, 1
%cmp = icmp slt i32 %next, %n
br i1 %cmp, label %header, label %exit
exit:
%r = phi i32 [ %acc, %header ], [ %next, %latch ]
ret i32 %r
}
; Trivially unswitchable header branch whose exit LCSSA reads header phi %acc.
; The condition is an OR of invariant %a and variant %b, so only %a is peeled.
define i32 @test_unswitch_header_phi_partial(i1 %a) {
; CHECK-LABEL: @test_unswitch_header_phi_partial(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_FR:%.*]] = freeze i1 [[A:%.*]]
; CHECK-NEXT: br i1 [[A_FR]], label [[EXIT_SPLIT:%.*]], label [[ENTRY_SPLIT:%.*]]
; CHECK: entry.split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[NEXT:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[ACC]], 5
; CHECK-NEXT: [[OR:%.*]] = or i1 false, [[B]]
; CHECK-NEXT: br i1 [[OR]], label [[EXIT:%.*]], label [[LATCH]]
; CHECK: latch:
; CHECK-NEXT: [[NEXT]] = add i32 [[ACC]], 1
; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[ACC]], [[HEADER]] ]
; CHECK-NEXT: br label [[EXIT_SPLIT]]
; CHECK: exit.split:
; CHECK-NEXT: [[R_SPLIT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R]], [[EXIT]] ]
; CHECK-NEXT: ret i32 [[R_SPLIT]]
;
entry:
br label %header
header:
%acc = phi i32 [ 0, %entry ], [ %next, %latch ]
%b = icmp eq i32 %acc, 5
%or = or i1 %a, %b
br i1 %or, label %exit, label %latch
latch:
%next = add i32 %acc, 1
br label %header
exit:
%r = phi i32 [ %acc, %header ]
ret i32 %r
}