From e6da4014e737da35d4b013fcc84b356de1607789 Mon Sep 17 00:00:00 2001 From: James Miller Date: Wed, 20 May 2015 13:40:04 +1200 Subject: [PATCH 1/2] Write RFC for adding an expect intrinsic --- text/0000-expect-intrinsic.md | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 text/0000-expect-intrinsic.md diff --git a/text/0000-expect-intrinsic.md b/text/0000-expect-intrinsic.md new file mode 100644 index 00000000000..078aba7ffa8 --- /dev/null +++ b/text/0000-expect-intrinsic.md @@ -0,0 +1,43 @@ +- Feature Name: expect_intrinsic +- Start Date: 2015-05-20 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary + +Provide an intrinsic function for hinting the likelyhood of branches being taken. + +# Motivation + +Branch prediction can have significant effects on the running time of some code. Especially tight +inner loops which may be run millions of times. While in general programmers aren't able to +effectively provide hints to the compiler, there are cases where the likelyhood of some branch +being taken can be known. + +For example: in arbitrary-precision arithmetic, operations are often performed in a base that is +equal to `2^word_size`. The most basic division algorithm, "Schoolbook Division", has a step that +will be taken in `2/B` cases (where `B` is the base the numbers are in), given random input. On a +32-bit processor that is approximately one in two billion cases, for 64-bit it's one in 18 +quintillion cases. + +# Detailed design + +Implement an `expect` intrinsic with the signature: `fn(bool, bool) -> bool`. The first argument is +the condition being tested, the second argument is the expected result. The return value is the +same as the first argument, meaning that `if foo == bar { .. }` can be simply replaced with +`if expect(foo == bar, false) { .. }`. + +The expected value is required to be a constant value. + +# Drawbacks + +The second argument is required to be a constant value, which can't be easily expressed. + +# Alternatives + +Provide a pair of intrinsics `likely` and `unlikely`, these are the same as `expect` just with +`true` and `false` substituted in for the expected value, respectively. + +# Unresolved questions + +None. \ No newline at end of file From 31d230b3f1f40797405589f107983c2052792807 Mon Sep 17 00:00:00 2001 From: James Miller Date: Thu, 28 May 2015 12:52:24 +1200 Subject: [PATCH 2/2] Re-write text to propose likely/unlikely instead of expect It's clear that `likely`/`unlikely` is the more popular option, so make that the main focus. Also expands on the guarantees the intrinsics provide (i.e. none) and mentions the prevalance of `LIKELY`/`UNLIKELY` macros in many C/C++ projects. --- text/0000-expect-intrinsic.md | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/text/0000-expect-intrinsic.md b/text/0000-expect-intrinsic.md index 078aba7ffa8..8162ef161b0 100644 --- a/text/0000-expect-intrinsic.md +++ b/text/0000-expect-intrinsic.md @@ -5,7 +5,7 @@ # Summary -Provide an intrinsic function for hinting the likelyhood of branches being taken. +Provide a pair of intrinsic functions for hinting the likelyhood of branches being taken. # Motivation @@ -22,21 +22,34 @@ quintillion cases. # Detailed design -Implement an `expect` intrinsic with the signature: `fn(bool, bool) -> bool`. The first argument is -the condition being tested, the second argument is the expected result. The return value is the -same as the first argument, meaning that `if foo == bar { .. }` can be simply replaced with -`if expect(foo == bar, false) { .. }`. +Implement a pair of intrinsics `likely` and `unlikely`, both with signature `fn(bool) -> bool` +which hint at the probability of the passed value being true or false. Specifically, `likely` hints +to the compiler that the passed value is likely to be true, and `unlikely` hints that it is likely +to be false. Both functions simply return the value they are passed. -The expected value is required to be a constant value. +The primary reason for this design is that it reflects common usage of this general feature in many +C and C++ projects, most of which define simple `LIKELY` and `UNLIKELY` macros around the gcc +`__builtin_expect` intrinsic. It also provides the most flexibility, allowing branches on any +condition to be hinted at, even if the process that produced the branched-upon value is +complex. For why an equivalent to `__builtin_expect` is not being exposed, see the Alternatives +section. + +There are no observable changes in behaviour from use of these intrinsics. It is valid to implement +these intrinsics simply as the identity function. Though it is expected that the intrinsics provide +information to the optimizer, that information is not guaranteed to change the decisions the +optimiser makes. # Drawbacks -The second argument is required to be a constant value, which can't be easily expressed. +The intrinsics cannot be used to hint at arms in `match` expressions. However, given that hints +would need to be variants, a simple intrinsic would not be sufficient for those purposes. # Alternatives -Provide a pair of intrinsics `likely` and `unlikely`, these are the same as `expect` just with -`true` and `false` substituted in for the expected value, respectively. +Expose an `expect` intrinsic. This is what gcc/clang does with `__builtin_expect`. However there is +a restriction that the second argument be a constant value, a requirement that is not easily +expressible in Rust code. The split into `likely` and `unlikely` intrinsics reflects the strategy +we have used for similar restrictions like the ordering constraint of the atomic intrinsics. # Unresolved questions