On X86, overflow checks should be cheap already because the carry and overflow flags will be set.
See MUL — Unsigned Multiply or IMUL — Signed Multiply for example.
Promoting to a larger integer size and then checking will not be faster.
You can confirm that Base.checked_add
’s generated code is just an add followed by jo
(jump if overflow flag is set):
# julia> @code_native debuginfo=:none syntax=:intel Base.checked_add(typemax(Int), 2)
.text
.file "checked_add"
.globl julia_checked_add_5462 # -- Begin function julia_checked_add_5462
.p2align 4, 0x90
.type julia_checked_add_5462,@function
julia_checked_add_5462: # @julia_checked_add_5462
.cfi_startproc
# %bb.0: # %top
mov rdx, rsi
mov rax, rdi
add rax, rsi
jo .LBB0_1
# %bb.2: # %L7
ret
.LBB0_1: # %L5
sub rsp, 8
.cfi_def_cfa_offset 16
mov rsi, rdi
movabs rax, offset j_throw_overflowerr_binaryop_5464
movabs rdi, 140041153683800
call rax
ud2
.Lfunc_end0:
.size julia_checked_add_5462, .Lfunc_end0-julia_checked_add_5462
.cfi_endproc
# -- End function
.section ".note.GNU-stack","",@progbits
Base.checked_add
, Base.checked_mul
, etc all already exist and are going to be about as efficient as it gets.