Override carrying_mul_add
in cg_llvm
This commit is contained in:
parent
2c0c9123fc
commit
4669c0d756
5 changed files with 181 additions and 2 deletions
|
@ -340,6 +340,37 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
self.const_i32(cache_type),
|
||||
])
|
||||
}
|
||||
sym::carrying_mul_add => {
|
||||
let (size, signed) = fn_args.type_at(0).int_size_and_signed(self.tcx);
|
||||
|
||||
let wide_llty = self.type_ix(size.bits() * 2);
|
||||
let args = args.as_array().unwrap();
|
||||
let [a, b, c, d] = args.map(|a| self.intcast(a.immediate(), wide_llty, signed));
|
||||
|
||||
let wide = if signed {
|
||||
let prod = self.unchecked_smul(a, b);
|
||||
let acc = self.unchecked_sadd(prod, c);
|
||||
self.unchecked_sadd(acc, d)
|
||||
} else {
|
||||
let prod = self.unchecked_umul(a, b);
|
||||
let acc = self.unchecked_uadd(prod, c);
|
||||
self.unchecked_uadd(acc, d)
|
||||
};
|
||||
|
||||
let narrow_llty = self.type_ix(size.bits());
|
||||
let low = self.trunc(wide, narrow_llty);
|
||||
let bits_const = self.const_uint(wide_llty, size.bits());
|
||||
// No need for ashr when signed; LLVM changes it to lshr anyway.
|
||||
let high = self.lshr(wide, bits_const);
|
||||
// FIXME: could be `trunc nuw`, even for signed.
|
||||
let high = self.trunc(high, narrow_llty);
|
||||
|
||||
let pair_llty = self.type_struct(&[narrow_llty, narrow_llty], false);
|
||||
let pair = self.const_poison(pair_llty);
|
||||
let pair = self.insert_value(pair, low, 0);
|
||||
let pair = self.insert_value(pair, high, 1);
|
||||
pair
|
||||
}
|
||||
sym::ctlz
|
||||
| sym::ctlz_nonzero
|
||||
| sym::cttz
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(slice_as_array)]
|
||||
#![feature(try_blocks)]
|
||||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue