File: recursive.ll

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.6-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,304 kB
  • sloc: cpp: 7,438,677; ansic: 1,393,822; asm: 1,012,926; python: 241,650; f90: 86,635; objc: 75,479; lisp: 42,144; pascal: 17,286; sh: 10,027; ml: 5,082; perl: 4,730; awk: 3,523; makefile: 3,349; javascript: 2,251; xml: 892; fortran: 672
file content (171 lines) | stat: -rw-r--r-- 8,810 bytes parent folder | download | duplicates (2)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
;; Test recursion handling during cloning.
;;
;; Original code looks like:
;;
;; #include <stdlib.h>
;; #include <string.h>
;; #include <unistd.h>
;; __attribute((noinline)) char *D() {
;;   return new char[10];
;; }
;; __attribute((noinline)) char *B(int n);
;; __attribute((noinline)) char *C(int n) {
;;   if (!n) {
;;     return D();
;;   }
;;   return B(n-1);
;; }
;; __attribute((noinline)) char *B(int n) {
;;   return C(n);
;; }
;; int main(int argc, char **argv) {
;;   char *x = B(1);
;;   char *y = B(1);
;;   char *z = B(0);
;;   memset(x, 0, 10);
;;   memset(y, 0, 10);
;;   memset(z, 0, 10);
;;   free(x);
;;   sleep(200);
;;   free(y);
;;   free(z);
;;   return 0;
;; }
;;
;; The IR was then reduced using llvm-reduce with the expected FileCheck input.

;; Check behavior when we enable cloning of contexts involved with recursive
;; cycles, but not through the cycle itself. I.e. until full support for
;; recursion is added, the cloned recursive call from C back to B (line 12) will
;; not be updated to call a clone.
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
; RUN:  -memprof-verify-ccg -memprof-verify-nodes \
; RUN:  -pass-remarks=memprof-context-disambiguation \
; RUN:	-memprof-allow-recursive-callsites=true \
; RUN:  %s -S 2>&1 | FileCheck %s \
; RUN:  --implicit-check-not "memprof_recursive3.cc:12:10: call in clone _Z1Ci.memprof.1 assigned" \
; RUN:  --check-prefix=ALL --check-prefix=ALLOW-RECUR-CALLSITES --check-prefix=ALLOW-RECUR-CONTEXTS

;; Skipping recursive callsites should result in no cloning.
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
; RUN:  -memprof-verify-ccg -memprof-verify-nodes \
; RUN:  -pass-remarks=memprof-context-disambiguation \
; RUN:	-memprof-allow-recursive-callsites=false \
; RUN:  %s -S 2>&1 | FileCheck %s \
; RUN:  --implicit-check-not "memprof_recursive3.cc:12:10: call in clone _Z1Ci.memprof.1 assigned" \
; RUN:  --implicit-check-not="created clone" \
; RUN:	--implicit-check-not="marked with memprof allocation attribute cold" \
; RUN:  --check-prefix=ALL

;; Check the default behavior (disabled recursive callsites).
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
; RUN:  -memprof-verify-ccg -memprof-verify-nodes \
; RUN:  -pass-remarks=memprof-context-disambiguation \
; RUN:  %s -S 2>&1 | FileCheck %s \
; RUN:  --implicit-check-not "memprof_recursive3.cc:12:10: call in clone _Z1Ci.memprof.1 assigned" \
; RUN:  --implicit-check-not="created clone" \
; RUN:	--implicit-check-not="marked with memprof allocation attribute cold" \
; RUN:  --check-prefix=ALL

;; Skipping recursive contexts should prevent spurious call to cloned version of
;; B from the context starting at memprof_recursive.cc:19:13, which is actually
;; recursive (until that support is added).
; RUN: opt -passes=memprof-context-disambiguation -supports-hot-cold-new \
; RUN:  -memprof-verify-ccg -memprof-verify-nodes \
; RUN:  -pass-remarks=memprof-context-disambiguation \
; RUN:	-memprof-allow-recursive-callsites=true \
; RUN:	-memprof-allow-recursive-contexts=false \
; RUN:  %s -S 2>&1 | FileCheck %s \
; RUN:  --implicit-check-not "memprof_recursive3.cc:12:10: call in clone _Z1Ci.memprof.1 assigned" \
; RUN:  --check-prefix=ALL --check-prefix=ALLOW-RECUR-CALLSITES --check-prefix=SKIP-RECUR-CONTEXTS

; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:4:0: created clone _Z1Dv.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:8:0: created clone _Z1Ci.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:14:0: created clone _Z1Bi.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:20:13: call in clone main assigned to call function clone _Z1Bi.memprof.1
;; We should only call the cold clone for the recursive context if we enabled
;; recursive contexts via -memprof-allow-recursive-contexts=true (default).
; ALLOW-RECUR-CONTEXTS: memprof_recursive.cc:19:13: call in clone main assigned to call function clone _Z1Bi.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:15:10: call in clone _Z1Bi.memprof.1 assigned to call function clone _Z1Ci.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:10:12: call in clone _Z1Ci.memprof.1 assigned to call function clone _Z1Dv.memprof.1
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:5:10: call in clone _Z1Dv.memprof.1 marked with memprof allocation attribute cold
;; We should call the original B for the recursive context if we have
;; disabled recursive contexts via -memprof-allow-recursive-contexts=false.
; SKIP-RECUR-CONTEXTS: memprof_recursive.cc:19:13: call in clone main assigned to call function clone _Z1Bi
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:12:10: call in clone _Z1Ci assigned to call function clone _Z1Bi
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:18:13: call in clone main assigned to call function clone _Z1Bi
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:15:10: call in clone _Z1Bi assigned to call function clone _Z1Ci
; ALLOW-RECUR-CALLSITES: memprof_recursive.cc:10:12: call in clone _Z1Ci assigned to call function clone _Z1Dv
; ALL: memprof_recursive.cc:5:10: call in clone _Z1Dv marked with memprof allocation attribute notcold

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define ptr @_Z1Dv() !dbg !3 {
entry:
  %call = tail call ptr @_Znam(i64 10), !dbg !6, !memprof !7, !callsite !14
  ret ptr null
}

define ptr @_Z1Ci(i32 %n) !dbg !15 {
entry:
  %call = tail call ptr @_Z1Dv(), !dbg !16, !callsite !17
  br label %return

if.end:                                           ; No predecessors!
  %call1 = tail call ptr @_Z1Bi(i32 0), !dbg !18, !callsite !19
  br label %return

return:                                           ; preds = %if.end, %entry
  ret ptr null
}

define ptr @_Z1Bi(i32 %n) !dbg !20 {
entry:
  %call = tail call ptr @_Z1Ci(i32 0), !dbg !21, !callsite !22
  ret ptr null
}

define i32 @main() {
entry:
  %call = tail call ptr @_Z1Bi(i32 0), !dbg !23, !callsite !25
  %call1 = tail call ptr @_Z1Bi(i32 0), !dbg !26, !callsite !27
  %call2 = tail call ptr @_Z1Bi(i32 0), !dbg !28, !callsite !29
  ret i32 0
}

declare ptr @_Znam(i64)

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2}

!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 20.0.0git (https://github.com/llvm/llvm-project.git 7aec6dc477f8148ed066d10dfc7a012a51b6599c)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None)
!1 = !DIFile(filename: "memprof_recursive.cc", directory: ".", checksumkind: CSK_MD5, checksum: "2f15f63b187a0e0d40e7fdd18b10576a")
!2 = !{i32 2, !"Debug Info Version", i32 3}
!3 = distinct !DISubprogram(name: "D", linkageName: "_Z1Dv", scope: !1, file: !1, line: 4, type: !4, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
!4 = !DISubroutineType(types: !5)
!5 = !{}
!6 = !DILocation(line: 5, column: 10, scope: !3)
!7 = !{!8, !10, !12}
!8 = !{!9, !"cold"}
!9 = !{i64 6541423618768552252, i64 -200552803509692312, i64 -2954124005641725917, i64 6307901912192269588}
!10 = !{!11, !"notcold"}
!11 = !{i64 6541423618768552252, i64 -200552803509692312, i64 -2954124005641725917, i64 -7155190423157709404, i64 -2954124005641725917, i64 8632435727821051414}
!12 = !{!13, !"cold"}
!13 = !{i64 6541423618768552252, i64 -200552803509692312, i64 -2954124005641725917, i64 -7155190423157709404, i64 -2954124005641725917, i64 -3421689549917153178}
!14 = !{i64 6541423618768552252}
!15 = distinct !DISubprogram(name: "C", linkageName: "_Z1Ci", scope: !1, file: !1, line: 8, type: !4, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
!16 = !DILocation(line: 10, column: 12, scope: !15)
!17 = !{i64 -200552803509692312}
!18 = !DILocation(line: 12, column: 10, scope: !15)
!19 = !{i64 -7155190423157709404}
!20 = distinct !DISubprogram(name: "B", linkageName: "_Z1Bi", scope: !1, file: !1, line: 14, type: !4, scopeLine: 14, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
!21 = !DILocation(line: 15, column: 10, scope: !20)
!22 = !{i64 -2954124005641725917}
!23 = !DILocation(line: 18, column: 13, scope: !24)
!24 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 17, type: !4, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
!25 = !{i64 8632435727821051414}
!26 = !DILocation(line: 19, column: 13, scope: !24)
!27 = !{i64 -3421689549917153178}
!28 = !DILocation(line: 20, column: 13, scope: !24)
!29 = !{i64 6307901912192269588}