Index: llvm/test/Transforms/MemCpyOpt/memcpy.ll =================================================================== --- llvm/test/Transforms/MemCpyOpt/memcpy.ll +++ llvm/test/Transforms/MemCpyOpt/memcpy.ll @@ -391,3 +391,106 @@ declare void @f1(ptr nocapture sret(%struct.big)) declare void @f2(ptr) + +declare void @f_noattr(ptr) +declare void @f_full_readonly(ptr nocapture noalias readonly) +declare void @f_full_readnone(ptr nocapture noalias readnone) +declare void @f_full_memory_none(ptr nocapture noalias) memory(none) +declare void @f_noa(ptr noalias) + +; TODO: remove memcpy, which is guaranteed to be invariant +; before and after the call because of its attributes. +define void @immut_param1(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param1( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_noattr(ptr noalias nocapture readonly align 4 [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_noattr(ptr align 4 nocapture noalias readonly %val1) + ret void +} + +; TODO: remove memcpy +define void @immut_param2_readonly(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param2( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_fullattr_immut(ptr align 4 [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_full_readonly(ptr align 4 %val1) + ret void +} + +define void @immut_param2_readnone(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param2( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_fullattr_immut(ptr align 4 [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_full_readnone(ptr align 4 %val1) + ret void +} + +define void @immut_param2_memory_none(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param2( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_fullattr_immut(ptr align 4 [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_full_memory_none(ptr align 4 %val1) + ret void +} + +; TODO: remove memcpy, cause union of attributes on call-site +; and palam shows immutability of arg ptr. +define void @immut_param3(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param3( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_noa(ptr align 4 [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_noa(ptr align 4 %val1) + ret void +} + +; can't remove memcpy because if the call doesn't specify the alignment, +; then it is some target specific value that we can't know. +define void @immut_param4_no_align(ptr align 4 noalias %val) { +; CHECK-LABEL: @immut_param4_no_align( +; CHECK-NEXT: start: +; CHECK-NEXT: [[VAL1:%.*]] = alloca i8, align 4 +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[VAL1]], ptr align 4 [[VAL:%.*]], i64 1, i1 false) +; CHECK-NEXT: call void @f_fullattr_immut(ptr [[VAL1]]) +; CHECK-NEXT: ret void +; +start: + %val1 = alloca i8, align 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %val1, ptr align 4 %val, i64 1, i1 false) + call void @f_full_readonly(ptr %val1) + ret void +}