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()";
5 unsafe { core::intrinsics::instrprof_increment(TEST_FUNC_NAME as *const u8, 1234 as u64, 3 as u32, 0 as u32) };
8 let _result = match a < b {
10 unsafe { core::intrinsics::instrprof_increment(TEST_FUNC_NAME as *const u8, 1234 as u64, 3 as u32, 1 as u32) };
21 IS IT MUCH EASIER TO INSERT COUNTERS AT THE TOP OF A REGION THAT MUST EXECUTE IN ENTIRETY IF
22 PANIC DOES NOT OCCUR? AND WHAT IF WE ADD SUPPORT FOR PANIC UNWIND (later)?
24 IS THERE A DETRACTOR COMPARED TO THE DEFERRED APPROACH WHEN CONSIDERING EXPRESSIONS MAY HAVE EARLY RETURNS?
26 (BECAUSE, WE STILL NEED TO COUNT THE REGION LEADING UP TO THE EXPRESSION ANYWAY)
28 =================================================
29 =================================================
31 To inject an intrinsic after computing a final expression value of a coverage region:
33 Replace the following basic block end (last statement plus terminator):
35 ... <statements to compute _4> ...
41 _4 = Lt(move _5, move _6)
44 <------ to insert instrprof_increment() here
45 FakeRead(ForMatchedPlace, _4)
46 --------------------------------------------------------------------------------------
50 =================================================
51 Insert call to intrinsic with:
53 StorageLive(_4) # _4 is now meant for deferred FakeRead(ForMatchdPlace, _4) in BasicBlock after increment() call
54 StorageLive(_5) # Unchanged except _4 is now _5
55 StorageLive(_6) # Unchanged except _5 is now _6
56 _6 = _1 # Unchanged except _5 is now _6
57 StorageLive(_7) # Unchanged except _6 is now _7
58 _7 = _2 # Unchanged except _6 is now _7
59 _5 = Lt(move _6, move _7) # Unchanged except _4, _5, _6 is now _5, _6, _7
60 StorageDead(_7) # Unchanged except _6 is now _7
61 StorageDead(_6) # Unchanged except _5 is now _6
63 FakeRead(ForLet, _5) # CHANGED ForMatchedPlace to ForLet
65 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
66 > StorageLive(_8) # ?? stores function pointer to instrprof_increment function?
70 > _11 = const {alloc1+0: &&[u8; 6]}
71 > _10 = &raw const (*(*_11))
72 > _9 = move _10 as *const u8 (Pointer(ArrayToPointer))
80 > --------------------------------------------------------------------------------------
81 > _8 = const std::intrinsics::instrprof_increment(move _9, move _12, move _13, move _14)
92 _4 = _5 # ARE THESE LINES REDUNDANT? CAN I JUST PASS _5 DIRECTLY TO FakeRead()?
93 StorageDead(_5) # DROP "_t" temp result of `let _t = a < b`
94 # (NOTE THAT IF SO, I CAN REMOVE _5 altogether, and use _4, which coincidentally makes less changes)
97 FakeRead(ForMatchedPlace, _4) # Unchanged
98 --------------------------------------------------------------------------------------
99 switchInt(_4) # Unchanged
102 =================================================
103 Can I skip the extra variable and insert call to intrinsic with:
105 StorageLive(_4) # Unchanged
106 StorageLive(_5) # Unchanged
108 StorageLive(_6) # Unchanged
110 _4 = Lt(move _5, move _6) # Unchanged
111 StorageDead(_6) # Unchanged
112 StorageDead(_5) # Unchanged
114 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
115 > FakeRead(ForLet, _4) # Save the post-increment result in temp "_t"
116 > StorageLive(_8) # ?? stores function pointer to instrprof_increment function?
120 > _11 = const {alloc1+0: &&[u8; 6]}
121 > _10 = &raw const (*(*_11))
122 > _9 = move _10 as *const u8 (Pointer(ArrayToPointer))
125 > _12 = const 1234u64
130 > --------------------------------------------------------------------------------------
131 > _8 = const std::intrinsics::instrprof_increment(move _9, move _12, move _13, move _14)
142 FakeRead(ForMatchedPlace, _4) # Unchanged (PREVIOUSLY USED IN FakeRead(ForLet), is that OK?)
143 --------------------------------------------------------------------------------------
144 switchInt(_4) # Unchanged
150 =================================================
151 =================================================
153 For the second inserted call to instrprof_increment, without that call we have:
155 --------------------------------------------------------------------------------------
156 switchInt(_4) # From above
158 -> otherwise # that is, "NOT false"
161 <------ to insert instrprof_increment() here
162 --------------------------------------------------------------------------------------
165 -> # No label. No condition, and not a "return"
167 FakeRead(ForLet, _3) # NOTE: Unused result
173 --------------------------------------------------------------------------------------
176 -> # No label. No condition, and not a "return"
181 =================================================
182 With the call to increment():
184 --------------------------------------------------------------------------------------
185 switchInt(_4) # From above
187 -> otherwise # "NOT false" # UNCHANGED
189 StorageLive(_15) # CHANGED! Allocated new storage (_15) for the result of match, if true.
190 _15 = const true # UNCHANGED except _3 is now _15
191 FakeRead(ForLet, _15) # CHANGED! Assign value to temporary (to be assigned to _3 later) ... Do I need to do this?
193 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
194 > StorageLive(_16) # pointer to instrprof_increment() function ?
198 > _19 = const {alloc1+0: &&[u8; 6]}
199 > _18 = &raw const (*(*_19))
200 > _17 = move _18 as *const u8 (Pointer(ArrayToPointer))
203 > _20 = const 1234u64
208 > --------------------------------------------------------------------------------------
209 > _16 = const std::intrinsics::instrprof_increment(move _17, move _20, move _21, move _22)
222 --------------------------------# UNCHANGED-------------------------------------------
227 FakeRead(ForLet, _3) # UNCHANGED
228 StorageDead(_4) # UNCHANGED
230 StorageDead(_3) # UNCHANGED
231 StorageDead(_2) # UNCHANGED
232 StorageDead(_1) # UNCHANGED
233 --------------------------------------------------------------------------------------
238 return # from main() # UNCHANGED
240 =================================================
241 As before, can I skip the extra variable (_15) and insert the call to intrinsic with _3 directly?:
244 --------------------------------------------------------------------------------------
245 switchInt(_4) # From above
247 -> otherwise # "NOT false" # UNCHANGED
249 _3 = const true # UNCHANGED?
251 > # ALL NEW AND NECESSARY TO CALL instrprof_increment()
252 > StorageLive(_16) # pointer to instrprof_increment() function ?
256 > _19 = const {alloc1+0: &&[u8; 6]}
257 > _18 = &raw const (*(*_19))
258 > _17 = move _18 as *const u8 (Pointer(ArrayToPointer))
261 > _20 = const 1234u64
266 > --------------------------------------------------------------------------------------
267 > _16 = const std::intrinsics::instrprof_increment(move _17, move _20, move _21, move _22)
278 --------------------------------# UNCHANGED-------------------------------------------
283 FakeRead(ForLet, _3) # UNCHANGED
284 StorageDead(_4) # UNCHANGED
286 StorageDead(_3) # UNCHANGED
287 StorageDead(_2) # UNCHANGED
288 StorageDead(_1) # UNCHANGED
289 --------------------------------------------------------------------------------------
294 return # from main() # UNCHANGED