[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / DeadStoreElimination / libcalls-chk.ll
blob737f99f539523d607073c69dbe22c6c4f2bd7475
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -aa-pipeline=basic-aa -passes=inferattrs,dse | FileCheck %s
4 target triple = "x86_64-unknown-linux-gnu"
6 declare ptr @__memset_chk(ptr writeonly, i32, i64, i64) argmemonly
7 declare ptr @__memcpy_chk(ptr writeonly, ptr readonly, i64, i64) argmemonly nounwind
9 declare ptr @strncpy(ptr %dest, ptr %src, i64 %n) nounwind
10 declare void @use(ptr)
12 ; strncpy -> __memset_chk, full overwrite
13 define void @dse_strncpy_memset_chk_test1(ptr noalias %out, ptr noalias %in, i64 %n) {
14 ; CHECK-LABEL: @dse_strncpy_memset_chk_test1(
15 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]])
16 ; CHECK-NEXT:    ret void
18   %call = tail call ptr @strncpy(ptr %out, ptr %in, i64 100)
19   %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
20   ret void
23 define void @dse_memset_chk_eliminate_store1(ptr %out, i64 %n) {
24 ; CHECK-LABEL: @dse_memset_chk_eliminate_store1(
25 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]])
26 ; CHECK-NEXT:    ret void
28   store i8 10, ptr %out
29   %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
30   ret void
33 define void @dse_memset_chk_eliminate_store2(ptr %out, i64 %n) {
34 ; CHECK-LABEL: @dse_memset_chk_eliminate_store2(
35 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[OUT:%.*]], i64 100
36 ; CHECK-NEXT:    store i8 10, ptr [[GEP]], align 1
37 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
38 ; CHECK-NEXT:    ret void
40   %gep = getelementptr inbounds i8, ptr %out, i64 100
41   store i8 10, ptr %gep
42   %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
43   ret void
46 define void @dse_memset_chk_eliminates_store_local_object_escapes_after(i64 %n) {
47 ; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_after(
48 ; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
49 ; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, ptr [[A]], i64 100
50 ; CHECK-NEXT:    store i8 10, ptr [[OUT_100]], align 1
51 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[A]], i32 42, i64 100, i64 [[N:%.*]])
52 ; CHECK-NEXT:    call void @use(ptr [[A]])
53 ; CHECK-NEXT:    ret void
55   %a = alloca [200 x i8]
56   store i8 10, ptr %a
57   %out.100 = getelementptr i8, ptr %a, i64 100
58   store i8 10, ptr %out.100
59   %call.2 = tail call ptr @__memset_chk(ptr %a, i32 42, i64 100, i64 %n)
60   call void @use(ptr %a)
61   ret void
64 define void @dse_memset_chk_eliminates_store_local_object_escapes_before(i64 %n) {
65 ; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_before(
66 ; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
67 ; CHECK-NEXT:    call void @use(ptr [[A]])
68 ; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, ptr [[A]], i64 100
69 ; CHECK-NEXT:    store i8 0, ptr [[OUT_100]], align 1
70 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[A]], i32 42, i64 100, i64 [[N:%.*]])
71 ; CHECK-NEXT:    call void @use(ptr [[A]])
72 ; CHECK-NEXT:    ret void
74   %a = alloca [200 x i8]
75   call void @use(ptr %a)
76   store i8 10, ptr %a
77   %out.100 = getelementptr i8, ptr %a, i64 100
78   store i8 0, ptr %out.100
79   %call.2 = tail call ptr @__memset_chk(ptr %a, i32 42, i64 100, i64 %n)
80   call void @use(ptr %a)
81   ret void
84 ; strncpy -> memset_chk, partial overwrite
85 define void @dse_strncpy_memset_chk_test2(ptr noalias %out, ptr noalias %in, i64 %n) {
86 ; CHECK-LABEL: @dse_strncpy_memset_chk_test2(
87 ; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @strncpy(ptr [[OUT:%.*]], ptr [[IN:%.*]], i64 100)
88 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT]], i32 42, i64 99, i64 [[N:%.*]])
89 ; CHECK-NEXT:    ret void
91   %call = tail call ptr @strncpy(ptr %out, ptr %in, i64 100)
92   %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 99, i64 %n)
93   ret void
96 ; strncpy -> memset_chk, different destination
97 define void @dse_strncpy_chk_test3(ptr noalias %out1, ptr noalias %out2, ptr noalias %in, i64 %n) {
98 ; CHECK-LABEL: @dse_strncpy_chk_test3(
99 ; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @strncpy(ptr [[OUT1:%.*]], ptr [[IN:%.*]], i64 100)
100 ; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT2:%.*]], i32 42, i64 100, i64 [[N:%.*]])
101 ; CHECK-NEXT:    ret void
103   %call = tail call ptr @strncpy(ptr %out1, ptr %in, i64 100)
104   %call.2 = tail call ptr @__memset_chk(ptr %out2, i32 42, i64 100, i64 %n)
105   ret void
108 define void @dse_strncpy_memcpy_chk_test1(ptr noalias %out, ptr noalias %in, i64 %n) {
109 ; CHECK-LABEL: @dse_strncpy_memcpy_chk_test1(
110 ; CHECK-NEXT:    [[CALL_1:%.*]] = tail call ptr @__memcpy_chk(ptr [[OUT:%.*]], ptr [[IN:%.*]], i64 100, i64 [[N:%.*]])
111 ; CHECK-NEXT:    ret void
113   store i32 0, ptr %out
114   %call.1 = tail call ptr @__memcpy_chk(ptr %out, ptr %in, i64 100, i64 %n)
115   ret void
118 define void @dse_strncpy_memcpy_chk_test2(ptr noalias %out, ptr noalias %in, i64 %n) {
119 ; CHECK-LABEL: @dse_strncpy_memcpy_chk_test2(
120 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[OUT:%.*]], i64 100
121 ; CHECK-NEXT:    store i8 10, ptr [[GEP]], align 1
122 ; CHECK-NEXT:    [[CALL_1:%.*]] = tail call ptr @__memcpy_chk(ptr [[OUT]], ptr [[IN:%.*]], i64 100, i64 [[N:%.*]])
123 ; CHECK-NEXT:    ret void
125   %gep = getelementptr inbounds i8, ptr %out, i64 100
126   store i8 10, ptr %gep
127   %call.1 = tail call ptr @__memcpy_chk(ptr %out, ptr %in, i64 100, i64 %n)
128   ret void
131 define void @test_memcpy_intrinsic_and_memcpy_chk(ptr %A, ptr %B, ptr noalias %C) {
132 ; CHECK-LABEL: @test_memcpy_intrinsic_and_memcpy_chk(
133 ; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[A:%.*]], ptr [[B:%.*]], i64 48, i1 false)
134 ; CHECK-NEXT:    [[CALL:%.*]] = call ptr @__memcpy_chk(ptr [[A]], ptr [[C:%.*]], i64 1, i64 10)
135 ; CHECK-NEXT:    ret void
137   tail call void @llvm.memcpy.p0.p0.i64(ptr %A, ptr %B, i64 48, i1 false)
138   %call = call ptr @__memcpy_chk(ptr %A, ptr %C, i64 1, i64 10)
139   ret void
142 declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)