Index: llvm/test/Transforms/DeadStoreElimination/MSSA/libcalls.ll =================================================================== --- llvm/test/Transforms/DeadStoreElimination/MSSA/libcalls.ll +++ llvm/test/Transforms/DeadStoreElimination/MSSA/libcalls.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -inferattrs -basic-aa -dse < %s | FileCheck %s +; RUN: opt -S -basic-aa -dse < %s | FileCheck %s --check-prefixes=CHECK,LPM +; RUN: opt -S -aa-pipeline=basic-aa -passes=inferattrs,dse < %s | FileCheck %s --check-prefixes=CHECK,NPM target triple = "x86_64-unknown-linux-gnu" @@ -48,8 +49,16 @@ } define void @test5(i8* nocapture %src) { -; CHECK-LABEL: @test5( -; CHECK-NEXT: ret void +; LPM-LABEL: @test5( +; LPM-NEXT: [[DEST:%.*]] = alloca [100 x i8], align 16 +; LPM-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [100 x i8], [100 x i8]* [[DEST]], i64 0, i64 0 +; LPM-NEXT: [[CALL:%.*]] = call i8* @strcpy(i8* [[ARRAYDECAY]], i8* [[SRC:%.*]]) +; LPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 10 +; LPM-NEXT: store i8 97, i8* [[ARRAYIDX]], align 1 +; LPM-NEXT: ret void +; +; NPM-LABEL: @test5( +; NPM-NEXT: ret void ; %dest = alloca [100 x i8], align 16 %arraydecay = getelementptr inbounds [100 x i8], [100 x i8]* %dest, i64 0, i64 0 @@ -85,6 +94,10 @@ ; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1 ; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1 +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2 +; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1 +; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3 +; CHECK-NEXT: store i8 52, i8* [[GEP_3]], align 1 ; CHECK-NEXT: [[RES:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2) ; CHECK-NEXT: ret i32 [[RES]] ; @@ -141,6 +154,10 @@ ; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1 ; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1 +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2 +; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1 +; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3 +; CHECK-NEXT: store i8 52, i8* [[GEP_3]], align 1 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @bcmp(i8* nonnull dereferenceable(2) [[FOO:%.*]], i8* nonnull dereferenceable(2) [[STACK_PTR]], i64 2) ; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: ret i1 [[RES]] @@ -201,6 +218,10 @@ ; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1 ; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1 +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2 +; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1 +; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3 +; CHECK-NEXT: store i8 52, i8* [[GEP_3]], align 1 ; CHECK-NEXT: [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 2) ; CHECK-NEXT: ret i8* [[CALL]] ; @@ -257,6 +278,10 @@ ; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1 ; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1 +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2 +; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1 +; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3 +; CHECK-NEXT: store i8 52, i8* [[GEP_3]], align 1 ; CHECK-NEXT: [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 2) ; CHECK-NEXT: ret i8* [[RES]] ; @@ -302,3 +327,74 @@ %res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 %n) ret i8* %res } + +define void @dse_strcpy(i8* nocapture readonly %src) { +; CHECK-LABEL: @dse_strcpy( +; CHECK-NEXT: [[A:%.*]] = alloca [256 x i8], align 16 +; CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strcpy(i8* nonnull [[BUF]], i8* nonnull dereferenceable(1) [[SRC:%.*]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: ret void +; + %a = alloca [256 x i8], align 16 + %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0 + call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf) + call i8* @strcpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src) + call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf) + ret void +} + +define void @dse_strncpy(i8* nocapture readonly %src) { +; CHECK-LABEL: @dse_strncpy( +; CHECK-NEXT: [[A:%.*]] = alloca [256 x i8], align 16 +; CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncpy(i8* nonnull [[BUF]], i8* nonnull dereferenceable(1) [[SRC:%.*]], i64 6) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: ret void +; + %a = alloca [256 x i8], align 16 + %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0 + call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf) + call i8* @strncpy(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6) + call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf) + ret void +} + +define void @dse_strcat(i8* nocapture readonly %src) { +; CHECK-LABEL: @dse_strcat( +; CHECK-NEXT: [[A:%.*]] = alloca [256 x i8], align 16 +; CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strcat(i8* nonnull [[BUF]], i8* nonnull dereferenceable(1) [[SRC:%.*]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: ret void +; + %a = alloca [256 x i8], align 16 + %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0 + call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf) + call i8* @strcat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src) + call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf) + ret void +} + +define void @dse_strncat(i8* nocapture readonly %src) { +; CHECK-LABEL: @dse_strncat( +; CHECK-NEXT: [[A:%.*]] = alloca [256 x i8], align 16 +; CHECK-NEXT: [[BUF:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i8* @strncat(i8* nonnull [[BUF]], i8* nonnull dereferenceable(1) [[SRC:%.*]], i64 6) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull [[BUF]]) +; CHECK-NEXT: ret void +; + %a = alloca [256 x i8], align 16 + %buf = getelementptr inbounds [256 x i8], [256 x i8]* %a, i64 0, i64 0 + call void @llvm.lifetime.start.p0i8(i64 256, i8* nonnull %buf) + call i8* @strncat(i8* nonnull %buf, i8* nonnull dereferenceable(1) %src, i64 6) + call void @llvm.lifetime.end.p0i8(i64 256, i8* nonnull %buf) + ret void +} + +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)