• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s 2>&1 | FileCheck %s
3
4declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
5
6declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
7
8declare void @cold_use(i8*) cold
9
10declare void @use(i8*)
11
12; In this CFG, splitting will extract the blocks extract{1,2}. I.e., it will
13; extract a lifetime.start marker, but not the corresponding lifetime.end
14; marker. Make sure that a lifetime.start marker is emitted before the call to
15; the split function, and *only* that marker.
16;
17;            entry
18;          /       \
19;      extract1  no-extract1
20;     (lt.start)    |
21;    /              |
22; extract2          |
23;    \_____         |
24;          \      /
25;            exit
26;          (lt.end)
27;
28; After splitting, we should see:
29;
30;            entry
31;          /       \
32;      codeRepl  no-extract1
33;     (lt.start)   |
34;          \      /
35;            exit
36;          (lt.end)
37define void @only_lifetime_start_is_cold() {
38; CHECK-LABEL: @only_lifetime_start_is_cold(
39; CHECK-NEXT:  entry:
40; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
41; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
42; CHECK-NEXT:    br i1 undef, label [[CODEREPL:%.*]], label [[NO_EXTRACT1:%.*]]
43; CHECK:       codeRepl:
44; CHECK-NEXT:    [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
45; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
46; CHECK-NEXT:    [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
47; CHECK-NEXT:    br i1 [[TARGETBLOCK]], label [[NO_EXTRACT1]], label [[EXIT:%.*]]
48; CHECK:       no-extract1:
49; CHECK-NEXT:    br label [[EXIT]]
50; CHECK:       exit:
51; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
52; CHECK-NEXT:    ret void
53;
54entry:
55  %local1 = alloca i256
56  %local1_cast = bitcast i256* %local1 to i8*
57  br i1 undef, label %extract1, label %no-extract1
58
59extract1:
60  ; lt.start
61  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
62  call void @cold_use(i8* %local1_cast)
63  br i1 undef, label %extract2, label %no-extract1
64
65extract2:
66  br label %exit
67
68no-extract1:
69  br label %exit
70
71exit:
72  ; lt.end
73  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
74  ret void
75}
76
77; In this CFG, splitting will extract the block extract1. I.e., it will extract
78; a lifetime.end marker, but not the corresponding lifetime.start marker. Do
79; not emit a lifetime.end marker after the call to the split function.
80;
81;            entry
82;         (lt.start)
83;        /          \
84;   no-extract1  extract1
85;    (lt.end)    (lt.end)
86;        \         /
87;            exit
88;
89; After splitting, we should see:
90;
91;            entry
92;         (lt.start)
93;        /          \
94;   no-extract1  codeRepl
95;    (lt.end)
96;        \         /
97;            exit
98define void @only_lifetime_end_is_cold() {
99; CHECK-LABEL: @only_lifetime_end_is_cold(
100; CHECK-NEXT:  entry:
101; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
102; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
103; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
104; CHECK-NEXT:    br i1 undef, label [[NO_EXTRACT1:%.*]], label [[CODEREPL:%.*]]
105; CHECK:       no-extract1:
106; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
107; CHECK-NEXT:    br label [[EXIT:%.*]]
108; CHECK:       codeRepl:
109; CHECK-NEXT:    call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
110; CHECK-NEXT:    br label [[EXIT]]
111; CHECK:       exit:
112; CHECK-NEXT:    ret void
113;
114entry:
115  ; lt.start
116  %local1 = alloca i256
117  %local1_cast = bitcast i256* %local1 to i8*
118  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
119  br i1 undef, label %no-extract1, label %extract1
120
121no-extract1:
122  ; lt.end
123  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
124  br label %exit
125
126extract1:
127  ; lt.end
128  call void @cold_use(i8* %local1_cast)
129  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
130  br label %exit
131
132exit:
133  ret void
134}
135
136; In this CFG, splitting will extract the blocks extract{1,2,3}. Lifting the
137; lifetime.end marker would be a miscompile.
138define void @do_not_lift_lifetime_end() {
139; CHECK-LABEL: @do_not_lift_lifetime_end(
140; CHECK-NEXT:  entry:
141; CHECK-NEXT:    [[LOCAL1:%.*]] = alloca i256
142; CHECK-NEXT:    [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
143; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
144; CHECK-NEXT:    br label [[HEADER:%.*]]
145; CHECK:       header:
146; CHECK-NEXT:    call void @use(i8* [[LOCAL1_CAST]])
147; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]]
148; CHECK:       codeRepl:
149; CHECK-NEXT:    [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3
150; CHECK-NEXT:    br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]]
151; CHECK:       exit:
152; CHECK-NEXT:    ret void
153;
154entry:
155  ; lt.start
156  %local1 = alloca i256
157  %local1_cast = bitcast i256* %local1 to i8*
158  call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
159  br label %header
160
161header:
162  ; If the lifetime.end marker is lifted, this use becomes dead the second time
163  ; the header block is executed.
164  call void @use(i8* %local1_cast)
165  br i1 undef, label %exit, label %extract1
166
167extract1:
168  call void @cold_use(i8* %local1_cast)
169  br i1 undef, label %extract2, label %extract3
170
171extract2:
172  ; Backedge.
173  br label %header
174
175extract3:
176  ; lt.end
177  call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
178  br label %exit
179
180exit:
181  ret void
182}
183