brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.7 KiB · ed530be Raw
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