107142b30SJingu Kang; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
207142b30SJingu Kang; RUN: opt -passes='loop-mssa(unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s
307142b30SJingu Kang
407142b30SJingu Kangdeclare void @clobber()
507142b30SJingu Kang
607142b30SJingu Kangdefine i32 @partial_unswitch_true_successor(i32* %ptr, i32 %N) {
707142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_successor(
807142b30SJingu Kang; CHECK-NEXT:  entry:
9*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
10*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
11*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
12*88b259c0SJingu Kang; CHECK:       entry.split.us:
13*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
14*88b259c0SJingu Kang; CHECK:       loop.header.us:
15*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
16*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
17*88b259c0SJingu Kang; CHECK:       noclobber.us:
18*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
19*88b259c0SJingu Kang; CHECK:       loop.latch.us:
20*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
21*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
22*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
23*88b259c0SJingu Kang; CHECK:       exit.split.us:
24*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
25*88b259c0SJingu Kang; CHECK:       entry.split:
2607142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
2707142b30SJingu Kang; CHECK:       loop.header:
28*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
29*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
3007142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
3107142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
3207142b30SJingu Kang; CHECK:       noclobber:
3307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
3407142b30SJingu Kang; CHECK:       clobber:
3507142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
3607142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
3707142b30SJingu Kang; CHECK:       loop.latch:
38*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
3907142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
40*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
41*88b259c0SJingu Kang; CHECK:       exit.split:
42*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
4307142b30SJingu Kang; CHECK:       exit:
4407142b30SJingu Kang; CHECK-NEXT:    ret i32 10
4507142b30SJingu Kang;
4607142b30SJingu Kangentry:
4707142b30SJingu Kang  br label %loop.header
4807142b30SJingu Kang
4907142b30SJingu Kangloop.header:
5007142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
5107142b30SJingu Kang  %lv = load i32, i32* %ptr
5207142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
5307142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
5407142b30SJingu Kang
5507142b30SJingu Kangnoclobber:
5607142b30SJingu Kang  br label %loop.latch
5707142b30SJingu Kang
5807142b30SJingu Kangclobber:
5907142b30SJingu Kang  call void @clobber()
6007142b30SJingu Kang  br label %loop.latch
6107142b30SJingu Kang
6207142b30SJingu Kangloop.latch:
6307142b30SJingu Kang  %c = icmp ult i32 %iv, %N
6407142b30SJingu Kang  %iv.next = add i32 %iv, 1
6507142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
6607142b30SJingu Kang
6707142b30SJingu Kangexit:
6807142b30SJingu Kang  ret i32 10
6907142b30SJingu Kang}
7007142b30SJingu Kang
7107142b30SJingu Kangdefine i32 @partial_unswitch_false_successor(i32* %ptr, i32 %N) {
7207142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_false_successor(
7307142b30SJingu Kang; CHECK-NEXT:  entry:
74*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
75*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
76*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
77*88b259c0SJingu Kang; CHECK:       entry.split.us:
78*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
79*88b259c0SJingu Kang; CHECK:       loop.header.us:
80*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
81*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
82*88b259c0SJingu Kang; CHECK:       noclobber.us:
83*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
84*88b259c0SJingu Kang; CHECK:       loop.latch.us:
85*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
86*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
87*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
88*88b259c0SJingu Kang; CHECK:       exit.split.us:
89*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
90*88b259c0SJingu Kang; CHECK:       entry.split:
9107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
9207142b30SJingu Kang; CHECK:       loop.header:
93*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
94*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
9507142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
9607142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
9707142b30SJingu Kang; CHECK:       clobber:
9807142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
9907142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
10007142b30SJingu Kang; CHECK:       noclobber:
10107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
10207142b30SJingu Kang; CHECK:       loop.latch:
103*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
10407142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
105*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
106*88b259c0SJingu Kang; CHECK:       exit.split:
107*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
10807142b30SJingu Kang; CHECK:       exit:
10907142b30SJingu Kang; CHECK-NEXT:    ret i32 10
11007142b30SJingu Kang;
11107142b30SJingu Kangentry:
11207142b30SJingu Kang  br label %loop.header
11307142b30SJingu Kang
11407142b30SJingu Kangloop.header:
11507142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
11607142b30SJingu Kang  %lv = load i32, i32* %ptr
11707142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
11807142b30SJingu Kang  br i1 %sc, label %clobber, label %noclobber
11907142b30SJingu Kang
12007142b30SJingu Kangclobber:
12107142b30SJingu Kang  call void @clobber()
12207142b30SJingu Kang  br label %loop.latch
12307142b30SJingu Kang
12407142b30SJingu Kangnoclobber:
12507142b30SJingu Kang  br label %loop.latch
12607142b30SJingu Kang
12707142b30SJingu Kangloop.latch:
12807142b30SJingu Kang  %c = icmp ult i32 %iv, %N
12907142b30SJingu Kang  %iv.next = add i32 %iv, 1
13007142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
13107142b30SJingu Kang
13207142b30SJingu Kangexit:
13307142b30SJingu Kang  ret i32 10
13407142b30SJingu Kang}
13507142b30SJingu Kang
13607142b30SJingu Kangdefine i32 @partial_unswtich_gep_load_icmp(i32** %ptr, i32 %N) {
13707142b30SJingu Kang; CHECK-LABEL: @partial_unswtich_gep_load_icmp(
13807142b30SJingu Kang; CHECK-NEXT:  entry:
139*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i32*, i32** [[PTR:%.*]], i32 1
140*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = load i32*, i32** [[TMP0]], align 8
141*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 4
142*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 100
143*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP3]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
144*88b259c0SJingu Kang; CHECK:       entry.split.us:
145*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
146*88b259c0SJingu Kang; CHECK:       loop.header.us:
147*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
148*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
149*88b259c0SJingu Kang; CHECK:       noclobber.us:
150*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
151*88b259c0SJingu Kang; CHECK:       loop.latch.us:
152*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
153*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
154*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
155*88b259c0SJingu Kang; CHECK:       exit.split.us:
156*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
157*88b259c0SJingu Kang; CHECK:       entry.split:
15807142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
15907142b30SJingu Kang; CHECK:       loop.header:
160*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
161*88b259c0SJingu Kang; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32*, i32** [[PTR]], i32 1
16207142b30SJingu Kang; CHECK-NEXT:    [[LV_1:%.*]] = load i32*, i32** [[GEP]], align 8
16307142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[LV_1]], align 4
16407142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
16507142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
16607142b30SJingu Kang; CHECK:       noclobber:
16707142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
16807142b30SJingu Kang; CHECK:       clobber:
16907142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
17007142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
17107142b30SJingu Kang; CHECK:       loop.latch:
172*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
17307142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
174*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
175*88b259c0SJingu Kang; CHECK:       exit.split:
176*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
17707142b30SJingu Kang; CHECK:       exit:
17807142b30SJingu Kang; CHECK-NEXT:    ret i32 10
17907142b30SJingu Kang;
18007142b30SJingu Kangentry:
18107142b30SJingu Kang  br label %loop.header
18207142b30SJingu Kang
18307142b30SJingu Kangloop.header:
18407142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
18507142b30SJingu Kang  %gep = getelementptr i32*, i32** %ptr, i32 1
18607142b30SJingu Kang  %lv.1 = load i32*, i32** %gep
18707142b30SJingu Kang  %lv = load i32, i32* %lv.1
18807142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
18907142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
19007142b30SJingu Kang
19107142b30SJingu Kangnoclobber:
19207142b30SJingu Kang  br label %loop.latch
19307142b30SJingu Kang
19407142b30SJingu Kangclobber:
19507142b30SJingu Kang  call void @clobber()
19607142b30SJingu Kang  br label %loop.latch
19707142b30SJingu Kang
19807142b30SJingu Kangloop.latch:
19907142b30SJingu Kang  %c = icmp ult i32 %iv, %N
20007142b30SJingu Kang  %iv.next = add i32 %iv, 1
20107142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
20207142b30SJingu Kang
20307142b30SJingu Kangexit:
20407142b30SJingu Kang  ret i32 10
20507142b30SJingu Kang}
20607142b30SJingu Kang
20707142b30SJingu Kangdefine i32 @partial_unswitch_reduction_phi(i32* %ptr, i32 %N) {
20807142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_reduction_phi(
20907142b30SJingu Kang; CHECK-NEXT:  entry:
210*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
211*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
212*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
213*88b259c0SJingu Kang; CHECK:       entry.split.us:
214*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
215*88b259c0SJingu Kang; CHECK:       loop.header.us:
216*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
217*88b259c0SJingu Kang; CHECK-NEXT:    [[RED_US:%.*]] = phi i32 [ 20, [[ENTRY_SPLIT_US]] ], [ [[RED_NEXT_US:%.*]], [[LOOP_LATCH_US]] ]
218*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
219*88b259c0SJingu Kang; CHECK:       noclobber.us:
220*88b259c0SJingu Kang; CHECK-NEXT:    [[ADD_10_US:%.*]] = add i32 [[RED_US]], 10
221*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
222*88b259c0SJingu Kang; CHECK:       loop.latch.us:
223*88b259c0SJingu Kang; CHECK-NEXT:    [[RED_NEXT_US]] = phi i32 [ [[ADD_10_US]], [[NOCLOBBER_US]] ]
224*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
225*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
226*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
227*88b259c0SJingu Kang; CHECK:       exit.split.us:
228*88b259c0SJingu Kang; CHECK-NEXT:    [[RED_NEXT_LCSSA_US:%.*]] = phi i32 [ [[RED_NEXT_US]], [[LOOP_LATCH_US]] ]
229*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
230*88b259c0SJingu Kang; CHECK:       entry.split:
23107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
23207142b30SJingu Kang; CHECK:       loop.header:
233*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
234*88b259c0SJingu Kang; CHECK-NEXT:    [[RED:%.*]] = phi i32 [ 20, [[ENTRY_SPLIT]] ], [ [[RED_NEXT:%.*]], [[LOOP_LATCH]] ]
235*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
23607142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
23707142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
23807142b30SJingu Kang; CHECK:       clobber:
23907142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
24007142b30SJingu Kang; CHECK-NEXT:    [[ADD_5:%.*]] = add i32 [[RED]], 5
24107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
24207142b30SJingu Kang; CHECK:       noclobber:
24307142b30SJingu Kang; CHECK-NEXT:    [[ADD_10:%.*]] = add i32 [[RED]], 10
24407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
24507142b30SJingu Kang; CHECK:       loop.latch:
24607142b30SJingu Kang; CHECK-NEXT:    [[RED_NEXT]] = phi i32 [ [[ADD_5]], [[CLOBBER]] ], [ [[ADD_10]], [[NOCLOBBER]] ]
247*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
24807142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
249*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
250*88b259c0SJingu Kang; CHECK:       exit.split:
251ab728717SJingu Kang; CHECK-NEXT:    [[RED_NEXT_LCSSA:%.*]] = phi i32 [ [[RED_NEXT]], [[LOOP_LATCH]] ]
252*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
253*88b259c0SJingu Kang; CHECK:       exit:
254*88b259c0SJingu Kang; CHECK-NEXT:    [[DOTUS_PHI:%.*]] = phi i32 [ [[RED_NEXT_LCSSA]], [[EXIT_SPLIT]] ], [ [[RED_NEXT_LCSSA_US]], [[EXIT_SPLIT_US]] ]
255*88b259c0SJingu Kang; CHECK-NEXT:    ret i32 [[DOTUS_PHI]]
25607142b30SJingu Kang;
25707142b30SJingu Kangentry:
25807142b30SJingu Kang  br label %loop.header
25907142b30SJingu Kang
26007142b30SJingu Kangloop.header:
26107142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
26207142b30SJingu Kang  %red = phi i32 [ 20, %entry ], [ %red.next, %loop.latch ]
26307142b30SJingu Kang  %lv = load i32, i32* %ptr
26407142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
26507142b30SJingu Kang  br i1 %sc, label %clobber, label %noclobber
26607142b30SJingu Kang
26707142b30SJingu Kangclobber:
26807142b30SJingu Kang  call void @clobber()
26907142b30SJingu Kang  %add.5 = add i32 %red, 5
27007142b30SJingu Kang  br label %loop.latch
27107142b30SJingu Kang
27207142b30SJingu Kangnoclobber:
27307142b30SJingu Kang  %add.10 = add i32 %red, 10
27407142b30SJingu Kang  br label %loop.latch
27507142b30SJingu Kang
27607142b30SJingu Kangloop.latch:
27707142b30SJingu Kang  %red.next = phi i32 [ %add.5, %clobber ], [ %add.10, %noclobber ]
27807142b30SJingu Kang  %c = icmp ult i32 %iv, %N
27907142b30SJingu Kang  %iv.next = add i32 %iv, 1
28007142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
28107142b30SJingu Kang
28207142b30SJingu Kangexit:
28307142b30SJingu Kang  %red.next.lcssa = phi i32 [ %red.next, %loop.latch ]
28407142b30SJingu Kang  ret i32 %red.next.lcssa
28507142b30SJingu Kang}
28607142b30SJingu Kang
28707142b30SJingu Kang; Partial unswitching is possible, because the store in %noclobber does not
28807142b30SJingu Kang; alias the load of the condition.
28907142b30SJingu Kangdefine i32 @partial_unswitch_true_successor_noclobber(i32* noalias %ptr.1, i32* noalias %ptr.2, i32 %N) {
29007142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_successor_noclobber(
29107142b30SJingu Kang; CHECK-NEXT:  entry:
292*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4
293*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
294*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
295*88b259c0SJingu Kang; CHECK:       entry.split.us:
296*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
297*88b259c0SJingu Kang; CHECK:       loop.header.us:
298*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
299*88b259c0SJingu Kang; CHECK-NEXT:    [[LV_US:%.*]] = load i32, i32* [[PTR_1]], align 4
300*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
301*88b259c0SJingu Kang; CHECK:       noclobber.us:
302*88b259c0SJingu Kang; CHECK-NEXT:    [[GEP_1_US:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV_US]]
303*88b259c0SJingu Kang; CHECK-NEXT:    store i32 [[LV_US]], i32* [[GEP_1_US]], align 4
304*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
305*88b259c0SJingu Kang; CHECK:       loop.latch.us:
306*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
307*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
308*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
309*88b259c0SJingu Kang; CHECK:       exit.split.us:
310*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
311*88b259c0SJingu Kang; CHECK:       entry.split:
31207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
31307142b30SJingu Kang; CHECK:       loop.header:
314*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
315*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR_1]], align 4
31607142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
31707142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
31807142b30SJingu Kang; CHECK:       noclobber:
319*88b259c0SJingu Kang; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2]], i32 [[IV]]
32007142b30SJingu Kang; CHECK-NEXT:    store i32 [[LV]], i32* [[GEP_1]], align 4
32107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
32207142b30SJingu Kang; CHECK:       clobber:
32307142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
32407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
32507142b30SJingu Kang; CHECK:       loop.latch:
326*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
32707142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
328*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
329*88b259c0SJingu Kang; CHECK:       exit.split:
330*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
33107142b30SJingu Kang; CHECK:       exit:
33207142b30SJingu Kang; CHECK-NEXT:    ret i32 10
33307142b30SJingu Kang;
33407142b30SJingu Kangentry:
33507142b30SJingu Kang  br label %loop.header
33607142b30SJingu Kang
33707142b30SJingu Kangloop.header:
33807142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
33907142b30SJingu Kang  %lv = load i32, i32* %ptr.1
34007142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
34107142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
34207142b30SJingu Kang
34307142b30SJingu Kangnoclobber:
34407142b30SJingu Kang  %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv
34507142b30SJingu Kang  store i32 %lv, i32* %gep.1
34607142b30SJingu Kang  br label %loop.latch
34707142b30SJingu Kang
34807142b30SJingu Kangclobber:
34907142b30SJingu Kang  call void @clobber()
35007142b30SJingu Kang  br label %loop.latch
35107142b30SJingu Kang
35207142b30SJingu Kangloop.latch:
35307142b30SJingu Kang  %c = icmp ult i32 %iv, %N
35407142b30SJingu Kang  %iv.next = add i32 %iv, 1
35507142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
35607142b30SJingu Kang
35707142b30SJingu Kangexit:
35807142b30SJingu Kang  ret i32 10
35907142b30SJingu Kang}
36007142b30SJingu Kang
36107142b30SJingu Kangdefine void @no_partial_unswitch_phi_cond(i1 %lc, i32 %N) {
36207142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_phi_cond(
36307142b30SJingu Kang; CHECK-NEXT:  entry:
36407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
36507142b30SJingu Kang; CHECK:       loop.header:
36607142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
36707142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = phi i1 [ [[LC:%.*]], [[ENTRY]] ], [ true, [[LOOP_LATCH]] ]
36807142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[CLOBBER:%.*]], label [[NOCLOBBER:%.*]]
36907142b30SJingu Kang; CHECK:       clobber:
37007142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
37107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
37207142b30SJingu Kang; CHECK:       noclobber:
37307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
37407142b30SJingu Kang; CHECK:       loop.latch:
37507142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
37607142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
37707142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
37807142b30SJingu Kang; CHECK:       exit:
37907142b30SJingu Kang; CHECK-NEXT:    ret void
38007142b30SJingu Kang;
38107142b30SJingu Kangentry:
38207142b30SJingu Kang  br label %loop.header
38307142b30SJingu Kang
38407142b30SJingu Kangloop.header:
38507142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
38607142b30SJingu Kang  %sc = phi i1 [ %lc, %entry ], [ true, %loop.latch ]
38707142b30SJingu Kang  br i1 %sc, label %clobber, label %noclobber
38807142b30SJingu Kang
38907142b30SJingu Kangclobber:
39007142b30SJingu Kang  call void @clobber()
39107142b30SJingu Kang  br label %loop.latch
39207142b30SJingu Kang
39307142b30SJingu Kangnoclobber:
39407142b30SJingu Kang  br label %loop.latch
39507142b30SJingu Kang
39607142b30SJingu Kangloop.latch:
39707142b30SJingu Kang  %c = icmp ult i32 %iv, %N
39807142b30SJingu Kang  %iv.next = add i32 %iv, 1
39907142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
40007142b30SJingu Kang
40107142b30SJingu Kangexit:
40207142b30SJingu Kang  ret void
40307142b30SJingu Kang}
40407142b30SJingu Kang
40507142b30SJingu Kangdefine void @no_partial_unswitch_clobber_latch(i32* %ptr, i32 %N) {
40607142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_clobber_latch(
40707142b30SJingu Kang; CHECK-NEXT:  entry:
40807142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
40907142b30SJingu Kang; CHECK:       loop.header:
41007142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
41107142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
41207142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
41307142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
41407142b30SJingu Kang; CHECK:       noclobber:
41507142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
41607142b30SJingu Kang; CHECK:       clobber:
41707142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
41807142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
41907142b30SJingu Kang; CHECK:       loop.latch:
42007142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
42107142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
42207142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
42307142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
42407142b30SJingu Kang; CHECK:       exit:
42507142b30SJingu Kang; CHECK-NEXT:    ret void
42607142b30SJingu Kang;
42707142b30SJingu Kangentry:
42807142b30SJingu Kang  br label %loop.header
42907142b30SJingu Kang
43007142b30SJingu Kangloop.header:
43107142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
43207142b30SJingu Kang  %lv = load i32, i32* %ptr
43307142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
43407142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
43507142b30SJingu Kang
43607142b30SJingu Kangnoclobber:
43707142b30SJingu Kang  br label %loop.latch
43807142b30SJingu Kang
43907142b30SJingu Kangclobber:
44007142b30SJingu Kang  call void @clobber()
44107142b30SJingu Kang  br label %loop.latch
44207142b30SJingu Kang
44307142b30SJingu Kangloop.latch:
44407142b30SJingu Kang  call void @clobber()
44507142b30SJingu Kang  %c = icmp ult i32 %iv, %N
44607142b30SJingu Kang  %iv.next = add i32 %iv, 1
44707142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
44807142b30SJingu Kang
44907142b30SJingu Kangexit:
45007142b30SJingu Kang  ret void
45107142b30SJingu Kang}
45207142b30SJingu Kang
45307142b30SJingu Kangdefine void @no_partial_unswitch_clobber_header(i32* %ptr, i32 %N) {
45407142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_clobber_header(
45507142b30SJingu Kang; CHECK-NEXT:  entry:
45607142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
45707142b30SJingu Kang; CHECK:       loop.header:
45807142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
45907142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
46007142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
46107142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
46207142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
46307142b30SJingu Kang; CHECK:       noclobber:
46407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
46507142b30SJingu Kang; CHECK:       clobber:
46607142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
46707142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
46807142b30SJingu Kang; CHECK:       loop.latch:
46907142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
47007142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
47107142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
47207142b30SJingu Kang; CHECK:       exit:
47307142b30SJingu Kang; CHECK-NEXT:    ret void
47407142b30SJingu Kang;
47507142b30SJingu Kangentry:
47607142b30SJingu Kang  br label %loop.header
47707142b30SJingu Kang
47807142b30SJingu Kangloop.header:
47907142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
48007142b30SJingu Kang  call void @clobber()
48107142b30SJingu Kang  %lv = load i32, i32* %ptr
48207142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
48307142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
48407142b30SJingu Kang
48507142b30SJingu Kangnoclobber:
48607142b30SJingu Kang  br label %loop.latch
48707142b30SJingu Kang
48807142b30SJingu Kangclobber:
48907142b30SJingu Kang  call void @clobber()
49007142b30SJingu Kang  br label %loop.latch
49107142b30SJingu Kang
49207142b30SJingu Kangloop.latch:
49307142b30SJingu Kang  %c = icmp ult i32 %iv, %N
49407142b30SJingu Kang  %iv.next = add i32 %iv, 1
49507142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
49607142b30SJingu Kang
49707142b30SJingu Kangexit:
49807142b30SJingu Kang  ret void
49907142b30SJingu Kang}
50007142b30SJingu Kang
50107142b30SJingu Kangdefine void @no_partial_unswitch_clobber_both(i32* %ptr, i32 %N) {
50207142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_clobber_both(
50307142b30SJingu Kang; CHECK-NEXT:  entry:
50407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
50507142b30SJingu Kang; CHECK:       loop.header:
50607142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
50707142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
50807142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
50907142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
51007142b30SJingu Kang; CHECK:       noclobber:
51107142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
51207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
51307142b30SJingu Kang; CHECK:       clobber:
51407142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
51507142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
51607142b30SJingu Kang; CHECK:       loop.latch:
51707142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
51807142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
51907142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
52007142b30SJingu Kang; CHECK:       exit:
52107142b30SJingu Kang; CHECK-NEXT:    ret void
52207142b30SJingu Kang;
52307142b30SJingu Kangentry:
52407142b30SJingu Kang  br label %loop.header
52507142b30SJingu Kang
52607142b30SJingu Kangloop.header:
52707142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
52807142b30SJingu Kang  %lv = load i32, i32* %ptr
52907142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
53007142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
53107142b30SJingu Kang
53207142b30SJingu Kangnoclobber:
53307142b30SJingu Kang  call void @clobber()
53407142b30SJingu Kang  br label %loop.latch
53507142b30SJingu Kang
53607142b30SJingu Kangclobber:
53707142b30SJingu Kang  call void @clobber()
53807142b30SJingu Kang  br label %loop.latch
53907142b30SJingu Kang
54007142b30SJingu Kangloop.latch:
54107142b30SJingu Kang  %c = icmp ult i32 %iv, %N
54207142b30SJingu Kang  %iv.next = add i32 %iv, 1
54307142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
54407142b30SJingu Kang
54507142b30SJingu Kangexit:
54607142b30SJingu Kang  ret void
54707142b30SJingu Kang}
54807142b30SJingu Kang
54907142b30SJingu Kangdefine i32 @no_partial_unswitch_true_successor_storeclobber(i32* %ptr.1, i32* %ptr.2, i32 %N) {
55007142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_true_successor_storeclobber(
55107142b30SJingu Kang; CHECK-NEXT:  entry:
55207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
55307142b30SJingu Kang; CHECK:       loop.header:
55407142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
55507142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR_1:%.*]], align 4
55607142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
55707142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
55807142b30SJingu Kang; CHECK:       noclobber:
55907142b30SJingu Kang; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i32, i32* [[PTR_2:%.*]], i32 [[IV]]
56007142b30SJingu Kang; CHECK-NEXT:    store i32 [[LV]], i32* [[GEP_1]], align 4
56107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
56207142b30SJingu Kang; CHECK:       clobber:
56307142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
56407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
56507142b30SJingu Kang; CHECK:       loop.latch:
56607142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
56707142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
56807142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
56907142b30SJingu Kang; CHECK:       exit:
57007142b30SJingu Kang; CHECK-NEXT:    ret i32 10
57107142b30SJingu Kang;
57207142b30SJingu Kangentry:
57307142b30SJingu Kang  br label %loop.header
57407142b30SJingu Kang
57507142b30SJingu Kangloop.header:
57607142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
57707142b30SJingu Kang  %lv = load i32, i32* %ptr.1
57807142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
57907142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
58007142b30SJingu Kang
58107142b30SJingu Kangnoclobber:
58207142b30SJingu Kang  %gep.1 = getelementptr i32, i32* %ptr.2, i32 %iv
58307142b30SJingu Kang  store i32 %lv, i32* %gep.1
58407142b30SJingu Kang  br label %loop.latch
58507142b30SJingu Kang
58607142b30SJingu Kangclobber:
58707142b30SJingu Kang  call void @clobber()
58807142b30SJingu Kang  br label %loop.latch
58907142b30SJingu Kang
59007142b30SJingu Kangloop.latch:
59107142b30SJingu Kang  %c = icmp ult i32 %iv, %N
59207142b30SJingu Kang  %iv.next = add i32 %iv, 1
59307142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
59407142b30SJingu Kang
59507142b30SJingu Kangexit:
59607142b30SJingu Kang  ret i32 10
59707142b30SJingu Kang}
59807142b30SJingu Kang
59907142b30SJingu Kang; Make sure the duplicated instructions are moved to a preheader that always
60007142b30SJingu Kang; executes when the loop body also executes. Do not check the unswitched code,
60107142b30SJingu Kang; because it is already checked in the @partial_unswitch_true_successor test
60207142b30SJingu Kang; case.
60307142b30SJingu Kangdefine i32 @partial_unswitch_true_successor_preheader_insertion(i32* %ptr, i32 %N) {
60407142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_successor_preheader_insertion(
60507142b30SJingu Kang; CHECK-NEXT:  entry:
60607142b30SJingu Kang; CHECK-NEXT:    [[EC:%.*]] = icmp ne i32* [[PTR:%.*]], null
60707142b30SJingu Kang; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_PH:%.*]], label [[EXIT:%.*]]
60807142b30SJingu Kang; CHECK:       loop.ph:
609*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR]], align 4
610*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
611*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_PH_SPLIT_US:%.*]], label [[LOOP_PH_SPLIT:%.*]]
612*88b259c0SJingu Kang; CHECK:       loop.ph.split.us:
613*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
614*88b259c0SJingu Kang; CHECK:       loop.header.us:
615*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[LOOP_PH_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
616*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
617*88b259c0SJingu Kang; CHECK:       noclobber.us:
618*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
619*88b259c0SJingu Kang; CHECK:       loop.latch.us:
620*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
621*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
622*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_LOOPEXIT_SPLIT_US:%.*]]
623*88b259c0SJingu Kang; CHECK:       exit.loopexit.split.us:
624*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT_LOOPEXIT:%.*]]
625*88b259c0SJingu Kang; CHECK:       loop.ph.split:
62607142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
62707142b30SJingu Kang; CHECK:       loop.header:
628*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[LOOP_PH_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
62907142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
63007142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
63107142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
63207142b30SJingu Kang; CHECK:       noclobber:
63307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
63407142b30SJingu Kang; CHECK:       clobber:
63507142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
63607142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
63707142b30SJingu Kang; CHECK:       loop.latch:
638*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
63907142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
640*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT_SPLIT:%.*]]
641*88b259c0SJingu Kang; CHECK:       exit.loopexit.split:
642*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT_LOOPEXIT]]
64307142b30SJingu Kang; CHECK:       exit.loopexit:
64407142b30SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
64507142b30SJingu Kang; CHECK:       exit:
64607142b30SJingu Kang; CHECK-NEXT:    ret i32 10
64707142b30SJingu Kang;
64807142b30SJingu Kang
64907142b30SJingu Kangentry:
65007142b30SJingu Kang  %ec = icmp ne i32* %ptr, null
65107142b30SJingu Kang  br i1 %ec, label %loop.ph, label %exit
65207142b30SJingu Kang
65307142b30SJingu Kangloop.ph:
65407142b30SJingu Kang  br label %loop.header
65507142b30SJingu Kang
65607142b30SJingu Kangloop.header:
65707142b30SJingu Kang  %iv = phi i32 [ 0, %loop.ph ], [ %iv.next, %loop.latch ]
65807142b30SJingu Kang  %lv = load i32, i32* %ptr
65907142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
66007142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
66107142b30SJingu Kang
66207142b30SJingu Kangnoclobber:
66307142b30SJingu Kang  br label %loop.latch
66407142b30SJingu Kang
66507142b30SJingu Kangclobber:
66607142b30SJingu Kang  call void @clobber()
66707142b30SJingu Kang  br label %loop.latch
66807142b30SJingu Kang
66907142b30SJingu Kangloop.latch:
67007142b30SJingu Kang  %c = icmp ult i32 %iv, %N
67107142b30SJingu Kang  %iv.next = add i32 %iv, 1
67207142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
67307142b30SJingu Kang
67407142b30SJingu Kangexit:
67507142b30SJingu Kang  ret i32 10
67607142b30SJingu Kang}
67707142b30SJingu Kang
67807142b30SJingu Kang; Make sure the duplicated instructions are hoisted just before the branch of
67907142b30SJingu Kang; the preheader. Do not check the unswitched code, because it is already checked
68007142b30SJingu Kang; in the @partial_unswitch_true_successor test case
68107142b30SJingu Kangdefine i32 @partial_unswitch_true_successor_insert_point(i32* %ptr, i32 %N) {
68207142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_successor_insert_point(
68307142b30SJingu Kang; CHECK-NEXT:  entry:
68407142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
685*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
686*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
687*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
688*88b259c0SJingu Kang; CHECK:       entry.split.us:
689*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
690*88b259c0SJingu Kang; CHECK:       loop.header.us:
691*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
692*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
693*88b259c0SJingu Kang; CHECK:       noclobber.us:
694*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
695*88b259c0SJingu Kang; CHECK:       loop.latch.us:
696*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
697*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
698*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
699*88b259c0SJingu Kang; CHECK:       exit.split.us:
700*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
701*88b259c0SJingu Kang; CHECK:       entry.split:
70207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
70307142b30SJingu Kang; CHECK:       loop.header:
704*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
705*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
70607142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
70707142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
70807142b30SJingu Kang; CHECK:       noclobber:
70907142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
71007142b30SJingu Kang; CHECK:       clobber:
71107142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
71207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
71307142b30SJingu Kang; CHECK:       loop.latch:
714*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
71507142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
716*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
717*88b259c0SJingu Kang; CHECK:       exit.split:
718*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
71907142b30SJingu Kang; CHECK:       exit:
72007142b30SJingu Kang; CHECK-NEXT:    ret i32 10
72107142b30SJingu Kang;
72207142b30SJingu Kangentry:
72307142b30SJingu Kang  call void @clobber()
72407142b30SJingu Kang  br label %loop.header
72507142b30SJingu Kang
72607142b30SJingu Kangloop.header:
72707142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
72807142b30SJingu Kang  %lv = load i32, i32* %ptr
72907142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
73007142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
73107142b30SJingu Kang
73207142b30SJingu Kangnoclobber:
73307142b30SJingu Kang  br label %loop.latch
73407142b30SJingu Kang
73507142b30SJingu Kangclobber:
73607142b30SJingu Kang  call void @clobber()
73707142b30SJingu Kang  br label %loop.latch
73807142b30SJingu Kang
73907142b30SJingu Kangloop.latch:
74007142b30SJingu Kang  %c = icmp ult i32 %iv, %N
74107142b30SJingu Kang  %iv.next = add i32 %iv, 1
74207142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
74307142b30SJingu Kang
74407142b30SJingu Kangexit:
74507142b30SJingu Kang  ret i32 10
74607142b30SJingu Kang}
74707142b30SJingu Kang
74807142b30SJingu Kang; Make sure invariant instructions in the loop are also hoisted to the preheader.
74907142b30SJingu Kang; Do not check the unswitched code, because it is already checked in the
75007142b30SJingu Kang; @partial_unswitch_true_successor test case
75107142b30SJingu Kangdefine i32 @partial_unswitch_true_successor_hoist_invariant(i32* %ptr, i32 %N) {
75207142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_successor_hoist_invariant(
75307142b30SJingu Kang; CHECK-NEXT:  entry:
754*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 1
755*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4
756*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 100
757*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP2]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
758*88b259c0SJingu Kang; CHECK:       entry.split.us:
759*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
760*88b259c0SJingu Kang; CHECK:       loop.header.us:
761*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
762*88b259c0SJingu Kang; CHECK-NEXT:    br label [[NOCLOBBER_US:%.*]]
763*88b259c0SJingu Kang; CHECK:       noclobber.us:
764*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
765*88b259c0SJingu Kang; CHECK:       loop.latch.us:
766*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
767*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
768*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
769*88b259c0SJingu Kang; CHECK:       exit.split.us:
770*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
771*88b259c0SJingu Kang; CHECK:       entry.split:
77207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
77307142b30SJingu Kang; CHECK:       loop.header:
774*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
775*88b259c0SJingu Kang; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, i32* [[PTR]], i64 1
77607142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[GEP]], align 4
77707142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
77807142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
77907142b30SJingu Kang; CHECK:       noclobber:
78007142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
78107142b30SJingu Kang; CHECK:       clobber:
78207142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
78307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
78407142b30SJingu Kang; CHECK:       loop.latch:
785*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
78607142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
787*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
788*88b259c0SJingu Kang; CHECK:       exit.split:
789*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
79007142b30SJingu Kang; CHECK:       exit:
79107142b30SJingu Kang; CHECK-NEXT:    ret i32 10
79207142b30SJingu Kang;
79307142b30SJingu Kangentry:
79407142b30SJingu Kang  br label %loop.header
79507142b30SJingu Kang
79607142b30SJingu Kangloop.header:
79707142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
79807142b30SJingu Kang  %gep = getelementptr i32, i32* %ptr, i64 1
79907142b30SJingu Kang  %lv = load i32, i32* %gep
80007142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
80107142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
80207142b30SJingu Kang
80307142b30SJingu Kangnoclobber:
80407142b30SJingu Kang  br label %loop.latch
80507142b30SJingu Kang
80607142b30SJingu Kangclobber:
80707142b30SJingu Kang  call void @clobber()
80807142b30SJingu Kang  br label %loop.latch
80907142b30SJingu Kang
81007142b30SJingu Kangloop.latch:
81107142b30SJingu Kang  %c = icmp ult i32 %iv, %N
81207142b30SJingu Kang  %iv.next = add i32 %iv, 1
81307142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
81407142b30SJingu Kang
81507142b30SJingu Kangexit:
81607142b30SJingu Kang  ret i32 10
81707142b30SJingu Kang}
81807142b30SJingu Kang
81907142b30SJingu Kang; Do not unswitch if the condition depends on an atomic load. Duplicating such
82007142b30SJingu Kang; loads is not safe.
82107142b30SJingu Kangdefine i32 @no_partial_unswitch_atomic_load_unordered(i32* %ptr, i32 %N) {
82207142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_atomic_load_unordered(
82307142b30SJingu Kang; CHECK-NEXT:  entry:
82407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
82507142b30SJingu Kang; CHECK:       loop.header:
82607142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
82707142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] unordered, align 4
82807142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
82907142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
83007142b30SJingu Kang; CHECK:       noclobber:
83107142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
83207142b30SJingu Kang; CHECK:       clobber:
83307142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
83407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
83507142b30SJingu Kang; CHECK:       loop.latch:
83607142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
83707142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
83807142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
83907142b30SJingu Kang; CHECK:       exit:
84007142b30SJingu Kang; CHECK-NEXT:    ret i32 10
84107142b30SJingu Kang;
84207142b30SJingu Kangentry:
84307142b30SJingu Kang  br label %loop.header
84407142b30SJingu Kang
84507142b30SJingu Kangloop.header:
84607142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
84707142b30SJingu Kang  %lv = load atomic i32, i32* %ptr unordered, align 4
84807142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
84907142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
85007142b30SJingu Kang
85107142b30SJingu Kangnoclobber:
85207142b30SJingu Kang  br label %loop.latch
85307142b30SJingu Kang
85407142b30SJingu Kangclobber:
85507142b30SJingu Kang  call void @clobber()
85607142b30SJingu Kang  br label %loop.latch
85707142b30SJingu Kang
85807142b30SJingu Kangloop.latch:
85907142b30SJingu Kang  %c = icmp ult i32 %iv, %N
86007142b30SJingu Kang  %iv.next = add i32 %iv, 1
86107142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
86207142b30SJingu Kang
86307142b30SJingu Kangexit:
86407142b30SJingu Kang  ret i32 10
86507142b30SJingu Kang}
86607142b30SJingu Kang
86707142b30SJingu Kang; Do not unswitch if the condition depends on an atomic load. Duplicating such
86807142b30SJingu Kang; loads is not safe.
86907142b30SJingu Kangdefine i32 @no_partial_unswitch_atomic_load_monotonic(i32* %ptr, i32 %N) {
87007142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_atomic_load_monotonic(
87107142b30SJingu Kang; CHECK-NEXT:  entry:
87207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
87307142b30SJingu Kang; CHECK:       loop.header:
87407142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
87507142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load atomic i32, i32* [[PTR:%.*]] monotonic, align 4
87607142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
87707142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
87807142b30SJingu Kang; CHECK:       noclobber:
87907142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
88007142b30SJingu Kang; CHECK:       clobber:
88107142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
88207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
88307142b30SJingu Kang; CHECK:       loop.latch:
88407142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
88507142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
88607142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
88707142b30SJingu Kang; CHECK:       exit:
88807142b30SJingu Kang; CHECK-NEXT:    ret i32 10
88907142b30SJingu Kang;
89007142b30SJingu Kangentry:
89107142b30SJingu Kang  br label %loop.header
89207142b30SJingu Kang
89307142b30SJingu Kangloop.header:
89407142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
89507142b30SJingu Kang  %lv = load atomic i32, i32* %ptr monotonic, align 4
89607142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
89707142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
89807142b30SJingu Kang
89907142b30SJingu Kangnoclobber:
90007142b30SJingu Kang  br label %loop.latch
90107142b30SJingu Kang
90207142b30SJingu Kangclobber:
90307142b30SJingu Kang  call void @clobber()
90407142b30SJingu Kang  br label %loop.latch
90507142b30SJingu Kang
90607142b30SJingu Kangloop.latch:
90707142b30SJingu Kang  %c = icmp ult i32 %iv, %N
90807142b30SJingu Kang  %iv.next = add i32 %iv, 1
90907142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
91007142b30SJingu Kang
91107142b30SJingu Kangexit:
91207142b30SJingu Kang  ret i32 10
91307142b30SJingu Kang}
91407142b30SJingu Kang
91507142b30SJingu Kang
91607142b30SJingu Kangdeclare i32 @get_value()
91707142b30SJingu Kang
91807142b30SJingu Kang; Do not unswitch if the condition depends on a call, that may clobber memory.
91907142b30SJingu Kang; Duplicating such a call is not safe.
92007142b30SJingu Kangdefine i32 @no_partial_unswitch_cond_call(i32* %ptr, i32 %N) {
92107142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_cond_call(
92207142b30SJingu Kang; CHECK-NEXT:  entry:
92307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
92407142b30SJingu Kang; CHECK:       loop.header:
92507142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
92607142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = call i32 @get_value()
92707142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
92807142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[CLOBBER:%.*]]
92907142b30SJingu Kang; CHECK:       noclobber:
93007142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
93107142b30SJingu Kang; CHECK:       clobber:
93207142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
93307142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
93407142b30SJingu Kang; CHECK:       loop.latch:
93507142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
93607142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
93707142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
93807142b30SJingu Kang; CHECK:       exit:
93907142b30SJingu Kang; CHECK-NEXT:    ret i32 10
94007142b30SJingu Kang;
94107142b30SJingu Kangentry:
94207142b30SJingu Kang  br label %loop.header
94307142b30SJingu Kang
94407142b30SJingu Kangloop.header:
94507142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
94607142b30SJingu Kang  %lv = call i32 @get_value()
94707142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
94807142b30SJingu Kang  br i1 %sc, label %noclobber, label %clobber
94907142b30SJingu Kang
95007142b30SJingu Kangnoclobber:
95107142b30SJingu Kang  br label %loop.latch
95207142b30SJingu Kang
95307142b30SJingu Kangclobber:
95407142b30SJingu Kang  call void @clobber()
95507142b30SJingu Kang  br label %loop.latch
95607142b30SJingu Kang
95707142b30SJingu Kangloop.latch:
95807142b30SJingu Kang  %c = icmp ult i32 %iv, %N
95907142b30SJingu Kang  %iv.next = add i32 %iv, 1
96007142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
96107142b30SJingu Kang
96207142b30SJingu Kangexit:
96307142b30SJingu Kang  ret i32 10
96407142b30SJingu Kang}
96507142b30SJingu Kang
96607142b30SJingu Kangdefine i32 @no_partial_unswitch_true_successor_exit(i32* %ptr, i32 %N) {
96707142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_true_successor_exit(
96807142b30SJingu Kang; CHECK-NEXT:  entry:
96907142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
97007142b30SJingu Kang; CHECK:       loop.header:
97107142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
97207142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
97307142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
97407142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[EXIT:%.*]], label [[CLOBBER:%.*]]
97507142b30SJingu Kang; CHECK:       clobber:
97607142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
97707142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
97807142b30SJingu Kang; CHECK:       loop.latch:
97907142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
98007142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
98107142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT]]
98207142b30SJingu Kang; CHECK:       exit:
98307142b30SJingu Kang; CHECK-NEXT:    ret i32 10
98407142b30SJingu Kang;
98507142b30SJingu Kangentry:
98607142b30SJingu Kang  br label %loop.header
98707142b30SJingu Kang
98807142b30SJingu Kangloop.header:
98907142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
99007142b30SJingu Kang  %lv = load i32, i32* %ptr
99107142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
99207142b30SJingu Kang  br i1 %sc, label %exit, label %clobber
99307142b30SJingu Kang
99407142b30SJingu Kangclobber:
99507142b30SJingu Kang  call void @clobber()
99607142b30SJingu Kang  br label %loop.latch
99707142b30SJingu Kang
99807142b30SJingu Kangloop.latch:
99907142b30SJingu Kang  %c = icmp ult i32 %iv, %N
100007142b30SJingu Kang  %iv.next = add i32 %iv, 1
100107142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
100207142b30SJingu Kang
100307142b30SJingu Kangexit:
100407142b30SJingu Kang  ret i32 10
100507142b30SJingu Kang}
100607142b30SJingu Kang
100707142b30SJingu Kangdefine i32 @no_partial_unswitch_true_same_successor(i32* %ptr, i32 %N) {
100807142b30SJingu Kang; CHECK-LABEL: @no_partial_unswitch_true_same_successor(
100907142b30SJingu Kang; CHECK-NEXT:  entry:
101007142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
101107142b30SJingu Kang; CHECK:       loop.header:
101207142b30SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
101307142b30SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR:%.*]], align 4
101407142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
101507142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[NOCLOBBER:%.*]], label [[NOCLOBBER]]
101607142b30SJingu Kang; CHECK:       noclobber:
101707142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
101807142b30SJingu Kang; CHECK:       loop.latch:
101907142b30SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
102007142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
102107142b30SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
102207142b30SJingu Kang; CHECK:       exit:
102307142b30SJingu Kang; CHECK-NEXT:    ret i32 10
102407142b30SJingu Kang;
102507142b30SJingu Kangentry:
102607142b30SJingu Kang  br label %loop.header
102707142b30SJingu Kang
102807142b30SJingu Kangloop.header:
102907142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
103007142b30SJingu Kang  %lv = load i32, i32* %ptr
103107142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
103207142b30SJingu Kang  br i1 %sc, label %noclobber, label %noclobber
103307142b30SJingu Kang
103407142b30SJingu Kangnoclobber:
103507142b30SJingu Kang  br label %loop.latch
103607142b30SJingu Kang
103707142b30SJingu Kangloop.latch:
103807142b30SJingu Kang  %c = icmp ult i32 %iv, %N
103907142b30SJingu Kang  %iv.next = add i32 %iv, 1
104007142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
104107142b30SJingu Kang
104207142b30SJingu Kangexit:
104307142b30SJingu Kang  ret i32 10
104407142b30SJingu Kang}
104507142b30SJingu Kang
104607142b30SJingu Kangdefine i32 @partial_unswitch_true_to_latch(i32* %ptr, i32 %N) {
104707142b30SJingu Kang; CHECK-LABEL: @partial_unswitch_true_to_latch(
104807142b30SJingu Kang; CHECK-NEXT:  entry:
1049*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[PTR:%.*]], align 4
1050*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 100
1051*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1052*88b259c0SJingu Kang; CHECK:       entry.split.us:
1053*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER_US:%.*]]
1054*88b259c0SJingu Kang; CHECK:       loop.header.us:
1055*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ], [ [[IV_NEXT_US:%.*]], [[LOOP_LATCH_US:%.*]] ]
1056*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
1057*88b259c0SJingu Kang; CHECK:       loop.latch.us:
1058*88b259c0SJingu Kang; CHECK-NEXT:    [[C_US:%.*]] = icmp ult i32 [[IV_US]], [[N:%.*]]
1059*88b259c0SJingu Kang; CHECK-NEXT:    [[IV_NEXT_US]] = add i32 [[IV_US]], 1
1060*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C_US]], label [[LOOP_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
1061*88b259c0SJingu Kang; CHECK:       exit.split.us:
1062*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
1063*88b259c0SJingu Kang; CHECK:       entry.split:
106407142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
106507142b30SJingu Kang; CHECK:       loop.header:
1066*88b259c0SJingu Kang; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
1067*88b259c0SJingu Kang; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[PTR]], align 4
106807142b30SJingu Kang; CHECK-NEXT:    [[SC:%.*]] = icmp eq i32 [[LV]], 100
106907142b30SJingu Kang; CHECK-NEXT:    br i1 [[SC]], label [[LOOP_LATCH]], label [[CLOBBER:%.*]]
107007142b30SJingu Kang; CHECK:       clobber:
107107142b30SJingu Kang; CHECK-NEXT:    call void @clobber()
107207142b30SJingu Kang; CHECK-NEXT:    br label [[LOOP_LATCH]]
107307142b30SJingu Kang; CHECK:       loop.latch:
1074*88b259c0SJingu Kang; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N]]
107507142b30SJingu Kang; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
1076*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[C]], label [[LOOP_HEADER]], label [[EXIT_SPLIT:%.*]]
1077*88b259c0SJingu Kang; CHECK:       exit.split:
1078*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT]]
107907142b30SJingu Kang; CHECK:       exit:
108007142b30SJingu Kang; CHECK-NEXT:    ret i32 10
108107142b30SJingu Kang;
108207142b30SJingu Kangentry:
108307142b30SJingu Kang  br label %loop.header
108407142b30SJingu Kang
108507142b30SJingu Kangloop.header:
108607142b30SJingu Kang  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
108707142b30SJingu Kang  %lv = load i32, i32* %ptr
108807142b30SJingu Kang  %sc = icmp eq i32 %lv, 100
108907142b30SJingu Kang  br i1 %sc, label %loop.latch, label %clobber
109007142b30SJingu Kang
109107142b30SJingu Kangclobber:
109207142b30SJingu Kang  call void @clobber()
109307142b30SJingu Kang  br label %loop.latch
109407142b30SJingu Kang
109507142b30SJingu Kangloop.latch:
109607142b30SJingu Kang  %c = icmp ult i32 %iv, %N
109707142b30SJingu Kang  %iv.next = add i32 %iv, 1
109807142b30SJingu Kang  br i1 %c, label %loop.header, label %exit
109907142b30SJingu Kang
110007142b30SJingu Kangexit:
110107142b30SJingu Kang  ret i32 10
110207142b30SJingu Kang}
1103*88b259c0SJingu Kang
1104*88b259c0SJingu Kang; There could be multiple unswitch candidates which include partially invariant
1105*88b259c0SJingu Kang; condition. When the exiting block is selected as best unswitch one, clone loop
1106*88b259c0SJingu Kang; blocks.
1107*88b259c0SJingu Kangdefine i32 @partial_unswitch_exiting_block_with_multiple_unswitch_candidates(i32 %0, i32 %1, i32* %ptr) {
1108*88b259c0SJingu Kang; CHECK-LABEL: @partial_unswitch_exiting_block_with_multiple_unswitch_candidates(
1109*88b259c0SJingu Kang; CHECK-NEXT:  entry:
1110*88b259c0SJingu Kang; CHECK-NEXT:    [[EXIT_COND:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
1111*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[EXIT_COND]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1112*88b259c0SJingu Kang; CHECK:       entry.split.us:
1113*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[PTR:%.*]], align 16
1114*88b259c0SJingu Kang; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[TMP2]], 41
1115*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[TMP3]], label [[ENTRY_SPLIT_US_SPLIT:%.*]], label [[ENTRY_SPLIT_US_SPLIT_US:%.*]]
1116*88b259c0SJingu Kang; CHECK:       entry.split.us.split.us:
1117*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_US_US:%.*]]
1118*88b259c0SJingu Kang; CHECK:       loop.us.us:
1119*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXITING_US_US:%.*]]
1120*88b259c0SJingu Kang; CHECK:       exiting.us.us:
1121*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_US_US]]
1122*88b259c0SJingu Kang; CHECK:       entry.split.us.split:
1123*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_US:%.*]]
1124*88b259c0SJingu Kang; CHECK:       loop.us:
1125*88b259c0SJingu Kang; CHECK-NEXT:    [[VAL_US:%.*]] = load i32, i32* [[PTR]], align 16
1126*88b259c0SJingu Kang; CHECK-NEXT:    [[IF_COND_US:%.*]] = icmp ult i32 [[VAL_US]], 41
1127*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[IF_COND_US]], label [[IF_THEN_US:%.*]], label [[EXITING_US:%.*]]
1128*88b259c0SJingu Kang; CHECK:       if.then.us:
1129*88b259c0SJingu Kang; CHECK-NEXT:    store i32 [[TMP1:%.*]], i32* [[PTR]], align 16
1130*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXITING_US]]
1131*88b259c0SJingu Kang; CHECK:       exiting.us:
1132*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP_US]]
1133*88b259c0SJingu Kang; CHECK:       entry.split:
1134*88b259c0SJingu Kang; CHECK-NEXT:    br label [[LOOP:%.*]]
1135*88b259c0SJingu Kang; CHECK:       loop:
1136*88b259c0SJingu Kang; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR]], align 16
1137*88b259c0SJingu Kang; CHECK-NEXT:    [[IF_COND:%.*]] = icmp ult i32 [[VAL]], 41
1138*88b259c0SJingu Kang; CHECK-NEXT:    br i1 [[IF_COND]], label [[IF_THEN:%.*]], label [[EXITING:%.*]]
1139*88b259c0SJingu Kang; CHECK:       if.then:
1140*88b259c0SJingu Kang; CHECK-NEXT:    store i32 [[TMP1]], i32* [[PTR]], align 16
1141*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXITING]]
1142*88b259c0SJingu Kang; CHECK:       exiting:
1143*88b259c0SJingu Kang; CHECK-NEXT:    br label [[EXIT:%.*]]
1144*88b259c0SJingu Kang; CHECK:       exit:
1145*88b259c0SJingu Kang; CHECK-NEXT:    [[RET_VAL:%.*]] = phi i32 [ 1, [[EXITING]] ]
1146*88b259c0SJingu Kang; CHECK-NEXT:    ret i32 [[RET_VAL]]
1147*88b259c0SJingu Kang;
1148*88b259c0SJingu Kangentry:
1149*88b259c0SJingu Kang  %exit.cond = icmp ne i32 %0, 0
1150*88b259c0SJingu Kang  br label %loop
1151*88b259c0SJingu Kang
1152*88b259c0SJingu Kangloop:
1153*88b259c0SJingu Kang  %val = load i32, i32* %ptr, align 16
1154*88b259c0SJingu Kang  %if.cond = icmp ult i32 %val, 41
1155*88b259c0SJingu Kang  br i1 %if.cond, label %if.then, label %exiting
1156*88b259c0SJingu Kang
1157*88b259c0SJingu Kangif.then:
1158*88b259c0SJingu Kang  store i32 %1, i32* %ptr, align 16
1159*88b259c0SJingu Kang  br label %exiting
1160*88b259c0SJingu Kang
1161*88b259c0SJingu Kangexiting:
1162*88b259c0SJingu Kang  br i1 %exit.cond, label %loop, label %exit
1163*88b259c0SJingu Kang
1164*88b259c0SJingu Kangexit:
1165*88b259c0SJingu Kang  %ret.val = phi i32 [ 1, %exiting ]
1166*88b259c0SJingu Kang  ret i32 %ret.val
1167*88b259c0SJingu Kang}
1168