llvm/llvm-project

Take advantage of `assume`s on `x * x` (with `nuw`)

Open

#122.412 geöffnet am 10. Jan. 2025

Auf GitHub ansehen
 (9 Kommentare) (0 Reaktionen) (1 zugewiesene Person)C++ (10.782 Forks)batch import
good first issuellvm:optimizationsmissed-optimization

Repository-Metriken

Stars
 (26.378 Stars)
PR-Merge-Metriken
 (Durchschn. Merge 1T 2h) (1.000 gemergte PRs in 30 T)

Beschreibung

Rust stabilized its isqrt method today, so I was looking at its codegen.

The output for

let root = u16::isqrt(num);

currently has a manual

assume(root <= 255)

I was thinking that it'd be nice to give LLVM a bit more specific information, like

assume(root * root <= num)

since that's (a partial) definition of what isqrt does, and strictly more specific.

Sadly, that assume today doesn't seem to be worth bothering adding, since opt seems like it doesn't take advantage of it even in a "simple" situation that doesn't need to know anything about num: https://llvm.godbolt.org/z/zoq4T5fKr

But Alive2 confirms that it would be allowed to https://alive2.llvm.org/ce/z/ko8HYR

define i1 @src(i16 noundef %num, i16 noundef %s) noundef zeroext {
start:
  %_4 = mul nuw i16 noundef %s, noundef %s
  %cond = icmp ule i16 %_4, noundef %num
  assume i1 %cond
  %_0 = icmp ult i16 noundef %s, 256
  ret i1 %_0
}
=>
define i1 @tgt(i16 noundef %num, i16 noundef %s) noundef zeroext {
start:
  ret i1 1
}
Transformation seems to be correct!

Original Rust code I used to get the LLVM IR: https://rust.godbolt.org/z/vM8qj4xjf

pub unsafe fn isqrt_facts(num: u16, s: u16) -> bool {
    std::hint::assert_unchecked(u16::unchecked_mul(s, s) <= num);
    s <= 255
}

cc https://github.com/rust-lang/rust/issues/116226

Contributor Guide