1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=indvars -S | FileCheck %s 3 4define void @test1() nounwind { 5; CHECK-LABEL: @test1( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: br label [[BB:%.*]] 8; CHECK: bb: 9; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ] 10; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double 11; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0:[0-9]+]] 12; CHECK-NEXT: [[DOTINT]] = add nuw nsw i32 [[IV_INT]], 1 13; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[DOTINT]], 10000 14; CHECK-NEXT: br i1 [[TMP1]], label [[BB]], label [[RETURN:%.*]] 15; CHECK: return: 16; CHECK-NEXT: ret void 17; 18entry: 19 br label %bb 20 21bb: ; preds = %bb, %entry 22 %iv = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] 23 %0 = tail call i32 @foo(double %iv) nounwind 24 %1 = fadd double %iv, 1.000000e+00 25 %2 = fcmp olt double %1, 1.000000e+04 26 br i1 %2, label %bb, label %return 27 28return: ; preds = %bb 29 ret void 30} 31 32declare i32 @foo(double) 33 34define void @test2() nounwind { 35; CHECK-LABEL: @test2( 36; CHECK-NEXT: entry: 37; CHECK-NEXT: br label [[BB:%.*]] 38; CHECK: bb: 39; CHECK-NEXT: [[IV_INT:%.*]] = phi i32 [ -10, [[ENTRY:%.*]] ], [ [[DOTINT:%.*]], [[BB]] ] 40; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[IV_INT]] to double 41; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[INDVAR_CONV]]) #[[ATTR0]] 42; CHECK-NEXT: [[DOTINT]] = add nsw i32 [[IV_INT]], 2 43; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[DOTINT]], -1 44; CHECK-NEXT: br i1 [[TMP1]], label [[BB]], label [[RETURN:%.*]] 45; CHECK: return: 46; CHECK-NEXT: ret void 47; 48entry: 49 br label %bb 50 51bb: ; preds = %bb, %entry 52 %iv = phi double [ -10.000000e+00, %entry ], [ %1, %bb ] 53 %0 = tail call i32 @foo(double %iv) nounwind 54 %1 = fadd double %iv, 2.000000e+00 55 %2 = fcmp olt double %1, -1.000000e+00 56 br i1 %2, label %bb, label %return 57 58return: ; preds = %bb 59 ret void 60} 61 62 63define void @test3() nounwind { 64; CHECK-LABEL: @test3( 65; CHECK-NEXT: entry: 66; CHECK-NEXT: br label [[BB:%.*]] 67; CHECK: bb: 68; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double 0.000000e+00) #[[ATTR0]] 69; CHECK-NEXT: br i1 false, label [[BB]], label [[RETURN:%.*]] 70; CHECK: return: 71; CHECK-NEXT: ret void 72; 73entry: 74 br label %bb 75 76bb: ; preds = %bb, %entry 77 %iv = phi double [ 0.000000e+00, %entry ], [ %1, %bb ] 78 %0 = tail call i32 @foo(double %iv) nounwind 79 %1 = fadd double %iv, 1.000000e+00 80 %2 = fcmp olt double %1, -1.000000e+00 81 br i1 %2, label %bb, label %return 82 83return: 84 ret void 85} 86 87define void @test4() nounwind { 88; CHECK-LABEL: @test4( 89; CHECK-NEXT: entry: 90; CHECK-NEXT: br label [[BB:%.*]] 91; CHECK: bb: 92; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double 4.000000e+01) #[[ATTR0]] 93; CHECK-NEXT: br i1 false, label [[BB]], label [[RETURN:%.*]] 94; CHECK: return: 95; CHECK-NEXT: ret void 96; 97entry: 98 br label %bb 99 100bb: ; preds = %bb, %entry 101 %iv = phi double [ 40.000000e+00, %entry ], [ %1, %bb ] 102 %0 = tail call i32 @foo(double %iv) nounwind 103 %1 = fadd double %iv, -1.000000e+00 104 %2 = fcmp olt double %1, 1.000000e+00 105 br i1 %2, label %bb, label %return 106 107return: 108 ret void 109} 110 111; PR6761 112define void @test5() nounwind { 113; <label>:0 114; CHECK-LABEL: @test5( 115; CHECK-NEXT: br label [[TMP1:%.*]] 116; CHECK: 1: 117; CHECK-NEXT: [[DOTINT:%.*]] = phi i32 [ 9, [[TMP0:%.*]] ], [ [[DOTINT1:%.*]], [[TMP1]] ] 118; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @foo(double 0.000000e+00) 119; CHECK-NEXT: [[DOTINT1]] = add nsw i32 [[DOTINT]], -1 120; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[DOTINT1]], 0 121; CHECK-NEXT: br i1 [[TMP3]], label [[EXIT:%.*]], label [[TMP1]] 122; CHECK: exit: 123; CHECK-NEXT: ret void 124; 125 br label %1 126 127; <label>:1 128 %2 = phi double [ 9.000000e+00, %0 ], [ %4, %1 ] 129 %3 = tail call i32 @foo(double 0.0) 130 %4 = fadd double %2, -1.000000e+00 131 %5 = fcmp ult double %4, 0.000000e+00 132 br i1 %5, label %exit, label %1 133 134exit: 135 ret void 136} 137 138define double @test_max_be() { 139; CHECK-LABEL: @test_max_be( 140; CHECK-NEXT: bb4: 141; CHECK-NEXT: br label [[BB8:%.*]] 142; CHECK: bb8: 143; CHECK-NEXT: [[TMP10:%.*]] = phi double [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ] 144; CHECK-NEXT: [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ] 145; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to double 146; CHECK-NEXT: [[TMP12]] = fadd double [[TMP10]], [[INDVAR_CONV]] 147; CHECK-NEXT: [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1 148; CHECK-NEXT: [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999 149; CHECK-NEXT: br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]] 150; CHECK: bb22: 151; CHECK-NEXT: br i1 true, label [[BB8]], label [[BB6]] 152; CHECK: bb6: 153; CHECK-NEXT: [[TMP12_LCSSA:%.*]] = phi double [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ] 154; CHECK-NEXT: ret double [[TMP12_LCSSA]] 155; 156bb4: 157 br label %bb8 158 159bb8: 160 %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ] 161 %tmp10 = phi double [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ] 162 %tmp11 = phi double [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ] 163 %tmp12 = fadd double %tmp10, %tmp11 164 %tmp13 = fadd double %tmp11, 1.000000e+00 165 %tmp14 = fcmp olt double %tmp13, 9.999900e+04 166 br i1 %tmp14, label %bb22, label %bb6 167 168bb22: 169 %tmp23 = add nuw nsw i64 %tmp9, 1 170 %tmp24 = icmp ult i64 %tmp9, 1048576 171 br i1 %tmp24, label %bb8, label %bb6 172 173bb6: 174 ret double %tmp12 175} 176 177define float @test_max_be2() { 178; CHECK-LABEL: @test_max_be2( 179; CHECK-NEXT: bb4: 180; CHECK-NEXT: br label [[BB8:%.*]] 181; CHECK: bb8: 182; CHECK-NEXT: [[TMP10:%.*]] = phi float [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ] 183; CHECK-NEXT: [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ] 184; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to float 185; CHECK-NEXT: [[TMP12]] = fadd float [[TMP10]], [[INDVAR_CONV]] 186; CHECK-NEXT: [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1 187; CHECK-NEXT: [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999 188; CHECK-NEXT: br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]] 189; CHECK: bb22: 190; CHECK-NEXT: br i1 true, label [[BB8]], label [[BB6]] 191; CHECK: bb6: 192; CHECK-NEXT: [[TMP12_LCSSA:%.*]] = phi float [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ] 193; CHECK-NEXT: ret float [[TMP12_LCSSA]] 194; 195bb4: 196 br label %bb8 197 198bb8: 199 %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ] 200 %tmp10 = phi float [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ] 201 %tmp11 = phi float [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ] 202 %tmp12 = fadd float %tmp10, %tmp11 203 %tmp13 = fadd float %tmp11, 1.000000e+00 204 %tmp14 = fcmp olt float %tmp13, 9.999900e+04 205 br i1 %tmp14, label %bb22, label %bb6 206 207bb22: 208 %tmp23 = add nuw nsw i64 %tmp9, 1 209 %tmp24 = icmp ult i64 %tmp9, 1048576 210 br i1 %tmp24, label %bb8, label %bb6 211 212bb6: 213 ret float %tmp12 214} 215 216; Bounds check 217define float @test_max_be3() { 218; CHECK-LABEL: @test_max_be3( 219; CHECK-NEXT: bb4: 220; CHECK-NEXT: br label [[BB8:%.*]] 221; CHECK: bb8: 222; CHECK-NEXT: [[TMP10:%.*]] = phi float [ 0.000000e+00, [[BB4:%.*]] ], [ [[TMP12:%.*]], [[BB22:%.*]] ] 223; CHECK-NEXT: [[TMP11_INT:%.*]] = phi i32 [ 0, [[BB4]] ], [ [[TMP13_INT:%.*]], [[BB22]] ] 224; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[TMP11_INT]] to float 225; CHECK-NEXT: [[TMP12]] = fadd float [[TMP10]], [[INDVAR_CONV]] 226; CHECK-NEXT: [[TMP13_INT]] = add nuw nsw i32 [[TMP11_INT]], 1 227; CHECK-NEXT: [[TMP14:%.*]] = icmp ult i32 [[TMP13_INT]], 99999 228; CHECK-NEXT: br i1 [[TMP14]], label [[BB22]], label [[BB6:%.*]] 229; CHECK: bb22: 230; CHECK-NEXT: br i1 true, label [[BB8]], label [[BB6]] 231; CHECK: bb6: 232; CHECK-NEXT: [[TMP12_LCSSA:%.*]] = phi float [ [[TMP12]], [[BB22]] ], [ [[TMP12]], [[BB8]] ] 233; CHECK-NEXT: ret float [[TMP12_LCSSA]] 234; 235bb4: 236 br label %bb8 237 238bb8: 239 %tmp9 = phi i64 [ 1, %bb4 ], [ %tmp23, %bb22 ] 240 %tmp10 = phi float [ 0.000000e+00, %bb4 ], [ %tmp12, %bb22 ] 241 %tmp11 = phi float [ 0.000000e+00, %bb4 ], [ %tmp13, %bb22 ] 242 %tmp12 = fadd float %tmp10, %tmp11 243 %tmp13 = fadd float %tmp11, 1.000000e+00 244 %tmp14 = fcmp olt float %tmp13, 9.999900e+04 245 br i1 %tmp14, label %bb22, label %bb6 246 247bb22: 248 %tmp23 = add nuw nsw i64 %tmp9, 1 249 ;; 2^23 = 16777215 250 %tmp24 = icmp ult i64 %tmp9, 16777215 251 br i1 %tmp24, label %bb8, label %bb6 252 253bb6: 254 ret float %tmp12 255} 256 257 258; Show that given a computeable exit count, we can remove an 259; fcmp of a casted integer IV. (TODO) 260define void @fcmp1() nounwind { 261; CHECK-LABEL: @fcmp1( 262; CHECK-NEXT: entry: 263; CHECK-NEXT: br label [[BB:%.*]] 264; CHECK: bb: 265; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 266; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], 20000 267; CHECK-NEXT: br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]] 268; CHECK: backedge: 269; CHECK-NEXT: [[IV_FP:%.*]] = sitofp i64 [[IV]] to double 270; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]] 271; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 272; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04 273; CHECK-NEXT: br i1 [[CMP2]], label [[BB]], label [[RETURN]] 274; CHECK: return: 275; CHECK-NEXT: ret void 276; 277entry: 278 br label %bb 279 280bb: ; preds = %bb, %entry 281 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] 282 %cmp1 = icmp slt i64 %iv, 20000 283 br i1 %cmp1, label %backedge, label %return 284 285backedge: 286 %iv.fp = sitofp i64 %iv to double 287 tail call i32 @foo(double %iv.fp) nounwind 288 %iv.next = add nsw nuw i64 %iv, 1 289 %cmp2 = fcmp olt double %iv.fp, 1.000000e+04 290 br i1 %cmp2, label %bb, label %return 291 292return: ; preds = %bb 293 ret void 294} 295 296define void @fcmp2() nounwind { 297; CHECK-LABEL: @fcmp2( 298; CHECK-NEXT: entry: 299; CHECK-NEXT: br label [[BB:%.*]] 300; CHECK: bb: 301; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 302; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], 2000 303; CHECK-NEXT: br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]] 304; CHECK: backedge: 305; CHECK-NEXT: [[IV_FP:%.*]] = sitofp i64 [[IV]] to double 306; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]] 307; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 308; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04 309; CHECK-NEXT: br i1 [[CMP2]], label [[BB]], label [[RETURN]] 310; CHECK: return: 311; CHECK-NEXT: ret void 312; 313entry: 314 br label %bb 315 316bb: ; preds = %bb, %entry 317 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] 318 %cmp1 = icmp slt i64 %iv, 2000 319 br i1 %cmp1, label %backedge, label %return 320 321backedge: 322 %iv.fp = sitofp i64 %iv to double 323 tail call i32 @foo(double %iv.fp) nounwind 324 %iv.next = add nsw nuw i64 %iv, 1 325 %cmp2 = fcmp olt double %iv.fp, 1.000000e+04 326 br i1 %cmp2, label %bb, label %return 327 328return: ; preds = %bb 329 ret void 330} 331 332define void @fcmp_neg1() nounwind { 333; CHECK-LABEL: @fcmp_neg1( 334; CHECK-NEXT: entry: 335; CHECK-NEXT: br label [[BB:%.*]] 336; CHECK: bb: 337; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 338; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[IV]], -20 339; CHECK-NEXT: br i1 [[CMP1]], label [[BACKEDGE]], label [[RETURN:%.*]] 340; CHECK: backedge: 341; CHECK-NEXT: [[IV_FP:%.*]] = sitofp i64 [[IV]] to double 342; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @foo(double [[IV_FP]]) #[[ATTR0]] 343; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1 344; CHECK-NEXT: [[CMP2:%.*]] = fcmp olt double [[IV_FP]], 1.000000e+04 345; CHECK-NEXT: br i1 [[CMP2]], label [[BB]], label [[RETURN]] 346; CHECK: return: 347; CHECK-NEXT: ret void 348; 349entry: 350 br label %bb 351 352bb: ; preds = %bb, %entry 353 %iv = phi i64 [ 0, %entry ], [ %iv.next, %backedge ] 354 ;; Range fact outside precise integer region 355 %cmp1 = icmp ult i64 %iv, -20 356 br i1 %cmp1, label %backedge, label %return 357 358backedge: 359 %iv.fp = sitofp i64 %iv to double 360 tail call i32 @foo(double %iv.fp) nounwind 361 %iv.next = add nuw i64 %iv, 1 362 %cmp2 = fcmp olt double %iv.fp, 1.000000e+04 363 br i1 %cmp2, label %bb, label %return 364 365return: ; preds = %bb 366 ret void 367} 368 369declare void @use.i16(i16) 370declare void @use.i32(i32) 371declare void @use.i64(i64) 372declare void @use.float(float) 373 374define void @pr55505_remove_redundant_fptosi_for_float_iv(i32 %index, ptr %dst) { 375; CHECK-LABEL: @pr55505_remove_redundant_fptosi_for_float_iv( 376; CHECK-NEXT: entry: 377; CHECK-NEXT: br label [[LOOP:%.*]] 378; CHECK: loop: 379; CHECK-NEXT: [[FLOAT_IV_INT:%.*]] = phi i32 [ 1000, [[ENTRY:%.*]] ], [ [[FLOAT_IV_NEXT_INT:%.*]], [[LOOP]] ] 380; CHECK-NEXT: [[INDVAR_CONV:%.*]] = sitofp i32 [[FLOAT_IV_INT]] to float 381; CHECK-NEXT: call void @use.float(float [[INDVAR_CONV]]) 382; CHECK-NEXT: call void @use.i32(i32 [[FLOAT_IV_INT]]) 383; CHECK-NEXT: [[FLOAT_IV_INT_TRUNC:%.*]] = trunc i32 [[FLOAT_IV_INT]] to i16 384; CHECK-NEXT: [[FLOAT_IV_INT_SEXT:%.*]] = sext i32 [[FLOAT_IV_INT]] to i64 385; CHECK-NEXT: call void @use.i16(i16 [[FLOAT_IV_INT_TRUNC]]) 386; CHECK-NEXT: call void @use.i64(i64 [[FLOAT_IV_INT_SEXT]]) 387; CHECK-NEXT: [[FLOAT_IV_INT_TRUNC2:%.*]] = trunc i32 [[FLOAT_IV_INT]] to i16 388; CHECK-NEXT: [[FLOAT_IV_INT_ZEXT:%.*]] = zext i32 [[FLOAT_IV_INT]] to i64 389; CHECK-NEXT: call void @use.i16(i16 [[FLOAT_IV_INT_TRUNC2]]) 390; CHECK-NEXT: call void @use.i64(i64 [[FLOAT_IV_INT_ZEXT]]) 391; CHECK-NEXT: [[FLOAT_IV_NEXT_INT]] = add nsw i32 [[FLOAT_IV_INT]], -1 392; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[FLOAT_IV_NEXT_INT]], 0 393; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 394; CHECK: exit: 395; CHECK-NEXT: ret void 396; 397entry: 398 br label %loop 399 400loop: 401 %float.iv = phi float [ 1.000000e+03, %entry ], [ %float.iv.next, %loop ] 402 call void @use.float(float %float.iv) 403 %conv.i32 = fptosi float %float.iv to i32 404 call void @use.i32(i32 %conv.i32) 405 %conv.i16 = fptosi float %float.iv to i16 406 %conv.i64 = fptosi float %float.iv to i64 407 call void @use.i16(i16 %conv.i16) 408 call void @use.i64(i64 %conv.i64) 409 %uconv.i16 = fptoui float %float.iv to i16 410 %uconv.i64 = fptoui float %float.iv to i64 411 call void @use.i16(i16 %uconv.i16) 412 call void @use.i64(i64 %uconv.i64) 413 %float.iv.next = fadd float %float.iv, -1.000000e+00 414 %cmp = fcmp ogt float %float.iv.next, 0.000000e+00 415 br i1 %cmp, label %loop, label %exit 416 417exit: 418 ret void 419} 420