1; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s 2 3; This test checks if we update the LoopInfo correctly in the presence 4; of parents, uncles and cousins. 5 6; Function Attrs: alwaysinline 7define void @inner_loop(i32* %arr, i32* %a_len_ptr, i32 %n) #0 { 8; CHECK: irce: in function inner_loop: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 9 10entry: 11 %len = load i32, i32* %a_len_ptr, !range !0 12 %first.itr.check = icmp sgt i32 %n, 0 13 br i1 %first.itr.check, label %loop, label %exit 14 15loop: ; preds = %in.bounds, %entry 16 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 17 %idx.next = add i32 %idx, 1 18 %abc = icmp slt i32 %idx, %len 19 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 20 21in.bounds: ; preds = %loop 22 %addr = getelementptr i32, i32* %arr, i32 %idx 23 store i32 0, i32* %addr 24 %next = icmp slt i32 %idx.next, %n 25 br i1 %next, label %loop, label %exit 26 27out.of.bounds: ; preds = %loop 28 ret void 29 30exit: ; preds = %in.bounds, %entry 31 ret void 32} 33 34; Function Attrs: alwaysinline 35define void @with_parent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 { 36; CHECK: irce: in function with_parent: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting> 37 38entry: 39 br label %loop 40 41loop: ; preds = %inner_loop.exit, %entry 42 %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit ] 43 %idx.next = add i32 %idx, 1 44 %next = icmp ult i32 %idx.next, %parent.count 45 %len.i = load i32, i32* %a_len_ptr, !range !0 46 %first.itr.check.i = icmp sgt i32 %n, 0 47 br i1 %first.itr.check.i, label %loop.i, label %exit.i 48 49loop.i: ; preds = %in.bounds.i, %loop 50 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ] 51 %idx.next.i = add i32 %idx.i, 1 52 %abc.i = icmp slt i32 %idx.i, %len.i 53 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1 54 55in.bounds.i: ; preds = %loop.i 56 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i 57 store i32 0, i32* %addr.i 58 %next.i = icmp slt i32 %idx.next.i, %n 59 br i1 %next.i, label %loop.i, label %exit.i 60 61out.of.bounds.i: ; preds = %loop.i 62 br label %inner_loop.exit 63 64exit.i: ; preds = %in.bounds.i, %loop 65 br label %inner_loop.exit 66 67inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i 68 br i1 %next, label %loop, label %exit 69 70exit: ; preds = %inner_loop.exit 71 ret void 72} 73 74; Function Attrs: alwaysinline 75define void @with_grandparent(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 { 76; CHECK: irce: in function with_grandparent: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting> 77 78entry: 79 br label %loop 80 81loop: ; preds = %with_parent.exit, %entry 82 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ] 83 %idx.next = add i32 %idx, 1 84 %next = icmp ult i32 %idx.next, %grandparent.count 85 br label %loop.i 86 87loop.i: ; preds = %inner_loop.exit.i, %loop 88 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ] 89 %idx.next.i = add i32 %idx.i, 1 90 %next.i = icmp ult i32 %idx.next.i, %parent.count 91 %len.i.i = load i32, i32* %a_len_ptr, !range !0 92 %first.itr.check.i.i = icmp sgt i32 %n, 0 93 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i 94 95loop.i.i: ; preds = %in.bounds.i.i, %loop.i 96 %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ] 97 %idx.next.i.i = add i32 %idx.i.i, 1 98 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i 99 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1 100 101in.bounds.i.i: ; preds = %loop.i.i 102 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i 103 store i32 0, i32* %addr.i.i 104 %next.i.i = icmp slt i32 %idx.next.i.i, %n 105 br i1 %next.i.i, label %loop.i.i, label %exit.i.i 106 107out.of.bounds.i.i: ; preds = %loop.i.i 108 br label %inner_loop.exit.i 109 110exit.i.i: ; preds = %in.bounds.i.i, %loop.i 111 br label %inner_loop.exit.i 112 113inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i 114 br i1 %next.i, label %loop.i, label %with_parent.exit 115 116with_parent.exit: ; preds = %inner_loop.exit.i 117 br i1 %next, label %loop, label %exit 118 119exit: ; preds = %with_parent.exit 120 ret void 121} 122 123; Function Attrs: alwaysinline 124define void @with_sibling(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count) #0 { 125; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting> 126; CHECK: irce: in function with_sibling: constrained Loop at depth 2 containing: %loop.i6<header><exiting>,%in.bounds.i9<latch><exiting> 127 128entry: 129 br label %loop 130 131loop: ; preds = %inner_loop.exit12, %entry 132 %idx = phi i32 [ 0, %entry ], [ %idx.next, %inner_loop.exit12 ] 133 %idx.next = add i32 %idx, 1 134 %next = icmp ult i32 %idx.next, %parent.count 135 %len.i = load i32, i32* %a_len_ptr, !range !0 136 %first.itr.check.i = icmp sgt i32 %n, 0 137 br i1 %first.itr.check.i, label %loop.i, label %exit.i 138 139loop.i: ; preds = %in.bounds.i, %loop 140 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ] 141 %idx.next.i = add i32 %idx.i, 1 142 %abc.i = icmp slt i32 %idx.i, %len.i 143 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1 144 145in.bounds.i: ; preds = %loop.i 146 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i 147 store i32 0, i32* %addr.i 148 %next.i = icmp slt i32 %idx.next.i, %n 149 br i1 %next.i, label %loop.i, label %exit.i 150 151out.of.bounds.i: ; preds = %loop.i 152 br label %inner_loop.exit 153 154exit.i: ; preds = %in.bounds.i, %loop 155 br label %inner_loop.exit 156 157inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i 158 %len.i1 = load i32, i32* %a_len_ptr, !range !0 159 %first.itr.check.i2 = icmp sgt i32 %n, 0 160 br i1 %first.itr.check.i2, label %loop.i6, label %exit.i11 161 162loop.i6: ; preds = %in.bounds.i9, %inner_loop.exit 163 %idx.i3 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i4, %in.bounds.i9 ] 164 %idx.next.i4 = add i32 %idx.i3, 1 165 %abc.i5 = icmp slt i32 %idx.i3, %len.i1 166 br i1 %abc.i5, label %in.bounds.i9, label %out.of.bounds.i10, !prof !1 167 168in.bounds.i9: ; preds = %loop.i6 169 %addr.i7 = getelementptr i32, i32* %arr, i32 %idx.i3 170 store i32 0, i32* %addr.i7 171 %next.i8 = icmp slt i32 %idx.next.i4, %n 172 br i1 %next.i8, label %loop.i6, label %exit.i11 173 174out.of.bounds.i10: ; preds = %loop.i6 175 br label %inner_loop.exit12 176 177exit.i11: ; preds = %in.bounds.i9, %inner_loop.exit 178 br label %inner_loop.exit12 179 180inner_loop.exit12: ; preds = %exit.i11, %out.of.bounds.i10 181 br i1 %next, label %loop, label %exit 182 183exit: ; preds = %inner_loop.exit12 184 ret void 185} 186 187; Function Attrs: alwaysinline 188define void @with_cousin(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 { 189; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting> 190; CHECK: irce: in function with_cousin: constrained Loop at depth 3 containing: %loop.i.i10<header><exiting>,%in.bounds.i.i13<latch><exiting> 191 192entry: 193 br label %loop 194 195loop: ; preds = %with_parent.exit17, %entry 196 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit17 ] 197 %idx.next = add i32 %idx, 1 198 %next = icmp ult i32 %idx.next, %grandparent.count 199 br label %loop.i 200 201loop.i: ; preds = %inner_loop.exit.i, %loop 202 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %inner_loop.exit.i ] 203 %idx.next.i = add i32 %idx.i, 1 204 %next.i = icmp ult i32 %idx.next.i, %parent.count 205 %len.i.i = load i32, i32* %a_len_ptr, !range !0 206 %first.itr.check.i.i = icmp sgt i32 %n, 0 207 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i 208 209loop.i.i: ; preds = %in.bounds.i.i, %loop.i 210 %idx.i.i = phi i32 [ 0, %loop.i ], [ %idx.next.i.i, %in.bounds.i.i ] 211 %idx.next.i.i = add i32 %idx.i.i, 1 212 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i 213 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1 214 215in.bounds.i.i: ; preds = %loop.i.i 216 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i 217 store i32 0, i32* %addr.i.i 218 %next.i.i = icmp slt i32 %idx.next.i.i, %n 219 br i1 %next.i.i, label %loop.i.i, label %exit.i.i 220 221out.of.bounds.i.i: ; preds = %loop.i.i 222 br label %inner_loop.exit.i 223 224exit.i.i: ; preds = %in.bounds.i.i, %loop.i 225 br label %inner_loop.exit.i 226 227inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i 228 br i1 %next.i, label %loop.i, label %with_parent.exit 229 230with_parent.exit: ; preds = %inner_loop.exit.i 231 br label %loop.i6 232 233loop.i6: ; preds = %inner_loop.exit.i16, %with_parent.exit 234 %idx.i1 = phi i32 [ 0, %with_parent.exit ], [ %idx.next.i2, %inner_loop.exit.i16 ] 235 %idx.next.i2 = add i32 %idx.i1, 1 236 %next.i3 = icmp ult i32 %idx.next.i2, %parent.count 237 %len.i.i4 = load i32, i32* %a_len_ptr, !range !0 238 %first.itr.check.i.i5 = icmp sgt i32 %n, 0 239 br i1 %first.itr.check.i.i5, label %loop.i.i10, label %exit.i.i15 240 241loop.i.i10: ; preds = %in.bounds.i.i13, %loop.i6 242 %idx.i.i7 = phi i32 [ 0, %loop.i6 ], [ %idx.next.i.i8, %in.bounds.i.i13 ] 243 %idx.next.i.i8 = add i32 %idx.i.i7, 1 244 %abc.i.i9 = icmp slt i32 %idx.i.i7, %len.i.i4 245 br i1 %abc.i.i9, label %in.bounds.i.i13, label %out.of.bounds.i.i14, !prof !1 246 247in.bounds.i.i13: ; preds = %loop.i.i10 248 %addr.i.i11 = getelementptr i32, i32* %arr, i32 %idx.i.i7 249 store i32 0, i32* %addr.i.i11 250 %next.i.i12 = icmp slt i32 %idx.next.i.i8, %n 251 br i1 %next.i.i12, label %loop.i.i10, label %exit.i.i15 252 253out.of.bounds.i.i14: ; preds = %loop.i.i10 254 br label %inner_loop.exit.i16 255 256exit.i.i15: ; preds = %in.bounds.i.i13, %loop.i6 257 br label %inner_loop.exit.i16 258 259inner_loop.exit.i16: ; preds = %exit.i.i15, %out.of.bounds.i.i14 260 br i1 %next.i3, label %loop.i6, label %with_parent.exit17 261 262with_parent.exit17: ; preds = %inner_loop.exit.i16 263 br i1 %next, label %loop, label %exit 264 265exit: ; preds = %with_parent.exit17 266 ret void 267} 268 269; Function Attrs: alwaysinline 270define void @with_uncle(i32* %arr, i32* %a_len_ptr, i32 %n, i32 %parent.count, i32 %grandparent.count) #0 { 271; CHECK: irce: in function with_uncle: constrained Loop at depth 2 containing: %loop.i<header><exiting>,%in.bounds.i<latch><exiting> 272; CHECK: irce: in function with_uncle: constrained Loop at depth 3 containing: %loop.i.i<header><exiting>,%in.bounds.i.i<latch><exiting> 273 274entry: 275 br label %loop 276 277loop: ; preds = %with_parent.exit, %entry 278 %idx = phi i32 [ 0, %entry ], [ %idx.next, %with_parent.exit ] 279 %idx.next = add i32 %idx, 1 280 %next = icmp ult i32 %idx.next, %grandparent.count 281 %len.i = load i32, i32* %a_len_ptr, !range !0 282 %first.itr.check.i = icmp sgt i32 %n, 0 283 br i1 %first.itr.check.i, label %loop.i, label %exit.i 284 285loop.i: ; preds = %in.bounds.i, %loop 286 %idx.i = phi i32 [ 0, %loop ], [ %idx.next.i, %in.bounds.i ] 287 %idx.next.i = add i32 %idx.i, 1 288 %abc.i = icmp slt i32 %idx.i, %len.i 289 br i1 %abc.i, label %in.bounds.i, label %out.of.bounds.i, !prof !1 290 291in.bounds.i: ; preds = %loop.i 292 %addr.i = getelementptr i32, i32* %arr, i32 %idx.i 293 store i32 0, i32* %addr.i 294 %next.i = icmp slt i32 %idx.next.i, %n 295 br i1 %next.i, label %loop.i, label %exit.i 296 297out.of.bounds.i: ; preds = %loop.i 298 br label %inner_loop.exit 299 300exit.i: ; preds = %in.bounds.i, %loop 301 br label %inner_loop.exit 302 303inner_loop.exit: ; preds = %exit.i, %out.of.bounds.i 304 br label %loop.i4 305 306loop.i4: ; preds = %inner_loop.exit.i, %inner_loop.exit 307 %idx.i1 = phi i32 [ 0, %inner_loop.exit ], [ %idx.next.i2, %inner_loop.exit.i ] 308 %idx.next.i2 = add i32 %idx.i1, 1 309 %next.i3 = icmp ult i32 %idx.next.i2, %parent.count 310 %len.i.i = load i32, i32* %a_len_ptr, !range !0 311 %first.itr.check.i.i = icmp sgt i32 %n, 0 312 br i1 %first.itr.check.i.i, label %loop.i.i, label %exit.i.i 313 314loop.i.i: ; preds = %in.bounds.i.i, %loop.i4 315 %idx.i.i = phi i32 [ 0, %loop.i4 ], [ %idx.next.i.i, %in.bounds.i.i ] 316 %idx.next.i.i = add i32 %idx.i.i, 1 317 %abc.i.i = icmp slt i32 %idx.i.i, %len.i.i 318 br i1 %abc.i.i, label %in.bounds.i.i, label %out.of.bounds.i.i, !prof !1 319 320in.bounds.i.i: ; preds = %loop.i.i 321 %addr.i.i = getelementptr i32, i32* %arr, i32 %idx.i.i 322 store i32 0, i32* %addr.i.i 323 %next.i.i = icmp slt i32 %idx.next.i.i, %n 324 br i1 %next.i.i, label %loop.i.i, label %exit.i.i 325 326out.of.bounds.i.i: ; preds = %loop.i.i 327 br label %inner_loop.exit.i 328 329exit.i.i: ; preds = %in.bounds.i.i, %loop.i4 330 br label %inner_loop.exit.i 331 332inner_loop.exit.i: ; preds = %exit.i.i, %out.of.bounds.i.i 333 br i1 %next.i3, label %loop.i4, label %with_parent.exit 334 335with_parent.exit: ; preds = %inner_loop.exit.i 336 br i1 %next, label %loop, label %exit 337 338exit: ; preds = %with_parent.exit 339 ret void 340} 341 342attributes #0 = { alwaysinline } 343 344!0 = !{i32 0, i32 2147483647} 345!1 = !{!"branch_weights", i32 64, i32 4} 346