@@ -310,34 +310,6 @@ pub fn spin_loop() {
310
310
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
311
311
/// certain optimizations are not desired, such as benchmarks.
312
312
///
313
- /// In practice, `black_box` serves two purposes:
314
- ///
315
- /// 1. It forces the input to be calculated, even if its results are never used
316
- /// 2. It prevents the compiler from making optimizations related to the value of the returned
317
- /// type
318
- ///
319
- /// Note that `black_box` does not prevent its inputs from being optimized before they are passed
320
- /// to the function, though.
321
- ///
322
- /// ```
323
- /// # use std::hint::black_box;
324
- /// #
325
- /// // This...
326
- /// let y = black_box(5 * 10);
327
- /// // ...will still be optimized to this:
328
- /// let y = black_box(50);
329
- /// ```
330
- ///
331
- /// In the above example, `5 * 10` is replaced with `50` by the compiler. You can prevent this by
332
- /// moving the multiplication outside of `black_box`:
333
- ///
334
- /// ```
335
- /// # use std::hint::black_box;
336
- /// #
337
- /// // No assumptions can be made about either number, so the multiplication is kept.
338
- /// let y = black_box(5) * black_box(10);
339
- /// ```
340
- ///
341
313
/// <div class="warning">
342
314
///
343
315
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
@@ -419,6 +391,85 @@ pub fn spin_loop() {
419
391
///
420
392
/// This makes our benchmark much more realistic to how the function would actually be used, where
421
393
/// arguments are usually not known at compile time and the result is used in some way.
394
+ ///
395
+ /// # How to use this
396
+ ///
397
+ /// In practice, `black_box` serves two purposes:
398
+ ///
399
+ /// 1. It prevents the compiler from making optimizations related to the value of the returned
400
+ /// type
401
+ /// 2. It forces the input to be calculated, even if its results are never used
402
+ ///
403
+ /// ```
404
+ /// use std::hint::black_box;
405
+ ///
406
+ /// let zero = 0;
407
+ /// let five = 5;
408
+ ///
409
+ /// // The compiler will see this and remove the `* five` call, because it knows that multiplying
410
+ /// // any integer by 0 will result in 0. This is a value optimization: the compiler knows the
411
+ /// // value of `zero` must be 0, and thus can make optimizations related to that.
412
+ /// let c = zero * five;
413
+ ///
414
+ /// // Adding `black_box` here disables the compiler's ability to reason about the value of `zero`.
415
+ /// // It is forced to assume that it can be any possible number, so it cannot remove the `* five`
416
+ /// // operation.
417
+ /// let c = black_box(zero) * five;
418
+ /// ```
419
+ ///
420
+ /// While most cases will not be as clear-cut as the above example, it still illustrates how
421
+ /// `black_box` can be used. When benchmarking a function, you usually want to wrap its inputs in
422
+ /// `black_box` so the compiler cannot make optimizations that would be unrealistic in real-life
423
+ /// use.
424
+ ///
425
+ /// ```
426
+ /// use std::hint::black_box;
427
+ ///
428
+ /// // This is a simple function that increments its input by 1. Note that it is pure, meaning it
429
+ /// // has no side-effects. This function has no effect if its result is unused. (An example of a
430
+ /// // function *with* side-effects is `println!()`.)
431
+ /// fn increment(x: u8) -> u8 {
432
+ /// x + 1
433
+ /// }
434
+ ///
435
+ /// // Here, we call `increment` but discard its result. The compiler, seeing this and knowing that
436
+ /// // `increment` is pure, will eliminate this function call entirely. This may not be desired,
437
+ /// // though, especially if we're trying to track how much time `increment` takes to execute.
438
+ /// let _ = increment(black_box(5));
439
+ ///
440
+ /// // Here, we force `increment` to be executed. This is because the compiler treats `black_box`
441
+ /// // as if it has side-effects, and thus must compute its input.
442
+ /// let _ = black_box(increment(black_box(5)));
443
+ /// ```
444
+ ///
445
+ /// There may be additional situations where you want to wrap the result of a function in
446
+ /// `black_box` to force its execution. This is situational though, and may not have any effect
447
+ /// (such as when the function returns a [`()` unit][unit]).
448
+ ///
449
+ /// Note that `black_box` has no effect on how its input is treated, only its output. As such,
450
+ /// expressions passed to `black_box` may still be optimized:
451
+ ///
452
+ /// ```
453
+ /// use std::hint::black_box;
454
+ ///
455
+ /// // The compiler sees this...
456
+ /// let y = black_box(5 * 10);
457
+ ///
458
+ /// // ...as this. As such, it will likely simplify `5 * 10` to just `50`.
459
+ /// let _0 = 5 * 10;
460
+ /// let y = black_box(_0);
461
+ /// ```
462
+ ///
463
+ /// In the above example, the `5 * 10` expression is considered distinct from the `black_box` call,
464
+ /// and thus is still optimized by the compiler. You can prevent this by moving the multiplication
465
+ /// operation outside of `black_box`:
466
+ ///
467
+ /// ```
468
+ /// use std::hint::black_box;
469
+ ///
470
+ /// // No assumptions can be made about either number, so the multiplication is kept.
471
+ /// let y = black_box(5) * black_box(10);
472
+ /// ```
422
473
#[ inline]
423
474
#[ stable( feature = "bench_black_box" , since = "1.66.0" ) ]
424
475
#[ rustc_const_unstable( feature = "const_black_box" , issue = "none" ) ]
0 commit comments