114 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=memcpyopt -S %s | FileCheck %s3 4declare void @init(ptr nocapture sret(i64) align 8)5 6declare i1 @check(ptr readonly byval(i64) align 8) readonly argmemonly7 8declare void @clobber(ptr) argmemonly9 10declare void @llvm.lifetime.start.p0(ptr nocapture)11declare void @llvm.lifetime.end.p0(ptr nocapture)12declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)13 14; %a.2's lifetime ends before the call to @check. We must remove the call to15; @llvm.lifetime.end in order to replace %a.1 with %a.2 in the call to @check.16define i1 @alloca_forwarding_lifetime_end_clobber() {17; CHECK-LABEL: @alloca_forwarding_lifetime_end_clobber(18; CHECK-NEXT: entry:19; CHECK-NEXT: [[A_2:%.*]] = alloca i64, align 820; CHECK-NEXT: call void @init(ptr sret(i64) align 8 [[A_2]])21; CHECK-NEXT: store i8 0, ptr [[A_2]], align 122; CHECK-NEXT: [[CALL:%.*]] = call i1 @check(ptr byval(i64) align 8 [[A_2]])23; CHECK-NEXT: ret i1 [[CALL]]24;25entry:26 %a.1 = alloca i64, align 827 %a.2 = alloca i64, align 828 call void @llvm.lifetime.start.p0(ptr %a.2)29 call void @init(ptr sret(i64) align 8 %a.2)30 store i8 0, ptr %a.231 call void @llvm.memcpy.p0.p0.i64(ptr %a.1, ptr %a.2, i64 8, i1 false)32 call void @llvm.lifetime.end.p0(ptr %a.2)33 ;call void @clobber(ptr %a.2)34 %call = call i1 @check(ptr byval(i64) align 8 %a.1)35 ret i1 %call36}37 38; There is a call clobbering %a.2 before the call to @check. Cannot replace39; %a.1 with %a.2 in the call to @check.40define i1 @alloca_forwarding_call_clobber() {41; CHECK-LABEL: @alloca_forwarding_call_clobber(42; CHECK-NEXT: entry:43; CHECK-NEXT: [[A_1:%.*]] = alloca i64, align 844; CHECK-NEXT: [[A_2:%.*]] = alloca i64, align 845; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_2]])46; CHECK-NEXT: call void @init(ptr sret(i64) align 8 [[A_2]])47; CHECK-NEXT: store i8 0, ptr [[A_2]], align 148; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A_1]], ptr [[A_2]], i64 8, i1 false)49; CHECK-NEXT: call void @clobber(ptr [[A_2]])50; CHECK-NEXT: [[CALL:%.*]] = call i1 @check(ptr byval(i64) align 8 [[A_1]])51; CHECK-NEXT: ret i1 [[CALL]]52;53entry:54 %a.1 = alloca i64, align 855 %a.2 = alloca i64, align 856 call void @llvm.lifetime.start.p0(ptr %a.2)57 call void @init(ptr sret(i64) align 8 %a.2)58 store i8 0, ptr %a.259 call void @llvm.memcpy.p0.p0.i64(ptr %a.1, ptr %a.2, i64 8, i1 false)60 call void @clobber(ptr %a.2)61 %call = call i1 @check(ptr byval(i64) align 8 %a.1)62 ret i1 %call63}64 65define i1 @alloca_forwarding_call_clobber_after() {66; CHECK-LABEL: @alloca_forwarding_call_clobber_after(67; CHECK-NEXT: entry:68; CHECK-NEXT: [[A_1:%.*]] = alloca i64, align 869; CHECK-NEXT: [[A_2:%.*]] = alloca i64, align 870; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[A_2]])71; CHECK-NEXT: call void @init(ptr sret(i64) align 8 [[A_2]])72; CHECK-NEXT: store i8 0, ptr [[A_2]], align 173; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A_1]], ptr [[A_2]], i64 8, i1 false)74; CHECK-NEXT: [[CALL:%.*]] = call i1 @check(ptr byval(i64) align 8 [[A_2]])75; CHECK-NEXT: call void @clobber(ptr [[A_2]])76; CHECK-NEXT: ret i1 [[CALL]]77;78entry:79 %a.1 = alloca i64, align 880 %a.2 = alloca i64, align 881 call void @llvm.lifetime.start.p0(ptr %a.2)82 call void @init(ptr sret(i64) align 8 %a.2)83 store i8 0, ptr %a.284 call void @llvm.memcpy.p0.p0.i64(ptr %a.1, ptr %a.2, i64 8, i1 false)85 %call = call i1 @check(ptr byval(i64) align 8 %a.1)86 call void @clobber(ptr %a.2)87 ret i1 %call88}89 90define i1 @alloca_forwarding_unrelated_call_noclobber() {91; CHECK-LABEL: @alloca_forwarding_unrelated_call_noclobber(92; CHECK-NEXT: entry:93; CHECK-NEXT: [[A_2:%.*]] = alloca i64, align 894; CHECK-NEXT: [[A_3:%.*]] = alloca i64, align 895; CHECK-NEXT: call void @init(ptr sret(i64) align 8 [[A_2]])96; CHECK-NEXT: store i8 0, ptr [[A_2]], align 197; CHECK-NEXT: call void @clobber(ptr [[A_3]])98; CHECK-NEXT: [[CALL:%.*]] = call i1 @check(ptr byval(i64) align 8 [[A_2]])99; CHECK-NEXT: ret i1 [[CALL]]100;101entry:102 %a.1 = alloca i64, align 8103 %a.2 = alloca i64, align 8104 %a.3 = alloca i64, align 8105 call void @llvm.lifetime.start.p0(ptr %a.2)106 call void @init(ptr sret(i64) align 8 %a.2)107 store i8 0, ptr %a.2108 call void @llvm.memcpy.p0.p0.i64(ptr %a.1, ptr %a.2, i64 8, i1 false)109 call void @clobber(ptr %a.3)110 %call = call i1 @check(ptr byval(i64) align 8 %a.1)111 ret i1 %call112}113 114