1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4define i32 @fold(i32 %x) { 5; CHECK-LABEL: @fold( 6; CHECK-NEXT: [[Y:%.*]] = freeze i32 [[X:%.*]] 7; CHECK-NEXT: ret i32 [[Y]] 8; 9 %y = freeze i32 %x 10 %z = freeze i32 %y 11 ret i32 %z 12} 13 14define i32 @make_const() { 15; CHECK-LABEL: @make_const( 16; CHECK-NEXT: ret i32 10 17; 18 %x = freeze i32 10 19 ret i32 %x 20} 21 22define i32 @and_freeze_undef(i32 %x) { 23; CHECK-LABEL: @and_freeze_undef( 24; CHECK-NEXT: ret i32 0 25; 26 %f = freeze i32 undef 27 %res = and i32 %x, %f 28 ret i32 %res 29} 30 31declare void @use_i32(i32) 32declare void @use_p32(ptr) 33 34define i32 @and_freeze_undef_multipleuses(i32 %x) { 35; CHECK-LABEL: @and_freeze_undef_multipleuses( 36; CHECK-NEXT: call void @use_i32(i32 0) 37; CHECK-NEXT: ret i32 0 38; 39 %f = freeze i32 undef 40 %res = and i32 %x, %f 41 call void @use_i32(i32 %f) 42 ret i32 %res 43} 44 45define i32 @or_freeze_undef(i32 %x) { 46; CHECK-LABEL: @or_freeze_undef( 47; CHECK-NEXT: ret i32 -1 48; 49 %f = freeze i32 undef 50 %res = or i32 %x, %f 51 ret i32 %res 52} 53 54define i32 @or_freeze_undef_multipleuses(i32 %x) { 55; CHECK-LABEL: @or_freeze_undef_multipleuses( 56; CHECK-NEXT: call void @use_i32(i32 0) 57; CHECK-NEXT: ret i32 [[X:%.*]] 58; 59 %f = freeze i32 undef 60 %res = or i32 %x, %f 61 call void @use_i32(i32 %f) 62 ret i32 %res 63} 64 65declare void @use_i32_i1(i32, i1) 66 67define void @or_select_multipleuses(i32 %x, i1 %y) { 68; CHECK-LABEL: @or_select_multipleuses( 69; CHECK-NEXT: call void @use_i32_i1(i32 32, i1 [[Y:%.*]]) 70; CHECK-NEXT: ret void 71; 72 %f = freeze i1 undef 73 %a = select i1 %f, i32 %x, i32 32 ; prefers %f to be false 74 %b = or i1 %f, %y ; prefers %f to be true 75 call void @use_i32_i1(i32 %a, i1 %b) 76 ret void 77} 78 79define void @or_select_multipleuses_logical(i32 %x, i1 %y) { 80; CHECK-LABEL: @or_select_multipleuses_logical( 81; CHECK-NEXT: call void @use_i32_i1(i32 32, i1 [[Y:%.*]]) 82; CHECK-NEXT: ret void 83; 84 %f = freeze i1 undef 85 %a = select i1 %f, i32 %x, i32 32 ; prefers %f to be false 86 %b = select i1 %f, i1 true, i1 %y ; prefers %f to be true 87 call void @use_i32_i1(i32 %a, i1 %b) 88 ret void 89} 90 91define <3 x i4> @partial_undef_vec() { 92; CHECK-LABEL: @partial_undef_vec( 93; CHECK-NEXT: ret <3 x i4> <i4 0, i4 1, i4 0> 94; 95 %f = freeze <3 x i4> <i4 poison, i4 1, i4 undef> 96 ret <3 x i4> %f 97} 98 99; Move the freeze forward to prevent poison from spreading. 100 101define i32 @early_freeze_test1(i32 %x, i32 %y) { 102; CHECK-LABEL: @early_freeze_test1( 103; CHECK-NEXT: [[V1:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 104; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 105; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1_FR]], 1 106; CHECK-NEXT: [[V3:%.*]] = and i32 [[V2]], 2 107; CHECK-NEXT: ret i32 [[V3]] 108; 109 %v1 = add i32 %x, %y 110 %v2 = shl i32 %v1, 1 111 %v3 = and i32 %v2, 2 112 %v3.fr = freeze i32 %v3 113 ret i32 %v3.fr 114} 115 116define i1 @early_freeze_test2(ptr %ptr) { 117; CHECK-LABEL: @early_freeze_test2( 118; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[PTR:%.*]], align 4 119; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 120; CHECK-NEXT: [[V2:%.*]] = and i32 [[V1_FR]], 1 121; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V2]], 0 122; CHECK-NEXT: ret i1 [[COND]] 123; 124 %v1 = load i32, ptr %ptr 125 %v2 = and i32 %v1, 1 126 %cond = icmp eq i32 %v2, 0 127 %cond.fr = freeze i1 %cond 128 ret i1 %cond.fr 129} 130 131define i32 @early_freeze_test3(i32 %v1) { 132; CHECK-LABEL: @early_freeze_test3( 133; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1:%.*]] 134; CHECK-NEXT: [[V2:%.*]] = shl i32 [[V1_FR]], 1 135; CHECK-NEXT: [[V4:%.*]] = add i32 [[V2]], 3 136; CHECK-NEXT: ret i32 [[V4]] 137; 138 %v2 = shl i32 %v1, 1 139 %v3 = add nuw i32 %v2, 2 140 %v4 = or i32 %v3, 1 141 %v4.fr = freeze i32 %v4 142 ret i32 %v4.fr 143} 144 145; If replace all dominated uses of v to freeze(v). 146 147define void @freeze_dominated_uses_test1(i32 %v) { 148; CHECK-LABEL: @freeze_dominated_uses_test1( 149; CHECK-NEXT: [[V_FR:%.*]] = freeze i32 [[V:%.*]] 150; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 151; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 152; CHECK-NEXT: ret void 153; 154 %v.fr = freeze i32 %v 155 call void @use_i32(i32 %v) 156 call void @use_i32(i32 %v.fr) 157 ret void 158} 159 160define void @freeze_dominated_uses_test2(i32 %v) { 161; CHECK-LABEL: @freeze_dominated_uses_test2( 162; CHECK-NEXT: entry: 163; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 164; CHECK-NEXT: [[V_FR:%.*]] = freeze i32 [[V:%.*]] 165; CHECK-NEXT: call void @use_p32(ptr nonnull [[A]]) 166; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 167; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[V_FR]], 0 168; CHECK-NEXT: br i1 [[COND]], label [[BB0:%.*]], label [[BB1:%.*]] 169; CHECK: bb0: 170; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 171; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 172; CHECK-NEXT: br label [[END:%.*]] 173; CHECK: bb1: 174; CHECK-NEXT: call void @use_i32(i32 [[V_FR]]) 175; CHECK-NEXT: br label [[END]] 176; CHECK: end: 177; CHECK-NEXT: ret void 178; 179entry: 180 %a = alloca i32 181 call void @use_p32(ptr %a) 182 call void @use_i32(i32 %v) 183 %cond = icmp eq i32 %v, 0 184 br i1 %cond, label %bb0, label %bb1 185 186bb0: 187 %v.fr = freeze i32 %v 188 call void @use_i32(i32 %v.fr) 189 call void @use_i32(i32 %v) 190 br label %end 191 192bb1: 193 call void @use_i32(i32 %v) 194 br label %end 195 196end: 197 ret void 198} 199 200; If there is a duplicate freeze, it will be removed. 201 202define void @freeze_dominated_uses_test3(i32 %v, i1 %cond) { 203; CHECK-LABEL: @freeze_dominated_uses_test3( 204; CHECK-NEXT: entry: 205; CHECK-NEXT: [[V_FR1:%.*]] = freeze i32 [[V:%.*]] 206; CHECK-NEXT: call void @use_i32(i32 [[V_FR1]]) 207; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 208; CHECK: bb0: 209; CHECK-NEXT: call void @use_i32(i32 [[V_FR1]]) 210; CHECK-NEXT: br label [[END:%.*]] 211; CHECK: bb1: 212; CHECK-NEXT: call void @use_i32(i32 [[V_FR1]]) 213; CHECK-NEXT: br label [[END]] 214; CHECK: end: 215; CHECK-NEXT: ret void 216; 217entry: 218 %v.fr1 = freeze i32 %v 219 call void @use_i32(i32 %v.fr1) 220 br i1 %cond, label %bb0, label %bb1 221 222bb0: 223 %v.fr2 = freeze i32 %v 224 call void @use_i32(i32 %v.fr2) 225 br label %end 226 227bb1: 228 call void @use_i32(i32 %v) 229 br label %end 230 231end: 232 ret void 233} 234 235declare i32 @__CxxFrameHandler3(...) 236 237define void @freeze_dominated_uses_catchswitch(i1 %c, i32 %x) personality ptr @__CxxFrameHandler3 { 238; CHECK-LABEL: @freeze_dominated_uses_catchswitch( 239; CHECK-NEXT: entry: 240; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 241; CHECK: if.then: 242; CHECK-NEXT: invoke void @use_i32(i32 0) 243; CHECK-NEXT: to label [[CLEANUP:%.*]] unwind label [[CATCH_DISPATCH:%.*]] 244; CHECK: if.else: 245; CHECK-NEXT: invoke void @use_i32(i32 1) 246; CHECK-NEXT: to label [[CLEANUP]] unwind label [[CATCH_DISPATCH]] 247; CHECK: catch.dispatch: 248; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ [[X:%.*]], [[IF_ELSE]] ] 249; CHECK-NEXT: [[CS:%.*]] = catchswitch within none [label [[CATCH:%.*]], label %catch2] unwind to caller 250; CHECK: catch: 251; CHECK-NEXT: [[CP:%.*]] = catchpad within [[CS]] [ptr null, i32 64, ptr null] 252; CHECK-NEXT: [[PHI_FREEZE:%.*]] = freeze i32 [[PHI]] 253; CHECK-NEXT: call void @use_i32(i32 [[PHI_FREEZE]]) [ "funclet"(token [[CP]]) ] 254; CHECK-NEXT: unreachable 255; CHECK: catch2: 256; CHECK-NEXT: [[CP2:%.*]] = catchpad within [[CS]] [ptr null, i32 64, ptr null] 257; CHECK-NEXT: call void @use_i32(i32 [[PHI]]) [ "funclet"(token [[CP2]]) ] 258; CHECK-NEXT: unreachable 259; CHECK: cleanup: 260; CHECK-NEXT: ret void 261; 262entry: 263 br i1 %c, label %if.then, label %if.else 264 265if.then: 266 invoke void @use_i32(i32 0) 267 to label %cleanup unwind label %catch.dispatch 268 269if.else: 270 invoke void @use_i32(i32 1) 271 to label %cleanup unwind label %catch.dispatch 272 273catch.dispatch: 274 %phi = phi i32 [ 0, %if.then ], [ %x, %if.else ] 275 %cs = catchswitch within none [label %catch, label %catch2] unwind to caller 276 277catch: 278 %cp = catchpad within %cs [ptr null, i32 64, ptr null] 279 %phi.freeze = freeze i32 %phi 280 call void @use_i32(i32 %phi.freeze) [ "funclet"(token %cp) ] 281 unreachable 282 283catch2: 284 %cp2 = catchpad within %cs [ptr null, i32 64, ptr null] 285 call void @use_i32(i32 %phi) [ "funclet"(token %cp2) ] 286 unreachable 287 288cleanup: 289 ret void 290} 291 292declare i32 @get_i32() 293 294define i32 @freeze_use_in_different_branches(i1 %c) { 295; CHECK-LABEL: @freeze_use_in_different_branches( 296; CHECK-NEXT: entry: 297; CHECK-NEXT: [[X:%.*]] = call i32 @get_i32() 298; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 299; CHECK-NEXT: call void @use_i32(i32 0) 300; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] 301; CHECK: if: 302; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 303; CHECK-NEXT: ret i32 0 304; CHECK: else: 305; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 306; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 307; CHECK-NEXT: ret i32 1 308; 309entry: 310 %x = call i32 @get_i32() 311 call void @use_i32(i32 0) 312 br i1 %c, label %if, label %else 313 314if: 315 call void @use_i32(i32 %x) 316 ret i32 0 317 318else: 319 call void @use_i32(i32 %x) 320 %fr = freeze i32 %x 321 call void @use_i32(i32 %fr) 322 ret i32 1 323} 324 325define i32 @freeze_phi_use(i1 %c) { 326; CHECK-LABEL: @freeze_phi_use( 327; CHECK-NEXT: entry: 328; CHECK-NEXT: [[X:%.*]] = call i32 @get_i32() 329; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 330; CHECK-NEXT: call void @use_i32(i32 0) 331; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 332; CHECK: if: 333; CHECK-NEXT: br label [[JOIN]] 334; CHECK: join: 335; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[FR]], [[IF]] ], [ 0, [[ENTRY:%.*]] ] 336; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 337; CHECK-NEXT: ret i32 [[PHI]] 338; 339entry: 340 %x = call i32 @get_i32() 341 call void @use_i32(i32 0) 342 br i1 %c, label %if, label %join 343 344if: 345 br label %join 346 347join: 348 %phi = phi i32 [ %x, %if ], [ 0, %entry ] 349 %fr = freeze i32 %x 350 call void @use_i32(i32 %fr) 351 ret i32 %phi 352} 353 354define i32 @freeze_phi_followed_by_phi(i1 %c, i32 %y, i32 %z) { 355; CHECK-LABEL: @freeze_phi_followed_by_phi( 356; CHECK-NEXT: entry: 357; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]] 358; CHECK: if: 359; CHECK-NEXT: br label [[JOIN]] 360; CHECK: join: 361; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[Y:%.*]], [[IF]] ], [ [[Z:%.*]], [[ENTRY:%.*]] ] 362; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[Z]], [[IF]] ], [ [[Y]], [[ENTRY]] ] 363; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 364; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 365; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 366; CHECK-NEXT: ret i32 [[PHI]] 367; 368entry: 369 br i1 %c, label %if, label %join 370 371if: 372 br label %join 373 374join: 375 %x = phi i32 [ %y, %if ], [ %z, %entry ] 376 %phi = phi i32 [ %z, %if ], [ %y, %entry ] 377 call void @use_i32(i32 %x) 378 %fr = freeze i32 %x 379 call void @use_i32(i32 %fr) 380 ret i32 %phi 381} 382 383define i32 @freeze_invoke_use_in_phi(i1 %c) personality ptr undef { 384; CHECK-LABEL: @freeze_invoke_use_in_phi( 385; CHECK-NEXT: entry: 386; CHECK-NEXT: [[X:%.*]] = invoke i32 @get_i32() 387; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[INVOKE_UNWIND:%.*]] 388; CHECK: invoke.cont: 389; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[INVOKE_CONT]] ] 390; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 391; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 392; CHECK-NEXT: call void @use_i32(i32 [[PHI]]) 393; CHECK-NEXT: br label [[INVOKE_CONT]] 394; CHECK: invoke.unwind: 395; CHECK-NEXT: [[TMP0:%.*]] = landingpad i8 396; CHECK-NEXT: cleanup 397; CHECK-NEXT: unreachable 398; 399entry: 400 %x = invoke i32 @get_i32() 401 to label %invoke.cont unwind label %invoke.unwind 402 403invoke.cont: 404 %phi = phi i32 [ %x, %entry ], [ 0, %invoke.cont ] 405 %fr = freeze i32 %x 406 call void @use_i32(i32 %fr) 407 call void @use_i32(i32 %phi) 408 br label %invoke.cont 409 410invoke.unwind: 411 landingpad i8 cleanup 412 unreachable 413} 414 415define i32 @freeze_invoke_use_after_phi(i1 %c) personality ptr undef { 416; CHECK-LABEL: @freeze_invoke_use_after_phi( 417; CHECK-NEXT: entry: 418; CHECK-NEXT: [[X:%.*]] = invoke i32 @get_i32() 419; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[INVOKE_UNWIND:%.*]] 420; CHECK: invoke.cont: 421; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[INVOKE_CONT]] ] 422; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 423; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 424; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 425; CHECK-NEXT: call void @use_i32(i32 [[PHI]]) 426; CHECK-NEXT: br label [[INVOKE_CONT]] 427; CHECK: invoke.unwind: 428; CHECK-NEXT: [[TMP0:%.*]] = landingpad i8 429; CHECK-NEXT: cleanup 430; CHECK-NEXT: unreachable 431; 432entry: 433 %x = invoke i32 @get_i32() 434 to label %invoke.cont unwind label %invoke.unwind 435 436invoke.cont: 437 %phi = phi i32 [ %x, %entry ], [ 0, %invoke.cont ] 438 call void @use_i32(i32 %x) 439 %fr = freeze i32 %x 440 call void @use_i32(i32 %fr) 441 call void @use_i32(i32 %phi) 442 br label %invoke.cont 443 444invoke.unwind: 445 landingpad i8 cleanup 446 unreachable 447} 448 449define i32 @freeze_callbr_use_after_phi(i1 %c) { 450; CHECK-LABEL: @freeze_callbr_use_after_phi( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[X:%.*]] = callbr i32 asm sideeffect "", "=r"() #[[ATTR1:[0-9]+]] 453; CHECK-NEXT: to label [[CALLBR_CONT:%.*]] [] 454; CHECK: callbr.cont: 455; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ 0, [[CALLBR_CONT]] ] 456; CHECK-NEXT: call void @use_i32(i32 [[X]]) 457; CHECK-NEXT: [[FR:%.*]] = freeze i32 [[X]] 458; CHECK-NEXT: call void @use_i32(i32 [[FR]]) 459; CHECK-NEXT: call void @use_i32(i32 [[PHI]]) 460; CHECK-NEXT: br label [[CALLBR_CONT]] 461; 462entry: 463 %x = callbr i32 asm sideeffect "", "=r"() 464 to label %callbr.cont [] 465 466callbr.cont: 467 %phi = phi i32 [ %x, %entry ], [ 0, %callbr.cont ] 468 call void @use_i32(i32 %x) 469 %fr = freeze i32 %x 470 call void @use_i32(i32 %fr) 471 call void @use_i32(i32 %phi) 472 br label %callbr.cont 473} 474 475define i1 @combine_and_after_freezing_uses(i32 %x) { 476; CHECK-LABEL: @combine_and_after_freezing_uses( 477; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]] 478; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X_FR]], 15 479; CHECK-NEXT: [[AND:%.*]] = icmp eq i32 [[TMP1]], 15 480; CHECK-NEXT: ret i1 [[AND]] 481; 482 %and1 = and i32 %x, 4 483 %cmp1 = icmp ne i32 %and1, 0 484 %x.fr = freeze i32 %x 485 %and2 = and i32 %x.fr, 11 486 %cmp2 = icmp eq i32 %and2, 11 487 %and = and i1 %cmp1, %cmp2 488 ret i1 %and 489} 490 491declare i1 @mock_use(i64, i64) 492define i1 @fully_propagate_freeze(i32 %0, i32 noundef %1) { 493; CHECK-LABEL: @fully_propagate_freeze( 494; CHECK-NEXT: [[DOTFR:%.*]] = freeze i32 [[TMP0:%.*]] 495; CHECK-NEXT: [[DR:%.*]] = lshr i32 [[DOTFR]], 2 496; CHECK-NEXT: [[IDX1:%.*]] = zext nneg i32 [[DR]] to i64 497; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[DR]], 1 498; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD]], [[TMP1:%.*]] 499; CHECK-NEXT: [[IDX2:%.*]] = zext nneg i32 [[DR]] to i64 500; CHECK-NEXT: [[V:%.*]] = call i1 @mock_use(i64 [[IDX1]], i64 [[IDX2]]) 501; CHECK-NEXT: [[RET:%.*]] = and i1 [[V]], [[CMP]] 502; CHECK-NEXT: ret i1 [[RET]] 503; 504 %dr = lshr i32 %0, 2 505 %idx1 = zext i32 %dr to i64 506 %add = add i32 %dr, 1 507 %cmp = icmp slt i32 %add, %1 508 %cmp.fr = freeze i1 %cmp 509 %idx2 = zext i32 %dr to i64 510 %v = call i1 @mock_use(i64 %idx1, i64 %idx2) 511 %ret = and i1 %v, %cmp.fr 512 ret i1 %ret 513} 514 515define i32 @propagate_drop_flags_add(i32 %arg) { 516; CHECK-LABEL: @propagate_drop_flags_add( 517; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 518; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG_FR]], 2 519; CHECK-NEXT: ret i32 [[V1]] 520; 521 %v1 = add nsw nuw i32 %arg, 2 522 %v1.fr = freeze i32 %v1 523 ret i32 %v1.fr 524} 525 526define i32 @propagate_drop_flags_add_foldaway(i32 noundef %arg) { 527; CHECK-LABEL: @propagate_drop_flags_add_foldaway( 528; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG:%.*]], 2 529; CHECK-NEXT: ret i32 [[V1]] 530; 531 %v1 = add nsw nuw i32 %arg, 2 532 %v1.fr = freeze i32 %v1 533 ret i32 %v1.fr 534} 535 536define i32 @propagate_drop_flags_sub(i32 %arg) { 537; CHECK-LABEL: @propagate_drop_flags_sub( 538; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 539; CHECK-NEXT: [[V1:%.*]] = add i32 [[ARG_FR]], -2 540; CHECK-NEXT: ret i32 [[V1]] 541; 542 %v1 = sub nsw nuw i32 %arg, 2 543 %v1.fr = freeze i32 %v1 544 ret i32 %v1.fr 545} 546 547define i32 @propagate_drop_flags_mul(i32 %arg) { 548; CHECK-LABEL: @propagate_drop_flags_mul( 549; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 550; CHECK-NEXT: [[V1:%.*]] = shl i32 [[ARG_FR]], 1 551; CHECK-NEXT: ret i32 [[V1]] 552; 553 %v1 = mul nsw nuw i32 %arg, 2 554 %v1.fr = freeze i32 %v1 555 ret i32 %v1.fr 556} 557 558define i32 @propagate_drop_flags_udiv(i32 %arg) { 559; CHECK-LABEL: @propagate_drop_flags_udiv( 560; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 561; CHECK-NEXT: [[V11:%.*]] = lshr i32 [[ARG_FR]], 1 562; CHECK-NEXT: ret i32 [[V11]] 563; 564 %v1 = udiv exact i32 %arg, 2 565 %v1.fr = freeze i32 %v1 566 ret i32 %v1.fr 567} 568 569define i32 @propagate_drop_flags_sdiv(i32 %arg) { 570; CHECK-LABEL: @propagate_drop_flags_sdiv( 571; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 572; CHECK-NEXT: [[V1:%.*]] = ashr i32 [[ARG_FR]], 1 573; CHECK-NEXT: ret i32 [[V1]] 574; 575 %v1 = sdiv exact i32 %arg, 2 576 %v1.fr = freeze i32 %v1 577 ret i32 %v1.fr 578} 579 580define i32 @propagate_drop_shl1(i32 %arg) { 581; CHECK-LABEL: @propagate_drop_shl1( 582; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 583; CHECK-NEXT: [[V1:%.*]] = shl i32 [[ARG_FR]], 2 584; CHECK-NEXT: ret i32 [[V1]] 585; 586 %v1 = shl nsw nuw i32 %arg, 2 587 %v1.fr = freeze i32 %v1 588 ret i32 %v1.fr 589} 590 591define i32 @propagate_drop_shl2(i32 %arg, i32 %unknown) { 592; CHECK-LABEL: @propagate_drop_shl2( 593; CHECK-NEXT: [[V1:%.*]] = shl nuw nsw i32 [[ARG:%.*]], [[UNKNOWN:%.*]] 594; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 595; CHECK-NEXT: ret i32 [[V1_FR]] 596; 597 %v1 = shl nsw nuw i32 %arg, %unknown 598 %v1.fr = freeze i32 %v1 599 ret i32 %v1.fr 600} 601 602define i32 @propagate_drop_ashr1(i32 %arg) { 603; CHECK-LABEL: @propagate_drop_ashr1( 604; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 605; CHECK-NEXT: [[V1:%.*]] = ashr i32 [[ARG_FR]], 2 606; CHECK-NEXT: ret i32 [[V1]] 607; 608 %v1 = ashr exact i32 %arg, 2 609 %v1.fr = freeze i32 %v1 610 ret i32 %v1.fr 611} 612 613define i32 @propagate_drop_ashr2(i32 %arg, i32 %unknown) { 614; CHECK-LABEL: @propagate_drop_ashr2( 615; CHECK-NEXT: [[V1:%.*]] = ashr exact i32 [[ARG:%.*]], [[UNKNOWN:%.*]] 616; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 617; CHECK-NEXT: ret i32 [[V1_FR]] 618; 619 %v1 = ashr exact i32 %arg, %unknown 620 %v1.fr = freeze i32 %v1 621 ret i32 %v1.fr 622} 623 624define i32 @propagate_drop_lshr1(i32 %arg) { 625; CHECK-LABEL: @propagate_drop_lshr1( 626; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 627; CHECK-NEXT: [[V1:%.*]] = lshr i32 [[ARG_FR]], 2 628; CHECK-NEXT: ret i32 [[V1]] 629; 630 %v1 = lshr exact i32 %arg, 2 631 %v1.fr = freeze i32 %v1 632 ret i32 %v1.fr 633} 634 635define i32 @propagate_drop_lshr2(i32 %arg, i32 %unknown) { 636; CHECK-LABEL: @propagate_drop_lshr2( 637; CHECK-NEXT: [[V1:%.*]] = lshr exact i32 [[ARG:%.*]], [[UNKNOWN:%.*]] 638; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]] 639; CHECK-NEXT: ret i32 [[V1_FR]] 640; 641 %v1 = lshr exact i32 %arg, %unknown 642 %v1.fr = freeze i32 %v1 643 ret i32 %v1.fr 644} 645 646define ptr @propagate_drop_gep1(ptr %arg) { 647; CHECK-LABEL: @propagate_drop_gep1( 648; CHECK-NEXT: [[ARG_FR:%.*]] = freeze ptr [[ARG:%.*]] 649; CHECK-NEXT: [[V1:%.*]] = getelementptr i8, ptr [[ARG_FR]], i64 16 650; CHECK-NEXT: ret ptr [[V1]] 651; 652 %v1 = getelementptr inbounds i8, ptr %arg, i64 16 653 %v1.fr = freeze ptr %v1 654 ret ptr %v1.fr 655} 656 657define float @propagate_drop_fneg(float %arg) { 658; CHECK-LABEL: @propagate_drop_fneg( 659; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 660; CHECK-NEXT: [[V1:%.*]] = fneg float [[ARG_FR]] 661; CHECK-NEXT: ret float [[V1]] 662; 663 %v1 = fneg ninf nnan float %arg 664 %v1.fr = freeze float %v1 665 ret float %v1.fr 666} 667 668 669define float @propagate_drop_fadd(float %arg) { 670; CHECK-LABEL: @propagate_drop_fadd( 671; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 672; CHECK-NEXT: [[V1:%.*]] = fadd float [[ARG_FR]], 2.000000e+00 673; CHECK-NEXT: ret float [[V1]] 674; 675 %v1 = fadd ninf nnan float %arg, 2.0 676 %v1.fr = freeze float %v1 677 ret float %v1.fr 678} 679 680define float @propagate_drop_fsub(float %arg) { 681; CHECK-LABEL: @propagate_drop_fsub( 682; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 683; CHECK-NEXT: [[V1:%.*]] = fadd float [[ARG_FR]], -2.000000e+00 684; CHECK-NEXT: ret float [[V1]] 685; 686 %v1 = fsub ninf nnan float %arg, 2.0 687 %v1.fr = freeze float %v1 688 ret float %v1.fr 689} 690 691define float @propagate_drop_fmul(float %arg) { 692; CHECK-LABEL: @propagate_drop_fmul( 693; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 694; CHECK-NEXT: [[V1:%.*]] = fmul float [[ARG_FR]], 2.000000e+00 695; CHECK-NEXT: ret float [[V1]] 696; 697 %v1 = fmul ninf nnan float %arg, 2.0 698 %v1.fr = freeze float %v1 699 ret float %v1.fr 700} 701 702define float @propagate_drop_fdiv(float %arg) { 703; CHECK-LABEL: @propagate_drop_fdiv( 704; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 705; CHECK-NEXT: [[V1:%.*]] = fmul float [[ARG_FR]], 5.000000e-01 706; CHECK-NEXT: ret float [[V1]] 707; 708 %v1 = fdiv ninf nnan float %arg, 2.0 709 %v1.fr = freeze float %v1 710 ret float %v1.fr 711} 712 713define float @propagate_drop_frem(float %arg) { 714; CHECK-LABEL: @propagate_drop_frem( 715; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 716; CHECK-NEXT: [[V1:%.*]] = frem float [[ARG_FR]], 2.000000e+00 717; CHECK-NEXT: ret float [[V1]] 718; 719 %v1 = frem ninf nnan float %arg, 2.0 720 %v1.fr = freeze float %v1 721 ret float %v1.fr 722} 723 724define i1 @propagate_drop_fcmp(float %arg) { 725; CHECK-LABEL: @propagate_drop_fcmp( 726; CHECK-NEXT: [[ARG_FR:%.*]] = freeze float [[ARG:%.*]] 727; CHECK-NEXT: [[V1:%.*]] = fcmp une float [[ARG_FR]], 2.000000e+00 728; CHECK-NEXT: ret i1 [[V1]] 729; 730 %v1 = fcmp ninf nnan une float %arg, 2.0 731 %v1.fr = freeze i1 %v1 732 ret i1 %v1.fr 733} 734 735define float @propagate_drop_fmath_select(i1 %arg) { 736; CHECK-LABEL: @propagate_drop_fmath_select( 737; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]] 738; CHECK-NEXT: [[V1:%.*]] = select i1 [[ARG_FR]], float 1.000000e+00, float -1.000000e+00 739; CHECK-NEXT: ret float [[V1]] 740; 741 %v1 = select ninf nnan i1 %arg, float 1.0, float -1.0 742 %v1.fr = freeze float %v1 743 ret float %v1.fr 744} 745 746define void @fold_phi_noop(i32 noundef %init, i32 %n) { 747; CHECK-LABEL: @fold_phi_noop( 748; CHECK-NEXT: entry: 749; CHECK-NEXT: br label [[LOOP:%.*]] 750; CHECK: loop: 751; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 752; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 753; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 754; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 755; CHECK: exit: 756; CHECK-NEXT: ret void 757; 758entry: 759 br label %loop 760 761loop: ; preds = %loop, %entry 762 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 763 %i.fr = freeze i32 %i 764 %i.next = add i32 %i.fr, 1 765 %cond = icmp eq i32 %i.next, %n 766 br i1 %cond, label %loop, label %exit 767 768exit: ; preds = %loop 769 ret void 770} 771 772define void @fold_phi_through(i32 %init, i32 %n) { 773; CHECK-LABEL: @fold_phi_through( 774; CHECK-NEXT: entry: 775; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[INIT:%.*]] 776; CHECK-NEXT: br label [[LOOP:%.*]] 777; CHECK: loop: 778; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 779; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 780; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 781; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 782; CHECK: exit: 783; CHECK-NEXT: ret void 784; 785entry: 786 br label %loop 787 788loop: ; preds = %loop, %entry 789 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 790 %i.fr = freeze i32 %i 791 %i.next = add i32 %i.fr, 1 792 %cond = icmp eq i32 %i.next, %n 793 br i1 %cond, label %loop, label %exit 794 795exit: ; preds = %loop 796 ret void 797} 798 799define void @fold_phi_drop_flags(i32 %init, i32 %n) { 800; CHECK-LABEL: @fold_phi_drop_flags( 801; CHECK-NEXT: entry: 802; CHECK-NEXT: [[INIT_FR:%.*]] = freeze i32 [[INIT:%.*]] 803; CHECK-NEXT: br label [[LOOP:%.*]] 804; CHECK: loop: 805; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 806; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 807; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 808; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 809; CHECK: exit: 810; CHECK-NEXT: ret void 811; 812entry: 813 br label %loop 814 815loop: ; preds = %loop, %entry 816 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 817 %i.fr = freeze i32 %i 818 %i.next = add nsw nuw i32 %i.fr, 1 819 %cond = icmp eq i32 %i.next, %n 820 br i1 %cond, label %loop, label %exit 821 822exit: ; preds = %loop 823 ret void 824} 825 826define void @fold_phi_non_add(i32 %init, i32 %n) { 827; CHECK-LABEL: @fold_phi_non_add( 828; CHECK-NEXT: entry: 829; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[INIT:%.*]] 830; CHECK-NEXT: br label [[LOOP:%.*]] 831; CHECK: loop: 832; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 833; CHECK-NEXT: [[I_NEXT]] = shl i32 [[I]], 1 834; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 835; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 836; CHECK: exit: 837; CHECK-NEXT: ret void 838; 839entry: 840 br label %loop 841 842loop: ; preds = %loop, %entry 843 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 844 %i.fr = freeze i32 %i 845 %i.next = shl i32 %i.fr, 1 846 %cond = icmp eq i32 %i.next, %n 847 br i1 %cond, label %loop, label %exit 848 849exit: ; preds = %loop 850 ret void 851} 852 853define void @fold_phi_gep(ptr %init, ptr %end) { 854; CHECK-LABEL: @fold_phi_gep( 855; CHECK-NEXT: entry: 856; CHECK-NEXT: [[TMP0:%.*]] = freeze ptr [[INIT:%.*]] 857; CHECK-NEXT: br label [[LOOP:%.*]] 858; CHECK: loop: 859; CHECK-NEXT: [[I:%.*]] = phi ptr [ [[TMP0]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 860; CHECK-NEXT: [[I_NEXT]] = getelementptr i8, ptr [[I]], i64 1 861; CHECK-NEXT: [[COND:%.*]] = icmp eq ptr [[I_NEXT]], [[END:%.*]] 862; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 863; CHECK: exit: 864; CHECK-NEXT: ret void 865; 866entry: 867 br label %loop 868 869loop: ; preds = %loop, %entry 870 %i = phi ptr [ %init, %entry ], [ %i.next, %loop ] 871 %i.fr = freeze ptr %i 872 %i.next = getelementptr i8, ptr %i.fr, i64 1 873 %cond = icmp eq ptr %i.next, %end 874 br i1 %cond, label %loop, label %exit 875 876exit: ; preds = %loop 877 ret void 878} 879 880define void @fold_phi_multiple_insts(i32 %init, i32 %n) { 881; CHECK-LABEL: @fold_phi_multiple_insts( 882; CHECK-NEXT: entry: 883; CHECK-NEXT: [[INIT_FR:%.*]] = freeze i32 [[INIT:%.*]] 884; CHECK-NEXT: br label [[LOOP:%.*]] 885; CHECK: loop: 886; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 887; CHECK-NEXT: [[I_SQ:%.*]] = mul i32 [[I]], [[I]] 888; CHECK-NEXT: [[I_NEXT]] = add i32 [[I_SQ]], 1 889; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 890; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 891; CHECK: exit: 892; CHECK-NEXT: ret void 893; 894entry: 895 br label %loop 896 897loop: ; preds = %loop, %entry 898 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 899 %i.fr = freeze i32 %i 900 %i.sq = mul nsw nuw i32 %i.fr, %i.fr 901 %i.next = add nsw nuw i32 %i.sq, 1 902 %cond = icmp eq i32 %i.next, %n 903 br i1 %cond, label %loop, label %exit 904 905exit: ; preds = %loop 906 ret void 907} 908 909define void @fold_phi_multiple_back_edges(i32 %init, i32 %n, i32 %m) { 910; CHECK-LABEL: @fold_phi_multiple_back_edges( 911; CHECK-NEXT: entry: 912; CHECK-NEXT: [[INIT_FR:%.*]] = freeze i32 [[INIT:%.*]] 913; CHECK-NEXT: br label [[LOOP:%.*]] 914; CHECK: loop: 915; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT_FR]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[I_NEXT2:%.*]], [[LOOP_LATCH2:%.*]] ] 916; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 917; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 918; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[LOOP_LATCH2]] 919; CHECK: loop.latch2: 920; CHECK-NEXT: [[I_NEXT2]] = add i32 [[I]], 2 921; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[I_NEXT]], [[M:%.*]] 922; CHECK-NEXT: br i1 [[COND2]], label [[LOOP]], label [[EXIT:%.*]] 923; CHECK: exit: 924; CHECK-NEXT: ret void 925; 926entry: 927 br label %loop 928 929loop: ; preds = %loop, %entry 930 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ], [ %i.next2, %loop.latch2 ] 931 %i.fr = freeze i32 %i 932 %i.next = add nsw nuw i32 %i.fr, 1 933 %cond = icmp eq i32 %i.next, %n 934 br i1 %cond, label %loop, label %loop.latch2 935 936loop.latch2: 937 %i.next2 = add nsw nuw i32 %i.fr, 2 938 %cond2 = icmp eq i32 %i.next, %m 939 br i1 %cond2, label %loop, label %exit 940 941exit: ; preds = %loop 942 ret void 943} 944 945define void @fold_phi_multiple_start_values(i1 %c, i32 %init, i32 %init2, i32 %n) { 946; CHECK-LABEL: @fold_phi_multiple_start_values( 947; CHECK-NEXT: entry: 948; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[LOOP:%.*]] 949; CHECK: if: 950; CHECK-NEXT: br label [[LOOP]] 951; CHECK: loop: 952; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT:%.*]], [[ENTRY:%.*]] ], [ [[INIT2:%.*]], [[IF]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 953; CHECK-NEXT: [[I_FR:%.*]] = freeze i32 [[I]] 954; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I_FR]], 1 955; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 956; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 957; CHECK: exit: 958; CHECK-NEXT: ret void 959; 960entry: 961 br i1 %c, label %if, label %loop 962 963if: 964 br label %loop 965 966loop: 967 %i = phi i32 [ %init, %entry ], [ %init2, %if ], [ %i.next, %loop ] 968 %i.fr = freeze i32 %i 969 %i.next = add nsw nuw i32 %i.fr, 1 970 %cond = icmp eq i32 %i.next, %n 971 br i1 %cond, label %loop, label %exit 972 973exit: 974 ret void 975} 976 977define void @fold_phi_invoke_start_value(i32 %n) personality ptr undef { 978; CHECK-LABEL: @fold_phi_invoke_start_value( 979; CHECK-NEXT: entry: 980; CHECK-NEXT: [[INIT:%.*]] = invoke i32 @get_i32() 981; CHECK-NEXT: to label [[LOOP:%.*]] unwind label [[UNWIND:%.*]] 982; CHECK: loop: 983; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 984; CHECK-NEXT: [[I_FR:%.*]] = freeze i32 [[I]] 985; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I_FR]], 1 986; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 987; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 988; CHECK: unwind: 989; CHECK-NEXT: [[TMP0:%.*]] = landingpad i8 990; CHECK-NEXT: cleanup 991; CHECK-NEXT: unreachable 992; CHECK: exit: 993; CHECK-NEXT: ret void 994; 995entry: 996 %init = invoke i32 @get_i32() 997 to label %loop unwind label %unwind 998 999loop: 1000 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 1001 %i.fr = freeze i32 %i 1002 %i.next = add nsw nuw i32 %i.fr, 1 1003 %cond = icmp eq i32 %i.next, %n 1004 br i1 %cond, label %loop, label %exit 1005 1006unwind: 1007 landingpad i8 cleanup 1008 unreachable 1009 1010exit: 1011 ret void 1012} 1013 1014define void @fold_phi_invoke_noundef_start_value(i32 %n) personality ptr undef { 1015; CHECK-LABEL: @fold_phi_invoke_noundef_start_value( 1016; CHECK-NEXT: entry: 1017; CHECK-NEXT: [[INIT:%.*]] = invoke noundef i32 @get_i32() 1018; CHECK-NEXT: to label [[LOOP:%.*]] unwind label [[UNWIND:%.*]] 1019; CHECK: loop: 1020; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INIT]], [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP]] ] 1021; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 1022; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N:%.*]] 1023; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]] 1024; CHECK: unwind: 1025; CHECK-NEXT: [[TMP0:%.*]] = landingpad i8 1026; CHECK-NEXT: cleanup 1027; CHECK-NEXT: unreachable 1028; CHECK: exit: 1029; CHECK-NEXT: ret void 1030; 1031entry: 1032 %init = invoke noundef i32 @get_i32() 1033 to label %loop unwind label %unwind 1034 1035loop: 1036 %i = phi i32 [ %init, %entry ], [ %i.next, %loop ] 1037 %i.fr = freeze i32 %i 1038 %i.next = add nsw nuw i32 %i.fr, 1 1039 %cond = icmp eq i32 %i.next, %n 1040 br i1 %cond, label %loop, label %exit 1041 1042unwind: 1043 landingpad i8 cleanup 1044 unreachable 1045 1046exit: 1047 ret void 1048} 1049 1050define ptr @freeze_load_noundef(ptr %ptr) { 1051; CHECK-LABEL: @freeze_load_noundef( 1052; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !noundef [[META0:![0-9]+]] 1053; CHECK-NEXT: ret ptr [[P]] 1054; 1055 %p = load ptr, ptr %ptr, !noundef !0 1056 %p.fr = freeze ptr %p 1057 ret ptr %p.fr 1058} 1059 1060define ptr @freeze_load_dereferenceable(ptr %ptr) { 1061; CHECK-LABEL: @freeze_load_dereferenceable( 1062; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable [[META1:![0-9]+]] 1063; CHECK-NEXT: ret ptr [[P]] 1064; 1065 %p = load ptr, ptr %ptr, !dereferenceable !1 1066 %p.fr = freeze ptr %p 1067 ret ptr %p.fr 1068} 1069 1070define ptr @freeze_load_dereferenceable_or_null(ptr %ptr) { 1071; CHECK-LABEL: @freeze_load_dereferenceable_or_null( 1072; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable_or_null [[META1]] 1073; CHECK-NEXT: ret ptr [[P]] 1074; 1075 %p = load ptr, ptr %ptr, !dereferenceable_or_null !1 1076 %p.fr = freeze ptr %p 1077 ret ptr %p.fr 1078} 1079 1080define i32 @freeze_load_with_range(ptr %ptr) { 1081; CHECK-LABEL: @freeze_load_with_range( 1082; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[PTR:%.*]], align 4, !range [[RNG2:![0-9]+]] 1083; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X]] 1084; CHECK-NEXT: ret i32 [[X_FR]] 1085; 1086 %x = load i32, ptr %ptr, !range !2 1087 %x.fr = freeze i32 %x 1088 ret i32 %x.fr 1089} 1090 1091declare i32 @foo.i32() 1092 1093define i32 @freeze_call_with_range() { 1094; CHECK-LABEL: @freeze_call_with_range( 1095; CHECK-NEXT: [[X:%.*]] = call i32 @foo.i32(), !range [[RNG2]] 1096; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X]] 1097; CHECK-NEXT: ret i32 [[X_FR]] 1098; 1099 %x = call i32 @foo.i32(), !range !2 1100 %x.fr = freeze i32 %x 1101 ret i32 %x.fr 1102} 1103 1104declare i32 @llvm.ctpop.i32(i32) 1105 1106define i32 @freeze_ctpop(i32 %x) { 1107; CHECK-LABEL: @freeze_ctpop( 1108; CHECK-NEXT: [[Y:%.*]] = lshr i32 2047, [[X:%.*]] 1109; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]] 1110; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[Y_FR]]) 1111; CHECK-NEXT: ret i32 [[CTPOP]] 1112; 1113 %y = lshr i32 2047, %x 1114 %ctpop = call i32 @llvm.ctpop.i32(i32 %y) 1115 %fr = freeze i32 %ctpop 1116 ret i32 %fr 1117} 1118 1119define i32 @freeze_zext_nneg(i8 %x) { 1120; CHECK-LABEL: @freeze_zext_nneg( 1121; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 1122; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[X_FR]] to i32 1123; CHECK-NEXT: ret i32 [[ZEXT]] 1124; 1125 %zext = zext nneg i8 %x to i32 1126 %fr = freeze i32 %zext 1127 ret i32 %fr 1128} 1129 1130define float @freeze_uitofp_nneg(i8 %x) { 1131; CHECK-LABEL: @freeze_uitofp_nneg( 1132; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]] 1133; CHECK-NEXT: [[UITOFP:%.*]] = uitofp i8 [[X_FR]] to float 1134; CHECK-NEXT: ret float [[UITOFP]] 1135; 1136 %uitofp = uitofp nneg i8 %x to float 1137 %fr = freeze float %uitofp 1138 ret float %fr 1139} 1140 1141define i32 @propagate_drop_flags_or(i32 %arg) { 1142; CHECK-LABEL: @propagate_drop_flags_or( 1143; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]] 1144; CHECK-NEXT: [[V1:%.*]] = or i32 [[ARG_FR]], 2 1145; CHECK-NEXT: ret i32 [[V1]] 1146; 1147 %v1 = or disjoint i32 %arg, 2 1148 %v1.fr = freeze i32 %v1 1149 ret i32 %v1.fr 1150} 1151 1152define i32 @propagate_drop_flags_trunc(i64 %arg) { 1153; CHECK-LABEL: @propagate_drop_flags_trunc( 1154; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i64 [[ARG:%.*]] 1155; CHECK-NEXT: [[V1:%.*]] = trunc i64 [[ARG_FR]] to i32 1156; CHECK-NEXT: ret i32 [[V1]] 1157; 1158 %v1 = trunc nsw nuw i64 %arg to i32 1159 %v1.fr = freeze i32 %v1 1160 ret i32 %v1.fr 1161} 1162 1163define ptr @propagate_drop_flags_gep_nusw(ptr %p) { 1164; CHECK-LABEL: @propagate_drop_flags_gep_nusw( 1165; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]] 1166; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P_FR]], i64 1 1167; CHECK-NEXT: ret ptr [[GEP]] 1168; 1169 %gep = getelementptr nusw i8, ptr %p, i64 1 1170 %gep.fr = freeze ptr %gep 1171 ret ptr %gep.fr 1172} 1173 1174define ptr @propagate_drop_flags_gep_nuw(ptr %p) { 1175; CHECK-LABEL: @propagate_drop_flags_gep_nuw( 1176; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]] 1177; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[P_FR]], i64 1 1178; CHECK-NEXT: ret ptr [[GEP]] 1179; 1180 %gep = getelementptr nuw i8, ptr %p, i64 1 1181 %gep.fr = freeze ptr %gep 1182 ret ptr %gep.fr 1183} 1184 1185define i1 @propagate_drop_flags_icmp(i32 %a, i32 %b) { 1186; CHECK-LABEL: @propagate_drop_flags_icmp( 1187; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]] 1188; CHECK-NEXT: [[RET:%.*]] = icmp ult i32 [[A_FR]], 3 1189; CHECK-NEXT: ret i1 [[RET]] 1190; 1191 %ret = icmp samesign ult i32 %a, 3 1192 %ret.fr = freeze i1 %ret 1193 ret i1 %ret.fr 1194} 1195 1196declare i32 @llvm.umax.i32(i32 %a, i32 %b) 1197 1198define i32 @freeze_call_with_range_attr(i32 %a) { 1199; CHECK-LABEL: @freeze_call_with_range_attr( 1200; CHECK-NEXT: [[Y:%.*]] = lshr i32 2047, [[A:%.*]] 1201; CHECK-NEXT: [[Y_FR:%.*]] = freeze i32 [[Y]] 1202; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.umax.i32(i32 [[Y_FR]], i32 50) 1203; CHECK-NEXT: ret i32 [[X]] 1204; 1205 %y = lshr i32 2047, %a 1206 %x = call range(i32 0, 2048) i32 @llvm.umax.i32(i32 %y, i32 50) 1207 %x.fr = freeze i32 %x 1208 ret i32 %x.fr 1209} 1210 1211declare ptr @llvm.ptrmask.p0.i64(ptr, i64) 1212 1213define ptr @freeze_ptrmask_align(ptr %p, i64 noundef %m) { 1214; CHECK-LABEL: @freeze_ptrmask_align( 1215; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]] 1216; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]]) 1217; CHECK-NEXT: ret ptr [[MASK]] 1218; 1219 %mask = call align(4) ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m) 1220 %fr = freeze ptr %mask 1221 ret ptr %fr 1222} 1223 1224define ptr @freeze_ptrmask_nonnull(ptr %p, i64 noundef %m) { 1225; CHECK-LABEL: @freeze_ptrmask_nonnull( 1226; CHECK-NEXT: [[P_FR:%.*]] = freeze ptr [[P:%.*]] 1227; CHECK-NEXT: [[MASK:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P_FR]], i64 [[M:%.*]]) 1228; CHECK-NEXT: ret ptr [[MASK]] 1229; 1230 %mask = call nonnull ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m) 1231 %fr = freeze ptr %mask 1232 ret ptr %fr 1233} 1234 1235!0 = !{} 1236!1 = !{i64 4} 1237!2 = !{i32 0, i32 100} 1238;. 1239; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } 1240; CHECK: attributes #[[ATTR1]] = { nounwind } 1241;. 1242; CHECK: [[META0]] = !{} 1243; CHECK: [[META1]] = !{i64 4} 1244; CHECK: [[RNG2]] = !{i32 0, i32 100} 1245;. 1246