1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: -p
2; RUN: opt < %s -indvars -S | FileCheck %s
3; RUN: opt < %s -passes=indvars -S | FileCheck %s
4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
5
6declare i1 @foo(i8*, i8*)
7declare i1 @bar()
8declare i1 @baz()
9
10define i1 @kill_backedge_and_phis(i8* align 1 %lhs, i8* align 1 %rhs, i32 %len) {
11; CHECK-LABEL: @kill_backedge_and_phis(
12; CHECK-NEXT:  entry:
13; CHECK-NEXT:    %length_not_zero = icmp ne i32 %len, 0
14; CHECK-NEXT:    br i1 %length_not_zero, label %loop_preheader, label %exit
15; CHECK:       loop_preheader:
16; CHECK-NEXT:    br label %loop
17; CHECK:       loop:
18; CHECK-NEXT:    %iv.next = add nuw nsw i32 0, 1
19; CHECK-NEXT:    %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 0
20; CHECK-NEXT:    %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 0
21; CHECK-NEXT:    %result = call i1 @foo(i8* %left_ptr, i8* %right_ptr)
22; CHECK-NEXT:    br i1 %result, label %exiting_1, label %exit.loopexit
23; CHECK:       exiting_1:
24; CHECK-NEXT:    %iv.wide.is_not_zero = icmp ne i64 0, 0
25; CHECK-NEXT:    br i1 false, label %exiting_2, label %exit.loopexit
26; CHECK:       exiting_2:
27; CHECK-NEXT:    %bar_ret = call i1 @bar()
28; CHECK-NEXT:    br i1 %bar_ret, label %exit.loopexit, label %exiting_3
29; CHECK:       exiting_3:
30; CHECK-NEXT:    %baz_ret = call i1 @baz()
31; CHECK-NEXT:    %continue = icmp ne i32 %iv.next, %len
32; CHECK-NEXT:    %or.cond = select i1 %baz_ret, i1 %continue, i1 false
33; CHECK-NEXT:    br i1 %or.cond, label %loop, label %exit.loopexit
34; CHECK:       exit.loopexit:
35; CHECK-NEXT:    %val.ph = phi i1 [ %baz_ret, %exiting_3 ], [ %bar_ret, %exiting_2 ], [ %iv.wide.is_not_zero, %exiting_1 ], [ %result, %loop ]
36; CHECK-NEXT:    br label %exit
37; CHECK:       exit:
38; CHECK-NEXT:    %val = phi i1 [ false, %entry ], [ %val.ph, %exit.loopexit ]
39; CHECK-NEXT:    ret i1 %val
40;
41entry:
42  %length_not_zero = icmp ne i32 %len, 0
43  br i1 %length_not_zero, label %loop_preheader, label %exit
44
45loop_preheader:
46  br label %loop
47
48loop:
49  %iv = phi i32 [ 0, %loop_preheader ], [ %iv.next, %latch ]
50  %iv.wide = phi i64 [ 0, %loop_preheader ], [ %iv.wide.next, %latch ]
51  %iv.next = add i32 %iv, 1
52  %iv.wide.next = add i64 %iv.wide, 1
53  %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 %iv
54  %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 %iv
55  %result = call i1 @foo(i8* %left_ptr, i8* %right_ptr)
56  br i1 %result, label %exiting_1, label %exit
57
58exiting_1:
59  %iv.wide.is_not_zero = icmp ne i64 %iv.wide, 0
60  br i1 %iv.wide.is_not_zero, label %exiting_2, label %exit
61
62exiting_2:
63  %bar_ret = call i1 @bar()
64  br i1 %bar_ret, label %exit, label %exiting_3
65
66exiting_3:
67  %baz_ret = call i1 @baz()
68  br i1 %baz_ret, label %latch, label %exit
69
70latch:
71  %continue = icmp ne i32 %iv.next, %len
72  br i1 %continue, label %loop, label %exit
73
74exit:
75  %val = phi i1 [ %result, %loop ], [ %iv.wide.is_not_zero, %exiting_1 ],
76  [ %bar_ret, %exiting_2 ], [ %baz_ret, %exiting_3 ],
77  [ %baz_ret, %latch ], [ 0, %entry ]
78  ret i1 %val
79}
80
81define i1 @siblings(i8* align 1 %lhs, i8* align 1 %rhs, i32 %len) {
82; CHECK-LABEL: @siblings(
83; CHECK-NEXT:  entry:
84; CHECK-NEXT:    %length_not_zero = icmp ne i32 %len, 0
85; CHECK-NEXT:    br i1 %length_not_zero, label %weird_loop.preheader, label %exit
86; CHECK:       weird_loop.preheader:
87; CHECK-NEXT:    br label %weird_loop
88; CHECK:       weird_loop:
89; CHECK-NEXT:    %weird.iv = phi i32 [ %weird.iv.next, %weird_loop ], [ 0, %weird_loop.preheader ]
90; CHECK-NEXT:    %weird.iv.next = add i32 %weird.iv, 1
91; CHECK-NEXT:    %weird.iv.wide = zext i32 %weird.iv to i64
92; CHECK-NEXT:    %weird.cond = call i1 @bar()
93; CHECK-NEXT:    br i1 %weird.cond, label %weird_loop, label %loop.preheader
94; CHECK:       loop.preheader:
95; CHECK-NEXT:    %weird.iv.lcssa = phi i32 [ %weird.iv, %weird_loop ]
96; CHECK-NEXT:    %weird.iv.wide.lcssa = phi i64 [ %weird.iv.wide, %weird_loop ]
97; CHECK-NEXT:    br label %loop
98; CHECK:       loop:
99; CHECK-NEXT:    %iv.next = add i32 %weird.iv.lcssa, 1
100; CHECK-NEXT:    %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 %weird.iv.lcssa
101; CHECK-NEXT:    %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 %weird.iv.lcssa
102; CHECK-NEXT:    %result = call i1 @foo(i8* %left_ptr, i8* %right_ptr)
103; CHECK-NEXT:    br i1 %result, label %exiting_1, label %exit.loopexit
104; CHECK:       exiting_1:
105; CHECK-NEXT:    %iv.wide.is_not_zero = icmp ne i64 %weird.iv.wide.lcssa, %weird.iv.wide.lcssa
106; CHECK-NEXT:    br i1 false, label %exiting_2, label %exit.loopexit
107; CHECK:       exiting_2:
108; CHECK-NEXT:    %bar_ret = call i1 @bar()
109; CHECK-NEXT:    br i1 %bar_ret, label %exit.loopexit, label %exiting_3
110; CHECK:       exiting_3:
111; CHECK-NEXT:    %baz_ret = call i1 @baz()
112; CHECK-NEXT:    %continue = icmp ne i32 %iv.next, %len
113; CHECK-NEXT:    %or.cond = select i1 %baz_ret, i1 %continue, i1 false
114; CHECK-NEXT:    br i1 %or.cond, label %loop, label %exit.loopexit
115; CHECK:       exit.loopexit:
116; CHECK-NEXT:    %val.ph = phi i1 [ %baz_ret, %exiting_3 ], [ %bar_ret, %exiting_2 ], [ %iv.wide.is_not_zero, %exiting_1 ], [ %result, %loop ]
117; CHECK-NEXT:    br label %exit
118; CHECK:       exit:
119; CHECK-NEXT:    %val = phi i1 [ false, %entry ], [ %val.ph, %exit.loopexit ]
120; CHECK-NEXT:    ret i1 %val
121;
122entry:
123  %length_not_zero = icmp ne i32 %len, 0
124  br i1 %length_not_zero, label %weird_loop, label %exit
125
126weird_loop:
127  %weird.iv = phi i32 [ 0, %entry ], [ %weird.iv.next, %weird_loop ]
128  %weird.iv.next = add i32 %weird.iv, 1
129  %weird.iv.wide = zext i32 %weird.iv to i64
130  %weird.cond = call i1 @bar()
131  br i1 %weird.cond, label %weird_loop, label %loop
132
133loop:
134  %iv = phi i32 [ %weird.iv, %weird_loop ], [ %iv.next, %latch ]
135  %iv.wide = phi i64 [ %weird.iv.wide, %weird_loop ], [ %iv.wide.next, %latch ]
136  %iv.next = add i32 %iv, 1
137  %iv.wide.next = add i64 %iv.wide, 1
138  %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 %iv
139  %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 %iv
140  %result = call i1 @foo(i8* %left_ptr, i8* %right_ptr)
141  br i1 %result, label %exiting_1, label %exit
142
143exiting_1:
144  %iv.wide.is_not_zero = icmp ne i64 %iv.wide, %weird.iv.wide
145  br i1 %iv.wide.is_not_zero, label %exiting_2, label %exit
146
147exiting_2:
148  %bar_ret = call i1 @bar()
149  br i1 %bar_ret, label %exit, label %exiting_3
150
151exiting_3:
152  %baz_ret = call i1 @baz()
153  br i1 %baz_ret, label %latch, label %exit
154
155latch:
156  %continue = icmp ne i32 %iv.next, %len
157  br i1 %continue, label %loop, label %exit
158
159exit:
160  %val = phi i1 [ %result, %loop ], [ %iv.wide.is_not_zero, %exiting_1 ],
161  [ %bar_ret, %exiting_2 ], [ %baz_ret, %exiting_3 ],
162  [ %baz_ret, %latch ], [ 0, %entry ]
163  ret i1 %val
164}
165