mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Merge pull request #2337 from rtfeldman/i/2331
Use unsigned LLVM intrinsic arithmetic for unsigned integers
This commit is contained in:
commit
f83f50a9a7
14 changed files with 302 additions and 216 deletions
|
@ -493,6 +493,12 @@ fn add_int_intrinsic<'ctx, F>(
|
|||
};
|
||||
}
|
||||
|
||||
check!(IntWidth::U8, ctx.i8_type());
|
||||
check!(IntWidth::U16, ctx.i16_type());
|
||||
check!(IntWidth::U32, ctx.i32_type());
|
||||
check!(IntWidth::U64, ctx.i64_type());
|
||||
check!(IntWidth::U128, ctx.i128_type());
|
||||
|
||||
check!(IntWidth::I8, ctx.i8_type());
|
||||
check!(IntWidth::I16, ctx.i16_type());
|
||||
check!(IntWidth::I32, ctx.i32_type());
|
||||
|
@ -562,23 +568,31 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) {
|
|||
});
|
||||
add_float_intrinsic(ctx, module, &LLVM_FLOOR, |t| t.fn_type(&[t.into()], false));
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_SADD_WITH_OVERFLOW, |t| {
|
||||
add_int_intrinsic(ctx, module, &LLVM_ADD_WITH_OVERFLOW, |t| {
|
||||
let fields = [t.into(), i1_type.into()];
|
||||
ctx.struct_type(&fields, false)
|
||||
.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_SSUB_WITH_OVERFLOW, |t| {
|
||||
add_int_intrinsic(ctx, module, &LLVM_SUB_WITH_OVERFLOW, |t| {
|
||||
let fields = [t.into(), i1_type.into()];
|
||||
ctx.struct_type(&fields, false)
|
||||
.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_SMUL_WITH_OVERFLOW, |t| {
|
||||
add_int_intrinsic(ctx, module, &LLVM_MUL_WITH_OVERFLOW, |t| {
|
||||
let fields = [t.into(), i1_type.into()];
|
||||
ctx.struct_type(&fields, false)
|
||||
.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_ADD_SATURATED, |t| {
|
||||
t.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
|
||||
add_int_intrinsic(ctx, module, &LLVM_SUB_SATURATED, |t| {
|
||||
t.fn_type(&[t.into(), t.into()], false)
|
||||
});
|
||||
}
|
||||
|
||||
const LLVM_POW: IntrinsicName = float_intrinsic!("llvm.pow");
|
||||
|
@ -602,9 +616,15 @@ static LLVM_STACK_SAVE: &str = "llvm.stacksave";
|
|||
static LLVM_SETJMP: &str = "llvm.eh.sjlj.setjmp";
|
||||
pub static LLVM_LONGJMP: &str = "llvm.eh.sjlj.longjmp";
|
||||
|
||||
const LLVM_SADD_WITH_OVERFLOW: IntrinsicName = int_intrinsic!("llvm.sadd.with.overflow");
|
||||
const LLVM_SSUB_WITH_OVERFLOW: IntrinsicName = int_intrinsic!("llvm.ssub.with.overflow");
|
||||
const LLVM_SMUL_WITH_OVERFLOW: IntrinsicName = int_intrinsic!("llvm.smul.with.overflow");
|
||||
const LLVM_ADD_WITH_OVERFLOW: IntrinsicName =
|
||||
int_intrinsic!("llvm.sadd.with.overflow", "llvm.uadd.with.overflow");
|
||||
const LLVM_SUB_WITH_OVERFLOW: IntrinsicName =
|
||||
int_intrinsic!("llvm.ssub.with.overflow", "llvm.usub.with.overflow");
|
||||
const LLVM_MUL_WITH_OVERFLOW: IntrinsicName =
|
||||
int_intrinsic!("llvm.smul.with.overflow", "llvm.umul.with.overflow");
|
||||
|
||||
const LLVM_ADD_SATURATED: IntrinsicName = int_intrinsic!("llvm.sadd.sat", "llvm.uadd.sat");
|
||||
const LLVM_SUB_SATURATED: IntrinsicName = int_intrinsic!("llvm.ssub.sat", "llvm.usub.sat");
|
||||
|
||||
fn add_intrinsic<'ctx>(
|
||||
module: &Module<'ctx>,
|
||||
|
@ -5806,8 +5826,9 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte | NumRemUnchecked
|
||||
| NumIsMultipleOf | NumAddWrap | NumAddChecked | NumDivUnchecked | NumDivCeilUnchecked
|
||||
| NumPow | NumPowInt | NumSubWrap | NumSubChecked | NumMulWrap | NumMulChecked => {
|
||||
| NumIsMultipleOf | NumAddWrap | NumAddChecked | NumAddSaturated | NumDivUnchecked
|
||||
| NumDivCeilUnchecked | NumPow | NumPowInt | NumSubWrap | NumSubChecked
|
||||
| NumSubSaturated | NumMulWrap | NumMulChecked => {
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
@ -6392,7 +6413,7 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
NumAdd => {
|
||||
let result = env
|
||||
.call_intrinsic(
|
||||
&LLVM_SADD_WITH_OVERFLOW[int_width],
|
||||
&LLVM_ADD_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
)
|
||||
.into_struct_value();
|
||||
|
@ -6401,13 +6422,16 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
}
|
||||
NumAddWrap => bd.build_int_add(lhs, rhs, "add_int_wrap").into(),
|
||||
NumAddChecked => env.call_intrinsic(
|
||||
&LLVM_SADD_WITH_OVERFLOW[int_width],
|
||||
&LLVM_ADD_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
),
|
||||
NumAddSaturated => {
|
||||
env.call_intrinsic(&LLVM_ADD_SATURATED[int_width], &[lhs.into(), rhs.into()])
|
||||
}
|
||||
NumSub => {
|
||||
let result = env
|
||||
.call_intrinsic(
|
||||
&LLVM_SSUB_WITH_OVERFLOW[int_width],
|
||||
&LLVM_SUB_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
)
|
||||
.into_struct_value();
|
||||
|
@ -6416,13 +6440,16 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
}
|
||||
NumSubWrap => bd.build_int_sub(lhs, rhs, "sub_int").into(),
|
||||
NumSubChecked => env.call_intrinsic(
|
||||
&LLVM_SSUB_WITH_OVERFLOW[int_width],
|
||||
&LLVM_SUB_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
),
|
||||
NumSubSaturated => {
|
||||
env.call_intrinsic(&LLVM_SUB_SATURATED[int_width], &[lhs.into(), rhs.into()])
|
||||
}
|
||||
NumMul => {
|
||||
let result = env
|
||||
.call_intrinsic(
|
||||
&LLVM_SMUL_WITH_OVERFLOW[int_width],
|
||||
&LLVM_MUL_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
)
|
||||
.into_struct_value();
|
||||
|
@ -6431,7 +6458,7 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
}
|
||||
NumMulWrap => bd.build_int_mul(lhs, rhs, "mul_int").into(),
|
||||
NumMulChecked => env.call_intrinsic(
|
||||
&LLVM_SMUL_WITH_OVERFLOW[int_width],
|
||||
&LLVM_MUL_WITH_OVERFLOW[int_width],
|
||||
&[lhs.into(), rhs.into()],
|
||||
),
|
||||
NumGt => bd.build_int_compare(SGT, lhs, rhs, "int_gt").into(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue