1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @use(i1) 5 6define void @loop_phi_pos_start_value(i32 %y, i1 %c, i32 %n) { 7; CHECK-LABEL: @loop_phi_pos_start_value( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]] 10; CHECK: loop.header: 11; CHECK-NEXT: [[X:%.*]] = phi i32 [ 10, [[ENTRY:%.*]] ], [ [[X_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 12; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[X]], [[N:%.*]] 13; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]] 14; CHECK: loop.latch: 15; CHECK-NEXT: call void @use(i1 true) 16; CHECK-NEXT: call void @use(i1 false) 17; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[X]], 10 18; CHECK-NEXT: call void @use(i1 [[T_2]]) 19; CHECK-NEXT: [[C_2:%.*]] = icmp sle i32 [[X]], 9 20; CHECK-NEXT: call void @use(i1 [[C_2]]) 21; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i32 [[X]], 9 22; CHECK-NEXT: call void @use(i1 [[C_3]]) 23; CHECK-NEXT: call void @use(i1 true) 24; CHECK-NEXT: [[C_5:%.*]] = icmp sge i32 [[X]], 9 25; CHECK-NEXT: call void @use(i1 [[C_5]]) 26; CHECK-NEXT: [[X_NEXT]] = add nsw i32 [[X]], 1 27; CHECK-NEXT: br label [[LOOP_HEADER]] 28; CHECK: exit: 29; CHECK-NEXT: [[C_6:%.*]] = icmp sgt i32 [[Y:%.*]], 10 30; CHECK-NEXT: call void @use(i1 [[C_6]]) 31; CHECK-NEXT: ret void 32; 33entry: 34 br i1 %c, label %loop.header, label %exit 35 36loop.header: 37 %x = phi i32 [ 10, %entry ], [ %x.next, %loop.latch ] 38 %c.1 = icmp slt i32 %x, %n 39 br i1 %c.1, label %loop.latch, label %exit 40 41loop.latch: 42 %f.1 = icmp sle i32 %x, %n 43 call void @use(i1 %f.1) 44 %t.1 = icmp sgt i32 %x, %n 45 call void @use(i1 %t.1) 46 %t.2 = icmp sge i32 %x, 10 47 call void @use(i1 %t.2) 48 49 %c.2 = icmp sle i32 %x, 9 50 call void @use(i1 %c.2) 51 %c.3 = icmp sgt i32 %x, 9 52 call void @use(i1 %c.3) 53 %c.4 = icmp sge i32 %x, 0 54 call void @use(i1 %c.4) 55 %c.5 = icmp sge i32 %x, 9 56 call void @use(i1 %c.5) 57 58 %x.next = add nsw i32 %x, 1 59 br label %loop.header 60 61exit: 62 %c.6 = icmp sgt i32 %y, 10 63 call void @use(i1 %c.6) 64 ret void 65} 66 67define void @loop_phi_neg_start_value(i32 %y, i1 %c, i32 %n) { 68; CHECK-LABEL: @loop_phi_neg_start_value( 69; CHECK-NEXT: entry: 70; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]] 71; CHECK: loop.header: 72; CHECK-NEXT: [[X:%.*]] = phi i32 [ -10, [[ENTRY:%.*]] ], [ [[X_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 73; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[X]], [[N:%.*]] 74; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]] 75; CHECK: loop.latch: 76; CHECK-NEXT: call void @use(i1 true) 77; CHECK-NEXT: call void @use(i1 false) 78; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[X]], -10 79; CHECK-NEXT: call void @use(i1 [[T_2]]) 80; CHECK-NEXT: [[C_2:%.*]] = icmp sle i32 [[X]], 9 81; CHECK-NEXT: call void @use(i1 [[C_2]]) 82; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i32 [[X]], 9 83; CHECK-NEXT: call void @use(i1 [[C_3]]) 84; CHECK-NEXT: [[C_4:%.*]] = icmp sge i32 [[X]], 0 85; CHECK-NEXT: call void @use(i1 [[C_4]]) 86; CHECK-NEXT: [[C_5:%.*]] = icmp sge i32 [[X]], 9 87; CHECK-NEXT: call void @use(i1 [[C_5]]) 88; CHECK-NEXT: [[X_NEXT]] = add nsw i32 [[X]], 1 89; CHECK-NEXT: br label [[LOOP_HEADER]] 90; CHECK: exit: 91; CHECK-NEXT: [[C_6:%.*]] = icmp sgt i32 [[Y:%.*]], 10 92; CHECK-NEXT: call void @use(i1 [[C_6]]) 93; CHECK-NEXT: ret void 94; 95entry: 96 br i1 %c, label %loop.header, label %exit 97 98loop.header: 99 %x = phi i32 [ -10, %entry ], [ %x.next, %loop.latch ] 100 %c.1 = icmp slt i32 %x, %n 101 br i1 %c.1, label %loop.latch, label %exit 102 103loop.latch: 104 %f.1 = icmp sle i32 %x, %n 105 call void @use(i1 %f.1) 106 %t.1 = icmp sgt i32 %x, %n 107 call void @use(i1 %t.1) 108 %t.2 = icmp sge i32 %x, -10 109 call void @use(i1 %t.2) 110 111 %c.2 = icmp sle i32 %x, 9 112 call void @use(i1 %c.2) 113 %c.3 = icmp sgt i32 %x, 9 114 call void @use(i1 %c.3) 115 %c.4 = icmp sge i32 %x, 0 116 call void @use(i1 %c.4) 117 %c.5 = icmp sge i32 %x, 9 118 call void @use(i1 %c.5) 119 120 %x.next = add nsw i32 %x, 1 121 br label %loop.header 122 123exit: 124 %c.6 = icmp sgt i32 %y, 10 125 call void @use(i1 %c.6) 126 ret void 127} 128 129define void @loop_count_down(i32 %y, i1 %c, i32 %n) { 130; CHECK-LABEL: @loop_count_down( 131; CHECK-NEXT: entry: 132; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]] 133; CHECK: loop.header: 134; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[X_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 135; CHECK-NEXT: [[C_1:%.*]] = icmp sge i32 [[X]], 0 136; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]] 137; CHECK: loop.latch: 138; CHECK-NEXT: [[F_1:%.*]] = icmp sle i32 [[X]], [[N]] 139; CHECK-NEXT: call void @use(i1 [[F_1]]) 140; CHECK-NEXT: [[T_1:%.*]] = icmp sgt i32 [[X]], [[N]] 141; CHECK-NEXT: call void @use(i1 [[T_1]]) 142; CHECK-NEXT: call void @use(i1 true) 143; CHECK-NEXT: call void @use(i1 true) 144; CHECK-NEXT: [[C_2:%.*]] = icmp sle i32 [[X]], 9 145; CHECK-NEXT: call void @use(i1 [[C_2]]) 146; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i32 [[X]], 9 147; CHECK-NEXT: call void @use(i1 [[C_3]]) 148; CHECK-NEXT: [[C_4:%.*]] = icmp sge i32 [[X]], 1 149; CHECK-NEXT: call void @use(i1 [[C_4]]) 150; CHECK-NEXT: [[C_5:%.*]] = icmp sge i32 [[X]], 2 151; CHECK-NEXT: call void @use(i1 [[C_5]]) 152; CHECK-NEXT: [[X_NEXT]] = add nsw i32 [[X]], 1 153; CHECK-NEXT: br label [[LOOP_HEADER]] 154; CHECK: exit: 155; CHECK-NEXT: [[C_6:%.*]] = icmp sgt i32 [[Y:%.*]], 10 156; CHECK-NEXT: call void @use(i1 [[C_6]]) 157; CHECK-NEXT: ret void 158; 159entry: 160 br i1 %c, label %loop.header, label %exit 161 162loop.header: 163 %x = phi i32 [ %n, %entry ], [ %x.next, %loop.latch ] 164 %c.1 = icmp sge i32 %x, 0 165 br i1 %c.1, label %loop.latch, label %exit 166 167loop.latch: 168 %f.1 = icmp sle i32 %x, %n 169 call void @use(i1 %f.1) 170 %t.1 = icmp sgt i32 %x, %n 171 call void @use(i1 %t.1) 172 %t.2 = icmp sge i32 %x, 0 173 call void @use(i1 %t.2) 174 %t.3 = icmp sge i32 %x, -1 175 call void @use(i1 %t.3) 176 177 %c.2 = icmp sle i32 %x, 9 178 call void @use(i1 %c.2) 179 %c.3 = icmp sgt i32 %x, 9 180 call void @use(i1 %c.3) 181 %c.4 = icmp sge i32 %x, 1 182 call void @use(i1 %c.4) 183 %c.5 = icmp sge i32 %x, 2 184 call void @use(i1 %c.5) 185 186 %x.next = add nsw i32 %x, 1 187 br label %loop.header 188 189exit: 190 %c.6 = icmp sgt i32 %y, 10 191 call void @use(i1 %c.6) 192 ret void 193} 194 195define void @loop_latch_may_not_executed(i32 %y, i1 %c, i32 %n) { 196; CHECK-LABEL: @loop_latch_may_not_executed( 197; CHECK-NEXT: entry: 198; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]] 199; CHECK: loop.header: 200; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 201; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[X]], [[N:%.*]] 202; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]] 203; CHECK: loop.latch: 204; CHECK-NEXT: call void @use(i1 false) 205; CHECK-NEXT: call void @use(i1 true) 206; CHECK-NEXT: [[C_2:%.*]] = icmp ule i32 [[X]], 9 207; CHECK-NEXT: call void @use(i1 [[C_2]]) 208; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[X]], 9 209; CHECK-NEXT: call void @use(i1 [[C_3]]) 210; CHECK-NEXT: [[X_NEXT]] = add i32 [[X]], 1 211; CHECK-NEXT: br label [[LOOP_HEADER]] 212; CHECK: exit: 213; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[Y:%.*]], 10 214; CHECK-NEXT: call void @use(i1 [[C_4]]) 215; CHECK-NEXT: ret void 216; 217entry: 218 br i1 %c, label %loop.header, label %exit 219 220loop.header: 221 %x = phi i32 [ 0, %entry ], [ %x.next, %loop.latch ] 222 %c.1 = icmp ugt i32 %x, %n 223 br i1 %c.1, label %loop.latch, label %exit 224 225loop.latch: 226 %f.1 = icmp ule i32 %x, %n 227 call void @use(i1 %f.1) 228 %t.1 = icmp ugt i32 %x, %n 229 call void @use(i1 %t.1) 230 231 %c.2 = icmp ule i32 %x, 9 232 call void @use(i1 %c.2) 233 %c.3 = icmp ugt i32 %x, 9 234 call void @use(i1 %c.3) 235 236 %x.next = add i32 %x, 1 237 br label %loop.header 238 239exit: 240 %c.4 = icmp ugt i32 %y, 10 241 call void @use(i1 %c.4) 242 ret void 243} 244 245define void @loop_latch_not_executed_constant_bound(i32 %y, i1 %c) { 246; CHECK-LABEL: @loop_latch_not_executed_constant_bound( 247; CHECK-NEXT: entry: 248; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP_HEADER:%.*]], label [[EXIT:%.*]] 249; CHECK: loop.header: 250; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 251; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[X]], 10 252; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_LATCH]], label [[EXIT]] 253; CHECK: loop.latch: 254; CHECK-NEXT: call void @use(i1 false) 255; CHECK-NEXT: call void @use(i1 true) 256; CHECK-NEXT: call void @use(i1 false) 257; CHECK-NEXT: call void @use(i1 true) 258; CHECK-NEXT: [[X_NEXT]] = add i32 [[X]], 1 259; CHECK-NEXT: br label [[LOOP_HEADER]] 260; CHECK: exit: 261; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[Y:%.*]], 10 262; CHECK-NEXT: call void @use(i1 [[C_4]]) 263; CHECK-NEXT: ret void 264; 265entry: 266 br i1 %c, label %loop.header, label %exit 267 268loop.header: 269 %x = phi i32 [ 0, %entry ], [ %x.next, %loop.latch ] 270 %c.1 = icmp ugt i32 %x, 10 271 br i1 %c.1, label %loop.latch, label %exit 272 273loop.latch: 274 %t.1 = icmp ule i32 %x, 10 275 call void @use(i1 %t.1) 276 %f.1 = icmp ugt i32 %x, 10 277 call void @use(i1 %f.1) 278 279 %c.2 = icmp ule i32 %x, 9 280 call void @use(i1 %c.2) 281 %c.3 = icmp ugt i32 %x, 9 282 call void @use(i1 %c.3) 283 284 %x.next = add i32 %x, 1 285 br label %loop.header 286 287exit: 288 %c.4 = icmp ugt i32 %y, 10 289 call void @use(i1 %c.4) 290 ret void 291} 292 293 294define void @loop_iv_cond_variable_bound(i32 %n) { 295; CHECK-LABEL: @loop_iv_cond_variable_bound( 296; CHECK-NEXT: entry: 297; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 298; CHECK: loop.header: 299; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 300; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], [[N:%.*]] 301; CHECK-NEXT: call void @use(i1 [[T_1]]) 302; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0 303; CHECK-NEXT: call void @use(i1 [[T_2]]) 304; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1 305; CHECK-NEXT: call void @use(i1 [[T_3]]) 306; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], [[N]] 307; CHECK-NEXT: call void @use(i1 [[C_1]]) 308; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1 309; CHECK-NEXT: call void @use(i1 [[C_2]]) 310; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV]], [[N]] 311; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 312; CHECK: loop.latch: 313; CHECK-NEXT: call void @use(i1 true) 314; CHECK-NEXT: [[C_3:%.*]] = icmp ult i32 [[IV]], 2 315; CHECK-NEXT: call void @use(i1 [[C_3]]) 316; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[IV]], 1 317; CHECK-NEXT: call void @use(i1 [[C_4]]) 318; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 319; CHECK-NEXT: br label [[LOOP_HEADER]] 320; CHECK: exit: 321; CHECK-NEXT: ret void 322; 323entry: 324 br label %loop.header 325 326loop.header: 327 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 328 %t.1 = icmp ule i32 %iv, %n 329 call void @use(i1 %t.1) 330 %t.2 = icmp sge i32 %iv, 0 331 call void @use(i1 %t.2) 332 %t.3 = icmp sge i32 %iv, -1 333 call void @use(i1 %t.3) 334 335 %c.1 = icmp ult i32 %iv, %n 336 call void @use(i1 %c.1) 337 %c.2 = icmp ugt i32 %iv, 1 338 call void @use(i1 %c.2) 339 340 %cmp = icmp ult i32 %iv, %n 341 br i1 %cmp, label %loop.latch, label %exit 342 343loop.latch: 344 %t.4 = icmp ule i32 %iv, %n 345 call void @use(i1 %t.4) 346 347 %c.3 = icmp ult i32 %iv, 2 348 call void @use(i1 %c.3) 349 %c.4 = icmp ugt i32 %iv, 1 350 call void @use(i1 %c.4) 351 352 %iv.next = add nuw nsw i32 %iv, 1 353 br label %loop.header 354 355exit: 356 ret void 357} 358 359define void @loop_iv_cond_constant_bound() { 360; CHECK-LABEL: @loop_iv_cond_constant_bound( 361; CHECK-NEXT: entry: 362; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] 363; CHECK: loop.header: 364; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] 365; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], 2 366; CHECK-NEXT: call void @use(i1 [[T_1]]) 367; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0 368; CHECK-NEXT: call void @use(i1 [[T_2]]) 369; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1 370; CHECK-NEXT: call void @use(i1 [[T_3]]) 371; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], 2 372; CHECK-NEXT: call void @use(i1 [[C_1]]) 373; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1 374; CHECK-NEXT: call void @use(i1 [[C_2]]) 375; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV]], 2 376; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_LATCH]], label [[EXIT:%.*]] 377; CHECK: loop.latch: 378; CHECK-NEXT: call void @use(i1 true) 379; CHECK-NEXT: call void @use(i1 true) 380; CHECK-NEXT: call void @use(i1 false) 381; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 382; CHECK-NEXT: br label [[LOOP_HEADER]] 383; CHECK: exit: 384; CHECK-NEXT: ret void 385; 386entry: 387 br label %loop.header 388 389loop.header: 390 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ] 391 %t.1 = icmp ule i32 %iv, 2 392 call void @use(i1 %t.1) 393 %t.2 = icmp sge i32 %iv, 0 394 call void @use(i1 %t.2) 395 %t.3 = icmp sge i32 %iv, -1 396 call void @use(i1 %t.3) 397 398 %c.1 = icmp ult i32 %iv, 2 399 call void @use(i1 %c.1) 400 %c.2 = icmp ugt i32 %iv, 1 401 call void @use(i1 %c.2) 402 403 %cmp = icmp ult i32 %iv, 2 404 br i1 %cmp, label %loop.latch, label %exit 405 406loop.latch: 407 %t.4 = icmp ule i32 %iv, 2 408 call void @use(i1 %t.4) 409 410 %c.3 = icmp ult i32 %iv, 2 411 call void @use(i1 %c.3) 412 %c.4 = icmp ugt i32 %iv, 1 413 call void @use(i1 %c.4) 414 415 %iv.next = add nuw nsw i32 %iv, 1 416 br label %loop.header 417 418exit: 419 ret void 420} 421