1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -loop-rotate -o - -verify-loop-info -verify-dom-info | FileCheck %s
3
4@d = external global i64, align 8
5@f = external global i32, align 4
6@g = external global i32, align 4
7@i = external global i32, align 4
8@h = external global i32, align 4
9
10define i32 @o() #0 {
11; CHECK-LABEL: @o(
12; CHECK-NEXT:    [[TMP1:%.*]] = alloca [1 x i32], align 4
13; CHECK-NEXT:    [[TMP2:%.*]] = load i8*, i8** bitcast (i64* @d to i8**), align 8
14; CHECK-NEXT:    [[TMP3:%.*]] = load i32, i32* @f, align 4
15; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
16; CHECK-NEXT:    br i1 [[TMP4]], label [[TMP17:%.*]], label [[DOTLR_PH4:%.*]]
17; CHECK:       .lr.ph4:
18; CHECK-NEXT:    br label [[TMP5:%.*]]
19; CHECK:       5:
20; CHECK-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP3]], [[DOTLR_PH4]] ], [ [[TMP15:%.*]], [[M_EXIT:%.*]] ]
21; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i32 [[TMP6]], 4
22; CHECK-NEXT:    [[TMP8:%.*]] = zext i1 [[TMP7]] to i32
23; CHECK-NEXT:    store i32 [[TMP8]], i32* @g, align 4
24; CHECK-NEXT:    [[TMP9:%.*]] = bitcast [1 x i32]* [[TMP1]] to i8*
25; CHECK-NEXT:    [[TMP10:%.*]] = call i32 @n(i8* nonnull [[TMP9]], i8* [[TMP2]])
26; CHECK-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
27; CHECK-NEXT:    br i1 [[TMP11]], label [[THREAD_PRE_SPLIT:%.*]], label [[DOT_CRIT_EDGE:%.*]]
28; CHECK:       thread-pre-split:
29; CHECK-NEXT:    [[DOTPR:%.*]] = load i32, i32* @i, align 4
30; CHECK-NEXT:    [[TMP12:%.*]] = icmp eq i32 [[DOTPR]], 0
31; CHECK-NEXT:    br i1 [[TMP12]], label [[M_EXIT]], label [[DOTLR_PH:%.*]]
32; CHECK:       .lr.ph:
33; CHECK-NEXT:    br label [[TMP13:%.*]]
34; CHECK:       13:
35; CHECK-NEXT:    [[DOT11:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP14:%.*]], [[J_EXIT_I:%.*]] ]
36; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #[[ATTR1:[0-9]+]]
37; CHECK-NEXT:    to label [[J_EXIT_I]] [label %.m.exit_crit_edge]
38; CHECK:       j.exit.i:
39; CHECK-NEXT:    [[TMP14]] = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #[[ATTR2:[0-9]+]]
40; CHECK-NEXT:    br i1 [[TMP12]], label [[DOTM_EXIT_CRIT_EDGE2:%.*]], label [[TMP13]]
41; CHECK:       .m.exit_crit_edge:
42; CHECK-NEXT:    [[SPLIT:%.*]] = phi i32 [ [[DOT11]], [[TMP13]] ]
43; CHECK-NEXT:    br label [[M_EXIT]]
44; CHECK:       .m.exit_crit_edge2:
45; CHECK-NEXT:    [[SPLIT3:%.*]] = phi i32 [ [[TMP14]], [[J_EXIT_I]] ]
46; CHECK-NEXT:    br label [[M_EXIT]]
47; CHECK:       m.exit:
48; CHECK-NEXT:    [[DOT1_LCSSA:%.*]] = phi i32 [ [[SPLIT]], [[DOTM_EXIT_CRIT_EDGE:%.*]] ], [ [[SPLIT3]], [[DOTM_EXIT_CRIT_EDGE2]] ], [ undef, [[THREAD_PRE_SPLIT]] ]
49; CHECK-NEXT:    store i32 [[DOT1_LCSSA]], i32* @h, align 4
50; CHECK-NEXT:    [[TMP15]] = load i32, i32* @f, align 4
51; CHECK-NEXT:    [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
52; CHECK-NEXT:    br i1 [[TMP16]], label [[DOT_CRIT_EDGE5:%.*]], label [[TMP5]]
53; CHECK:       ._crit_edge:
54; CHECK-NEXT:    br label [[TMP17]]
55; CHECK:       ._crit_edge5:
56; CHECK-NEXT:    br label [[TMP17]]
57; CHECK:       17:
58; CHECK-NEXT:    ret i32 undef
59;
60  %1 = alloca [1 x i32], align 4
61  %2 = load i8*, i8** bitcast (i64* @d to i8**), align 8
62  br label %3
63
64; <label>:3:                                      ; preds = %m.exit, %0
65  %4 = load i32, i32* @f, align 4
66  %5 = icmp eq i32 %4, 0
67  br i1 %5, label %16, label %6
68
69; <label>:6:                                      ; preds = %3
70  %7 = icmp ult i32 %4, 4
71  %8 = zext i1 %7 to i32
72  store i32 %8, i32* @g, align 4
73  %9 = bitcast [1 x i32]* %1 to i8*
74  %10 = call i32 @n(i8* nonnull %9, i8* %2)
75  %11 = icmp eq i32 %10, 0
76  br i1 %11, label %thread-pre-split, label %16
77
78thread-pre-split:                                 ; preds = %6
79  %.pr = load i32, i32* @i, align 4
80  br label %12
81
82; <label>:12:                                     ; preds = %j.exit.i, %thread-pre-split
83  %.1 = phi i32 [ %15, %j.exit.i ], [ undef, %thread-pre-split ]
84  %13 = icmp eq i32 %.pr, 0
85  br i1 %13, label %m.exit, label %14
86
87; <label>:14:                                     ; preds = %12
88  callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"() #1
89  to label %j.exit.i [label %m.exit]
90
91j.exit.i:                                         ; preds = %14
92  %15 = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
93  br label %12
94
95m.exit:                                           ; preds = %14, %12
96  %.1.lcssa = phi i32 [ %.1, %14 ], [ %.1, %12 ]
97  store i32 %.1.lcssa, i32* @h, align 4
98  br label %3
99
100; <label>:16:                                     ; preds = %6, %3
101  ret i32 undef
102}
103
104declare i32 @n(i8*, i8*)  #0
105
106attributes #0 = { "use-soft-float"="false" }
107attributes #1 = { nounwind }
108attributes #2 = { nounwind readnone }
109