1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes=indvars -S | FileCheck %s 3; RUN: opt -passes=lcssa,loop-simplify -S < %s | opt -S -passes='require<target-ir>,require<scalar-evolution>,require<domtree>,loop(indvars)' 4 5;; --- signed --- 6 7define void @min.signed.1(ptr %a, i32 %a_len, i32 %n) { 8; CHECK-LABEL: define void @min.signed.1( 9; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[SMIN_CMP:%.*]] = icmp slt i32 [[A_LEN]], [[N]] 12; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 [[A_LEN]], i32 [[N]] 13; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]] 14; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 15; CHECK: loop.preheader: 16; CHECK-NEXT: br label [[LOOP:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 19; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 20; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 21; CHECK: ok: 22; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 23; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 24; CHECK-NEXT: br label [[LATCH]] 25; CHECK: latch: 26; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]] 27; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 28; CHECK: exit.loopexit: 29; CHECK-NEXT: br label [[EXIT]] 30; CHECK: exit: 31; CHECK-NEXT: ret void 32; 33entry: 34 %smin.cmp = icmp slt i32 %a_len, %n 35 %smin = select i1 %smin.cmp, i32 %a_len, i32 %n 36 %entry.cond = icmp slt i32 0, %smin 37 br i1 %entry.cond, label %loop, label %exit 38 39loop: 40 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 41 %idx.inc = add i32 %idx, 1 42 %in.bounds = icmp slt i32 %idx, %a_len 43 br i1 %in.bounds, label %ok, label %latch 44 45ok: 46 %addr = getelementptr i32, ptr %a, i32 %idx 47 store i32 %idx, ptr %addr 48 br label %latch 49 50latch: 51 %be.cond = icmp slt i32 %idx.inc, %smin 52 br i1 %be.cond, label %loop, label %exit 53 54exit: 55 ret void 56} 57 58define void @min.signed.2(ptr %a, i32 %a_len, i32 %n) { 59; CHECK-LABEL: define void @min.signed.2( 60; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 61; CHECK-NEXT: entry: 62; CHECK-NEXT: [[SMIN_CMP:%.*]] = icmp slt i32 [[A_LEN]], [[N]] 63; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 [[A_LEN]], i32 [[N]] 64; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]] 65; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 66; CHECK: loop.preheader: 67; CHECK-NEXT: br label [[LOOP:%.*]] 68; CHECK: loop: 69; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 70; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 71; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 72; CHECK: ok: 73; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 74; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 75; CHECK-NEXT: br label [[LATCH]] 76; CHECK: latch: 77; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]] 78; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 79; CHECK: exit.loopexit: 80; CHECK-NEXT: br label [[EXIT]] 81; CHECK: exit: 82; CHECK-NEXT: ret void 83; 84entry: 85 %smin.cmp = icmp slt i32 %a_len, %n 86 %smin = select i1 %smin.cmp, i32 %a_len, i32 %n 87 %entry.cond = icmp slt i32 0, %smin 88 br i1 %entry.cond, label %loop, label %exit 89 90loop: 91 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 92 %idx.inc = add i32 %idx, 1 93 %in.bounds = icmp sgt i32 %a_len, %idx 94 br i1 %in.bounds, label %ok, label %latch 95 96ok: 97 %addr = getelementptr i32, ptr %a, i32 %idx 98 store i32 %idx, ptr %addr 99 br label %latch 100 101latch: 102 %be.cond = icmp slt i32 %idx.inc, %smin 103 br i1 %be.cond, label %loop, label %exit 104 105exit: 106 ret void 107} 108 109define void @min.signed.3(ptr %a, i32 %n) { 110; CHECK-LABEL: define void @min.signed.3( 111; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) { 112; CHECK-NEXT: entry: 113; CHECK-NEXT: [[SMIN_CMP:%.*]] = icmp slt i32 42, [[N]] 114; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 42, i32 [[N]] 115; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]] 116; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 117; CHECK: loop.preheader: 118; CHECK-NEXT: br label [[LOOP:%.*]] 119; CHECK: loop: 120; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 121; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 122; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 123; CHECK: ok: 124; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 125; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 126; CHECK-NEXT: br label [[LATCH]] 127; CHECK: latch: 128; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]] 129; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 130; CHECK: exit.loopexit: 131; CHECK-NEXT: br label [[EXIT]] 132; CHECK: exit: 133; CHECK-NEXT: ret void 134; 135entry: 136 %smin.cmp = icmp slt i32 42, %n 137 %smin = select i1 %smin.cmp, i32 42, i32 %n 138 %entry.cond = icmp slt i32 0, %smin 139 br i1 %entry.cond, label %loop, label %exit 140 141loop: 142 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 143 %idx.inc = add i32 %idx, 1 144 %in.bounds = icmp slt i32 %idx, 42 145 br i1 %in.bounds, label %ok, label %latch 146 147ok: 148 %addr = getelementptr i32, ptr %a, i32 %idx 149 store i32 %idx, ptr %addr 150 br label %latch 151 152latch: 153 %be.cond = icmp slt i32 %idx.inc, %smin 154 br i1 %be.cond, label %loop, label %exit 155 156exit: 157 ret void 158} 159 160define void @min.signed.4(ptr %a, i32 %n) { 161; CHECK-LABEL: define void @min.signed.4( 162; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) { 163; CHECK-NEXT: entry: 164; CHECK-NEXT: [[SMIN_CMP:%.*]] = icmp slt i32 42, [[N]] 165; CHECK-NEXT: [[SMIN:%.*]] = select i1 [[SMIN_CMP]], i32 42, i32 [[N]] 166; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp slt i32 0, [[SMIN]] 167; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 168; CHECK: loop.preheader: 169; CHECK-NEXT: br label [[LOOP:%.*]] 170; CHECK: loop: 171; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 172; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 173; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 174; CHECK: ok: 175; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 176; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 177; CHECK-NEXT: br label [[LATCH]] 178; CHECK: latch: 179; CHECK-NEXT: [[BE_COND:%.*]] = icmp slt i32 [[IDX_INC]], [[SMIN]] 180; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 181; CHECK: exit.loopexit: 182; CHECK-NEXT: br label [[EXIT]] 183; CHECK: exit: 184; CHECK-NEXT: ret void 185; 186entry: 187 %smin.cmp = icmp slt i32 42, %n 188 %smin = select i1 %smin.cmp, i32 42, i32 %n 189 %entry.cond = icmp slt i32 0, %smin 190 br i1 %entry.cond, label %loop, label %exit 191 192loop: 193 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 194 %idx.inc = add i32 %idx, 1 195 %in.bounds = icmp sgt i32 42, %idx 196 br i1 %in.bounds, label %ok, label %latch 197 198ok: 199 %addr = getelementptr i32, ptr %a, i32 %idx 200 store i32 %idx, ptr %addr 201 br label %latch 202 203latch: 204 %be.cond = icmp slt i32 %idx.inc, %smin 205 br i1 %be.cond, label %loop, label %exit 206 207exit: 208 ret void 209} 210 211define void @max.signed.1(ptr %a, i32 %a_len, i32 %n) { 212; CHECK-LABEL: define void @max.signed.1( 213; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 214; CHECK-NEXT: entry: 215; CHECK-NEXT: [[SMAX_CMP:%.*]] = icmp sgt i32 [[A_LEN]], [[N]] 216; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 [[A_LEN]], i32 [[N]] 217; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 0, [[SMAX]] 218; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 219; CHECK: loop.preheader: 220; CHECK-NEXT: br label [[LOOP:%.*]] 221; CHECK: loop: 222; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 223; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 224; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 225; CHECK: ok: 226; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 227; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 228; CHECK-NEXT: br label [[LATCH]] 229; CHECK: latch: 230; CHECK-NEXT: [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]] 231; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 232; CHECK: exit.loopexit: 233; CHECK-NEXT: br label [[EXIT]] 234; CHECK: exit: 235; CHECK-NEXT: ret void 236; 237entry: 238 %smax.cmp = icmp sgt i32 %a_len, %n 239 %smax = select i1 %smax.cmp, i32 %a_len, i32 %n 240 %entry.cond = icmp sgt i32 0, %smax 241 br i1 %entry.cond, label %loop, label %exit 242 243loop: 244 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 245 %idx.inc = add i32 %idx, 1 246 %in.bounds = icmp sgt i32 %idx, %a_len 247 br i1 %in.bounds, label %ok, label %latch 248 249ok: 250 %addr = getelementptr i32, ptr %a, i32 %idx 251 store i32 %idx, ptr %addr 252 br label %latch 253 254latch: 255 %be.cond = icmp sgt i32 %idx.inc, %smax 256 br i1 %be.cond, label %loop, label %exit 257 258exit: 259 ret void 260} 261 262define void @max.signed.2(ptr %a, i32 %a_len, i32 %n) { 263; CHECK-LABEL: define void @max.signed.2( 264; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 265; CHECK-NEXT: entry: 266; CHECK-NEXT: [[SMAX_CMP:%.*]] = icmp sgt i32 [[A_LEN]], [[N]] 267; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 [[A_LEN]], i32 [[N]] 268; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 0, [[SMAX]] 269; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 270; CHECK: loop.preheader: 271; CHECK-NEXT: br label [[LOOP:%.*]] 272; CHECK: loop: 273; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 274; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 275; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 276; CHECK: ok: 277; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 278; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 279; CHECK-NEXT: br label [[LATCH]] 280; CHECK: latch: 281; CHECK-NEXT: [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]] 282; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 283; CHECK: exit.loopexit: 284; CHECK-NEXT: br label [[EXIT]] 285; CHECK: exit: 286; CHECK-NEXT: ret void 287; 288entry: 289 %smax.cmp = icmp sgt i32 %a_len, %n 290 %smax = select i1 %smax.cmp, i32 %a_len, i32 %n 291 %entry.cond = icmp sgt i32 0, %smax 292 br i1 %entry.cond, label %loop, label %exit 293 294loop: 295 %idx = phi i32 [ 0, %entry ], [ %idx.inc, %latch ] 296 %idx.inc = add i32 %idx, 1 297 %in.bounds = icmp slt i32 %a_len, %idx 298 br i1 %in.bounds, label %ok, label %latch 299 300ok: 301 %addr = getelementptr i32, ptr %a, i32 %idx 302 store i32 %idx, ptr %addr 303 br label %latch 304 305latch: 306 %be.cond = icmp sgt i32 %idx.inc, %smax 307 br i1 %be.cond, label %loop, label %exit 308 309exit: 310 ret void 311} 312 313define void @max.signed.3(ptr %a, i32 %n, i32 %init) { 314; CHECK-LABEL: define void @max.signed.3( 315; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) { 316; CHECK-NEXT: entry: 317; CHECK-NEXT: [[SMAX_CMP:%.*]] = icmp sgt i32 42, [[N]] 318; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 42, i32 [[N]] 319; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 [[INIT]], [[SMAX]] 320; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 321; CHECK: loop.preheader: 322; CHECK-NEXT: br label [[LOOP:%.*]] 323; CHECK: loop: 324; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ] 325; CHECK-NEXT: [[IDX_INC]] = add nuw i32 [[IDX]], 1 326; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 327; CHECK: ok: 328; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 329; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 330; CHECK-NEXT: br label [[LATCH]] 331; CHECK: latch: 332; CHECK-NEXT: [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]] 333; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 334; CHECK: exit.loopexit: 335; CHECK-NEXT: br label [[EXIT]] 336; CHECK: exit: 337; CHECK-NEXT: ret void 338; 339entry: 340 %smax.cmp = icmp sgt i32 42, %n 341 %smax = select i1 %smax.cmp, i32 42, i32 %n 342 %entry.cond = icmp sgt i32 %init, %smax 343 br i1 %entry.cond, label %loop, label %exit 344 345loop: 346 %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] 347 %idx.inc = add i32 %idx, 1 348 %in.bounds = icmp sgt i32 %idx, 42 349 br i1 %in.bounds, label %ok, label %latch 350 351ok: 352 %addr = getelementptr i32, ptr %a, i32 %idx 353 store i32 %idx, ptr %addr 354 br label %latch 355 356latch: 357 %be.cond = icmp sgt i32 %idx.inc, %smax 358 br i1 %be.cond, label %loop, label %exit 359 360exit: 361 ret void 362} 363 364define void @max.signed.4(ptr %a, i32 %n, i32 %init) { 365; CHECK-LABEL: define void @max.signed.4( 366; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) { 367; CHECK-NEXT: entry: 368; CHECK-NEXT: [[SMAX_CMP:%.*]] = icmp sgt i32 42, [[N]] 369; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[SMAX_CMP]], i32 42, i32 [[N]] 370; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp sgt i32 [[INIT]], [[SMAX]] 371; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 372; CHECK: loop.preheader: 373; CHECK-NEXT: br label [[LOOP:%.*]] 374; CHECK: loop: 375; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ] 376; CHECK-NEXT: [[IDX_INC]] = add nuw i32 [[IDX]], 1 377; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 378; CHECK: ok: 379; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 380; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 381; CHECK-NEXT: br label [[LATCH]] 382; CHECK: latch: 383; CHECK-NEXT: [[BE_COND:%.*]] = icmp sgt i32 [[IDX_INC]], [[SMAX]] 384; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 385; CHECK: exit.loopexit: 386; CHECK-NEXT: br label [[EXIT]] 387; CHECK: exit: 388; CHECK-NEXT: ret void 389; 390entry: 391 %smax.cmp = icmp sgt i32 42, %n 392 %smax = select i1 %smax.cmp, i32 42, i32 %n 393 %entry.cond = icmp sgt i32 %init, %smax 394 br i1 %entry.cond, label %loop, label %exit 395 396loop: 397 %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] 398 %idx.inc = add i32 %idx, 1 399 %in.bounds = icmp slt i32 42, %idx 400 br i1 %in.bounds, label %ok, label %latch 401 402ok: 403 %addr = getelementptr i32, ptr %a, i32 %idx 404 store i32 %idx, ptr %addr 405 br label %latch 406 407latch: 408 %be.cond = icmp sgt i32 %idx.inc, %smax 409 br i1 %be.cond, label %loop, label %exit 410 411exit: 412 ret void 413} 414 415;; --- unsigned --- 416 417define void @min.unsigned.1(ptr %a, i32 %a_len, i32 %n) { 418; CHECK-LABEL: define void @min.unsigned.1( 419; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 420; CHECK-NEXT: entry: 421; CHECK-NEXT: [[UMIN_CMP:%.*]] = icmp ult i32 [[A_LEN]], [[N]] 422; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 [[A_LEN]], i32 [[N]] 423; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]] 424; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 425; CHECK: loop.preheader: 426; CHECK-NEXT: br label [[LOOP:%.*]] 427; CHECK: loop: 428; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 429; CHECK-NEXT: [[IDX_INC]] = add nuw i32 [[IDX]], 1 430; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 431; CHECK: ok: 432; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 433; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 434; CHECK-NEXT: br label [[LATCH]] 435; CHECK: latch: 436; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]] 437; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 438; CHECK: exit.loopexit: 439; CHECK-NEXT: br label [[EXIT]] 440; CHECK: exit: 441; CHECK-NEXT: ret void 442; 443entry: 444 %umin.cmp = icmp ult i32 %a_len, %n 445 %umin = select i1 %umin.cmp, i32 %a_len, i32 %n 446 %entry.cond = icmp ult i32 5, %umin 447 br i1 %entry.cond, label %loop, label %exit 448 449loop: 450 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 451 %idx.inc = add i32 %idx, 1 452 %in.bounds = icmp ult i32 %idx, %a_len 453 br i1 %in.bounds, label %ok, label %latch 454 455ok: 456 %addr = getelementptr i32, ptr %a, i32 %idx 457 store i32 %idx, ptr %addr 458 br label %latch 459 460latch: 461 %be.cond = icmp ult i32 %idx.inc, %umin 462 br i1 %be.cond, label %loop, label %exit 463 464exit: 465 ret void 466} 467 468define void @min.unsigned.2(ptr %a, i32 %a_len, i32 %n) { 469; CHECK-LABEL: define void @min.unsigned.2( 470; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 471; CHECK-NEXT: entry: 472; CHECK-NEXT: [[UMIN_CMP:%.*]] = icmp ult i32 [[A_LEN]], [[N]] 473; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 [[A_LEN]], i32 [[N]] 474; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]] 475; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 476; CHECK: loop.preheader: 477; CHECK-NEXT: br label [[LOOP:%.*]] 478; CHECK: loop: 479; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 480; CHECK-NEXT: [[IDX_INC]] = add nuw i32 [[IDX]], 1 481; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 482; CHECK: ok: 483; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 484; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 485; CHECK-NEXT: br label [[LATCH]] 486; CHECK: latch: 487; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]] 488; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 489; CHECK: exit.loopexit: 490; CHECK-NEXT: br label [[EXIT]] 491; CHECK: exit: 492; CHECK-NEXT: ret void 493; 494entry: 495 %umin.cmp = icmp ult i32 %a_len, %n 496 %umin = select i1 %umin.cmp, i32 %a_len, i32 %n 497 %entry.cond = icmp ult i32 5, %umin 498 br i1 %entry.cond, label %loop, label %exit 499 500loop: 501 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 502 %idx.inc = add i32 %idx, 1 503 %in.bounds = icmp ugt i32 %a_len, %idx 504 br i1 %in.bounds, label %ok, label %latch 505 506ok: 507 %addr = getelementptr i32, ptr %a, i32 %idx 508 store i32 %idx, ptr %addr 509 br label %latch 510 511latch: 512 %be.cond = icmp ult i32 %idx.inc, %umin 513 br i1 %be.cond, label %loop, label %exit 514 515exit: 516 ret void 517} 518 519define void @min.unsigned.3(ptr %a, i32 %n) { 520; CHECK-LABEL: define void @min.unsigned.3( 521; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) { 522; CHECK-NEXT: entry: 523; CHECK-NEXT: [[UMIN_CMP:%.*]] = icmp ult i32 42, [[N]] 524; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 42, i32 [[N]] 525; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]] 526; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 527; CHECK: loop.preheader: 528; CHECK-NEXT: br label [[LOOP:%.*]] 529; CHECK: loop: 530; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 531; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 532; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 533; CHECK: ok: 534; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 535; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 536; CHECK-NEXT: br label [[LATCH]] 537; CHECK: latch: 538; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]] 539; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 540; CHECK: exit.loopexit: 541; CHECK-NEXT: br label [[EXIT]] 542; CHECK: exit: 543; CHECK-NEXT: ret void 544; 545entry: 546 %umin.cmp = icmp ult i32 42, %n 547 %umin = select i1 %umin.cmp, i32 42, i32 %n 548 %entry.cond = icmp ult i32 5, %umin 549 br i1 %entry.cond, label %loop, label %exit 550 551loop: 552 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 553 %idx.inc = add i32 %idx, 1 554 %in.bounds = icmp ult i32 %idx, 42 555 br i1 %in.bounds, label %ok, label %latch 556 557ok: 558 %addr = getelementptr i32, ptr %a, i32 %idx 559 store i32 %idx, ptr %addr 560 br label %latch 561 562latch: 563 %be.cond = icmp ult i32 %idx.inc, %umin 564 br i1 %be.cond, label %loop, label %exit 565 566exit: 567 ret void 568} 569 570define void @min.unsigned.4(ptr %a, i32 %n) { 571; CHECK-LABEL: define void @min.unsigned.4( 572; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]]) { 573; CHECK-NEXT: entry: 574; CHECK-NEXT: [[UMIN_CMP:%.*]] = icmp ult i32 42, [[N]] 575; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[UMIN_CMP]], i32 42, i32 [[N]] 576; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ult i32 5, [[UMIN]] 577; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 578; CHECK: loop.preheader: 579; CHECK-NEXT: br label [[LOOP:%.*]] 580; CHECK: loop: 581; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 582; CHECK-NEXT: [[IDX_INC]] = add nuw nsw i32 [[IDX]], 1 583; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 584; CHECK: ok: 585; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 586; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 587; CHECK-NEXT: br label [[LATCH]] 588; CHECK: latch: 589; CHECK-NEXT: [[BE_COND:%.*]] = icmp ult i32 [[IDX_INC]], [[UMIN]] 590; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 591; CHECK: exit.loopexit: 592; CHECK-NEXT: br label [[EXIT]] 593; CHECK: exit: 594; CHECK-NEXT: ret void 595; 596entry: 597 %umin.cmp = icmp ult i32 42, %n 598 %umin = select i1 %umin.cmp, i32 42, i32 %n 599 %entry.cond = icmp ult i32 5, %umin 600 br i1 %entry.cond, label %loop, label %exit 601 602loop: 603 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 604 %idx.inc = add i32 %idx, 1 605 %in.bounds = icmp ugt i32 42, %idx 606 br i1 %in.bounds, label %ok, label %latch 607 608ok: 609 %addr = getelementptr i32, ptr %a, i32 %idx 610 store i32 %idx, ptr %addr 611 br label %latch 612 613latch: 614 %be.cond = icmp ult i32 %idx.inc, %umin 615 br i1 %be.cond, label %loop, label %exit 616 617exit: 618 ret void 619} 620 621define void @max.unsigned.1(ptr %a, i32 %a_len, i32 %n) { 622; CHECK-LABEL: define void @max.unsigned.1( 623; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 624; CHECK-NEXT: entry: 625; CHECK-NEXT: [[UMAX_CMP:%.*]] = icmp ugt i32 [[A_LEN]], [[N]] 626; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 [[A_LEN]], i32 [[N]] 627; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ugt i32 5, [[UMAX]] 628; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 629; CHECK: loop.preheader: 630; CHECK-NEXT: br label [[LOOP:%.*]] 631; CHECK: loop: 632; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 633; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 634; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 635; CHECK: ok: 636; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 637; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 638; CHECK-NEXT: br label [[LATCH]] 639; CHECK: latch: 640; CHECK-NEXT: [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]] 641; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 642; CHECK: exit.loopexit: 643; CHECK-NEXT: br label [[EXIT]] 644; CHECK: exit: 645; CHECK-NEXT: ret void 646; 647entry: 648 %umax.cmp = icmp ugt i32 %a_len, %n 649 %umax = select i1 %umax.cmp, i32 %a_len, i32 %n 650 %entry.cond = icmp ugt i32 5, %umax 651 br i1 %entry.cond, label %loop, label %exit 652 653loop: 654 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 655 %idx.inc = add i32 %idx, 1 656 %in.bounds = icmp ugt i32 %idx, %a_len 657 br i1 %in.bounds, label %ok, label %latch 658 659ok: 660 %addr = getelementptr i32, ptr %a, i32 %idx 661 store i32 %idx, ptr %addr 662 br label %latch 663 664latch: 665 %be.cond = icmp ugt i32 %idx.inc, %umax 666 br i1 %be.cond, label %loop, label %exit 667 668exit: 669 ret void 670} 671 672define void @max.unsigned.2(ptr %a, i32 %a_len, i32 %n) { 673; CHECK-LABEL: define void @max.unsigned.2( 674; CHECK-SAME: ptr [[A:%.*]], i32 [[A_LEN:%.*]], i32 [[N:%.*]]) { 675; CHECK-NEXT: entry: 676; CHECK-NEXT: [[UMAX_CMP:%.*]] = icmp ugt i32 [[A_LEN]], [[N]] 677; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 [[A_LEN]], i32 [[N]] 678; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ugt i32 5, [[UMAX]] 679; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 680; CHECK: loop.preheader: 681; CHECK-NEXT: br label [[LOOP:%.*]] 682; CHECK: loop: 683; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ 5, [[LOOP_PREHEADER]] ] 684; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 685; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 686; CHECK: ok: 687; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 688; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 689; CHECK-NEXT: br label [[LATCH]] 690; CHECK: latch: 691; CHECK-NEXT: [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]] 692; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 693; CHECK: exit.loopexit: 694; CHECK-NEXT: br label [[EXIT]] 695; CHECK: exit: 696; CHECK-NEXT: ret void 697; 698entry: 699 %umax.cmp = icmp ugt i32 %a_len, %n 700 %umax = select i1 %umax.cmp, i32 %a_len, i32 %n 701 %entry.cond = icmp ugt i32 5, %umax 702 br i1 %entry.cond, label %loop, label %exit 703 704loop: 705 %idx = phi i32 [ 5, %entry ], [ %idx.inc, %latch ] 706 %idx.inc = add i32 %idx, 1 707 %in.bounds = icmp ult i32 %a_len, %idx 708 br i1 %in.bounds, label %ok, label %latch 709 710ok: 711 %addr = getelementptr i32, ptr %a, i32 %idx 712 store i32 %idx, ptr %addr 713 br label %latch 714 715latch: 716 %be.cond = icmp ugt i32 %idx.inc, %umax 717 br i1 %be.cond, label %loop, label %exit 718 719exit: 720 ret void 721} 722 723define void @max.unsigned.3(ptr %a, i32 %n, i32 %init) { 724; CHECK-LABEL: define void @max.unsigned.3( 725; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) { 726; CHECK-NEXT: entry: 727; CHECK-NEXT: [[UMAX_CMP:%.*]] = icmp ugt i32 42, [[N]] 728; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 42, i32 [[N]] 729; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ugt i32 [[INIT]], [[UMAX]] 730; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 731; CHECK: loop.preheader: 732; CHECK-NEXT: br label [[LOOP:%.*]] 733; CHECK: loop: 734; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ] 735; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 736; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 737; CHECK: ok: 738; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 739; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 740; CHECK-NEXT: br label [[LATCH]] 741; CHECK: latch: 742; CHECK-NEXT: [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]] 743; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 744; CHECK: exit.loopexit: 745; CHECK-NEXT: br label [[EXIT]] 746; CHECK: exit: 747; CHECK-NEXT: ret void 748; 749entry: 750 %umax.cmp = icmp ugt i32 42, %n 751 %umax = select i1 %umax.cmp, i32 42, i32 %n 752 %entry.cond = icmp ugt i32 %init, %umax 753 br i1 %entry.cond, label %loop, label %exit 754 755loop: 756 %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] 757 %idx.inc = add i32 %idx, 1 758 %in.bounds = icmp ugt i32 %idx, 42 759 br i1 %in.bounds, label %ok, label %latch 760 761ok: 762 %addr = getelementptr i32, ptr %a, i32 %idx 763 store i32 %idx, ptr %addr 764 br label %latch 765 766latch: 767 %be.cond = icmp ugt i32 %idx.inc, %umax 768 br i1 %be.cond, label %loop, label %exit 769 770exit: 771 ret void 772} 773 774define void @max.unsigned.4(ptr %a, i32 %n, i32 %init) { 775; CHECK-LABEL: define void @max.unsigned.4( 776; CHECK-SAME: ptr [[A:%.*]], i32 [[N:%.*]], i32 [[INIT:%.*]]) { 777; CHECK-NEXT: entry: 778; CHECK-NEXT: [[UMAX_CMP:%.*]] = icmp ugt i32 42, [[N]] 779; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[UMAX_CMP]], i32 42, i32 [[N]] 780; CHECK-NEXT: [[ENTRY_COND:%.*]] = icmp ugt i32 [[INIT]], [[UMAX]] 781; CHECK-NEXT: br i1 [[ENTRY_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 782; CHECK: loop.preheader: 783; CHECK-NEXT: br label [[LOOP:%.*]] 784; CHECK: loop: 785; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_INC:%.*]], [[LATCH:%.*]] ], [ [[INIT]], [[LOOP_PREHEADER]] ] 786; CHECK-NEXT: [[IDX_INC]] = add i32 [[IDX]], 1 787; CHECK-NEXT: br i1 true, label [[OK:%.*]], label [[LATCH]] 788; CHECK: ok: 789; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[A]], i32 [[IDX]] 790; CHECK-NEXT: store i32 [[IDX]], ptr [[ADDR]], align 4 791; CHECK-NEXT: br label [[LATCH]] 792; CHECK: latch: 793; CHECK-NEXT: [[BE_COND:%.*]] = icmp ugt i32 [[IDX_INC]], [[UMAX]] 794; CHECK-NEXT: br i1 [[BE_COND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 795; CHECK: exit.loopexit: 796; CHECK-NEXT: br label [[EXIT]] 797; CHECK: exit: 798; CHECK-NEXT: ret void 799; 800entry: 801 %umax.cmp = icmp ugt i32 42, %n 802 %umax = select i1 %umax.cmp, i32 42, i32 %n 803 %entry.cond = icmp ugt i32 %init, %umax 804 br i1 %entry.cond, label %loop, label %exit 805 806loop: 807 %idx = phi i32 [ %init, %entry ], [ %idx.inc, %latch ] 808 %idx.inc = add i32 %idx, 1 809 %in.bounds = icmp ult i32 42, %idx 810 br i1 %in.bounds, label %ok, label %latch 811 812ok: 813 %addr = getelementptr i32, ptr %a, i32 %idx 814 store i32 %idx, ptr %addr 815 br label %latch 816 817latch: 818 %be.cond = icmp ugt i32 %idx.inc, %umax 819 br i1 %be.cond, label %loop, label %exit 820 821exit: 822 ret void 823} 824