Description
There are multiple thousand intrinsics for various platforms which users might want to use to speed up their code. It is unrealistic to implement all of these (although a certain subgroup like https://github.com/rust-lang-nursery/stdsimd/blob/05c2f61c384e2097a3a4c648344114fc4ac983be/coresimd/simd_llvm.rs seem to be manageable.
@rkruppe and @gnzlbg mentioned (with discomfort) a way to "runtime" detect whether we're in const eval or runtime (which would get completely optimized during codegen). While this would be trivial to implement, it seems very unfortunate to have to resolve to this.
There's precedent in c++ for such an escape hatch.
I am not very happy that we even need that many intrinsics outside the libstd and don't quite understand why these can't be optimizations that "just happen". Requiring users to "fix" optimizer deficiencies by giving them multiple thousand ways to gain a few cycles seems suboptimal.
It's perfectly fine not to support calling e.g. an interrupt register fiddling intrinsic at compile-time (there's no use for doing that, or it could be a noop in many cases). But when/if performance intrinsics are sprinkled onto code used by many users and there's an algorithm that works both at compile-time and runtime and could be optimized, it seems very unfortunate to scrap compile-time evaluability.
Activity
hanna-kruppe commentedon Aug 30, 2018
gnzlbg commentedon Aug 30, 2018
There is a solution proposed for C++20 (I am not sure if it has been merged - EDIT: It was accepted LEWG and sent to LWG and CWG) called
is_constant_evaluated
(latest paper: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0595r1.html) that attacks this problem.Having to choose between whether code can be const evaluated or whether it performs good at run-time is a weird spot to be in as a programmer. I don't know whether this problem is worth solving, but the problem is real. The C++ solution, doesn't feel right, but I don't have any alternatives either.
oli-obk commentedon Aug 30, 2018
@gnzlbg gave us a great summary on irc. Here's the gist:
foo()
is const propagated by optimizatons ?if constexpr() { ... }
to if std::is_constant_evaluated() to discourage its useoli-obk commentedon May 24, 2019
Note that we can "just" add such a
std::is_constant_evaluated
function and make itunsafe
to make it clear what's going on. The unsafe documentation would then state that the result of this function may not change the behaviour of any code. There could even be an additional-Z
flag for fuzzers and testing that turns the flag totrue
during regular compilationgnzlbg commentedon May 24, 2019
When
miri
evaluates Rust program like this:it could attempt to evaluate both branches, and compare that both produce the same result, which is the only effect that both branches can have. If the
bar
branch attempts to mutate global memory, read from astatic
, etc.miri
could error.oli-obk commentedon Jan 20, 2020
We have changed course. Discussion is in https://github.com/rust-lang/rust/pull/64683/files/223c832b3894fe6ce6d61d4f459f0aa827bec264#discussion_r327153517
The TLDR is that we'd create an intrinsic
that calls
called_in_const(arg)
if we're in a const eval context andcalled_at_rt(arg)
if not.F
andG
must be function types (not function pointers).minerva commentedon Jan 20, 2020
How about a language-level
if const { .. }
? I think C++20 demonstrates why a library function to handle this job in conjunction with a regularif
is a bad solution.Similar to how ISO NB comments tried to change C++20's
if (std::is_constant_evaluated()) { .. }
toif consteval { .. }
.oli-obk commentedon Jan 20, 2020
I think we race-conditioned on posting. See my above post for a solution that is much simpler to implement, since it doesn't pollute the const part of a function with the non-const part.
const fn
hashing RustCrypto/hashes#288const_eval_select
intrinsic rust-lang/rust#8924724 remaining items