307 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes=early-cse -earlycse-debug-hash | FileCheck %s3; RUN: opt < %s -S -passes='early-cse<memssa>' | FileCheck %s4 5define i32 @test12(i1 %B, ptr %P1, ptr %P2) {6; CHECK-LABEL: @test12(7; CHECK-NEXT: [[LOAD0:%.*]] = load i32, ptr [[P1:%.*]], align 48; CHECK-NEXT: [[TMP1:%.*]] = load atomic i32, ptr [[P2:%.*]] seq_cst, align 49; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[P1]], align 410; CHECK-NEXT: [[SEL:%.*]] = select i1 [[B:%.*]], i32 [[LOAD0]], i32 [[LOAD1]]11; CHECK-NEXT: ret i32 [[SEL]]12;13 %load0 = load i32, ptr %P114 %1 = load atomic i32, ptr %P2 seq_cst, align 415 %load1 = load i32, ptr %P116 %sel = select i1 %B, i32 %load0, i32 %load117 ret i32 %sel18}19 20; atomic to non-atomic forwarding is legal21define i32 @test13(i1 %B, ptr %P1) {22; CHECK-LABEL: @test13(23; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1:%.*]] seq_cst, align 424; CHECK-NEXT: ret i32 025;26 %a = load atomic i32, ptr %P1 seq_cst, align 427 %b = load i32, ptr %P128 %res = sub i32 %a, %b29 ret i32 %res30}31 32; atomic to unordered atomic forwarding is legal33define i32 @test14(i1 %B, ptr %P1) {34; CHECK-LABEL: @test14(35; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1:%.*]] seq_cst, align 436; CHECK-NEXT: ret i32 037;38 %a = load atomic i32, ptr %P1 seq_cst, align 439 %b = load atomic i32, ptr %P1 unordered, align 440 %res = sub i32 %a, %b41 ret i32 %res42}43 44; implementation restriction: can't forward to stonger45; than unordered46define i32 @test15(i1 %B, ptr %P1, ptr %P2) {47; CHECK-LABEL: @test15(48; CHECK-NEXT: [[A:%.*]] = load atomic i32, ptr [[P1:%.*]] seq_cst, align 449; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] seq_cst, align 450; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]51; CHECK-NEXT: ret i32 [[RES]]52;53 %a = load atomic i32, ptr %P1 seq_cst, align 454 %b = load atomic i32, ptr %P1 seq_cst, align 455 %res = sub i32 %a, %b56 ret i32 %res57}58 59; forwarding non-atomic to atomic is wrong! (However,60; it would be legal to use the later value in place of the61; former in this particular example. We just don't62; do that right now.)63define i32 @test16(i1 %B, ptr %P1, ptr %P2) {64; CHECK-LABEL: @test16(65; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P1:%.*]], align 466; CHECK-NEXT: [[B:%.*]] = load atomic i32, ptr [[P1]] unordered, align 467; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]68; CHECK-NEXT: ret i32 [[RES]]69;70 %a = load i32, ptr %P1, align 471 %b = load atomic i32, ptr %P1 unordered, align 472 %res = sub i32 %a, %b73 ret i32 %res74}75 76; Can't DSE across a full fence77define void @fence_seq_cst_store(i1 %B, ptr %P1, ptr %P2) {78; CHECK-LABEL: @fence_seq_cst_store(79; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 480; CHECK-NEXT: store atomic i32 0, ptr [[P2:%.*]] seq_cst, align 481; CHECK-NEXT: store i32 0, ptr [[P1]], align 482; CHECK-NEXT: ret void83;84 store i32 0, ptr %P1, align 485 store atomic i32 0, ptr %P2 seq_cst, align 486 store i32 0, ptr %P1, align 487 ret void88}89 90; Can't DSE across a full fence91define void @fence_seq_cst(i1 %B, ptr %P1, ptr %P2) {92; CHECK-LABEL: @fence_seq_cst(93; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 494; CHECK-NEXT: fence seq_cst95; CHECK-NEXT: store i32 0, ptr [[P1]], align 496; CHECK-NEXT: ret void97;98 store i32 0, ptr %P1, align 499 fence seq_cst100 store i32 0, ptr %P1, align 4101 ret void102}103 104; Can't DSE across a full fence105define void @fence_asm_sideeffect(i1 %B, ptr %P1, ptr %P2) {106; CHECK-LABEL: @fence_asm_sideeffect(107; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 4108; CHECK-NEXT: call void asm sideeffect "", ""()109; CHECK-NEXT: store i32 0, ptr [[P1]], align 4110; CHECK-NEXT: ret void111;112 store i32 0, ptr %P1, align 4113 call void asm sideeffect "", ""()114 store i32 0, ptr %P1, align 4115 ret void116}117 118; Can't DSE across a full fence119define void @fence_asm_memory(i1 %B, ptr %P1, ptr %P2) {120; CHECK-LABEL: @fence_asm_memory(121; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 4122; CHECK-NEXT: call void asm "", "~{memory}"()123; CHECK-NEXT: store i32 0, ptr [[P1]], align 4124; CHECK-NEXT: ret void125;126 store i32 0, ptr %P1, align 4127 call void asm "", "~{memory}"()128 store i32 0, ptr %P1, align 4129 ret void130}131 132; Can't remove a volatile load133define i32 @volatile_load(i1 %B, ptr %P1, ptr %P2) {134; CHECK-LABEL: @volatile_load(135; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P1:%.*]], align 4136; CHECK-NEXT: [[B:%.*]] = load volatile i32, ptr [[P1]], align 4137; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]138; CHECK-NEXT: ret i32 [[RES]]139;140 %a = load i32, ptr %P1, align 4141 %b = load volatile i32, ptr %P1, align 4142 %res = sub i32 %a, %b143 ret i32 %res144}145 146; Can't remove redundant volatile loads147define i32 @redundant_volatile_load(i1 %B, ptr %P1, ptr %P2) {148; CHECK-LABEL: @redundant_volatile_load(149; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr [[P1:%.*]], align 4150; CHECK-NEXT: [[B:%.*]] = load volatile i32, ptr [[P1]], align 4151; CHECK-NEXT: [[RES:%.*]] = sub i32 [[A]], [[B]]152; CHECK-NEXT: ret i32 [[RES]]153;154 %a = load volatile i32, ptr %P1, align 4155 %b = load volatile i32, ptr %P1, align 4156 %res = sub i32 %a, %b157 ret i32 %res158}159 160; Can't DSE a volatile store161define void @volatile_store(i1 %B, ptr %P1, ptr %P2) {162; CHECK-LABEL: @volatile_store(163; CHECK-NEXT: store volatile i32 0, ptr [[P1:%.*]], align 4164; CHECK-NEXT: store i32 3, ptr [[P1]], align 4165; CHECK-NEXT: ret void166;167 store volatile i32 0, ptr %P1, align 4168 store i32 3, ptr %P1, align 4169 ret void170}171 172; Can't DSE a redundant volatile store173define void @redundant_volatile_store(i1 %B, ptr %P1, ptr %P2) {174; CHECK-LABEL: @redundant_volatile_store(175; CHECK-NEXT: store volatile i32 0, ptr [[P1:%.*]], align 4176; CHECK-NEXT: store volatile i32 0, ptr [[P1]], align 4177; CHECK-NEXT: ret void178;179 store volatile i32 0, ptr %P1, align 4180 store volatile i32 0, ptr %P1, align 4181 ret void182}183 184; Can value forward from volatiles185define i32 @test20(i1 %B, ptr %P1, ptr %P2) {186; CHECK-LABEL: @test20(187; CHECK-NEXT: [[A:%.*]] = load volatile i32, ptr [[P1:%.*]], align 4188; CHECK-NEXT: ret i32 0189;190 %a = load volatile i32, ptr %P1, align 4191 %b = load i32, ptr %P1, align 4192 %res = sub i32 %a, %b193 ret i32 %res194}195 196; Can DSE a non-volatile store in favor of a volatile one197; currently a missed optimization198define void @test21(i1 %B, ptr %P1, ptr %P2) {199; CHECK-LABEL: @test21(200; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 4201; CHECK-NEXT: store volatile i32 3, ptr [[P1]], align 4202; CHECK-NEXT: ret void203;204 store i32 0, ptr %P1, align 4205 store volatile i32 3, ptr %P1, align 4206 ret void207}208 209; Can DSE a normal store in favor of a unordered one210define void @test22(i1 %B, ptr %P1, ptr %P2) {211; CHECK-LABEL: @test22(212; CHECK-NEXT: store atomic i32 3, ptr [[P1:%.*]] unordered, align 4213; CHECK-NEXT: ret void214;215 store i32 0, ptr %P1, align 4216 store atomic i32 3, ptr %P1 unordered, align 4217 ret void218}219 220; Can also DSE a unordered store in favor of a normal one221define void @test23(i1 %B, ptr %P1, ptr %P2) {222; CHECK-LABEL: @test23(223; CHECK-NEXT: store i32 0, ptr [[P1:%.*]], align 4224; CHECK-NEXT: ret void225;226 store atomic i32 3, ptr %P1 unordered, align 4227 store i32 0, ptr %P1, align 4228 ret void229}230 231; As an implementation limitation, can't remove ordered stores232; Note that we could remove the earlier store if we could233; represent the required ordering.234define void @test24(i1 %B, ptr %P1, ptr %P2) {235; CHECK-LABEL: @test24(236; CHECK-NEXT: store atomic i32 3, ptr [[P1:%.*]] release, align 4237; CHECK-NEXT: store i32 0, ptr [[P1]], align 4238; CHECK-NEXT: ret void239;240 store atomic i32 3, ptr %P1 release, align 4241 store i32 0, ptr %P1, align 4242 ret void243}244 245; Can't remove volatile stores - each is independently observable and246; the count of such stores is an observable program side effect.247define void @test25(i1 %B, ptr %P1, ptr %P2) {248; CHECK-LABEL: @test25(249; CHECK-NEXT: store volatile i32 3, ptr [[P1:%.*]], align 4250; CHECK-NEXT: store volatile i32 0, ptr [[P1]], align 4251; CHECK-NEXT: ret void252;253 store volatile i32 3, ptr %P1, align 4254 store volatile i32 0, ptr %P1, align 4255 ret void256}257 258; Can DSE a unordered store in favor of a unordered one259define void @test26(i1 %B, ptr %P1, ptr %P2) {260; CHECK-LABEL: @test26(261; CHECK-NEXT: store atomic i32 3, ptr [[P1:%.*]] unordered, align 4262; CHECK-NEXT: ret void263;264 store atomic i32 0, ptr %P1 unordered, align 4265 store atomic i32 3, ptr %P1 unordered, align 4266 ret void267}268 269; Can DSE a unordered store in favor of a ordered one,270; but current don't due to implementation limits271define void @test27(i1 %B, ptr %P1, ptr %P2) {272; CHECK-LABEL: @test27(273; CHECK-NEXT: store atomic i32 0, ptr [[P1:%.*]] unordered, align 4274; CHECK-NEXT: store atomic i32 3, ptr [[P1]] release, align 4275; CHECK-NEXT: ret void276;277 store atomic i32 0, ptr %P1 unordered, align 4278 store atomic i32 3, ptr %P1 release, align 4279 ret void280}281 282; Can DSE an unordered atomic store in favor of an283; ordered one, but current don't due to implementation limits284define void @test28(i1 %B, ptr %P1, ptr %P2) {285; CHECK-LABEL: @test28(286; CHECK-NEXT: store atomic i32 0, ptr [[P1:%.*]] unordered, align 4287; CHECK-NEXT: store atomic i32 3, ptr [[P1]] release, align 4288; CHECK-NEXT: ret void289;290 store atomic i32 0, ptr %P1 unordered, align 4291 store atomic i32 3, ptr %P1 release, align 4292 ret void293}294 295; As an implementation limitation, can't remove ordered stores296; see also: @test24297define void @test29(i1 %B, ptr %P1, ptr %P2) {298; CHECK-LABEL: @test29(299; CHECK-NEXT: store atomic i32 3, ptr [[P1:%.*]] release, align 4300; CHECK-NEXT: store atomic i32 0, ptr [[P1]] unordered, align 4301; CHECK-NEXT: ret void302;303 store atomic i32 3, ptr %P1 release, align 4304 store atomic i32 0, ptr %P1 unordered, align 4305 ret void306}307