From 21a5769afefb47553391ae1ef801f64a58253c33 Mon Sep 17 00:00:00 2001 From: travisstaloch Date: Wed, 1 Sep 2021 11:17:45 -0700 Subject: saturating arithmetic builtins: add, sub, mul, shl (#9619) - adds 1 simple behavior tests for each which does integer and vector ops at runtime and comptime - adds bigint_*_sat() methods for each - use CreateIntrinsic() which accepts a variable number of arguments to pass the scale parameter * update langref - added case to test/compile_errors.zig given floats - explain upstream bug in llvm.smul.fix.sat and link to #9643 in langref and commented out test cases * sat-arithmetic: skip mul tests if arch == .wasm32 because ci is erroring with 'LLVM ERROR: Unable to expand fixed point multiplication' when compiling for wasm32 --- src/stage1/codegen.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'src/stage1/codegen.cpp') diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index c44081c770..614ed8e26c 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -3335,6 +3335,46 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, } else { zig_unreachable(); } + case IrBinOpSatAdd: + if (scalar_type->id == ZigTypeIdInt) { + if (scalar_type->data.integral.is_signed) { + return ZigLLVMBuildSAddSat(g->builder, op1_value, op2_value, ""); + } else { + return ZigLLVMBuildUAddSat(g->builder, op1_value, op2_value, ""); + } + } else { + zig_unreachable(); + } + case IrBinOpSatSub: + if (scalar_type->id == ZigTypeIdInt) { + if (scalar_type->data.integral.is_signed) { + return ZigLLVMBuildSSubSat(g->builder, op1_value, op2_value, ""); + } else { + return ZigLLVMBuildUSubSat(g->builder, op1_value, op2_value, ""); + } + } else { + zig_unreachable(); + } + case IrBinOpSatMul: + if (scalar_type->id == ZigTypeIdInt) { + if (scalar_type->data.integral.is_signed) { + return ZigLLVMBuildSMulFixSat(g->builder, op1_value, op2_value, ""); + } else { + return ZigLLVMBuildUMulFixSat(g->builder, op1_value, op2_value, ""); + } + } else { + zig_unreachable(); + } + case IrBinOpSatShl: + if (scalar_type->id == ZigTypeIdInt) { + if (scalar_type->data.integral.is_signed) { + return ZigLLVMBuildSShlSat(g->builder, op1_value, op2_value, ""); + } else { + return ZigLLVMBuildUShlSat(g->builder, op1_value, op2_value, ""); + } + } else { + zig_unreachable(); + } } zig_unreachable(); } @@ -9096,6 +9136,10 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdReduce, "reduce", 2); create_builtin_fn(g, BuiltinFnIdMaximum, "maximum", 2); create_builtin_fn(g, BuiltinFnIdMinimum, "minimum", 2); + create_builtin_fn(g, BuiltinFnIdSatAdd, "addWithSaturation", 2); + create_builtin_fn(g, BuiltinFnIdSatSub, "subWithSaturation", 2); + create_builtin_fn(g, BuiltinFnIdSatMul, "mulWithSaturation", 2); + create_builtin_fn(g, BuiltinFnIdSatShl, "shlWithSaturation", 2); } static const char *bool_to_str(bool b) { -- cgit v1.2.3