xref: /llvm-project/llvm/test/Instrumentation/HeapProfiler/basic.ll (revision 5171712bb2783784eb3b95f415c8f8c3d565a294)
1; Test basic memory profiler instrumentation.
2;
3; RUN: opt < %s -passes='function(memprof),memprof-module' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
4; RUN: opt < %s -passes='function(memprof),memprof-module' -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
5
6; We need the requires since both memprof and memprof-module require reading module level metadata which is done once by the memprof-globals-md analysis
7; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
8; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
9
10target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
11target triple = "x86_64-unknown-linux-gnu"
12
13; CHECK: @llvm.used = appending global [1 x ptr] [ptr @memprof.module_ctor]
14; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @memprof.module_ctor, ptr null }]
15
16define i32 @test_load(ptr %a) {
17entry:
18  %tmp1 = load i32, ptr %a, align 4
19  ret i32 %tmp1
20}
21; CHECK-LABEL: @test_load
22; CHECK:         %[[SHADOW_OFFSET:[^ ]*]] = load i64, ptr @__memprof_shadow_memory_dynamic_address
23; CHECK-NEXT:    %[[LOAD_ADDR:[^ ]*]] = ptrtoint ptr %a to i64
24; CHECK-NEXT:    %[[MASKED_ADDR:[^ ]*]] = and i64 %[[LOAD_ADDR]], -64
25; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
26; CHECK-S5-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 5
27; CHECK-NEXT:    add i64 %[[SHIFTED_ADDR]], %[[SHADOW_OFFSET]]
28; CHECK-NEXT:    %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
29; CHECK-NEXT:    %[[LOAD_SHADOW:[^ ]*]] = load i64, ptr %[[LOAD_SHADOW_PTR]]
30; CHECK-NEXT:    %[[NEW_SHADOW:[^ ]*]] = add i64 %[[LOAD_SHADOW]], 1
31; CHECK-NEXT:    store i64 %[[NEW_SHADOW]], ptr %[[LOAD_SHADOW_PTR]]
32; The actual load.
33; CHECK-NEXT:    %tmp1 = load i32, ptr %a
34; CHECK-NEXT:    ret i32 %tmp1
35
36define void @test_store(ptr %a) {
37entry:
38  store i32 42, ptr %a, align 4
39  ret void
40}
41; CHECK-LABEL: @test_store
42; CHECK:         %[[SHADOW_OFFSET:[^ ]*]] = load i64, ptr @__memprof_shadow_memory_dynamic_address
43; CHECK-NEXT:    %[[STORE_ADDR:[^ ]*]] = ptrtoint ptr %a to i64
44; CHECK-NEXT:    %[[MASKED_ADDR:[^ ]*]] = and i64 %[[STORE_ADDR]], -64
45; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
46; CHECK-S5-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 5
47; CHECK-NEXT:    add i64 %[[SHIFTED_ADDR]], %[[SHADOW_OFFSET]]
48; CHECK-NEXT:    %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
49; CHECK-NEXT:    %[[STORE_SHADOW:[^ ]*]] = load i64, ptr %[[STORE_SHADOW_PTR]]
50; CHECK-NEXT:    %[[NEW_SHADOW:[^ ]*]] = add i64 %[[STORE_SHADOW]], 1
51; CHECK-NEXT:    store i64 %[[NEW_SHADOW]], ptr %[[STORE_SHADOW_PTR]]
52; The actual store.
53; CHECK-NEXT:    store i32 42, ptr %a
54; CHECK-NEXT:    ret void
55
56define void @FP80Test(ptr nocapture %a) nounwind uwtable {
57entry:
58    store x86_fp80 0xK3FFF8000000000000000, ptr %a, align 16
59    ret void
60}
61; CHECK-LABEL: @FP80Test
62; Exactly one shadow update for store access.
63; CHECK-NOT:  store i64
64; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
65; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
66; CHECK-NOT:  store i64
67; The actual store.
68; CHECK:      store x86_fp80 0xK3FFF8000000000000000, ptr %a
69; CHECK:      ret void
70
71define void @i40test(ptr %a, ptr %b) nounwind uwtable {
72entry:
73  %t = load i40, ptr %a
74  store i40 %t, ptr %b, align 8
75  ret void
76}
77; CHECK-LABEL: @i40test
78; Exactly one shadow update for load access.
79; CHECK-NOT:  store i64
80; CHECK:      %[[NEW_LD_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
81; CHECK-NEXT: store i64 %[[NEW_LD_SHADOW]]
82; CHECK-NOT:  store i64
83; The actual load.
84; CHECK:      %t = load i40, ptr %a
85; Exactly one shadow update for store access.
86; CHECK-NOT:  store i64
87; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
88; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
89; CHECK-NOT:  store i64
90; The actual store.
91; CHECK:      store i40 %t, ptr %b
92; CHECK:      ret void
93
94define void @i64test_align1(ptr %b) nounwind uwtable {
95  entry:
96  store i64 0, ptr %b, align 1
97  ret void
98}
99; CHECK-LABEL: @i64test
100; Exactly one shadow update for store access.
101; CHECK-NOT:  store i64
102; CHECK: %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
103; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
104; CHECK-NOT:  store i64
105; The actual store.
106; CHECK:      store i64 0, ptr %b
107; CHECK:      ret void
108
109define void @i80test(ptr %a, ptr %b) nounwind uwtable {
110  entry:
111  %t = load i80, ptr %a
112  store i80 %t, ptr %b, align 8
113  ret void
114}
115; CHECK-LABEL: i80test
116; Exactly one shadow update for load access.
117; CHECK-NOT:  store i64
118; CHECK:      %[[NEW_LD_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
119; CHECK-NEXT: store i64 %[[NEW_LD_SHADOW]]
120; CHECK-NOT:  store i64
121; The actual load.
122; CHECK:      %t = load i80, ptr %a
123; Exactly one shadow update for store access.
124; CHECK-NOT:  store i64
125; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
126; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
127; CHECK-NOT:  store i64
128; The actual store.
129; CHECK:      store i80 %t, ptr %b
130; CHECK:      ret void
131
132; memprof should not instrument functions with available_externally linkage.
133define available_externally i32 @f_available_externally(ptr %a)  {
134entry:
135  %tmp1 = load i32, ptr %a
136  ret i32 %tmp1
137}
138; CHECK-LABEL: @f_available_externally
139; CHECK-NOT: __memprof_shadow_memory_dynamic_address
140; CHECK: ret i32
141
142declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
143declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1) nounwind
144declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1) nounwind
145
146define void @memintr_test(ptr %a, ptr %b) nounwind uwtable {
147  entry:
148  tail call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 100, i1 false)
149  tail call void @llvm.memmove.p0.p0.i64(ptr %a, ptr %b, i64 100, i1 false)
150  tail call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 100, i1 false)
151  ret void
152}
153
154; CHECK-LABEL: memintr_test
155; CHECK: __memprof_memset
156; CHECK: __memprof_memmove
157; CHECK: __memprof_memcpy
158; CHECK: ret void
159
160declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture writeonly, i8, i64, i32) nounwind
161declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
162declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
163
164define void @memintr_element_atomic_test(ptr %a, ptr %b) nounwind uwtable {
165  ; This is a canary test to make sure that these don't get lowered into calls that don't
166  ; have the element-atomic property. Eventually, memprof will have to be enhanced to lower
167  ; these properly.
168  ; CHECK-LABEL: memintr_element_atomic_test
169  ; CHECK: tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %a, i8 0, i64 100, i32 1)
170  ; CHECK: tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %a, ptr align 1 %b, i64 100, i32 1)
171  ; CHECK: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %a, ptr align 1 %b, i64 100, i32 1)
172  ; CHECK: ret void
173  tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %a, i8 0, i64 100, i32 1)
174  tail call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %a, ptr align 1 %b, i64 100, i32 1)
175  tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %a, ptr align 1 %b, i64 100, i32 1)
176  ret void
177}
178
179
180; CHECK: define internal void @memprof.module_ctor()
181; CHECK: call void @__memprof_init()
182