Skip to content

saturating_add doc is not clear enough #64940

Closed
@tesuji

Description

@tesuji
Contributor

Godbolt link: https://godbolt.org/z/9rm4jF

So I expect these two functions has the same assembly:

pub fn foo(a: i32, b: i32) -> i32 {
    a.saturating_add(b)
}

pub fn bar(a: i32, b: i32) -> i32 {
    match a.checked_add(b) {
        Some(v) => v,
        None => i32::max_value(),
    }
}

But the result is not:

example::foo:
        xor     eax, eax
        mov     ecx, edi
        add     ecx, esi
        setns   al
        add     eax, 2147483647
        add     edi, esi
        cmovno  eax, edi
        ret

example::bar:
        add     edi, esi
        mov     eax, 2147483647
        cmovno  eax, edi
        ret

Activity

tesuji

tesuji commented on Oct 1, 2019

@tesuji
Author
added
C-bugCategory: This is a bug.
I-slowIssue: Problems and improvements with respect to performance of generated code.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Oct 1, 2019
hman523

hman523 commented on Oct 1, 2019

@hman523
Contributor

Hey I tried solving this but wasn't really sure how to. I believe the implementation to the LLVM generation is right here.

"saturating_add" | "saturating_sub" => {
let is_add = name == "saturating_add";
let lhs = args[0].immediate();
let rhs = args[1].immediate();
if llvm_util::get_major_version() >= 8 {
let llvm_name = &format!("llvm.{}{}.sat.i{}",
if signed { 's' } else { 'u' },
if is_add { "add" } else { "sub" },
width);
let llfn = self.get_intrinsic(llvm_name);
self.call(llfn, &[lhs, rhs], None)
} else {
let llvm_name = &format!("llvm.{}{}.with.overflow.i{}",
if signed { 's' } else { 'u' },
if is_add { "add" } else { "sub" },
width);
let llfn = self.get_intrinsic(llvm_name);
let pair = self.call(llfn, &[lhs, rhs], None);
let val = self.extract_value(pair, 0);
let overflow = self.extract_value(pair, 1);
let llty = self.type_ix(width);
let limit = if signed {
let limit_lo = self.const_uint_big(
llty, (i128::MIN >> (128 - width)) as u128);
let limit_hi = self.const_uint_big(
llty, (i128::MAX >> (128 - width)) as u128);
let neg = self.icmp(
IntPredicate::IntSLT, val, self.const_uint(llty, 0));
self.select(neg, limit_hi, limit_lo)
} else if is_add {
self.const_uint_big(llty, u128::MAX >> (128 - width))
} else {
self.const_uint(llty, 0)
};
self.select(overflow, limit, val)
}
},

Hope someone can solve this!

tesuji

tesuji commented on Oct 1, 2019

@tesuji
ContributorAuthor

Turn out I was wrong! The saturating_add is working correctly (i.e. those two functions
are not equivalent): https://github.com/rust-lang/rust/pull/58003/files#diff-01076f91a26400b2db49663d787c2576R885-R891

I would add some doctests to show that and close this issue.

changed the title [-]`saturating_add` has overhead?[/-] [+]`saturating_add` doc is not clear enough[/+] on Oct 1, 2019
removed
C-bugCategory: This is a bug.
I-slowIssue: Problems and improvements with respect to performance of generated code.
on Oct 1, 2019
added
C-enhancementCategory: An issue proposing an enhancement or a PR with one.
A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
and removed
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Oct 1, 2019
added 2 commits that reference this issue on Oct 1, 2019

Rollup merge of rust-lang#64943 - lzutao:doc-saturating, r=shepmaster

36d5d1e

Rollup merge of rust-lang#64943 - lzutao:doc-saturating, r=shepmaster

66148f6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-enhancementCategory: An issue proposing an enhancement or a PR with one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @jonas-schievink@tesuji@hman523@rustbot

      Issue actions

        `saturating_add` doc is not clear enough · Issue #64940 · rust-lang/rust