brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.3 KiB · 6c999c5 Raw
241 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=memcpyopt < %s -verify-memoryssa | FileCheck %s3 4define i8 @read_dest_between_call_and_memcpy() {5; CHECK-LABEL: @read_dest_between_call_and_memcpy(6; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 17; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 18; CHECK-NEXT:    store i8 1, ptr [[DEST]], align 19; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[SRC]], i8 0, i64 16, i1 false)10; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[DEST]], align 111; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[DEST]], i8 0, i64 16, i1 false)12; CHECK-NEXT:    ret i8 [[X]]13;14  %dest = alloca [16 x i8]15  %src = alloca [16 x i8]16  store i8 1, ptr %dest17  call void @llvm.memset.p0.i64(ptr %src, i8 0, i64 16, i1 false)18  %x = load i8, ptr %dest19  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)20  ret i8 %x21}22 23define i8 @read_src_between_call_and_memcpy() {24; CHECK-LABEL: @read_src_between_call_and_memcpy(25; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 126; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 127; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[SRC]], i8 0, i64 16, i1 false)28; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[SRC]], align 129; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[DEST]], i8 0, i64 16, i1 false)30; CHECK-NEXT:    ret i8 [[X]]31;32  %dest = alloca [16 x i8]33  %src = alloca [16 x i8]34  call void @llvm.memset.p0.i64(ptr %src, i8 0, i64 16, i1 false)35  %x = load i8, ptr %src36  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)37  ret i8 %x38}39 40define void @write_dest_between_call_and_memcpy() {41; CHECK-LABEL: @write_dest_between_call_and_memcpy(42; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 143; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 144; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[SRC]], i8 0, i64 16, i1 false)45; CHECK-NEXT:    store i8 1, ptr [[DEST]], align 146; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[DEST]], i8 0, i64 16, i1 false)47; CHECK-NEXT:    ret void48;49  %dest = alloca [16 x i8]50  %src = alloca [16 x i8]51  call void @llvm.memset.p0.i64(ptr %src, i8 0, i64 16, i1 false)52  store i8 1, ptr %dest53  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)54  ret void55}56 57define void @write_src_between_call_and_memcpy() {58; CHECK-LABEL: @write_src_between_call_and_memcpy(59; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 160; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[SRC]], i8 0, i64 16, i1 false)61; CHECK-NEXT:    store i8 1, ptr [[SRC]], align 162; CHECK-NEXT:    ret void63;64  %dest = alloca [16 x i8]65  %src = alloca [16 x i8]66  call void @llvm.memset.p0.i64(ptr %src, i8 0, i64 16, i1 false)67  store i8 1, ptr %src68  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)69  ret void70}71 72define void @throw_between_call_and_mempy(ptr writable dereferenceable(16) %dest.i8) {73; CHECK-LABEL: @throw_between_call_and_mempy(74; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 175; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[SRC]], i8 0, i64 16, i1 false)76; CHECK-NEXT:    call void @may_throw() #[[ATTR2:[0-9]+]]77; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[DEST_I8:%.*]], i8 0, i64 16, i1 false)78; CHECK-NEXT:    ret void79;80  %src = alloca [16 x i8]81  call void @llvm.memset.p0.i64(ptr %src, i8 0, i64 16, i1 false)82  call void @may_throw() readnone83  call void @llvm.memcpy.p0.p0.i64(ptr %dest.i8, ptr %src, i64 16, i1 false)84  ret void85}86 87define void @dest_is_gep_nounwind_call() {88; CHECK-LABEL: @dest_is_gep_nounwind_call(89; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 190; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 191; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], ptr [[DEST]], i64 0, i64 892; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST_I8]]) #[[ATTR3:[0-9]+]]93; CHECK-NEXT:    ret void94;95  %dest = alloca [16 x i8]96  %src = alloca [8 x i8]97  %dest.i8 = getelementptr [16 x i8], ptr %dest, i64 0, i64 898  call void @accept_ptr(ptr %src) nounwind99  call void @llvm.memcpy.p0.p0.i64(ptr %dest.i8, ptr %src, i64 8, i1 false)100  ret void101}102 103define void @dest_is_gep_may_throw_call() {104; CHECK-LABEL: @dest_is_gep_may_throw_call(105; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1106; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 1107; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], ptr [[DEST]], i64 0, i64 8108; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST_I8]])109; CHECK-NEXT:    ret void110;111  %dest = alloca [16 x i8]112  %src = alloca [8 x i8]113  %dest.i8 = getelementptr [16 x i8], ptr %dest, i64 0, i64 8114  call void @accept_ptr(ptr %src)115  call void @llvm.memcpy.p0.p0.i64(ptr %dest.i8, ptr %src, i64 8, i1 false)116  ret void117}118 119define void @dest_is_gep_requires_movement() {120; CHECK-LABEL: @dest_is_gep_requires_movement(121; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1122; CHECK-NEXT:    [[SRC:%.*]] = alloca [8 x i8], align 1123; CHECK-NEXT:    [[DEST_I8:%.*]] = getelementptr [16 x i8], ptr [[DEST]], i64 0, i64 8124; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST_I8]]) #[[ATTR3]]125; CHECK-NEXT:    ret void126;127  %dest = alloca [16 x i8]128  %src = alloca [8 x i8]129  call void @accept_ptr(ptr %src) nounwind130  %dest.i8 = getelementptr [16 x i8], ptr %dest, i64 0, i64 8131  call void @llvm.memcpy.p0.p0.i64(ptr %dest.i8, ptr %src, i64 8, i1 false)132  ret void133}134 135define void @capture_before_call_argmemonly() {136; CHECK-LABEL: @capture_before_call_argmemonly(137; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1138; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1139; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST]])140; CHECK-NEXT:    call void @accept_ptr(ptr captures(none) [[DEST]]) #[[ATTR4:[0-9]+]]141; CHECK-NEXT:    ret void142;143  %dest = alloca [16 x i8]144  %src = alloca [16 x i8]145  call void @accept_ptr(ptr %dest) ; capture146  call void @accept_ptr(ptr nocapture %src) argmemonly147  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)148  ret void149}150 151define void @capture_before_call_argmemonly_nounwind() {152; CHECK-LABEL: @capture_before_call_argmemonly_nounwind(153; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1154; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1155; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST]])156; CHECK-NEXT:    call void @accept_ptr(ptr captures(none) [[DEST]]) #[[ATTR5:[0-9]+]]157; CHECK-NEXT:    ret void158;159  %dest = alloca [16 x i8]160  %src = alloca [16 x i8]161  call void @accept_ptr(ptr %dest) ; capture162  ; NB: argmemonly currently implies willreturn.163  call void @accept_ptr(ptr nocapture %src) argmemonly nounwind164  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)165  ret void166}167 168define void @capture_before_call_argmemonly_nounwind_willreturn() {169; CHECK-LABEL: @capture_before_call_argmemonly_nounwind_willreturn(170; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1171; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1172; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST]])173; CHECK-NEXT:    call void @accept_ptr(ptr captures(none) [[DEST]]) #[[ATTR6:[0-9]+]]174; CHECK-NEXT:    ret void175;176  %dest = alloca [16 x i8]177  %src = alloca [16 x i8]178  call void @accept_ptr(ptr %dest) ; capture179  call void @accept_ptr(ptr nocapture %src) argmemonly nounwind willreturn180  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)181  ret void182}183 184; There is no path from the capture back to the memcpy.185; So we are allowed to perform the call slot optimization.186define void @capture_nopath_call(i1 %cond) {187; CHECK-LABEL: @capture_nopath_call(188; CHECK-NEXT:    [[DEST:%.*]] = alloca [16 x i8], align 1189; CHECK-NEXT:    [[SRC:%.*]] = alloca [16 x i8], align 1190; CHECK-NEXT:    br i1 [[COND:%.*]], label [[CAPTURES:%.*]], label [[NOCAPTURES:%.*]]191; CHECK:       captures:192; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST]])193; CHECK-NEXT:    ret void194; CHECK:       nocaptures:195; CHECK-NEXT:    call void @accept_ptr(ptr [[DEST]]) #[[ATTR3]]196; CHECK-NEXT:    ret void197;198  %dest = alloca [16 x i8]199  %src = alloca [16 x i8]200  br i1 %cond, label %captures, label %nocaptures201 202captures:203  call void @accept_ptr(ptr %dest) ; capture204  ret void205 206nocaptures:207  call void @accept_ptr(ptr %src) nounwind208  call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 16, i1 false)209  ret void210}211 212define void @source_alignment(ptr noalias writable dereferenceable(128) %dst) {213; CHECK-LABEL: @source_alignment(214; CHECK-NEXT:    [[SRC:%.*]] = alloca [128 x i8], align 4215; CHECK-NEXT:    call void @accept_ptr(ptr captures(none) [[DST:%.*]]) #[[ATTR3]]216; CHECK-NEXT:    ret void217;218  %src = alloca [128 x i8], align 4219  call void @accept_ptr(ptr nocapture %src) nounwind220  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dst, ptr %src, i64 128, i1 false)221  ret void222}223 224define void @dest_not_writable(ptr noalias dereferenceable(128) %dst) {225; CHECK-LABEL: @dest_not_writable(226; CHECK-NEXT:    [[SRC:%.*]] = alloca [128 x i8], align 4227; CHECK-NEXT:    call void @accept_ptr(ptr captures(none) [[SRC]]) #[[ATTR3]]228; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[DST:%.*]], ptr [[SRC]], i64 128, i1 false)229; CHECK-NEXT:    ret void230;231  %src = alloca [128 x i8], align 4232  call void @accept_ptr(ptr nocapture %src) nounwind233  call void @llvm.memcpy.p0.p0.i64(ptr align 4 %dst, ptr %src, i64 128, i1 false)234  ret void235}236 237declare void @may_throw()238declare void @accept_ptr(ptr)239declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)240declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)241