Skip to content

Commit 432285f

Browse files
authored
Implement llvm.x86.addcarry.64 and llvm.x86.subborrow.64 (#1178)
1 parent 75eff64 commit 432285f

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

src/intrinsics/llvm.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,26 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
106106
let dest = CPlace::for_ptr(Pointer::new(mem_addr), a.layout());
107107
dest.write_cvalue(fx, a);
108108
};
109+
"llvm.x86.addcarry.64", (v c_in, c a, c b) {
110+
llvm_add_sub(
111+
fx,
112+
BinOp::Add,
113+
ret,
114+
c_in,
115+
a,
116+
b
117+
);
118+
};
119+
"llvm.x86.subborrow.64", (v b_in, c a, c b) {
120+
llvm_add_sub(
121+
fx,
122+
BinOp::Sub,
123+
ret,
124+
b_in,
125+
a,
126+
b
127+
);
128+
};
109129
}
110130

111131
if let Some((_, dest)) = destination {
@@ -121,3 +141,43 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
121141
// llvm.x86.avx2.pshuf.b
122142
// llvm.x86.avx2.psrli.w
123143
// llvm.x86.sse2.psrli.w
144+
145+
fn llvm_add_sub<'tcx>(
146+
fx: &mut FunctionCx<'_, '_, 'tcx>,
147+
bin_op: BinOp,
148+
ret: CPlace<'tcx>,
149+
cb_in: Value,
150+
a: CValue<'tcx>,
151+
b: CValue<'tcx>
152+
) {
153+
assert_eq!(a.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 second operand must be u64");
154+
assert_eq!(b.layout().ty, fx.tcx.types.u64, "llvm.x86.addcarry.64/llvm.x86.subborrow.64 third operand must be u64");
155+
156+
// c + carry -> c + first intermediate carry or borrow respectively
157+
let int0 = crate::num::codegen_checked_int_binop(
158+
fx,
159+
bin_op,
160+
a,
161+
b,
162+
);
163+
let c = int0.value_field(fx, mir::Field::new(0));
164+
let cb0 = int0.value_field(fx, mir::Field::new(1)).load_scalar(fx);
165+
166+
// c + carry -> c + second intermediate carry or borrow respectively
167+
let cb_in_as_u64 = fx.bcx.ins().uextend(types::I64, cb_in);
168+
let cb_in_as_u64 = CValue::by_val(cb_in_as_u64, fx.layout_of(fx.tcx.types.u64));
169+
let int1 = crate::num::codegen_checked_int_binop(
170+
fx,
171+
bin_op,
172+
c,
173+
cb_in_as_u64,
174+
);
175+
let (c, cb1) = int1.load_scalar_pair(fx);
176+
177+
// carry0 | carry1 -> carry or borrow respectively
178+
let cb_out = fx.bcx.ins().bor(cb0, cb1);
179+
180+
let layout = fx.layout_of(fx.tcx.mk_tup([fx.tcx.types.u8, fx.tcx.types.u64].iter()));
181+
let val = CValue::by_val_pair(cb_out, c, layout);
182+
ret.write_cvalue(fx, val);
183+
}

0 commit comments

Comments
 (0)