brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.2 KiB · f877235 Raw
411 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; RUN: opt < %s -S -passes=early-cse | FileCheck %s5 6declare void @llvm.assume(i1) nounwind7 8define void @test1(i8 %V, ptr%P) {9; CHECK-LABEL: @test1(10; CHECK-NEXT:    store i32 23, ptr [[P:%.*]], align 411; CHECK-NEXT:    [[C:%.*]] = zext i8 [[V:%.*]] to i3212; CHECK-NEXT:    store volatile i32 [[C]], ptr [[P]], align 413; CHECK-NEXT:    store volatile i32 [[C]], ptr [[P]], align 414; CHECK-NEXT:    [[E:%.*]] = add i32 [[C]], [[C]]15; CHECK-NEXT:    store volatile i32 [[E]], ptr [[P]], align 416; CHECK-NEXT:    store volatile i32 [[E]], ptr [[P]], align 417; CHECK-NEXT:    store volatile i32 [[E]], ptr [[P]], align 418; CHECK-NEXT:    ret void19;20  %A = bitcast i64 42 to double  ;; dead21  %B = add i32 4, 19             ;; constant folds22  store i32 %B, ptr %P23 24  %C = zext i8 %V to i3225  %D = zext i8 %V to i32  ;; CSE26  store volatile i32 %C, ptr %P27  store volatile i32 %D, ptr %P28 29  %E = add i32 %C, %C30  %F = add i32 %C, %C31  store volatile i32 %E, ptr %P32  store volatile i32 %F, ptr %P33 34  %G = add nuw i32 %C, %C35  store volatile i32 %G, ptr %P36  ret void37}38 39 40;; Simple load value numbering.41define i32 @test2(ptr%P) {42; CHECK-LABEL: @test2(43; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P:%.*]], align 444; CHECK-NEXT:    ret i32 045;46  %V1 = load i32, ptr %P47  %V2 = load i32, ptr %P48  %Diff = sub i32 %V1, %V249  ret i32 %Diff50}51 52define i32 @test2a(ptr%P, i1 %b) {53; CHECK-LABEL: @test2a(54; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P:%.*]], align 455; CHECK-NEXT:    tail call void @llvm.assume(i1 [[B:%.*]])56; CHECK-NEXT:    ret i32 057;58  %V1 = load i32, ptr %P59  tail call void @llvm.assume(i1 %b)60  %V2 = load i32, ptr %P61  %Diff = sub i32 %V1, %V262  ret i32 %Diff63}64 65;; Cross block load value numbering.66define i32 @test3(ptr%P, i1 %Cond) {67; CHECK-LABEL: @test3(68; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P:%.*]], align 469; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]70; CHECK:       T:71; CHECK-NEXT:    store i32 4, ptr [[P]], align 472; CHECK-NEXT:    ret i32 4273; CHECK:       F:74; CHECK-NEXT:    ret i32 075;76  %V1 = load i32, ptr %P77  br i1 %Cond, label %T, label %F78T:79  store i32 4, ptr %P80  ret i32 4281F:82  %V2 = load i32, ptr %P83  %Diff = sub i32 %V1, %V284  ret i32 %Diff85}86 87define i32 @test3a(ptr%P, i1 %Cond, i1 %b) {88; CHECK-LABEL: @test3a(89; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P:%.*]], align 490; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]91; CHECK:       T:92; CHECK-NEXT:    store i32 4, ptr [[P]], align 493; CHECK-NEXT:    ret i32 4294; CHECK:       F:95; CHECK-NEXT:    tail call void @llvm.assume(i1 [[B:%.*]])96; CHECK-NEXT:    ret i32 097;98  %V1 = load i32, ptr %P99  br i1 %Cond, label %T, label %F100T:101  store i32 4, ptr %P102  ret i32 42103F:104  tail call void @llvm.assume(i1 %b)105  %V2 = load i32, ptr %P106  %Diff = sub i32 %V1, %V2107  ret i32 %Diff108}109 110;; Cross block load value numbering stops when stores happen.111define i32 @test4(ptr%P, i1 %Cond) {112; CHECK-LABEL: @test4(113; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P:%.*]], align 4114; CHECK-NEXT:    br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]115; CHECK:       T:116; CHECK-NEXT:    ret i32 42117; CHECK:       F:118; CHECK-NEXT:    store i32 42, ptr [[P]], align 4119; CHECK-NEXT:    [[DIFF:%.*]] = sub i32 [[V1]], 42120; CHECK-NEXT:    ret i32 [[DIFF]]121;122  %V1 = load i32, ptr %P123  br i1 %Cond, label %T, label %F124T:125  ret i32 42126F:127  ; Clobbers V1128  store i32 42, ptr %P129 130  %V2 = load i32, ptr %P131  %Diff = sub i32 %V1, %V2132  ret i32 %Diff133}134 135declare i32 @func(ptr%P) readonly136 137;; Simple call CSE'ing.138define i32 @test5(ptr%P) {139; CHECK-LABEL: @test5(140; CHECK-NEXT:    [[V1:%.*]] = call i32 @func(ptr [[P:%.*]]), !prof [[PROF0:![0-9]+]]141; CHECK-NEXT:    ret i32 0142;143  %V1 = call i32 @func(ptr %P), !prof !0144  %V2 = call i32 @func(ptr %P), !prof !1145  %Diff = sub i32 %V1, %V2146  ret i32 %Diff147}148 149declare void @void_func()150 151define void @void_func_cse_readonly(ptr %P) {152; CHECK-LABEL: @void_func_cse_readonly(153; CHECK-NEXT:    call void @void_func(ptr [[P:%.*]]) #[[ATTR1:[0-9]+]]154; CHECK-NEXT:    ret void155;156  call void @void_func(ptr %P) memory(read)157  call void @void_func(ptr %P) memory(read)158  ret void159}160 161define void @void_func_cse_readnone(ptr %P) {162; CHECK-LABEL: @void_func_cse_readnone(163; CHECK-NEXT:    call void @void_func(ptr [[P:%.*]]) #[[ATTR2:[0-9]+]]164; CHECK-NEXT:    ret void165;166  call void @void_func(ptr %P) memory(none)167  call void @void_func(ptr %P) memory(none)168  ret void169}170 171!0 = !{!"branch_weights", i32 95}172!1 = !{!"branch_weights", i32 95}173 174;; Trivial Store->load forwarding175define i32 @test6(ptr%P) {176; CHECK-LABEL: @test6(177; CHECK-NEXT:    store i32 42, ptr [[P:%.*]], align 4178; CHECK-NEXT:    ret i32 42179;180  store i32 42, ptr %P181  %V1 = load i32, ptr %P182  ret i32 %V1183}184 185define i32 @test6a(ptr%P, i1 %b) {186; CHECK-LABEL: @test6a(187; CHECK-NEXT:    store i32 42, ptr [[P:%.*]], align 4188; CHECK-NEXT:    tail call void @llvm.assume(i1 [[B:%.*]])189; CHECK-NEXT:    ret i32 42190;191  store i32 42, ptr %P192  tail call void @llvm.assume(i1 %b)193  %V1 = load i32, ptr %P194  ret i32 %V1195}196 197;; Trivial dead store elimination.198define void @test7(ptr%P) {199; CHECK-LABEL: @test7(200; CHECK-NEXT:    store i32 45, ptr [[P:%.*]], align 4201; CHECK-NEXT:    ret void202;203  store i32 42, ptr %P204  store i32 45, ptr %P205  ret void206}207 208;; Readnone functions aren't invalidated by stores.209define i32 @test8(ptr%P) {210; CHECK-LABEL: @test8(211; CHECK-NEXT:    [[V1:%.*]] = call i32 @func(ptr [[P:%.*]]) #[[ATTR2]]212; CHECK-NEXT:    store i32 4, ptr [[P]], align 4213; CHECK-NEXT:    ret i32 0214;215  %V1 = call i32 @func(ptr %P) readnone216  store i32 4, ptr %P217  %V2 = call i32 @func(ptr %P) readnone218  %Diff = sub i32 %V1, %V2219  ret i32 %Diff220}221 222;; Trivial DSE can't be performed across a readonly call.  The call223;; can observe the earlier write.224define i32 @test9(ptr%P) {225; CHECK-LABEL: @test9(226; CHECK-NEXT:    store i32 4, ptr [[P:%.*]], align 4227; CHECK-NEXT:    [[V1:%.*]] = call i32 @func(ptr [[P]]) #[[ATTR1]]228; CHECK-NEXT:    store i32 5, ptr [[P]], align 4229; CHECK-NEXT:    ret i32 [[V1]]230;231  store i32 4, ptr %P232  %V1 = call i32 @func(ptr %P) readonly233  store i32 5, ptr %P234  ret i32 %V1235}236 237;; Trivial DSE can be performed across a readnone nounwind call.238define i32 @test10(ptr%P) {239; CHECK-LABEL: @test10(240; CHECK-NEXT:    [[V1:%.*]] = call i32 @func(ptr [[P:%.*]]) #[[ATTR3:[0-9]+]]241; CHECK-NEXT:    store i32 5, ptr [[P]], align 4242; CHECK-NEXT:    ret i32 [[V1]]243;244  store i32 4, ptr %P245  %V1 = call i32 @func(ptr %P) readnone nounwind246  store i32 5, ptr %P247  ret i32 %V1248}249 250; Trivial DSE can't be performed across a potentially unwinding readnone251; call, as the caller may read the memory on unwind.252define i32 @test_readnone_missing_nounwind(ptr %P) {253; CHECK-LABEL: @test_readnone_missing_nounwind(254; CHECK-NEXT:    store i32 4, ptr [[P:%.*]], align 4255; CHECK-NEXT:    [[V1:%.*]] = call i32 @func(ptr [[P]]) #[[ATTR2]]256; CHECK-NEXT:    store i32 5, ptr [[P]], align 4257; CHECK-NEXT:    ret i32 [[V1]]258;259  store i32 4, ptr %P260  %V1 = call i32 @func(ptr %P) readnone261  store i32 5, ptr %P262  ret i32 %V1263}264 265;; Trivial dead store elimination - should work for an entire series of dead stores too.266define void @test11(ptr%P) {267; CHECK-LABEL: @test11(268; CHECK-NEXT:    store i32 45, ptr [[P:%.*]], align 4269; CHECK-NEXT:    ret void270;271  store i32 42, ptr %P272  store i32 43, ptr %P273  store i32 44, ptr %P274  store i32 45, ptr %P275  ret void276}277 278define i32 @test12(i1 %B, ptr %P1, ptr %P2) {279; CHECK-LABEL: @test12(280; CHECK-NEXT:    [[LOAD0:%.*]] = load i32, ptr [[P1:%.*]], align 4281; CHECK-NEXT:    [[TMP1:%.*]] = load atomic i32, ptr [[P2:%.*]] seq_cst, align 4282; CHECK-NEXT:    [[LOAD1:%.*]] = load i32, ptr [[P1]], align 4283; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[B:%.*]], i32 [[LOAD0]], i32 [[LOAD1]]284; CHECK-NEXT:    ret i32 [[SEL]]285;286  %load0 = load i32, ptr %P1287  %1 = load atomic i32, ptr %P2 seq_cst, align 4288  %load1 = load i32, ptr %P1289  %sel = select i1 %B, i32 %load0, i32 %load1290  ret i32 %sel291}292 293define void @dse1(ptr%P) {294; CHECK-LABEL: @dse1(295; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4296; CHECK-NEXT:    ret void297;298  %v = load i32, ptr %P299  store i32 %v, ptr %P300  ret void301}302 303define void @dse2(ptr%P) {304; CHECK-LABEL: @dse2(305; CHECK-NEXT:    [[V:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4306; CHECK-NEXT:    ret void307;308  %v = load atomic i32, ptr %P seq_cst, align 4309  store i32 %v, ptr %P310  ret void311}312 313define void @dse3(ptr%P) {314; CHECK-LABEL: @dse3(315; CHECK-NEXT:    [[V:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4316; CHECK-NEXT:    ret void317;318  %v = load atomic i32, ptr %P seq_cst, align 4319  store atomic i32 %v, ptr %P unordered, align 4320  ret void321}322 323define i32 @dse4(ptr%P, ptr%Q) {324; CHECK-LABEL: @dse4(325; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[Q:%.*]], align 4326; CHECK-NEXT:    [[V:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 4327; CHECK-NEXT:    ret i32 0328;329  %a = load i32, ptr %Q330  %v = load atomic i32, ptr %P unordered, align 4331  store atomic i32 %v, ptr %P unordered, align 4332  %b = load i32, ptr %Q333  %res = sub i32 %a, %b334  ret i32 %res335}336 337; Note that in this example, %P and %Q could in fact be the same338; pointer.  %v could be different than the value observed for %a339; and that's okay because we're using relaxed memory ordering.340; The only guarantee we have to provide is that each of the loads341; has to observe some value written to that location.  We  do342; not have to respect the order in which those writes were done.343define i32 @dse5(ptr%P, ptr%Q) {344; CHECK-LABEL: @dse5(345; CHECK-NEXT:    [[V:%.*]] = load atomic i32, ptr [[P:%.*]] unordered, align 4346; CHECK-NEXT:    [[A:%.*]] = load atomic i32, ptr [[Q:%.*]] unordered, align 4347; CHECK-NEXT:    ret i32 0348;349  %v = load atomic i32, ptr %P unordered, align 4350  %a = load atomic i32, ptr %Q unordered, align 4351  store atomic i32 %v, ptr %P unordered, align 4352  %b = load atomic i32, ptr %Q unordered, align 4353  %res = sub i32 %a, %b354  ret i32 %res355}356 357 358define void @dse_neg1(ptr%P) {359; CHECK-LABEL: @dse_neg1(360; CHECK-NEXT:    store i32 5, ptr [[P:%.*]], align 4361; CHECK-NEXT:    ret void362;363  %v = load i32, ptr %P364  store i32 5, ptr %P365  ret void366}367 368; Could remove the store, but only if ordering was somehow369; encoded.370define void @dse_neg2(ptr%P) {371; CHECK-LABEL: @dse_neg2(372; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P:%.*]], align 4373; CHECK-NEXT:    store atomic i32 [[V]], ptr [[P]] seq_cst, align 4374; CHECK-NEXT:    ret void375;376  %v = load i32, ptr %P377  store atomic i32 %v, ptr %P seq_cst, align 4378  ret void379}380 381@c = external global i32, align 4382declare i32 @reads_c(i32 returned)383define void @pr28763() {384; CHECK-LABEL: @pr28763(385; CHECK-NEXT:  entry:386; CHECK-NEXT:    store i32 0, ptr @c, align 4387; CHECK-NEXT:    [[CALL:%.*]] = call i32 @reads_c(i32 0)388; CHECK-NEXT:    store i32 2, ptr @c, align 4389; CHECK-NEXT:    ret void390;391entry:392  %load = load i32, ptr @c, align 4393  store i32 0, ptr @c, align 4394  %call = call i32 @reads_c(i32 0)395  store i32 2, ptr @c, align 4396  ret void397}398 399define i1 @cse_freeze(i1 %a) {400; CHECK-LABEL: @cse_freeze(401; CHECK-NEXT:  entry:402; CHECK-NEXT:    [[B:%.*]] = freeze i1 [[A:%.*]]403; CHECK-NEXT:    ret i1 [[B]]404;405entry:406  %b = freeze i1 %a407  %c = freeze i1 %a408  %and = and i1 %b, %c409  ret i1 %and410}411