diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 90b986f4998db..0ebd765b54900 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2354,7 +2354,7 @@ macro_rules! uint_impl { // to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic let (a, b) = self.overflowing_add(rhs); let (c, d) = a.overflowing_add(carry as $SelfT); - (c, b || d) + (c, b | d) } /// Calculates `self` + `rhs` with a signed `rhs`. diff --git a/tests/assembly/x86_64-bigint-add.rs b/tests/assembly/x86_64-bigint-add.rs new file mode 100644 index 0000000000000..4bcb9732c6405 --- /dev/null +++ b/tests/assembly/x86_64-bigint-add.rs @@ -0,0 +1,33 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O -C target-cpu=x86-64-v4 +//@ compile-flags: -C llvm-args=-x86-asm-syntax=intel + +#![no_std] +#![feature(bigint_helper_methods)] + +// This checks that the `carrying_add` implementation successfully chains, to catch +// issues like + +// This forces the ABI to avoid the windows-vs-linux ABI differences. + +// CHECK-LABEL: bigint_chain_carrying_add: +#[no_mangle] +pub unsafe extern "sysv64" fn bigint_chain_carrying_add( + dest: *mut u64, + src1: *const u64, + src2: *const u64, + n: usize, + mut carry: bool, +) -> bool { + // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + for i in 0..n { + (*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry); + } + carry +}