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