1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=indvars -S < %s | FileCheck %s 3 4; PR59777 5define i2 @iv_hoist_nsw_poison(i2 %arg) { 6; CHECK-LABEL: @iv_hoist_nsw_poison( 7; CHECK-NEXT: bb: 8; CHECK-NEXT: br label [[BB1:%.*]] 9; CHECK: bb1: 10; CHECK-NEXT: [[DOT07:%.*]] = phi i2 [ 1, [[BB:%.*]] ], [ [[I:%.*]], [[BB1]] ] 11; CHECK-NEXT: [[I]] = add nuw i2 [[DOT07]], 1 12; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 1, [[ARG:%.*]] 13; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[COMMON_RET:%.*]], label [[BB1]] 14; CHECK: common.ret: 15; CHECK-NEXT: [[I2_LCSSA:%.*]] = phi i2 [ [[I]], [[BB1]] ] 16; CHECK-NEXT: ret i2 [[I2_LCSSA]] 17; 18bb: 19 br label %bb1 20 21bb1: ; preds = %bb1, %bb 22 %.07 = phi i2 [ 1, %bb ], [ %i, %bb1 ] 23 %.0 = phi i2 [ 1, %bb ], [ %i2, %bb1 ] 24 %i = add nsw i2 %.07, 1 25 %i2 = add i2 %.0, 1 26 %.not.not = icmp ult i2 %.07, %arg 27 br i1 %.not.not, label %common.ret, label %bb1 28 29common.ret: ; preds = %bb1 30 ret i2 %i2 31} 32 33define i4 @iv_hoist_nsw_poison2(i4 %0, i4 %end, i4 %start) { 34; CHECK-LABEL: @iv_hoist_nsw_poison2( 35; CHECK-NEXT: entry: 36; CHECK-NEXT: br label [[LOOP:%.*]] 37; CHECK: loop: 38; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 39; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1 40; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[IV_0]], [[END:%.*]] 41; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 42; CHECK: exit: 43; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 44; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 45; 46entry: 47 br label %loop 48 49loop: 50 %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ] 51 %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ] 52 %iv.0.next = add i4 %iv.0, 1 53 %iv.1.next = add nsw i4 %iv.1, 1 54 %.not.not = icmp ult i4 %iv.0, %end 55 br i1 %.not.not, label %exit, label %loop 56 57exit: 58 ret i4 %iv.1.next 59} 60 61define i2 @iv_hoist_both_adds_nsw(i2 %arg) { 62; CHECK-LABEL: @iv_hoist_both_adds_nsw( 63; CHECK-NEXT: bb: 64; CHECK-NEXT: br label [[LOOP:%.*]] 65; CHECK: loop: 66; CHECK-NEXT: [[IV_0:%.*]] = phi i2 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 67; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i2 [[IV_0]], 1 68; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 1, [[ARG:%.*]] 69; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 70; CHECK: exit: 71; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i2 [ [[IV_0_NEXT]], [[LOOP]] ] 72; CHECK-NEXT: ret i2 [[IV_1_NEXT_LCSSA]] 73; 74bb: 75 br label %loop 76 77loop: 78 %iv.0 = phi i2 [ 1, %bb ], [ %iv.0.next, %loop ] 79 %iv.1 = phi i2 [ 1, %bb ], [ %iv.1.next, %loop ] 80 %iv.0.next = add nsw i2 %iv.0, 1 81 %iv.1.next = add nsw i2 %iv.1, 1 82 %.not.not = icmp ult i2 %iv.0, %arg 83 br i1 %.not.not, label %exit, label %loop 84 85exit: 86 ret i2 %iv.1.next 87} 88 89define i4 @iv_hoist_both_adds_nsw_extra_use(i4 %arg) { 90; CHECK-LABEL: @iv_hoist_both_adds_nsw_extra_use( 91; CHECK-NEXT: bb: 92; CHECK-NEXT: br label [[LOOP:%.*]] 93; CHECK: loop: 94; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 95; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1 96; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 97; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 98; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]] 99; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 100; CHECK: exit: 101; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 102; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 103; 104bb: 105 br label %loop 106 107loop: 108 %iv.0 = phi i4 [ 1, %bb ], [ %iv.0.next, %loop ] 109 %iv.1 = phi i4 [ 1, %bb ], [ %iv.1.next, %loop ] 110 %iv.0.next = add nsw i4 %iv.0, 1 111 call void @use(i4 %iv.0.next) 112 %iv.1.next = add nsw i4 %iv.1, 1 113 call void @use(i4 %iv.1.next) 114 %.not.not = icmp ult i4 %iv.0, %arg 115 br i1 %.not.not, label %exit, label %loop 116 117exit: 118 ret i4 %iv.1.next 119} 120 121define i4 @iv_hoist_both_adds_nsw_extra_use_incs_reordered(i4 %arg) { 122; CHECK-LABEL: @iv_hoist_both_adds_nsw_extra_use_incs_reordered( 123; CHECK-NEXT: bb: 124; CHECK-NEXT: br label [[LOOP:%.*]] 125; CHECK: loop: 126; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ 1, [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 127; CHECK-NEXT: [[IV_0_NEXT]] = add nuw nsw i4 [[IV_0]], 1 128; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 129; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 130; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 1, [[ARG:%.*]] 131; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 132; CHECK: exit: 133; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 134; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 135; 136bb: 137 br label %loop 138 139loop: 140 %iv.0 = phi i4 [ 1, %bb ], [ %iv.0.next, %loop ] 141 %iv.1 = phi i4 [ 1, %bb ], [ %iv.1.next, %loop ] 142 %iv.1.next = add nsw i4 %iv.1, 1 143 call void @use(i4 %iv.1.next) 144 %iv.0.next = add nsw i4 %iv.0, 1 145 call void @use(i4 %iv.0.next) 146 %.not.not = icmp ult i4 %iv.0, %arg 147 br i1 %.not.not, label %exit, label %loop 148 149exit: 150 ret i4 %iv.1.next 151} 152 153define i4 @iv_hoist_nsw_poison_extra_use(i4 %0, i4 %end, i4 %start) { 154; CHECK-LABEL: @iv_hoist_nsw_poison_extra_use( 155; CHECK-NEXT: entry: 156; CHECK-NEXT: br label [[LOOP:%.*]] 157; CHECK: loop: 158; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 159; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1 160; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 161; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[IV_0]], [[END:%.*]] 162; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 163; CHECK: exit: 164; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 165; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 166; 167entry: 168 br label %loop 169 170loop: 171 %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ] 172 %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ] 173 %iv.0.next = add i4 %iv.0, 1 174 call void @use(i4 %iv.0.next) 175 %iv.1.next = add nsw i4 %iv.1, 1 176 %.not.not = icmp ult i4 %iv.0, %end 177 br i1 %.not.not, label %exit, label %loop 178 179exit: 180 ret i4 %iv.1.next 181} 182 183declare void @use(i4) 184 185define i2 @iv_hoist_nuw_poison(i2 %arg, i2 %start) { 186; CHECK-LABEL: @iv_hoist_nuw_poison( 187; CHECK-NEXT: bb: 188; CHECK-NEXT: br label [[BB1:%.*]] 189; CHECK: bb1: 190; CHECK-NEXT: [[DOT07:%.*]] = phi i2 [ [[START:%.*]], [[BB:%.*]] ], [ [[I:%.*]], [[BB1]] ] 191; CHECK-NEXT: [[I]] = add i2 [[DOT07]], 1 192; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 [[START]], [[ARG:%.*]] 193; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[COMMON_RET:%.*]], label [[BB1]] 194; CHECK: common.ret: 195; CHECK-NEXT: [[I2_LCSSA:%.*]] = phi i2 [ [[I]], [[BB1]] ] 196; CHECK-NEXT: ret i2 [[I2_LCSSA]] 197; 198bb: 199 br label %bb1 200 201bb1: ; preds = %bb1, %bb 202 %.07 = phi i2 [ %start, %bb ], [ %i, %bb1 ] 203 %.0 = phi i2 [ %start, %bb ], [ %i2, %bb1 ] 204 %i = add nuw i2 %.07, 1 205 %i2 = add i2 %.0, 1 206 %.not.not = icmp ult i2 %.07, %arg 207 br i1 %.not.not, label %common.ret, label %bb1 208 209common.ret: ; preds = %bb1 210 ret i2 %i2 211} 212 213define i4 @iv_hoist_nuw_poison2(i4 %0, i4 %end, i4 %start) { 214; CHECK-LABEL: @iv_hoist_nuw_poison2( 215; CHECK-NEXT: entry: 216; CHECK-NEXT: br label [[LOOP:%.*]] 217; CHECK: loop: 218; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 219; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1 220; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[END:%.*]] 221; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 222; CHECK: exit: 223; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 224; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 225; 226entry: 227 br label %loop 228 229loop: 230 %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ] 231 %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ] 232 %iv.0.next = add i4 %iv.0, 1 233 %iv.1.next = add nuw i4 %iv.1, 1 234 %.not.not = icmp ult i4 %iv.0, %end 235 br i1 %.not.not, label %exit, label %loop 236 237exit: 238 ret i4 %iv.1.next 239} 240 241define i2 @iv_hoist_both_adds_nuw(i2 %arg, i2 %start) { 242; CHECK-LABEL: @iv_hoist_both_adds_nuw( 243; CHECK-NEXT: bb: 244; CHECK-NEXT: br label [[LOOP:%.*]] 245; CHECK: loop: 246; CHECK-NEXT: [[IV_0:%.*]] = phi i2 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 247; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i2 [[IV_0]], 1 248; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i2 [[START]], [[ARG:%.*]] 249; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 250; CHECK: exit: 251; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i2 [ [[IV_0_NEXT]], [[LOOP]] ] 252; CHECK-NEXT: ret i2 [[IV_1_NEXT_LCSSA]] 253; 254bb: 255 br label %loop 256 257loop: 258 %iv.0 = phi i2 [ %start, %bb ], [ %iv.0.next, %loop ] 259 %iv.1 = phi i2 [ %start, %bb ], [ %iv.1.next, %loop ] 260 %iv.0.next = add nuw i2 %iv.0, 1 261 %iv.1.next = add nuw i2 %iv.1, 1 262 %.not.not = icmp ult i2 %iv.0, %arg 263 br i1 %.not.not, label %exit, label %loop 264 265exit: 266 ret i2 %iv.1.next 267} 268 269define i4 @iv_hoist_both_adds_nuw_extra_use(i4 %arg, i4 %start) { 270; CHECK-LABEL: @iv_hoist_both_adds_nuw_extra_use( 271; CHECK-NEXT: bb: 272; CHECK-NEXT: br label [[LOOP:%.*]] 273; CHECK: loop: 274; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 275; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1 276; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 277; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 278; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]] 279; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 280; CHECK: exit: 281; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 282; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 283; 284bb: 285 br label %loop 286 287loop: 288 %iv.0 = phi i4 [ %start, %bb ], [ %iv.0.next, %loop ] 289 %iv.1 = phi i4 [ %start, %bb ], [ %iv.1.next, %loop ] 290 %iv.0.next = add nuw i4 %iv.0, 1 291 call void @use(i4 %iv.0.next) 292 %iv.1.next = add nuw i4 %iv.1, 1 293 call void @use(i4 %iv.1.next) 294 %.not.not = icmp ult i4 %iv.0, %arg 295 br i1 %.not.not, label %exit, label %loop 296 297exit: 298 ret i4 %iv.1.next 299} 300 301define i4 @iv_hoist_both_adds_nuw_extra_use_incs_reordered(i4 %arg, i4 %start) { 302; CHECK-LABEL: @iv_hoist_both_adds_nuw_extra_use_incs_reordered( 303; CHECK-NEXT: bb: 304; CHECK-NEXT: br label [[LOOP:%.*]] 305; CHECK: loop: 306; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[BB:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 307; CHECK-NEXT: [[IV_0_NEXT]] = add nuw i4 [[IV_0]], 1 308; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 309; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 310; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[ARG:%.*]] 311; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 312; CHECK: exit: 313; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 314; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 315; 316bb: 317 br label %loop 318 319loop: 320 %iv.0 = phi i4 [ %start, %bb ], [ %iv.0.next, %loop ] 321 %iv.1 = phi i4 [ %start, %bb ], [ %iv.1.next, %loop ] 322 %iv.1.next = add nuw i4 %iv.1, 1 323 call void @use(i4 %iv.1.next) 324 %iv.0.next = add nuw i4 %iv.0, 1 325 call void @use(i4 %iv.0.next) 326 %.not.not = icmp ult i4 %iv.0, %arg 327 br i1 %.not.not, label %exit, label %loop 328 329exit: 330 ret i4 %iv.1.next 331} 332 333define i4 @iv_hoist_nuw_poison_extra_use(i4 %0, i4 %end, i4 %start) { 334; CHECK-LABEL: @iv_hoist_nuw_poison_extra_use( 335; CHECK-NEXT: entry: 336; CHECK-NEXT: br label [[LOOP:%.*]] 337; CHECK: loop: 338; CHECK-NEXT: [[IV_0:%.*]] = phi i4 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_0_NEXT:%.*]], [[LOOP]] ] 339; CHECK-NEXT: [[IV_0_NEXT]] = add i4 [[IV_0]], 1 340; CHECK-NEXT: call void @use(i4 [[IV_0_NEXT]]) 341; CHECK-NEXT: [[DOTNOT_NOT:%.*]] = icmp ult i4 [[START]], [[END:%.*]] 342; CHECK-NEXT: br i1 [[DOTNOT_NOT]], label [[EXIT:%.*]], label [[LOOP]] 343; CHECK: exit: 344; CHECK-NEXT: [[IV_1_NEXT_LCSSA:%.*]] = phi i4 [ [[IV_0_NEXT]], [[LOOP]] ] 345; CHECK-NEXT: ret i4 [[IV_1_NEXT_LCSSA]] 346; 347entry: 348 br label %loop 349 350loop: 351 %iv.0 = phi i4 [ %start, %entry ], [ %iv.0.next, %loop ] 352 %iv.1 = phi i4 [ %start, %entry ], [ %iv.1.next, %loop ] 353 %iv.0.next = add i4 %iv.0, 1 354 call void @use(i4 %iv.0.next) 355 %iv.1.next = add nuw i4 %iv.1, 1 356 %.not.not = icmp ult i4 %iv.0, %end 357 br i1 %.not.not, label %exit, label %loop 358 359exit: 360 ret i4 %iv.1.next 361} 362