Skip to content

assumeing the result isn't setting the nsw flag on add #126406

Open
@scottmcm

Description

@scottmcm

Original Rust example: https://rust.godbolt.org/z/xze3vEx8E

pub unsafe fn extend_packed_unchecked(a: Layout, b: Layout) -> usize {
    a.extend_packed(b).unwrap_unchecked().size()
}

Actual output (-) and what I'd hope to get instead (+):

 define noundef i64 @extend_packed_unchecked(i64 noundef range(i64 1, -9223372036854775807) %0, i64 noundef %1, i64 noundef range(i64 1, -9223372036854775807) %b.0, i64 noundef %b.1) unnamed_addr {
 start:
-  %new_size = add nuw i64 %b.1, %1
+  %new_size = add nuw nsw i64 %b.1, %1
   %_11 = sub nuw i64 -9223372036854775808, %0
   %_10 = icmp ule i64 %new_size, %_11
   tail call void @llvm.assume(i1 %_10)
   ret i64 %new_size
 }

Note that %_11 sgt -1, thanks to the range attribute on the %0 parameter.

Alive proof that this is allowed: https://alive2.llvm.org/ce/z/Dn2P8R
Repro that more opt on trunk doesn't do it: https://llvm.godbolt.org/z/Kr8n37s41


Oh, turns out the simpler case of just

define noundef i64 @demo_b(i64 noundef %1, i64 noundef %b.1) unnamed_addr {
start:
  %new_size = add nuw i64 %b.1, %1
  %_10 = icmp ule i64 %new_size, 9223372036854775807
  tail call void @llvm.assume(i1 %_10)
  ret i64 %new_size
}

doesn't add the nsw either.

And that'd be allowed too: https://alive2.llvm.org/ce/z/PeC7No


Context: I've been looking at layout and pondering whether we need separate unchecked methods, or can just trust LLVM to optimize to the same things anyway when unwrap_unchecked is used.

PRs like rust-lang/rust#136575 have me thinking about nuw/nsw.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions