-
Notifications
You must be signed in to change notification settings - Fork 43
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
Panics on non consecutive blocks and vregs ids #211
Panics on non consecutive blocks and vregs ids #211
Conversation
Hi @iwanders -- thanks for the report. Actually I think the issue is a bit different, and much simpler, than this PR implies: regalloc2 requires accurate information about the range of block IDs, instruction IDs, and VReg IDs, because it pre-allocates structures indexed by these IDs. If you provide inaccurate information, the code will panic. Non-contiguous ranges, on the other hand, are perfectly fine; the allocator does not assume that the index spaces are fully filled. The So I don't think this PR is the right solution, but we should properly document this, and we should validate that all IDs are in range so we get a clearer error. Would you be willing to do that? |
Yeah, I think this is the main thing... the docs for those functions currently states they should return the number of blocks, not the value of the index of the highest block (plus one). So to make the code work, the only logical conclusion for me was to require the indices to be sequential and start at zero, otherwise they don't all end up with an index below
Yeah, no problem, I'll update it tomorrow. The fix (c536d39) only needs a rewording of the trace on line 20, but the actual checks only check whether it's in bounds of the allocated container. As for the docs of the |
Okay, I pushed a commit that rewords the documentation and makes the checks check the length.
About this though, there's a loop over the possible block indices here: Lines 79 to 83 in 925df1b
And the signature for Line 1138 in 925df1b
The naive solution in that case is to return an empty range, from instruction 0 to instruction 0, but that results in a debug assert: Line 149 in 925df1b
So, to handle non-consecutive blocks, one would have to do something like this: fn block_insns(&self, block: regalloc2::Block) -> InstRange {
println!("block: {block:?}");
if let Some(r) = self.blocks.get(&block) {
self.blocks[&block]
} else {
println!("Don't have this block, returning a dummy range");
InstRange::new(Inst::new(0), Inst::new(1))
}
} which is less than intuitive as a workaround? Edit; Actually, I think this makes the data in the instruction -> block lookup in the I wonder if, instead of |
Doesn't that assert in I suppose you're finding a few places where a contiguous-indices assumption has leaked in, which makes me think that maybe the most prudent solution is just to check that property. It's certainly what Cranelift provides in its input, so that will be the path of least resistance for other users as well. |
Sorry, yes, we hit the assert one function below that assert on 155; Line 155 in 925df1b
Which is called from the Backtrace``` thread 'main' panicked at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/index.rs:155:9: assertion failed: self.len() > 0 stack backtrace: 0: rust_begin_unwind at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/std/src/panicking.rs:692:5 1: core::panicking::panic_fmt at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:75:14 2: core::panicking::panic at /rustc/4d91de4e48198da2e33413efdcd9cd2cc0c46688/library/core/src/panicking.rs:145:5 3: regalloc2::index::InstRange::first at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/index.rs:155:9 4: regalloc2::cfg::CFGInfo::init at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/cfg.rs:84:60 5: regalloc2::cfg::CFGInfo::new at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/cfg.rs:46:9 6: regalloc2::fastalloc::run at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/fastalloc/mod.rs:1290:29 7: regalloc2::run at /home/ivor/Documents/Code/rust/bytecodealliance/regalloc2/src/lib.rs:1614:13 ```
Hmm, it is sure what it feels like. I only really ran into this because I manually hacked up a clif file and ended up with non-consecutive numbers, not sure if anyone else ever ran into this situation? I think it's fine to require them to be consecutive, as long as there's a clear indication that is required and validated for? |
Sorry, I'm a bit confused now. You wrote in the initial report
But now you're saying
I've confirmed that your CLIF compiles fine with Cranelift, and indeed it does so because Cranelift allocates into new ID spaces for machine-level blocks, instructions and vregs (it's a different IR layer). I want to make sure I have the precise details of your report right: are you somehow reaching this with CLIF ("because I manually hacked up a clif file")? |
Sorry for the confusion! Running When I mentioned 'clif file' I mean anything that ends in |
Sorry, this fell off my radar -- yes, given that a few consecutive-ID assumptions have slipped in, let's document it formally and check it. Happy to review a PR for that (which I guess is close to what you had originally?). |
9eeb788
to
cf441a9
Compare
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.
Thanks -- almost there, just one comment fix below.
And another small thing, compiling the fuzzer gave a warning in the pipeline. There's now an unused result here, I think we can just ignore it with Edit; I ignored the result in 06850ff happy to change it into an expect or something if you'd prefer that. |
Looks good, thanks! |
Hi, currently it is possible for two panics to happen when a function's SSA is being validated:
0
or is non consecutive.0
or is non consecutive.I ran into it after trying to use regalloc2's allocators in my toy/educational compiler project... I ended up with a hacked up clif file, something like:
Which worked fine in my register allocator, as it uses hashmaps, but when trying to run regalloc2's allocators I got panics. Running
clif-util test
from cranelift passes on this file, that probably relabels all ids before passing them to the register allocator?.I'm not sure if non conseuctive ids violate an unwritten rule about SSA notation, but I didn't find anything in the documentation about this and if it is not allowed, ideally the ssa validation should catch it and report an error, such that users can easily understand what the problem is.
The first one happens in the second argument of the
validate_ssa
call. Specifically here:regalloc2/src/postorder.rs
Line 38 in 925df1b
in the case the index of a block is outside of
num_blocks
.The other one here:
regalloc2/src/ssa.rs
Line 19 in 925df1b
In case the vregs ids are not consecutive.
A standalone minimal example that demonstrates the two problems can be found here.
Backtraces from that example
Commits are split out:
RegAllocError
enum, and a note inFunction
that states the requirement on the indices.[alloc_s]
not being an existing token, andOperand::fixed
not existing, I think that should beOperandConstraint::FixedReg
now?, lastlytarget/
in the.gitignore
doesn't match a symlink (I always use one to a ramdisk).With these changes, the mentioned minimal non working example runs cleanly en reports
Err
as a return from therun
method for both allocators.