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 ; RUN: opt < %s -S -loop-rotate -o - -verify-loop-info -verify-dom-info -enable-mssa-loop-dependency=true | FileCheck %s
5 @d = external global i64, align 8
6 @f = external global i32, align 4
7 @g = external global i32, align 4
8 @i = external global i32, align 4
9 @h = external global i32, align 4
13 ; CHECK-NEXT: [[TMP1:%.*]] = alloca [1 x i32], align 4
14 ; CHECK-NEXT: [[TMP2:%.*]] = load i8*, i8** bitcast (i64* @d to i8**), align 8
15 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @f, align 4
16 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0
17 ; CHECK-NEXT: br i1 [[TMP4]], label [[TMP17:%.*]], label [[DOTLR_PH2:%.*]]
19 ; CHECK-NEXT: br label [[TMP5:%.*]]
20 ; CHECK: [[TMP6:%.*]] = phi i32 [ [[TMP3]], [[DOTLR_PH2]] ], [ [[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:%.*]]
33 ; CHECK-NEXT: br label [[TMP13:%.*]]
34 ; CHECK: [[DOT11:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP14:%.*]], [[J_EXIT_I:%.*]] ]
35 ; CHECK-NEXT: callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, [[M_EXIT]])) #1
36 ; CHECK-NEXT: to label [[J_EXIT_I]] [label %m.exit]
38 ; CHECK-NEXT: [[TMP14]] = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
39 ; CHECK-NEXT: br i1 [[TMP12]], label [[DOTM_EXIT_CRIT_EDGE:%.*]], label [[TMP13]]
40 ; CHECK: .m.exit_crit_edge:
41 ; CHECK-NEXT: [[SPLIT:%.*]] = phi i32 [ [[TMP14]], [[J_EXIT_I]] ]
42 ; CHECK-NEXT: br label [[M_EXIT]]
44 ; CHECK-NEXT: [[DOT1_LCSSA:%.*]] = phi i32 [ [[DOT11]], [[TMP13]] ], [ [[SPLIT]], [[DOTM_EXIT_CRIT_EDGE]] ], [ undef, [[THREAD_PRE_SPLIT]] ]
45 ; CHECK-NEXT: store i32 [[DOT1_LCSSA]], i32* @h, align 4
46 ; CHECK-NEXT: [[TMP15]] = load i32, i32* @f, align 4
47 ; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], 0
48 ; CHECK-NEXT: br i1 [[TMP16]], label [[DOT_CRIT_EDGE3:%.*]], label [[TMP5]]
50 ; CHECK-NEXT: br label [[TMP17]]
51 ; CHECK: ._crit_edge3:
52 ; CHECK-NEXT: br label [[TMP17]]
53 ; CHECK: ret i32 undef
55 %1 = alloca [1 x i32], align 4
56 %2 = load i8*, i8** bitcast (i64* @d to i8**), align 8
59 ; <label>:3: ; preds = %m.exit, %0
60 %4 = load i32, i32* @f, align 4
61 %5 = icmp eq i32 %4, 0
62 br i1 %5, label %16, label %6
64 ; <label>:6: ; preds = %3
65 %7 = icmp ult i32 %4, 4
66 %8 = zext i1 %7 to i32
67 store i32 %8, i32* @g, align 4
68 %9 = bitcast [1 x i32]* %1 to i8*
69 %10 = call i32 @n(i8* nonnull %9, i8* %2)
70 %11 = icmp eq i32 %10, 0
71 br i1 %11, label %thread-pre-split, label %16
73 thread-pre-split: ; preds = %6
74 %.pr = load i32, i32* @i, align 4
77 ; <label>:12: ; preds = %j.exit.i, %thread-pre-split
78 %.1 = phi i32 [ %15, %j.exit.i ], [ undef, %thread-pre-split ]
79 %13 = icmp eq i32 %.pr, 0
80 br i1 %13, label %m.exit, label %14
82 ; <label>:14: ; preds = %12
83 callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@o, %m.exit)) #1
84 to label %j.exit.i [label %m.exit]
86 j.exit.i: ; preds = %14
87 %15 = tail call i32 asm "", "={ax},~{dirflag},~{fpsr},~{flags}"() #2
90 m.exit: ; preds = %14, %12
91 %.1.lcssa = phi i32 [ %.1, %14 ], [ %.1, %12 ]
92 store i32 %.1.lcssa, i32* @h, align 4
95 ; <label>:16: ; preds = %6, %3
99 declare i32 @n(i8*, i8*) #0
101 attributes #0 = { "use-soft-float"="false" }
102 attributes #1 = { nounwind }
103 attributes #2 = { nounwind readnone }