Skip to content

Commit

Permalink
Implement llvm.x86.addcarry.64 and llvm.x86.subborrow.64 (#1178)
Browse files Browse the repository at this point in the history
  • Loading branch information
shamatar committed Jun 15, 2021
1 parent 75eff64 commit 432285f
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/intrinsics/llvm.rs
Expand Up @@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
dest.write_cvalue(fx, a);
};
"llvm.x86.addcarry.64", (v c_in, c a, c b) {
llvm_add_sub(
fx,
BinOp::Add,
ret,
c_in,
a,
b
);
};
"llvm.x86.subborrow.64", (v b_in, c a, c b) {
llvm_add_sub(
fx,
BinOp::Sub,
ret,
b_in,
a,
b
);
};
}

if let Some((_, dest)) = destination {
Expand All @@ -121,3 +141,43 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
// llvm.x86.avx2.pshuf.b
// llvm.x86.avx2.psrli.w
// llvm.x86.sse2.psrli.w

fn llvm_add_sub<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
bin_op: BinOp,
ret: CPlace<'tcx>,
cb_in: Value,
a: CValue<'tcx>,
b: CValue<'tcx>
) {
assert_eq!(a.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64");
assert_eq!(b.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64");

// c + carry -> c + first intermediate carry or borrow respectively
let int0 = crate::num::codegen_checked_int_binop(
fx,
bin_op,
a,
b,
);
let c = int0.value_field(fx, mir::Field::new(0));
let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);

// c + carry -> c + second intermediate carry or borrow respectively
let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
let int1 = crate::num::codegen_checked_int_binop(
fx,
bin_op,
c,
cb_in_as_u64,
);
let (c, cb1) = int1.load_scalar_pair(fx);

// carry0 | carry1 -> carry or borrow respectively
let cb_out = fx.bcx.ins().bor(cb0, cb1);

let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
let val = CValue::by_val_pair(cb_out, c, layout);
ret.write_cvalue(fx, val);
}

0 comments on commit 432285f

Please sign in to comment.