164 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=early-cse -earlycse-debug-hash < %s | FileCheck %s --check-prefixes=CHECK,NO-MSSA3; RUN: opt -S -passes='early-cse<memssa>' < %s | FileCheck %s --check-prefixes=CHECK,MSSA4 5@var = global i32 undef6declare void @foo() nounwind7 8define void @test() {9; CHECK-LABEL: @test(10; CHECK-NEXT: call void @foo() #[[ATTR1:[0-9]+]]11; CHECK-NEXT: store i32 2, ptr @var, align 412; CHECK-NEXT: ret void13;14 store i32 1, ptr @var15 call void @foo() writeonly16 store i32 2, ptr @var17 ret void18}19 20declare void @writeonly_void() memory(write)21 22; Can CSE writeonly calls, including non-nounwind/willreturn.23define void @writeonly_cse() {24; CHECK-LABEL: @writeonly_cse(25; CHECK-NEXT: call void @writeonly_void()26; CHECK-NEXT: ret void27;28 call void @writeonly_void()29 call void @writeonly_void()30 ret void31}32 33; Can CSE, loads do not matter.34define i32 @writeonly_cse_intervening_load(ptr %p) {35; CHECK-LABEL: @writeonly_cse_intervening_load(36; CHECK-NEXT: call void @writeonly_void()37; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[P:%.*]], align 438; CHECK-NEXT: ret i32 [[V]]39;40 call void @writeonly_void()41 %v = load i32, ptr %p42 call void @writeonly_void()43 ret i32 %v44}45 46; Cannot CSE, the store may be to the same memory.47define void @writeonly_cse_intervening_store(ptr %p) {48; CHECK-LABEL: @writeonly_cse_intervening_store(49; CHECK-NEXT: call void @writeonly_void()50; CHECK-NEXT: store i32 0, ptr [[P:%.*]], align 451; CHECK-NEXT: call void @writeonly_void()52; CHECK-NEXT: ret void53;54 call void @writeonly_void()55 store i32 0, ptr %p56 call void @writeonly_void()57 ret void58}59 60; Can CSE, the store does not alias the writeonly call.61define void @writeonly_cse_intervening_noalias_store(ptr noalias %p) {62; NO-MSSA-LABEL: @writeonly_cse_intervening_noalias_store(63; NO-MSSA-NEXT: call void @writeonly_void()64; NO-MSSA-NEXT: store i32 0, ptr [[P:%.*]], align 465; NO-MSSA-NEXT: call void @writeonly_void()66; NO-MSSA-NEXT: ret void67;68; MSSA-LABEL: @writeonly_cse_intervening_noalias_store(69; MSSA-NEXT: call void @writeonly_void()70; MSSA-NEXT: store i32 0, ptr [[P:%.*]], align 471; MSSA-NEXT: ret void72;73 call void @writeonly_void()74 store i32 0, ptr %p75 call void @writeonly_void()76 ret void77}78 79; Cannot CSE loads across writeonly call.80define i32 @load_cse_across_writeonly(ptr %p) {81; CHECK-LABEL: @load_cse_across_writeonly(82; CHECK-NEXT: [[V1:%.*]] = load i32, ptr [[P:%.*]], align 483; CHECK-NEXT: call void @writeonly_void()84; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[P]], align 485; CHECK-NEXT: [[RES:%.*]] = sub i32 [[V1]], [[V2]]86; CHECK-NEXT: ret i32 [[RES]]87;88 %v1 = load i32, ptr %p89 call void @writeonly_void()90 %v2 = load i32, ptr %p91 %res = sub i32 %v1, %v292 ret i32 %res93}94 95; Can CSE loads across eliminated writeonly call.96define i32 @load_cse_across_csed_writeonly(ptr %p) {97; CHECK-LABEL: @load_cse_across_csed_writeonly(98; CHECK-NEXT: call void @writeonly_void()99; CHECK-NEXT: [[V2:%.*]] = load i32, ptr [[P:%.*]], align 4100; CHECK-NEXT: ret i32 0101;102 call void @writeonly_void()103 %v1 = load i32, ptr %p104 call void @writeonly_void()105 %v2 = load i32, ptr %p106 %res = sub i32 %v1, %v2107 ret i32 %res108}109 110declare i32 @writeonly(ptr %p) memory(write)111 112; Can CSE writeonly calls with arg and return.113define i32 @writeonly_ret_cse(ptr %p) {114; CHECK-LABEL: @writeonly_ret_cse(115; CHECK-NEXT: [[V2:%.*]] = call i32 @writeonly(ptr [[P:%.*]])116; CHECK-NEXT: ret i32 0117;118 %v1 = call i32 @writeonly(ptr %p)119 %v2 = call i32 @writeonly(ptr %p)120 %res = sub i32 %v1, %v2121 ret i32 %res122}123 124; Cannot CSE writeonly calls with different arguments.125define i32 @writeonly_different_args(ptr %p1, ptr %p2) {126; CHECK-LABEL: @writeonly_different_args(127; CHECK-NEXT: [[V1:%.*]] = call i32 @writeonly(ptr [[P1:%.*]])128; CHECK-NEXT: [[V2:%.*]] = call i32 @writeonly(ptr [[P2:%.*]])129; CHECK-NEXT: [[RES:%.*]] = sub i32 [[V1]], [[V2]]130; CHECK-NEXT: ret i32 [[RES]]131;132 %v1 = call i32 @writeonly(ptr %p1)133 %v2 = call i32 @writeonly(ptr %p2)134 %res = sub i32 %v1, %v2135 ret i32 %res136}137 138declare void @callee()139 140; These are weird cases where the same call is both readonly and writeonly141; based on call-site attributes. I believe this implies that both calls are142; actually readnone and safe to CSE, but leave them alone to be conservative.143define void @readonly_and_writeonly() {144; CHECK-LABEL: @readonly_and_writeonly(145; CHECK-NEXT: call void @callee() #[[ATTR2:[0-9]+]]146; CHECK-NEXT: call void @callee() #[[ATTR1]]147; CHECK-NEXT: ret void148;149 call void @callee() memory(read)150 call void @callee() memory(write)151 ret void152}153 154define void @writeonly_and_readonly() {155; CHECK-LABEL: @writeonly_and_readonly(156; CHECK-NEXT: call void @callee() #[[ATTR1]]157; CHECK-NEXT: call void @callee() #[[ATTR2]]158; CHECK-NEXT: ret void159;160 call void @callee() memory(write)161 call void @callee() memory(read)162 ret void163}164