File: libcalls-chk.ll

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (142 lines) | stat: -rw-r--r-- 6,122 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -aa-pipeline=basic-aa -passes=inferattrs,dse | FileCheck %s

target triple = "x86_64-unknown-linux-gnu"

declare ptr @__memset_chk(ptr writeonly, i32, i64, i64) argmemonly
declare ptr @__memcpy_chk(ptr writeonly, ptr readonly, i64, i64) argmemonly nounwind

declare ptr @strncpy(ptr %dest, ptr %src, i64 %n) nounwind
declare void @use(ptr)

; strncpy -> __memset_chk, full overwrite
define void @dse_strncpy_memset_chk_test1(ptr noalias %out, ptr noalias %in, i64 %n) {
; CHECK-LABEL: @dse_strncpy_memset_chk_test1(
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  %call = tail call ptr @strncpy(ptr %out, ptr %in, i64 100)
  %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
  ret void
}

define void @dse_memset_chk_eliminate_store1(ptr %out, i64 %n) {
; CHECK-LABEL: @dse_memset_chk_eliminate_store1(
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT:%.*]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  store i8 10, ptr %out
  %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
  ret void
}

define void @dse_memset_chk_eliminate_store2(ptr %out, i64 %n) {
; CHECK-LABEL: @dse_memset_chk_eliminate_store2(
; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[OUT:%.*]], i64 100
; CHECK-NEXT:    store i8 10, ptr [[GEP]], align 1
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  %gep = getelementptr inbounds i8, ptr %out, i64 100
  store i8 10, ptr %gep
  %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 100, i64 %n)
  ret void
}

define void @dse_memset_chk_eliminates_store_local_object_escapes_after(i64 %n) {
; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_after(
; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, ptr [[A]], i64 100
; CHECK-NEXT:    store i8 10, ptr [[OUT_100]], align 1
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[A]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    call void @use(ptr [[A]])
; CHECK-NEXT:    ret void
;
  %a = alloca [200 x i8]
  store i8 10, ptr %a
  %out.100 = getelementptr i8, ptr %a, i64 100
  store i8 10, ptr %out.100
  %call.2 = tail call ptr @__memset_chk(ptr %a, i32 42, i64 100, i64 %n)
  call void @use(ptr %a)
  ret void
}

define void @dse_memset_chk_eliminates_store_local_object_escapes_before(i64 %n) {
; CHECK-LABEL: @dse_memset_chk_eliminates_store_local_object_escapes_before(
; CHECK-NEXT:    [[A:%.*]] = alloca [200 x i8], align 1
; CHECK-NEXT:    call void @use(ptr [[A]])
; CHECK-NEXT:    [[OUT_100:%.*]] = getelementptr i8, ptr [[A]], i64 100
; CHECK-NEXT:    store i8 0, ptr [[OUT_100]], align 1
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[A]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    call void @use(ptr [[A]])
; CHECK-NEXT:    ret void
;
  %a = alloca [200 x i8]
  call void @use(ptr %a)
  store i8 10, ptr %a
  %out.100 = getelementptr i8, ptr %a, i64 100
  store i8 0, ptr %out.100
  %call.2 = tail call ptr @__memset_chk(ptr %a, i32 42, i64 100, i64 %n)
  call void @use(ptr %a)
  ret void
}

; strncpy -> memset_chk, partial overwrite
define void @dse_strncpy_memset_chk_test2(ptr noalias %out, ptr noalias %in, i64 %n) {
; CHECK-LABEL: @dse_strncpy_memset_chk_test2(
; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @strncpy(ptr [[OUT:%.*]], ptr [[IN:%.*]], i64 100)
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT]], i32 42, i64 99, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  %call = tail call ptr @strncpy(ptr %out, ptr %in, i64 100)
  %call.2 = tail call ptr @__memset_chk(ptr %out, i32 42, i64 99, i64 %n)
  ret void
}

; strncpy -> memset_chk, different destination
define void @dse_strncpy_chk_test3(ptr noalias %out1, ptr noalias %out2, ptr noalias %in, i64 %n) {
; CHECK-LABEL: @dse_strncpy_chk_test3(
; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr @strncpy(ptr [[OUT1:%.*]], ptr [[IN:%.*]], i64 100)
; CHECK-NEXT:    [[CALL_2:%.*]] = tail call ptr @__memset_chk(ptr [[OUT2:%.*]], i32 42, i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  %call = tail call ptr @strncpy(ptr %out1, ptr %in, i64 100)
  %call.2 = tail call ptr @__memset_chk(ptr %out2, i32 42, i64 100, i64 %n)
  ret void
}

define void @dse_strncpy_memcpy_chk_test1(ptr noalias %out, ptr noalias %in, i64 %n) {
; CHECK-LABEL: @dse_strncpy_memcpy_chk_test1(
; CHECK-NEXT:    [[CALL_1:%.*]] = tail call ptr @__memcpy_chk(ptr [[OUT:%.*]], ptr [[IN:%.*]], i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  store i32 0, ptr %out
  %call.1 = tail call ptr @__memcpy_chk(ptr %out, ptr %in, i64 100, i64 %n)
  ret void
}

define void @dse_strncpy_memcpy_chk_test2(ptr noalias %out, ptr noalias %in, i64 %n) {
; CHECK-LABEL: @dse_strncpy_memcpy_chk_test2(
; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[OUT:%.*]], i64 100
; CHECK-NEXT:    store i8 10, ptr [[GEP]], align 1
; CHECK-NEXT:    [[CALL_1:%.*]] = tail call ptr @__memcpy_chk(ptr [[OUT]], ptr [[IN:%.*]], i64 100, i64 [[N:%.*]])
; CHECK-NEXT:    ret void
;
  %gep = getelementptr inbounds i8, ptr %out, i64 100
  store i8 10, ptr %gep
  %call.1 = tail call ptr @__memcpy_chk(ptr %out, ptr %in, i64 100, i64 %n)
  ret void
}

define void @test_memcpy_intrinsic_and_memcpy_chk(ptr %A, ptr %B, ptr noalias %C) {
; CHECK-LABEL: @test_memcpy_intrinsic_and_memcpy_chk(
; CHECK-NEXT:    tail call void @llvm.memcpy.p0.p0.i64(ptr [[A:%.*]], ptr [[B:%.*]], i64 48, i1 false)
; CHECK-NEXT:    [[CALL:%.*]] = call ptr @__memcpy_chk(ptr [[A]], ptr [[C:%.*]], i64 1, i64 10)
; CHECK-NEXT:    ret void
;
  tail call void @llvm.memcpy.p0.p0.i64(ptr %A, ptr %B, i64 48, i1 false)
  %call = call ptr @__memcpy_chk(ptr %A, ptr %C, i64 1, i64 10)
  ret void
}

declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)