sorear / smetamath-rs

sorear's Metamath system engine - version 3 Rust
Apache License 2.0
22 stars 6 forks source link

replace bits_per_word with an actual constant function #21

Closed digama0 closed 8 years ago

sorear commented 8 years ago

I agree that's probably nicer (although I'm still on the fence about Rust getting rid of CHAR_BIT), but AFAICT both versions constant-fold?

sorear commented 8 years ago

very strange, count_ones seems to not be inlined in the opt-level=1 debug build, yet size_of is. will worry about why this is later

digama0 commented 8 years ago

Nope, I found this in the LLVM:

before:

$ cargo rustc -- --emit=llvm-ir &> /dev/null
$ grep 'define.*bits_per_word' target/debug/smetamath.1.ll -A 5
define internal fastcc i64 @_ZN9smetamath7bit_set13bits_per_word17h5f74a49eb59c1e5eE() unnamed_addr #10 !dbg !5429 {
entry-block:
  %0 = tail call i32 @"_ZN4core3num23_$LT$impl$u20$usize$GT$10count_ones17h5e294136e40f97eaE"(i64 -1), !dbg !21976
  %1 = zext i32 %0 to i64, !dbg !21976
  ret i64 %1, !dbg !21978
}

after:

$ grep 'define.*bits_per_word' target/debug/smetamath.1.ll -A 3
define internal fastcc i64 @_ZN9smetamath7bit_set13bits_per_word17h5f74a49eb59c1e5eE() unnamed_addr #10 !dbg !5429 {
entry-block:
  ret i64 64, !dbg !21973
}
sorear commented 8 years ago

Neither size_of nor count_ones is a const fn, so I'm not sure why either of them is being folded there. I suspect this may be a "random" thing cause by module round-robinning and the next time I add a new module, we'll discover that count_ones is folded and size_of isn't.

sorear commented 8 years ago

If you want to study the matter further, I'd suggest commenting out the codegen-units line in the Cargo.toml file to make sure this isn't a mirage.

digama0 commented 8 years ago

It would be even nicer to use std::usize::BITS but for some unfathomable reason it's getting deprecated. I believe this works because mem::size_of is hardcoded as a const fn somehow (there is talk on Rust board that if anything is a const fn, this is).

My own interpretation is that this works because they are zero-arg functions which are being inlined, along with basic arithmetic evaluation. count_ones probably has a loop, whose resulting value cannot be statically determined (the const fn support is not at the level of a general interpreter yet).

sorear commented 8 years ago

FWIW count_ones wraps @llvm.ctpop.u64. LLVM can constant-fold it, but rustc sees it as an intrinsic with unlimited side effects.