Skip to content

LLVM failed to use the knowledge from a never-overflow assumption #509

@dtcxzyw

Description

@dtcxzyw

Hi all, I am an LLVM developer working on the middle-end optimizations.

Recently I found an anti-pattern in some Rust applications from my benchmark. All of them come from hashbrown::raw::RawTableInner::free_buckets:

hashbrown/src/raw/mod.rs

Lines 3290 to 3294 in 274c7bb

// Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
Some(lco) => lco,
None => unsafe { hint::unreachable_unchecked() },
};

LLVM IR:

define i32 @src(i32 %x, i32 %y) {
  %res = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
  %ov = extractvalue { i32, i1 } %res, 1
  %nowrap = xor i1 %ov, true
  tail call void @llvm.assume(i1 %nowrap)
  %val = extractvalue { i32, i1 } %res, 0
  ret i32 %val
}
define i32 @tgt(i32 %x, i32 %y) {
  %res = mul nuw i32 %x, %y
  ret i32 %res
}

Alive2: https://alive2.llvm.org/ce/z/YBRjxc

Currently LLVM cannot use the knowledge from a never-overflow assumption. I have a draft patch for the fold and it enables more optimizations in downstream users of hashbrown. But I am not willing to do an application-specific optimization in LLVM. So I file this issue to see whether we can fix it in hashbrown.

cc @nikic @dianqk

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions