Skip to content

Commit 5b32f57

Browse files
committed
Fix chaining carrying_adds
Something about the MIR lowering for `||` ended up breaking this, but it's fixed by changing the code to use `|` instead. I also added an assembly test to ensure it *keeps* being `adc`.
1 parent 76f3ff6 commit 5b32f57

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

library/core/src/num/uint_macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2354,7 +2354,7 @@ macro_rules! uint_impl {
23542354
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
23552355
let (a, b) = self.overflowing_add(rhs);
23562356
let (c, d) = a.overflowing_add(carry as $SelfT);
2357-
(c, b || d)
2357+
(c, b | d)
23582358
}
23592359

23602360
/// Calculates `self` + `rhs` with a signed `rhs`.

tests/assembly/x86_64-bigint-add.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//@ only-x86_64
2+
//@ assembly-output: emit-asm
3+
//@ compile-flags: --crate-type=lib -O -C target-cpu=x86-64-v4
4+
//@ compile-flags: -C llvm-args=-x86-asm-syntax=intel
5+
6+
#![no_std]
7+
#![feature(bigint_helper_methods)]
8+
9+
// This checks that the `carrying_add` implementation successfully chains, to catch
10+
// issues like <https://github.com/rust-lang/rust/issues/85532#issuecomment-2495119815>
11+
12+
// This forces the ABI to avoid the windows-vs-linux ABI differences.
13+
14+
// CHECK-LABEL: bigint_chain_carrying_add:
15+
#[no_mangle]
16+
pub unsafe extern "sysv64" fn bigint_chain_carrying_add(
17+
dest: *mut u64,
18+
src1: *const u64,
19+
src2: *const u64,
20+
n: usize,
21+
mut carry: bool,
22+
) -> bool {
23+
24+
// CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8]
25+
// CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8]
26+
// CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]]
27+
// CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16]
28+
// CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16]
29+
// CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]]
30+
for i in 0..n {
31+
(*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry);
32+
}
33+
carry
34+
}

0 commit comments

Comments
 (0)