690 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -S -passes=gvn < %s | FileCheck %s3 4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"5 6@x = common global i32 0, align 47@y = common global i32 0, align 48 9; GVN across unordered store (allowed)10define i32 @test1() nounwind uwtable ssp {11; CHECK-LABEL: define i32 @test112; CHECK-SAME: () #[[ATTR0:[0-9]+]] {13; CHECK-NEXT: entry:14; CHECK-NEXT: [[X:%.*]] = load i32, ptr @y, align 415; CHECK-NEXT: store atomic i32 [[X]], ptr @x unordered, align 416; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], [[X]]17; CHECK-NEXT: ret i32 [[Z]]18;19entry:20 %x = load i32, ptr @y21 store atomic i32 %x, ptr @x unordered, align 422 %y = load i32, ptr @y23 %z = add i32 %x, %y24 ret i32 %z25}26 27; GVN across unordered load (allowed)28define i32 @test3() nounwind uwtable ssp {29; CHECK-LABEL: define i32 @test330; CHECK-SAME: () #[[ATTR0]] {31; CHECK-NEXT: entry:32; CHECK-NEXT: [[X:%.*]] = load i32, ptr @y, align 433; CHECK-NEXT: [[Y:%.*]] = load atomic i32, ptr @x unordered, align 434; CHECK-NEXT: [[A:%.*]] = add i32 [[X]], [[X]]35; CHECK-NEXT: [[B:%.*]] = add i32 [[Y]], [[A]]36; CHECK-NEXT: ret i32 [[B]]37;38entry:39 %x = load i32, ptr @y40 %y = load atomic i32, ptr @x unordered, align 441 %z = load i32, ptr @y42 %a = add i32 %x, %z43 %b = add i32 %y, %a44 ret i32 %b45}46 47; GVN load to unordered load (allowed)48define i32 @test5() nounwind uwtable ssp {49; CHECK-LABEL: define i32 @test550; CHECK-SAME: () #[[ATTR0]] {51; CHECK-NEXT: entry:52; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr @x unordered, align 453; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], [[X]]54; CHECK-NEXT: ret i32 [[Z]]55;56entry:57 %x = load atomic i32, ptr @x unordered, align 458 %y = load i32, ptr @x59 %z = add i32 %x, %y60 ret i32 %z61}62 63; GVN unordered load to load (unordered load must not be removed)64define i32 @test6() nounwind uwtable ssp {65; CHECK-LABEL: define i32 @test666; CHECK-SAME: () #[[ATTR0]] {67; CHECK-NEXT: entry:68; CHECK-NEXT: [[X:%.*]] = load i32, ptr @x, align 469; CHECK-NEXT: [[X2:%.*]] = load atomic i32, ptr @x unordered, align 470; CHECK-NEXT: [[X3:%.*]] = add i32 [[X]], [[X2]]71; CHECK-NEXT: ret i32 [[X3]]72;73entry:74 %x = load i32, ptr @x75 %x2 = load atomic i32, ptr @x unordered, align 476 %x3 = add i32 %x, %x277 ret i32 %x378}79 80; GVN across release-acquire pair (forbidden)81define i32 @test7() nounwind uwtable ssp {82; CHECK-LABEL: define i32 @test783; CHECK-SAME: () #[[ATTR0]] {84; CHECK-NEXT: entry:85; CHECK-NEXT: [[X:%.*]] = load i32, ptr @y, align 486; CHECK-NEXT: store atomic i32 [[X]], ptr @x release, align 487; CHECK-NEXT: [[W:%.*]] = load atomic i32, ptr @x acquire, align 488; CHECK-NEXT: [[Y:%.*]] = load i32, ptr @y, align 489; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], [[Y]]90; CHECK-NEXT: ret i32 [[Z]]91;92entry:93 %x = load i32, ptr @y94 store atomic i32 %x, ptr @x release, align 495 %w = load atomic i32, ptr @x acquire, align 496 %y = load i32, ptr @y97 %z = add i32 %x, %y98 ret i32 %z99}100 101; GVN across monotonic store (allowed)102define i32 @test9() nounwind uwtable ssp {103; CHECK-LABEL: define i32 @test9104; CHECK-SAME: () #[[ATTR0]] {105; CHECK-NEXT: entry:106; CHECK-NEXT: [[X:%.*]] = load i32, ptr @y, align 4107; CHECK-NEXT: store atomic i32 [[X]], ptr @x monotonic, align 4108; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], [[X]]109; CHECK-NEXT: ret i32 [[Z]]110;111entry:112 %x = load i32, ptr @y113 store atomic i32 %x, ptr @x monotonic, align 4114 %y = load i32, ptr @y115 %z = add i32 %x, %y116 ret i32 %z117}118 119; GVN of an unordered across monotonic load (not allowed)120define i32 @test10() nounwind uwtable ssp {121; CHECK-LABEL: define i32 @test10122; CHECK-SAME: () #[[ATTR0]] {123; CHECK-NEXT: entry:124; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr @y unordered, align 4125; CHECK-NEXT: [[CLOBBER:%.*]] = load atomic i32, ptr @x monotonic, align 4126; CHECK-NEXT: [[Y:%.*]] = load atomic i32, ptr @y monotonic, align 4127; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], [[Y]]128; CHECK-NEXT: ret i32 [[Z]]129;130entry:131 %x = load atomic i32, ptr @y unordered, align 4132 %clobber = load atomic i32, ptr @x monotonic, align 4133 %y = load atomic i32, ptr @y monotonic, align 4134 %z = add i32 %x, %y135 ret i32 %z136}137 138define i32 @PR22708(i1 %flag) {139; CHECK-LABEL: define i32 @PR22708140; CHECK-SAME: (i1 [[FLAG:%.*]]) {141; CHECK-NEXT: entry:142; CHECK-NEXT: br i1 [[FLAG]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]143; CHECK: if.then:144; CHECK-NEXT: store i32 43, ptr @y, align 4145; CHECK-NEXT: br label [[IF_END]]146; CHECK: if.end:147; CHECK-NEXT: [[TMP0:%.*]] = load atomic i32, ptr @x acquire, align 4148; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr @y, align 4149; CHECK-NEXT: ret i32 [[LOAD]]150;151entry:152 br i1 %flag, label %if.then, label %if.end153 154if.then:155 store i32 43, ptr @y, align 4156 br label %if.end157 158if.end:159 load atomic i32, ptr @x acquire, align 4160 %load = load i32, ptr @y, align 4161 ret i32 %load162}163 164; Can't remove a load over a ordering barrier165define i32 @test12(i1 %B, ptr %P1, ptr %P2) {166; CHECK-LABEL: define i32 @test12167; CHECK-SAME: (i1 [[B:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) {168; CHECK-NEXT: [[LOAD0:%.*]] = load i32, ptr [[P1]], align 4169; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, ptr [[P2]] seq_cst, align 4170; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[P1]], align 4171; CHECK-NEXT: [[SEL:%.*]] = select i1 [[B]], i32 [[LOAD0]], i32 [[LOAD1]]172; CHECK-NEXT: ret i32 [[SEL]]173;174 %load0 = load i32, ptr %P1175 %1 = load atomic i32, ptr %P2 seq_cst, align 4176 %load1 = load i32, ptr %P1177 %sel = select i1 %B, i32 %load0, i32 %load1178 ret i32 %sel179}180 181; atomic to non-atomic forwarding is legal182define i32 @test13(ptr %P1) {183; CHECK-LABEL: define i32 @test13184; CHECK-SAME: (ptr [[P1:%.*]]) {185; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4186; CHECK-NEXT: ret i32 0187;188 %a = load atomic i32, ptr %P1 seq_cst, align 4189 %b = load i32, ptr %P1190 %res = sub i32 %a, %b191 ret i32 %res192}193 194define i32 @test13b(ptr %P1) {195; CHECK-LABEL: define i32 @test13b196; CHECK-SAME: (ptr [[P1:%.*]]) {197; CHECK-NEXT: store atomic i32 0, ptr [[P1]] unordered, align 4198; CHECK-NEXT: ret i32 0199;200 store atomic i32 0, ptr %P1 unordered, align 4201 %b = load i32, ptr %P1202 ret i32 %b203}204 205; atomic to unordered atomic forwarding is legal206define i32 @test14(ptr %P1) {207; CHECK-LABEL: define i32 @test14208; CHECK-SAME: (ptr [[P1:%.*]]) {209; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4210; CHECK-NEXT: ret i32 0211;212 %a = load atomic i32, ptr %P1 seq_cst, align 4213 %b = load atomic i32, ptr %P1 unordered, align 4214 %res = sub i32 %a, %b215 ret i32 %res216}217 218; implementation restriction: can't forward to stonger219; than unordered220define i32 @test15(ptr %P1, ptr %P2) {221; CHECK-LABEL: define i32 @test15222; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {223; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4224; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4225; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]226; CHECK-NEXT: ret i32 [[RES]]227;228 %a = load atomic i32, ptr %P1 seq_cst, align 4229 %b = load atomic i32, ptr %P1 seq_cst, align 4230 %res = sub i32 %a, %b231 ret i32 %res232}233 234; forwarding non-atomic to atomic is wrong! (However,235; it would be legal to use the later value in place of the236; former in this particular example. We just don't237; do that right now.)238define i32 @test16(ptr %P1, ptr %P2) {239; CHECK-LABEL: define i32 @test16240; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {241; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P1]], align 4242; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4243; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]244; CHECK-NEXT: ret i32 [[RES]]245;246 %a = load i32, ptr %P1, align 4247 %b = load atomic i32, ptr %P1 unordered, align 4248 %res = sub i32 %a, %b249 ret i32 %res250}251 252define i32 @test16b(ptr %P1) {253; CHECK-LABEL: define i32 @test16b254; CHECK-SAME: (ptr [[P1:%.*]]) {255; CHECK-NEXT: store i32 0, ptr [[P1]], align 4256; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4257; CHECK-NEXT: ret i32 [[B]]258;259 store i32 0, ptr %P1260 %b = load atomic i32, ptr %P1 unordered, align 4261 ret i32 %b262}263 264; Can't DSE across a full fence265define void @fence_seq_cst_store(ptr %P1, ptr %P2) {266; CHECK-LABEL: define void @fence_seq_cst_store267; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {268; CHECK-NEXT: store i32 0, ptr [[P1]], align 4269; CHECK-NEXT: store atomic i32 0, ptr [[P2]] seq_cst, align 4270; CHECK-NEXT: store i32 0, ptr [[P1]], align 4271; CHECK-NEXT: ret void272;273 store i32 0, ptr %P1, align 4274 store atomic i32 0, ptr %P2 seq_cst, align 4275 store i32 0, ptr %P1, align 4276 ret void277}278 279; Can't DSE across a full fence280define void @fence_seq_cst(ptr %P1, ptr %P2) {281; CHECK-LABEL: define void @fence_seq_cst282; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {283; CHECK-NEXT: store i32 0, ptr [[P1]], align 4284; CHECK-NEXT: fence seq_cst285; CHECK-NEXT: store i32 0, ptr [[P1]], align 4286; CHECK-NEXT: ret void287;288 store i32 0, ptr %P1, align 4289 fence seq_cst290 store i32 0, ptr %P1, align 4291 ret void292}293 294; Can't DSE across a full syncscope("singlethread") fence295define void @fence_seq_cst_st(ptr %P1, ptr %P2) {296; CHECK-LABEL: define void @fence_seq_cst_st297; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {298; CHECK-NEXT: store i32 0, ptr [[P1]], align 4299; CHECK-NEXT: fence syncscope("singlethread") seq_cst300; CHECK-NEXT: store i32 0, ptr [[P1]], align 4301; CHECK-NEXT: ret void302;303 store i32 0, ptr %P1, align 4304 fence syncscope("singlethread") seq_cst305 store i32 0, ptr %P1, align 4306 ret void307}308 309; Can't DSE across a full fence310define void @fence_asm_sideeffect(ptr %P1, ptr %P2) {311; CHECK-LABEL: define void @fence_asm_sideeffect312; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {313; CHECK-NEXT: store i32 0, ptr [[P1]], align 4314; CHECK-NEXT: call void asm sideeffect "", ""()315; CHECK-NEXT: store i32 0, ptr [[P1]], align 4316; CHECK-NEXT: ret void317;318 store i32 0, ptr %P1, align 4319 call void asm sideeffect "", ""()320 store i32 0, ptr %P1, align 4321 ret void322}323 324; Can't DSE across a full fence325define void @fence_asm_memory(ptr %P1, ptr %P2) {326; CHECK-LABEL: define void @fence_asm_memory327; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {328; CHECK-NEXT: store i32 0, ptr [[P1]], align 4329; CHECK-NEXT: call void asm "", "~{memory}"()330; CHECK-NEXT: store i32 0, ptr [[P1]], align 4331; CHECK-NEXT: ret void332;333 store i32 0, ptr %P1, align 4334 call void asm "", "~{memory}"()335 store i32 0, ptr %P1, align 4336 ret void337}338 339; Can't remove a volatile load340define i32 @volatile_load(ptr %P1, ptr %P2) {341; CHECK-LABEL: define i32 @volatile_load342; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {343; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P1]], align 4344; CHECK-NEXT: [[B:%.*]] = load volatile i32, ptr [[P1]], align 4345; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]346; CHECK-NEXT: ret i32 [[RES]]347;348 %a = load i32, ptr %P1, align 4349 %b = load volatile i32, ptr %P1, align 4350 %res = sub i32 %a, %b351 ret i32 %res352}353 354; Can't remove redundant volatile loads355define i32 @redundant_volatile_load(ptr %P1, ptr %P2) {356; CHECK-LABEL: define i32 @redundant_volatile_load357; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {358; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr [[P1]], align 4359; CHECK-NEXT: [[B:%.*]] = load volatile i32, ptr [[P1]], align 4360; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]361; CHECK-NEXT: ret i32 [[RES]]362;363 %a = load volatile i32, ptr %P1, align 4364 %b = load volatile i32, ptr %P1, align 4365 %res = sub i32 %a, %b366 ret i32 %res367}368 369; Can't DSE a volatile store370define void @volatile_store(ptr %P1, ptr %P2) {371; CHECK-LABEL: define void @volatile_store372; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {373; CHECK-NEXT: store volatile i32 0, ptr [[P1]], align 4374; CHECK-NEXT: store i32 3, ptr [[P1]], align 4375; CHECK-NEXT: ret void376;377 store volatile i32 0, ptr %P1, align 4378 store i32 3, ptr %P1, align 4379 ret void380}381 382; Can't DSE a redundant volatile store383define void @redundant_volatile_store(ptr %P1, ptr %P2) {384; CHECK-LABEL: define void @redundant_volatile_store385; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {386; CHECK-NEXT: store volatile i32 0, ptr [[P1]], align 4387; CHECK-NEXT: store volatile i32 0, ptr [[P1]], align 4388; CHECK-NEXT: ret void389;390 store volatile i32 0, ptr %P1, align 4391 store volatile i32 0, ptr %P1, align 4392 ret void393}394 395; Can value forward from volatiles396define i32 @test20(ptr %P1, ptr %P2) {397; CHECK-LABEL: define i32 @test20398; CHECK-SAME: (ptr [[P1:%.*]], ptr [[P2:%.*]]) {399; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr [[P1]], align 4400; CHECK-NEXT: ret i32 0401;402 %a = load volatile i32, ptr %P1, align 4403 %b = load i32, ptr %P1, align 4404 %res = sub i32 %a, %b405 ret i32 %res406}407 408; We're currently conservative about widening409define i64 @widen1(ptr %P1) {410; CHECK-LABEL: define i64 @widen1411; CHECK-SAME: (ptr [[P1:%.*]]) {412; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4413; CHECK-NEXT: [[B:%.*]] = load atomic i64, ptr [[P1]] unordered, align 4414; CHECK-NEXT: [[A64:%.*]] = sext i32 [[A]] to i64415; CHECK-NEXT: [[RES:%.*]] = sub i64 [[A64]], [[B]]416; CHECK-NEXT: ret i64 [[RES]]417;418 %a = load atomic i32, ptr %P1 unordered, align 4419 %b = load atomic i64, ptr %P1 unordered, align 4420 %a64 = sext i32 %a to i64421 %res = sub i64 %a64, %b422 ret i64 %res423}424 425; narrowing does work426define i64 @narrow(ptr %P1) {427; CHECK-LABEL: define i64 @narrow428; CHECK-SAME: (ptr [[P1:%.*]]) {429; CHECK-NEXT: [[A64:%.*]] = load atomic i64, ptr [[P1]] unordered, align 4430; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A64]] to i32431; CHECK-NEXT: [[B64:%.*]] = sext i32 [[TMP1]] to i64432; CHECK-NEXT: [[RES:%.*]] = sub i64 [[A64]], [[B64]]433; CHECK-NEXT: ret i64 [[RES]]434;435 %a64 = load atomic i64, ptr %P1 unordered, align 4436 %b = load atomic i32, ptr %P1 unordered, align 4437 %b64 = sext i32 %b to i64438 %res = sub i64 %a64, %b64439 ret i64 %res440}441 442; Missed optimization, we don't yet optimize ordered loads443define i64 @narrow2(ptr %P1) {444; CHECK-LABEL: define i64 @narrow2445; CHECK-SAME: (ptr [[P1:%.*]]) {446; CHECK-NEXT: [[A64:%.*]] = load atomic i64, ptr [[P1]] acquire, align 4447; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] acquire, align 4448; CHECK-NEXT: [[B64:%.*]] = sext i32 [[B]] to i64449; CHECK-NEXT: [[RES:%.*]] = sub i64 [[A64]], [[B64]]450; CHECK-NEXT: ret i64 [[RES]]451;452 %a64 = load atomic i64, ptr %P1 acquire, align 4453 %b = load atomic i32, ptr %P1 acquire, align 4454 %b64 = sext i32 %b to i64455 %res = sub i64 %a64, %b64456 ret i64 %res457}458 459; Note: The cross block FRE testing is deliberately light. All of the tricky460; bits of legality are shared code with the block-local FRE above. These461; are here only to show that we haven't obviously broken anything.462 463; unordered atomic to unordered atomic464define i32 @non_local_fre(ptr %P1) {465; CHECK-LABEL: define i32 @non_local_fre466; CHECK-SAME: (ptr [[P1:%.*]]) {467; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4468; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0469; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]470; CHECK: early:471; CHECK-NEXT: ret i32 0472; CHECK: next:473; CHECK-NEXT: ret i32 0474;475 %a = load atomic i32, ptr %P1 unordered, align 4476 %cmp = icmp eq i32 %a, 0477 br i1 %cmp, label %early, label %next478early:479 ret i32 %a480next:481 %b = load atomic i32, ptr %P1 unordered, align 4482 %res = sub i32 %a, %b483 ret i32 %res484}485 486; unordered atomic to non-atomic487define i32 @non_local_fre2(ptr %P1) {488; CHECK-LABEL: define i32 @non_local_fre2489; CHECK-SAME: (ptr [[P1:%.*]]) {490; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4491; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0492; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]493; CHECK: early:494; CHECK-NEXT: ret i32 0495; CHECK: next:496; CHECK-NEXT: ret i32 0497;498 %a = load atomic i32, ptr %P1 unordered, align 4499 %cmp = icmp eq i32 %a, 0500 br i1 %cmp, label %early, label %next501early:502 ret i32 %a503next:504 %b = load i32, ptr %P1505 %res = sub i32 %a, %b506 ret i32 %res507}508 509; Can't forward ordered atomics.510define i32 @non_local_fre3(ptr %P1) {511; CHECK-LABEL: define i32 @non_local_fre3512; CHECK-SAME: (ptr [[P1:%.*]]) {513; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] acquire, align 4514; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0515; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]516; CHECK: early:517; CHECK-NEXT: ret i32 0518; CHECK: next:519; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] acquire, align 4520; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]521; CHECK-NEXT: ret i32 [[RES]]522;523 %a = load atomic i32, ptr %P1 acquire, align 4524 %cmp = icmp eq i32 %a, 0525 br i1 %cmp, label %early, label %next526early:527 ret i32 %a528next:529 %b = load atomic i32, ptr %P1 acquire, align 4530 %res = sub i32 %a, %b531 ret i32 %res532}533 534declare void @clobber()535 536; unordered atomic to unordered atomic537define i32 @non_local_pre(ptr %P1) {538; CHECK-LABEL: define i32 @non_local_pre539; CHECK-SAME: (ptr [[P1:%.*]]) {540; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4541; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0542; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]543; CHECK: early:544; CHECK-NEXT: call void @clobber()545; CHECK-NEXT: [[B_PRE:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4546; CHECK-NEXT: br label [[NEXT]]547; CHECK: next:548; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_PRE]], [[EARLY]] ], [ [[A]], [[TMP0:%.*]] ]549; CHECK-NEXT: ret i32 [[B]]550;551 %a = load atomic i32, ptr %P1 unordered, align 4552 %cmp = icmp eq i32 %a, 0553 br i1 %cmp, label %early, label %next554early:555 call void @clobber()556 br label %next557next:558 %b = load atomic i32, ptr %P1 unordered, align 4559 ret i32 %b560}561 562; unordered atomic to non-atomic563define i32 @non_local_pre2(ptr %P1) {564; CHECK-LABEL: define i32 @non_local_pre2565; CHECK-SAME: (ptr [[P1:%.*]]) {566; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4567; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0568; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]569; CHECK: early:570; CHECK-NEXT: call void @clobber()571; CHECK-NEXT: [[B_PRE:%.*]] = load i32, ptr [[P1]], align 4572; CHECK-NEXT: br label [[NEXT]]573; CHECK: next:574; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_PRE]], [[EARLY]] ], [ [[A]], [[TMP0:%.*]] ]575; CHECK-NEXT: ret i32 [[B]]576;577 %a = load atomic i32, ptr %P1 unordered, align 4578 %cmp = icmp eq i32 %a, 0579 br i1 %cmp, label %early, label %next580early:581 call void @clobber()582 br label %next583next:584 %b = load i32, ptr %P1585 ret i32 %b586}587 588; non-atomic to unordered atomic - can't forward!589define i32 @non_local_pre3(ptr %P1) {590; CHECK-LABEL: define i32 @non_local_pre3591; CHECK-SAME: (ptr [[P1:%.*]]) {592; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P1]], align 4593; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0594; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]595; CHECK: early:596; CHECK-NEXT: call void @clobber()597; CHECK-NEXT: br label [[NEXT]]598; CHECK: next:599; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4600; CHECK-NEXT: ret i32 [[B]]601;602 %a = load i32, ptr %P1603 %cmp = icmp eq i32 %a, 0604 br i1 %cmp, label %early, label %next605early:606 call void @clobber()607 br label %next608next:609 %b = load atomic i32, ptr %P1 unordered, align 4610 ret i32 %b611}612 613; ordered atomic to ordered atomic - can't forward614define i32 @non_local_pre4(ptr %P1) {615; CHECK-LABEL: define i32 @non_local_pre4616; CHECK-SAME: (ptr [[P1:%.*]]) {617; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4618; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0619; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]620; CHECK: early:621; CHECK-NEXT: call void @clobber()622; CHECK-NEXT: br label [[NEXT]]623; CHECK: next:624; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4625; CHECK-NEXT: ret i32 [[B]]626;627 %a = load atomic i32, ptr %P1 seq_cst, align 4628 %cmp = icmp eq i32 %a, 0629 br i1 %cmp, label %early, label %next630early:631 call void @clobber()632 br label %next633next:634 %b = load atomic i32, ptr %P1 seq_cst, align 4635 ret i32 %b636}637 638; can't remove volatile on any path639define i32 @non_local_pre5(ptr %P1) {640; CHECK-LABEL: define i32 @non_local_pre5641; CHECK-SAME: (ptr [[P1:%.*]]) {642; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4643; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0644; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]645; CHECK: early:646; CHECK-NEXT: call void @clobber()647; CHECK-NEXT: br label [[NEXT]]648; CHECK: next:649; CHECK-NEXT: [[B:%.*]] = load volatile i32, ptr [[P1]], align 4650; CHECK-NEXT: ret i32 [[B]]651;652 %a = load atomic i32, ptr %P1 seq_cst, align 4653 %cmp = icmp eq i32 %a, 0654 br i1 %cmp, label %early, label %next655early:656 call void @clobber()657 br label %next658next:659 %b = load volatile i32, ptr %P1660 ret i32 %b661}662 663 664; ordered atomic to unordered atomic665define i32 @non_local_pre6(ptr %P1) {666; CHECK-LABEL: define i32 @non_local_pre6667; CHECK-SAME: (ptr [[P1:%.*]]) {668; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 4669; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0670; CHECK-NEXT: br i1 [[CMP]], label [[EARLY:%.*]], label [[NEXT:%.*]]671; CHECK: early:672; CHECK-NEXT: call void @clobber()673; CHECK-NEXT: [[B_PRE:%.*]] = load atomic i32, ptr [[P1]] unordered, align 4674; CHECK-NEXT: br label [[NEXT]]675; CHECK: next:676; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[B_PRE]], [[EARLY]] ], [ [[A]], [[TMP0:%.*]] ]677; CHECK-NEXT: ret i32 [[B]]678;679 %a = load atomic i32, ptr %P1 seq_cst, align 4680 %cmp = icmp eq i32 %a, 0681 br i1 %cmp, label %early, label %next682early:683 call void @clobber()684 br label %next685next:686 %b = load atomic i32, ptr %P1 unordered, align 4687 ret i32 %b688}689 690