Open CJacob314 opened 3 months ago
@saethlin informed me that this is an issue with his mono-reachable traversal implementation.
I know that when I initially worked on this I searched the generated LLVM IR for the special "No predecessors!" comment that LLVM leaves on such orphaned basic blocks. There are a lot and I think I concluded they were all not actionable.
Clearly this case is.
There are actually two bugs here:
The mono-reachable traverasal only looks for a constant SwitchInt param coming from Rvalue::Use
and Rvalue::UbChecks
. In this case, we have Rvalue::BinOp
. GVN could fix this, but only if test
were inlined or we had post-mono MIR optimizations. So I lean towards it being worthwhile to teach mono-reachable traversal about this.
Even if we get the traversal right (this can be simulated by wrapping the comparison in an inline const) we still have an alloca for the argument, because we don't set up locals based on reachability.
I think that if you want this you should write
fn test<const SIZE: usize>() {
- if SIZE < 4096 {
+ if const { SIZE < 4096 } {
so that rust will know it's a constant, and be more likely to give you the behaviour you want in unoptimized builds.
(Or make your own trait so it can be <[u8; 4096]>::IS_SMALL
or something if you need an older MSRV.)
Anything else will just mean exactly the same bug comes back if you write it as SIZE.ilog2() < 12
instead, but if you write const { SIZE.ilog2() < 12 }
that'd be fine again.
@scottmcm That doesn't work, either. See version 1.80.0 or version 1.82.0-nightly on Compiler Explorer.
The following code, when compiled without optimization flags (or with
-Copt-level=0
) emits LLVM IR for an 8192-bytealloca
, which can easily cause 100% unnecessary stack overflow errors in a running executable.The following is the relevant LLVM IR:
%arr
only ends up being used bybb1
below, butbb1
has no predecessors:Here's a Godbolt Compiler Explorer link with all of the IR.