]> git.lizzy.rs Git - rust.git/blob - src/test/codegen/coverage-experiments/src/match_with_increment.rs
f618b37ed5247d928fbff6fe37465ab45c292d60
[rust.git] / src / test / codegen / coverage-experiments / src / match_with_increment.rs
1 #![feature(core_intrinsics)]
2 //static TEST_FUNC_NAME: &'static [u8; 7] = b"main()\0";
3   static TEST_FUNC_NAME: &'static [u8; 6] = b"main()";
4 fn main() {
5     let a = 1;
6     let b = 10;
7     let _result = match {
8         let _t = a < b;
9         unsafe { core::intrinsics::instrprof_increment(TEST_FUNC_NAME as *const u8, 1234 as u64, 3 as u32, 0 as u32) };
10         _t
11     } {
12         true => {
13             let _t = true;
14             unsafe { core::intrinsics::instrprof_increment(TEST_FUNC_NAME as *const u8, 1234 as u64, 3 as u32, 1 as u32) };
15             _t
16         }
17         _ => false,
18     };
19 }
20
21 /*
22
23 I NEED TO INSERT THE instrprof_increment() CALL:
24
25   1. JUST BEFORE THE switchInt(_4) (because we haven't counted entering the function main() yet, deferring that to "JUST BEFORE FIRST BRANCH")
26   2. SOME TIME AFTER THE switchInt(_4), AND JUST BEFORE ANOTHER BRANCH (in this case, before "goto")
27   2.a. NOT BEFORE BOTH GOTO'S AFTER switchInt(_4) (because one can be calculated by counter expression), BUT PERHAPS INSERT A noop PLACEHOLDER
28        AS A MARKER TO INCLUDE THE COVERAGE REGION AND REFERENCE THE COUNTERS TO BE SUBTRACTED (AND/OR SUMMED)?
29
30     WHY DEFER INSERTING COUNTERS TO "JUST BEFORE FIRST BRANCH"? We can ignore panic/unwind() and only count if the coverage region ACTUALLY
31     executed in entirety. BUT IS THAT NECESSARY? IS IT MUCH EASIER TO INSERT COUNTERS AT THE TOP OF A REGION THAT MUST EXECUTE IN ENTIRETY IF
32     PANIC DOES NOT OCCUR? AND WHAT IF WE ADD SUPPORT FOR PANIC UNWIND (later)?
33
34     IS THERE A BENEFIT OF THE DEFERRED APPROACH WHEN CONSIDERING EXPRESSIONS MAY HAVE EARLY RETURNS? (BECAUSE, WE STILL NEED TO COUNT THE REGION
35     LEADING UP TO THE EXPRESSION ANYWAY)
36
37 =================================================
38 =================================================
39
40 To inject an intrinsic after computing a final expression value of a coverage region:
41
42 Replace the following basic block end (last statement plus terminator):
43
44 ... <statements to compute _4> ...
45 StorageLive(_4)
46 StorageLive(_5)
47 _5 = _1
48 StorageLive(_6)
49 _6 = _2
50 _4 = Lt(move _5, move _6)
51 StorageDead(_6)
52 StorageDead(_5)
53                              <------ to insert instrprof_increment() here
54 FakeRead(ForMatchedPlace, _4)
55 --------------------------------------------------------------------------------------
56 switchInt(_4)
57
58
59 =================================================
60 Insert call to intrinsic with:
61
62 StorageLive(_4)        # _4 is now meant for deferred FakeRead(ForMatchdPlace, _4) in BasicBlock after increment() call
63 StorageLive(_5)                 # Unchanged except _4 is now _5
64 StorageLive(_6)                 # Unchanged except _5 is now _6
65 _6 = _1                         # Unchanged except _5 is now _6
66 StorageLive(_7)                 # Unchanged except _6 is now _7
67 _7 = _2                         # Unchanged except _6 is now _7
68 _5 = Lt(move _6, move _7)       # Unchanged except _4, _5, _6 is now _5, _6, _7
69 StorageDead(_7)                 # Unchanged except _6 is now _7
70 StorageDead(_6)                 # Unchanged except _5 is now _6
71
72 FakeRead(ForLet, _5)   # CHANGED ForMatchedPlace to ForLet
73
74 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
75 > StorageLive(_8)        # ?? stores function pointer to instrprof_increment function?
76 > StorageLive(_9)
77 > StorageLive(_10)
78 > StorageLive(_11)
79 > _11 = const {alloc1+0: &&[u8; 6]}
80 > _10 = &raw const (*(*_11))
81 > _9 = move _10 as *const u8 (Pointer(ArrayToPointer))
82 > StorageDead(_10)
83 > StorageLive(_12)
84 > _12 = const 1234u64
85 > StorageLive(_13)
86 > _13 = const 3u32
87 > StorageLive(_14)
88 > _14 = const 0u32
89 > --------------------------------------------------------------------------------------
90 > _8 = const std::intrinsics::instrprof_increment(move _9, move _12, move _13, move _14)
91 >
92 > -> return
93 >
94 > StorageDead(_14)
95 > StorageDead(_13)
96 > StorageDead(_12)
97 > StorageDead(_9)
98 > StorageDead(_11)
99 > StorageDead(_8)
100
101 _4 = _5                         # ARE THESE LINES REDUNDANT? CAN I JUST PASS _5 DIRECTLY TO FakeRead()?
102 StorageDead(_5)                 # DROP "_t" temp result of `let _t = a < b`
103                                 # (NOTE THAT IF SO, I CAN REMOVE _5 altogether, and use _4, which coincidentally makes less changes)
104                                 # SEE BELOW
105
106 FakeRead(ForMatchedPlace, _4)   # Unchanged
107 --------------------------------------------------------------------------------------
108 switchInt(_4)                   # Unchanged
109
110
111 =================================================
112 Can I skip the extra variable and insert call to intrinsic with:
113
114 StorageLive(_4)             # Unchanged
115 StorageLive(_5)             # Unchanged
116 _5 = _1                     # Unchanged
117 StorageLive(_6)             # Unchanged
118 _6 = _2                     # Unchanged
119 _4 = Lt(move _5, move _6)   # Unchanged
120 StorageDead(_6)             # Unchanged
121 StorageDead(_5)             # Unchanged
122
123 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
124 > FakeRead(ForLet, _4)   # Save the post-increment result in temp "_t"
125 > StorageLive(_8)        # ?? stores function pointer to instrprof_increment function?
126 > StorageLive(_9)
127 > StorageLive(_10)
128 > StorageLive(_11)
129 > _11 = const {alloc1+0: &&[u8; 6]}
130 > _10 = &raw const (*(*_11))
131 > _9 = move _10 as *const u8 (Pointer(ArrayToPointer))
132 > StorageDead(_10)
133 > StorageLive(_12)
134 > _12 = const 1234u64
135 > StorageLive(_13)
136 > _13 = const 3u32
137 > StorageLive(_14)
138 > _14 = const 0u32
139 > --------------------------------------------------------------------------------------
140 > _8 = const std::intrinsics::instrprof_increment(move _9, move _12, move _13, move _14)
141 >
142 > -> return
143 >
144 > StorageDead(_14)
145 > StorageDead(_13)
146 > StorageDead(_12)
147 > StorageDead(_9)
148 > StorageDead(_11)
149 > StorageDead(_8)
150
151 FakeRead(ForMatchedPlace, _4)   # Unchanged  (PREVIOUSLY USED IN FakeRead(ForLet), is that OK?)
152 --------------------------------------------------------------------------------------
153 switchInt(_4)                   # Unchanged
154
155
156
157
158
159 =================================================
160 =================================================
161
162 For the second inserted call to instrprof_increment, without that call we have:
163
164 --------------------------------------------------------------------------------------
165 switchInt(_4)                   # From above
166
167 -> otherwise   # that is, "NOT false"
168
169 _3 = const true
170                              <------ to insert instrprof_increment() here
171 --------------------------------------------------------------------------------------
172 goto
173
174 ->                              # No label. No condition, and not a "return"
175
176 FakeRead(ForLet, _3)            # NOTE: Unused result
177 StorageDead(_4)
178 _0 = ()
179 StorageDead(_3)
180 StorageDead(_2)
181 StorageDead(_1)
182 --------------------------------------------------------------------------------------
183 goto
184
185 ->                              # No label. No condition, and not a "return"
186
187 return   # from main()
188
189
190 =================================================
191 With the call to increment():
192
193 --------------------------------------------------------------------------------------
194 switchInt(_4)                   # From above
195
196 -> otherwise   # "NOT false"    # UNCHANGED
197
198 StorageLive(_15)                # CHANGED! Allocated new storage (_15) for the result of match, if true.
199 _15 = const true                # UNCHANGED except _3 is now _15
200 FakeRead(ForLet, _15)           # CHANGED! Assign value to temporary (to be assigned to _3 later) ... Do I need to do this?
201
202 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
203 > StorageLive(_16)                # pointer to instrprof_increment() function ?
204 > StorageLive(_17)
205 > StorageLive(_18)
206 > StorageLive(_19)
207 > _19 = const {alloc1+0: &&[u8; 6]}
208 > _18 = &raw const (*(*_19))
209 > _17 = move _18 as *const u8 (Pointer(ArrayToPointer))
210 > StorageDead(_18)
211 > StorageLive(_20)
212 > _20 = const 1234u64
213 > StorageLive(_21)
214 > _21 = const 3u32
215 > StorageLive(_22)
216 > _22 = const 1u32
217 > --------------------------------------------------------------------------------------
218 > _16 = const std::intrinsics::instrprof_increment(move _17, move _20, move _21, move _22)
219 >
220 > ->  return
221 >
222 > StorageDead(_22)
223 > StorageDead(_21)
224 > StorageDead(_20)
225 > StorageDead(_17)
226 > StorageDead(_19)
227 > StorageDead(_16)
228 > _3 = _15
229 > StorageDead(_15)
230
231 --------------------------------# UNCHANGED-------------------------------------------
232 goto                            # UNCHANGED
233
234 ->                              # UNCHANGED
235
236 FakeRead(ForLet, _3)            # UNCHANGED
237 StorageDead(_4)                 # UNCHANGED
238 _0 = ()                         # UNCHANGED
239 StorageDead(_3)                 # UNCHANGED
240 StorageDead(_2)                 # UNCHANGED
241 StorageDead(_1)                 # UNCHANGED
242 --------------------------------------------------------------------------------------
243 goto                            # UNCHANGED
244
245 ->                              # UNCHANGED
246
247 return   # from main()          # UNCHANGED
248
249 =================================================
250 As before, can I skip the extra variable (_15) and insert the call to intrinsic with _3 directly?:
251
252
253 --------------------------------------------------------------------------------------
254 switchInt(_4)                   # From above
255
256 -> otherwise   # "NOT false"    # UNCHANGED
257
258 _3 = const true                 # UNCHANGED?
259
260 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
261 > StorageLive(_16)                # pointer to instrprof_increment() function ?
262 > StorageLive(_17)
263 > StorageLive(_18)
264 > StorageLive(_19)
265 > _19 = const {alloc1+0: &&[u8; 6]}
266 > _18 = &raw const (*(*_19))
267 > _17 = move _18 as *const u8 (Pointer(ArrayToPointer))
268 > StorageDead(_18)
269 > StorageLive(_20)
270 > _20 = const 1234u64
271 > StorageLive(_21)
272 > _21 = const 3u32
273 > StorageLive(_22)
274 > _22 = const 1u32
275 > --------------------------------------------------------------------------------------
276 > _16 = const std::intrinsics::instrprof_increment(move _17, move _20, move _21, move _22)
277 >
278 > ->  return
279 >
280 > StorageDead(_22)
281 > StorageDead(_21)
282 > StorageDead(_20)
283 > StorageDead(_17)
284 > StorageDead(_19)
285 > StorageDead(_16)
286
287 --------------------------------# UNCHANGED-------------------------------------------
288 goto                            # UNCHANGED
289
290 ->                              # UNCHANGED
291
292 FakeRead(ForLet, _3)            # UNCHANGED
293 StorageDead(_4)                 # UNCHANGED
294 _0 = ()                         # UNCHANGED
295 StorageDead(_3)                 # UNCHANGED
296 StorageDead(_2)                 # UNCHANGED
297 StorageDead(_1)                 # UNCHANGED
298 --------------------------------------------------------------------------------------
299 goto                            # UNCHANGED
300
301 ->                              # UNCHANGED
302
303 return   # from main()          # UNCHANGED
304
305 */