… | |
… | |
184 | |
184 | |
185 | In addition to placing cold functions together (or at least away from hot |
185 | In addition to placing cold functions together (or at least away from hot |
186 | functions), this knowledge can be used in other ways, for example, the |
186 | functions), this knowledge can be used in other ways, for example, the |
187 | function will be optimised for size, as opposed to speed, and codepaths |
187 | function will be optimised for size, as opposed to speed, and codepaths |
188 | leading to calls to those functions can automatically be marked as if |
188 | leading to calls to those functions can automatically be marked as if |
189 | C<ecb_unlikely> had been used to reach them. |
189 | C<ecb_expect_false> had been used to reach them. |
190 | |
190 | |
191 | Good examples for such functions would be error reporting functions, or |
191 | Good examples for such functions would be error reporting functions, or |
192 | functions only called in exceptional or rare cases. |
192 | functions only called in exceptional or rare cases. |
193 | |
193 | |
194 | =item ecb_artificial |
194 | =item ecb_artificial |
… | |
… | |
256 | |
256 | |
257 | Evaluates C<expr> and returns it. In addition, it tells the compiler that |
257 | Evaluates C<expr> and returns it. In addition, it tells the compiler that |
258 | the C<expr> evaluates to C<value> a lot, which can be used for static |
258 | the C<expr> evaluates to C<value> a lot, which can be used for static |
259 | branch optimisations. |
259 | branch optimisations. |
260 | |
260 | |
261 | Usually, you want to use the more intuitive C<ecb_likely> and |
261 | Usually, you want to use the more intuitive C<ecb_expect_true> and |
262 | C<ecb_unlikely> functions instead. |
262 | C<ecb_expect_false> functions instead. |
263 | |
263 | |
|
|
264 | =item bool ecb_expect_true (cond) |
|
|
265 | |
264 | =item bool ecb_likely (cond) |
266 | =item bool ecb_expect_false (cond) |
265 | |
|
|
266 | =item bool ecb_unlikely (cond) |
|
|
267 | |
267 | |
268 | These two functions expect a expression that is true or false and return |
268 | These two functions expect a expression that is true or false and return |
269 | C<1> or C<0>, respectively, so when used in the condition of an C<if> or |
269 | C<1> or C<0>, respectively, so when used in the condition of an C<if> or |
270 | other conditional statement, it will not change the program: |
270 | other conditional statement, it will not change the program: |
271 | |
271 | |
272 | /* these two do the same thing */ |
272 | /* these two do the same thing */ |
273 | if (some_condition) ...; |
273 | if (some_condition) ...; |
274 | if (ecb_likely (some_condition)) ...; |
274 | if (ecb_expect_true (some_condition)) ...; |
275 | |
275 | |
276 | However, by using C<ecb_likely>, you tell the compiler that the condition |
276 | However, by using C<ecb_expect_true>, you tell the compiler that the |
277 | is likely to be true (and for C<ecb_unlikely>, that it is unlikely to be |
277 | condition is likely to be true (and for C<ecb_expect_false>, that it is |
278 | true). |
278 | unlikely to be true). |
279 | |
279 | |
280 | For example, when you check for a null pointer and expect this to be a |
280 | For example, when you check for a null pointer and expect this to be a |
281 | rare, exceptional, case, then use C<ecb_unlikely>: |
281 | rare, exceptional, case, then use C<ecb_expect_false>: |
282 | |
282 | |
283 | void my_free (void *ptr) |
283 | void my_free (void *ptr) |
284 | { |
284 | { |
285 | if (ecb_unlikely (ptr == 0)) |
285 | if (ecb_expect_false (ptr == 0)) |
286 | return; |
286 | return; |
287 | } |
287 | } |
288 | |
288 | |
289 | Consequent use of these functions to mark away exceptional cases or to |
289 | Consequent use of these functions to mark away exceptional cases or to |
290 | tell the compiler what the hot path through a function is can increase |
290 | tell the compiler what the hot path through a function is can increase |
291 | performance considerably. |
291 | performance considerably. |
|
|
292 | |
|
|
293 | You might know these functions under the name C<likely> and C<unlikely> |
|
|
294 | - while these are common aliases, we find that the expect name is easier |
|
|
295 | to understand when quickly skimming code. If you wish, you can use |
|
|
296 | C<ecb_likely> instead of C<ecb_expect_true> and C<ecb_unlikely> instead of |
|
|
297 | C<ecb_expect_false> - these are simply aliases. |
292 | |
298 | |
293 | A very good example is in a function that reserves more space for some |
299 | A very good example is in a function that reserves more space for some |
294 | memory block (for example, inside an implementation of a string stream) - |
300 | memory block (for example, inside an implementation of a string stream) - |
295 | each time something is added, you have to check for a buffer overrun, but |
301 | each time something is added, you have to check for a buffer overrun, but |
296 | you expect that most checks will turn out to be false: |
302 | you expect that most checks will turn out to be false: |
297 | |
303 | |
298 | /* make sure we have "size" extra room in our buffer */ |
304 | /* make sure we have "size" extra room in our buffer */ |
299 | ecb_inline void |
305 | ecb_inline void |
300 | reserve (int size) |
306 | reserve (int size) |
301 | { |
307 | { |
302 | if (ecb_unlikely (current + size > end)) |
308 | if (ecb_expect_false (current + size > end)) |
303 | real_reserve_method (size); /* presumably noinline */ |
309 | real_reserve_method (size); /* presumably noinline */ |
304 | } |
310 | } |
305 | |
311 | |
306 | =item bool ecb_assume (cond) |
312 | =item bool ecb_assume (cond) |
307 | |
313 | |
… | |
… | |
310 | |
316 | |
311 | This can be used to teach the compiler about invariants or other |
317 | This can be used to teach the compiler about invariants or other |
312 | conditions that might improve code generation, but which are impossible to |
318 | conditions that might improve code generation, but which are impossible to |
313 | deduce form the code itself. |
319 | deduce form the code itself. |
314 | |
320 | |
315 | For example, the example reservation function from the C<ecb_unlikely> |
321 | For example, the example reservation function from the C<ecb_expect_false> |
316 | description could be written thus (only C<ecb_assume> was added): |
322 | description could be written thus (only C<ecb_assume> was added): |
317 | |
323 | |
318 | ecb_inline void |
324 | ecb_inline void |
319 | reserve (int size) |
325 | reserve (int size) |
320 | { |
326 | { |
321 | if (ecb_unlikely (current + size > end)) |
327 | if (ecb_expect_false (current + size > end)) |
322 | real_reserve_method (size); /* presumably noinline */ |
328 | real_reserve_method (size); /* presumably noinline */ |
323 | |
329 | |
324 | ecb_assume (current + size <= end); |
330 | ecb_assume (current + size <= end); |
325 | } |
331 | } |
326 | |
332 | |