-
Notifications
You must be signed in to change notification settings - Fork 14k
Reexport likely/unlikely in std::hint #133695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -511,3 +511,143 @@ pub const fn black_box<T>(dummy: T) -> T { | |||
| pub const fn must_use<T>(value: T) -> T { | ||||
| value | ||||
| } | ||||
|
|
||||
| /// Hints to the compiler that a branch condition is likely to be true. | ||||
| /// Returns the value passed to it. | ||||
| /// | ||||
| /// It can be used with `if` or boolean `match` expressions. | ||||
| /// | ||||
| /// When used outside of a branch condition, it may still work if there is a branch close by, but | ||||
| /// it is not guaranteed to have any effect. | ||||
|
||||
| /// | ||||
| /// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to | ||||
| /// compound expressions, such as `likely(a && b)`. When applied to compound expressions, it has | ||||
| /// the following effect: | ||||
| /// ```text | ||||
| /// likely(!a) => !unlikely(a) | ||||
| /// likely(a && b) => likely(a) && likely(b) | ||||
| /// likely(a || b) => a || likely(b) | ||||
| /// ``` | ||||
| /// | ||||
| /// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code. | ||||
| /// | ||||
| /// # Examples | ||||
| /// | ||||
| /// ``` | ||||
| /// #![feature(likely_unlikely)] | ||||
| /// use core::hint::likely; | ||||
| /// | ||||
| /// fn foo(x: i32) { | ||||
| /// if likely(x > 0) { | ||||
| /// println!("this branch is likely to be taken"); | ||||
| /// } else { | ||||
| /// println!("this branch is unlikely to be taken"); | ||||
| /// } | ||||
| /// | ||||
| /// match likely(x > 0) { | ||||
| /// true => println!("this branch is likely to be taken"), | ||||
| /// false => println!("this branch is unlikely to be taken"), | ||||
| /// } | ||||
| /// | ||||
| /// // Use outside of a branch condition. This may still work if there is a branch close by, | ||||
| /// // but it is not guaranteed to have any effect | ||||
| /// let cond = likely(x != 0); | ||||
| /// if cond { | ||||
| /// println!("this branch is likely to be taken"); | ||||
| /// } | ||||
| /// } | ||||
| /// ``` | ||||
| /// | ||||
| /// | ||||
| #[unstable(feature = "likely_unlikely", issue = "26179")] | ||||
| #[rustc_nounwind] | ||||
|
||||
| #[rustc_nounwind] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute removed
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this attribute is appropriate for public functions.
| #[rustc_nounwind] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute removed
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this attribute is appropriate for public functions.
| #[rustc_nounwind] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attribute removed
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| //@ compile-flags: -O | ||
| #![crate_type = "lib"] | ||
| #![feature(cold_path)] | ||
|
|
||
| use std::hint::cold_path; | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_a() { | ||
| println!("path a"); | ||
| } | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_b() { | ||
| println!("path b"); | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test1(x: bool) { | ||
| if x { | ||
| path_a(); | ||
| } else { | ||
| cold_path(); | ||
| path_b(); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test1( | ||
| // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]] | ||
| // CHECK: bb2: | ||
| // CHECK: path_b | ||
| // CHECK: bb1: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test2(x: i32) { | ||
| match x > 0 { | ||
| true => path_a(), | ||
| false => { | ||
| cold_path(); | ||
| path_b() | ||
| } | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test2( | ||
| // CHECK: br i1 %_2, label %bb2, label %bb1, !prof ![[NUM]] | ||
| // CHECK: bb1: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| // CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| //@ compile-flags: -O | ||
| #![crate_type = "lib"] | ||
| #![feature(likely_unlikely)] | ||
|
|
||
| use std::hint::likely; | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_a() { | ||
| println!("path a"); | ||
| } | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_b() { | ||
| println!("path b"); | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test1(x: bool) { | ||
| if likely(x) { | ||
| path_a(); | ||
| } else { | ||
| path_b(); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test1( | ||
| // CHECK: br i1 %x, label %bb2, label %bb3, !prof ![[NUM:[0-9]+]] | ||
| // CHECK: bb3: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test2(x: i32) { | ||
| match likely(x > 0) { | ||
| true => path_a(), | ||
| false => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test2( | ||
| // CHECK: br i1 %_2, label %bb2, label %bb3, !prof ![[NUM]] | ||
| // CHECK: bb3: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test3(x: i8) { | ||
| match likely(x < 7) { | ||
| true => path_a(), | ||
| _ => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test3( | ||
| // CHECK: br i1 %_2, label %bb2, label %bb3, !prof ![[NUM]] | ||
| // CHECK: bb3: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test4(x: u64) { | ||
| match likely(x != 33) { | ||
| false => path_a(), | ||
| _ => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test4( | ||
| // CHECK: br i1 %0, label %bb3, label %bb2, !prof ![[NUM2:[0-9]+]] | ||
| // CHECK: bb3: | ||
| // CHECK: path_a | ||
| // CHECK: bb2: | ||
| // CHECK: path_b | ||
| } | ||
|
|
||
| // CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} | ||
| // CHECK: ![[NUM2]] = !{!"branch_weights", {{(!"expected", )?}}i32 1, i32 2000} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| //@ compile-flags: -O | ||
| #![crate_type = "lib"] | ||
| #![feature(likely_unlikely)] | ||
|
|
||
| use std::hint::unlikely; | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_a() { | ||
| println!("path a"); | ||
| } | ||
|
|
||
| #[inline(never)] | ||
| #[no_mangle] | ||
| pub fn path_b() { | ||
| println!("path b"); | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test1(x: bool) { | ||
| if unlikely(x) { | ||
| path_a(); | ||
| } else { | ||
| path_b(); | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test1( | ||
| // CHECK: br i1 %x, label %bb2, label %bb4, !prof ![[NUM:[0-9]+]] | ||
| // CHECK: bb4: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test2(x: i32) { | ||
| match unlikely(x > 0) { | ||
| true => path_a(), | ||
| false => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test2( | ||
| // CHECK: br i1 %_2, label %bb2, label %bb4, !prof ![[NUM]] | ||
| // CHECK: bb4: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test3(x: i8) { | ||
| match unlikely(x < 7) { | ||
| true => path_a(), | ||
| _ => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test3( | ||
| // CHECK: br i1 %_2, label %bb2, label %bb4, !prof ![[NUM]] | ||
| // CHECK: bb4: | ||
| // CHECK: path_b | ||
| // CHECK: bb2: | ||
| // CHECK: path_a | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub fn test4(x: u64) { | ||
| match unlikely(x != 33) { | ||
| false => path_a(), | ||
| _ => path_b(), | ||
| } | ||
|
|
||
| // CHECK-LABEL: @test4( | ||
| // CHECK: br i1 %0, label %bb4, label %bb2, !prof ![[NUM2:[0-9]+]] | ||
| // CHECK: bb4: | ||
| // CHECK: path_a | ||
| // CHECK: bb2: | ||
| // CHECK: path_b | ||
| } | ||
|
|
||
| // CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 1, i32 2000} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be expanded a bit? What happens if you use it outside (presumably, nothing)? Can this be used in a
&&or||expression?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also it would be good to point people to
cold_path(for which we just approved the ACP) for generalmatchandif let.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I also export
cold_path()in this PR, or create a new PR for that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do it in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also added a test for
cold_path(), but not with idiomatic Rust such asif let ...because this will only work after #133852