Closed
Description
/// ```rust
/// assert_eq!(fixed::i124f4_wrapping_mul(3 << 4, 2 << 4), 6 << 4);
/// ```
#[inline]
pub fn i124f4_wrapping_mul(lhs: i128, rhs: i128) -> i128 {
let (ans, _) = mul_overflow(lhs, rhs, 4);
ans
}
#[inline]
fn mul_overflow(lhs: i128, rhs: i128, frac_nbits: u32) -> (i128, bool) {
let (lh, ll) = hi_lo(lhs);
let (rh, rl) = hi_lo(rhs);
let ll_rl = ll.wrapping_mul(rl);
let lh_rl = lh.wrapping_mul(rl);
let ll_rh = ll.wrapping_mul(rh);
let lh_rh = lh.wrapping_mul(rh);
let col01 = ll_rl as u128;
let (col01_hi, col01_lo) = (col01 >> 64, col01 & !(!0 << 64));
let partial_col12 = lh_rl + col01_hi as i128;
let (col12, carry_col3) = carrying_add(partial_col12, ll_rh);
let (col12_hi, col12_lo) = hi_lo(col12);
let ans01 = shift_lo_up_unsigned(col12_lo) + col01_lo;
let ans23 = lh_rh + col12_hi + shift_lo_up(carry_col3);
let ret = combine_lo_then_shl(ans23, ans01, frac_nbits);
println!(
"combine_lo_then_shl({}, {}, {}) -> ({}, {})",
ans23, ans01, frac_nbits, ret.0, ret.1
);
ret
}
#[inline]
fn hi_lo(this: i128) -> (i128, i128) {
(this >> 64, this & !(!0 << 64))
}
#[inline]
fn combine_lo_then_shl(this: i128, lo: u128, shift: u32) -> (i128, bool) {
if shift == 128 {
(this, false)
} else if shift == 0 {
let ans = lo as i128;
(ans, this != if ans < 0 { -1 } else { 0 })
} else {
let lo = (lo >> shift) as i128;
let hi = this << (128 - shift);
let ans = lo | hi;
(ans, this >> shift != if ans < 0 { -1 } else { 0 })
}
}
#[inline]
fn carrying_add(this: i128, rhs: i128) -> (i128, i128) {
let (sum, overflow) = this.overflowing_add(rhs);
let carry = if overflow {
if sum < 0 {
1
} else {
-1
}
} else {
0
};
(sum, carry)
}
#[inline]
fn shift_lo_up(this: i128) -> i128 {
debug_assert!(this >> 64 == 0);
this << 64
}
#[inline]
fn shift_lo_up_unsigned(this: i128) -> u128 {
debug_assert!(this >> 64 == 0);
(this << 64) as u128
}
The test passes for 1.46.0 i686 stable release builds, for i686 beta/nightly debug builds, and for x86_64 beta/nightly release builds, but fails for i686 beta/nightly release builds.
CI logs from this code on GitLab:
Metadata
Metadata
Assignees
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: This is a bug.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessHelping to "clean up" bugs with minimal examples and bisectionsTarget: x86 processors, 32 bit (like i686-*) (IA-32)Medium priorityRelevant to the compiler team, which will review and decide on the PR/issue.Performance or correctness regression from stable to beta.