1
0
mirror of https://github.com/Interlisp/maiko.git synced 2026-01-26 11:52:25 +00:00

Use gcc / clang overflow builtins. (#142)

* Use gcc / clang overflow builtins.

This avoids expensive checks for overflow that employ undefined
behavior.

This is a step along the way towards replacing the old hand-written
assembler that did the same thing in terms of using the CPU's
overflow detection.

* Remove unimplemented SPARC asm for multiplication, divide, and remainder.

This wasn't implemented before, and for multiplication, it is now
implemented for gcc and friends using overflow detection.

* Remove USE_INLINE_ARITH.

Now that we have the compiler built-ins for detecting overflow,
we don't need custom assembly for it for each platform.

For now, we keep, but still don't use, the code that do a hot
path through the dispatch loop for some math. This code isn't
actually running or in use, but it is separate from how the
other inline arithmetic was being performed. These are the
`fast_op_*` functions that are implemented in assembler.
This commit is contained in:
Bruce Mitchener
2021-01-21 15:27:31 +07:00
committed by GitHub
parent 36b8695bf6
commit 95b482d5d5
9 changed files with 63 additions and 407 deletions

View File

@@ -31,28 +31,26 @@ N_OP_plus2
************************************************************/
LispPTR N_OP_plus2(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_GETNUMBER(tos, arg1, doufn);
N_GETNUMBER(tosm1, arg2, doufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = plus32(arg1, arg2);
if (__builtin_sadd_overflow(arg1, arg2, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
doufn2:
plus_err_label();
ERROR_EXIT(tos);
#else
/* UB: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int' */
result = arg1 + arg2;
if (((arg1 >= 0) == (arg2 >= 0)) && ((result >= 0) != (arg1 >= 0))) { ERROR_EXIT(tos); }
N_ARITH_SWITCH(result);
#endif /* USE_INLINE_ARITH */
#endif
doufn:
return (N_OP_fplus2(tosm1, tos));
@@ -68,18 +66,18 @@ doufn:
/************************************************************************/
LispPTR N_OP_iplus2(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_IGETNUMBER(tos, arg1, doufn);
N_IGETNUMBER(tosm1, arg2, doufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = iplus32(arg1, arg2);
if (__builtin_sadd_overflow(arg1, arg2, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
dummy:
iplus_err_label();
#else
@@ -88,7 +86,7 @@ dummy:
if (((arg1 >= 0) == (arg2 >= 0)) && ((result >= 0) != (arg1 >= 0))) { ERROR_EXIT(tos); }
N_ARITH_SWITCH(result);
#endif /* USE_INLINE_ARITH */
#endif
doufn:
ERROR_EXIT(tos);
@@ -102,21 +100,19 @@ N_OP_difference
************************************************************/
LispPTR N_OP_difference(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_GETNUMBER(tosm1, arg1, doufn);
N_GETNUMBER(tos, arg2, doufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = sub32(arg1, arg2);
if (__builtin_ssub_overflow(arg1, arg2, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
doufn2:
diff_err_label();
ERROR_EXIT(tos);
#else
/* UB: signed integer overflow: -2147483647 - 320 cannot be represented in type 'int' */
@@ -131,18 +127,18 @@ doufn:
}
LispPTR N_OP_idifference(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_IGETNUMBER(tosm1, arg1, doufn);
N_IGETNUMBER(tos, arg2, doufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = isub32(arg1, arg2);
if (__builtin_ssub_overflow(arg1, arg2, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
dummy:
idiff_err_label();
#else
/* UB: signed integer overflow: -2147483647 - 100 cannot be represented in type 'int' */
@@ -220,17 +216,17 @@ N_OP_iplusn
return(tos + n)
************************************************************/
LispPTR N_OP_iplusn(int tos, int n) {
register int arg1;
register int result;
int arg1;
int result;
N_IGETNUMBER(tos, arg1, do_ufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = iplus32n(arg1, n);
if (__builtin_sadd_overflow(arg1, n, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
dummy:
iplusn_err_label();
#else
@@ -250,17 +246,17 @@ N_OP_idifferencen
return(tos - n)
************************************************************/
LispPTR N_OP_idifferencen(int tos, int n) {
register int arg1;
register int result;
int arg1;
int result;
N_IGETNUMBER(tos, arg1, do_ufn);
#ifdef USE_INLINE_ARITH
#ifdef USE_OVERFLOW_BUILTINS
result = sub32n(arg1, n);
if (__builtin_ssub_overflow(arg1, n, &result)) {
ERROR_EXIT(tos);
}
N_ARITH_SWITCH(result);
dummy:
idiffn_err_label();
#else

View File

@@ -44,18 +44,18 @@
*/
/**********************************************************************/
int N_OP_times2(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_GETNUMBER(tosm1, arg1, doufn);
N_GETNUMBER(tos, arg2, doufn);
#ifdef SUN3_OS3_OR_OS4_IL
#ifdef USE_OVERFLOW_BUILTINS
result = mpy32(arg1, arg2);
if (__builtin_smul_overflow(arg1, arg2, &result)) {
goto doufn2;
}
N_ARITH_SWITCH(result);
dummy:
mpy_err_label();
#else
@@ -73,18 +73,18 @@ doufn:
} /* end N_OP_times2 */
int N_OP_itimes2(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_IGETNUMBER(tosm1, arg1, doufn);
N_IGETNUMBER(tos, arg2, doufn);
#ifdef SUN3_OS3_OR_OS4_IL
#ifdef USE_OVERFLOW_BUILTINS
result = impy32(arg1, arg2);
if (__builtin_smul_overflow(arg1, arg2, &result)) {
goto doufn;
}
N_ARITH_SWITCH(result);
dummy:
impy_err_label();
#else
@@ -108,25 +108,16 @@ doufn:
*/
/**********************************************************************/
int N_OP_quot(int tosm1, int tos) {
register int arg1, arg2;
register int result;
int arg1, arg2;
int result;
N_GETNUMBER(tosm1, arg1, doufn);
N_GETNUMBER(tos, arg2, doufn);
if (arg2 == 0) goto doufn2;
#ifdef SUN3_OS3_OR_OS4_IL
result = quot32(arg1, arg2);
N_ARITH_SWITCH(result);
dummy:
quot_err_label();
#else
result = arg1 / arg2; /* lmm: note: no error case!! */
N_ARITH_SWITCH(result);
#endif
doufn2:
ERROR_EXIT(tos);
doufn:
@@ -142,20 +133,9 @@ int N_OP_iquot(int tosm1, int tos) {
N_IGETNUMBER(tos, arg2, doufn);
if (arg2 == 0) goto doufn;
#ifdef SUN3_OS3_OR_OS4_IL
result = iquot32(arg1, arg2);
N_ARITH_SWITCH(result);
dummy:
iquot_err_label();
#else
result = arg1 / arg2;
N_ARITH_SWITCH(result);
#endif
doufn:
ERROR_EXIT(tos);
@@ -177,20 +157,9 @@ int N_OP_iremainder(int tosm1, int tos) {
N_IGETNUMBER(tos, arg2, doufn);
if (arg2 == 0) goto doufn;
#ifdef SUN3_OS3_OR_OS4_IL
result = irem32(arg1, arg2);
N_ARITH_SWITCH(result);
dummy:
irem_err_label();
#else
result = arg1 % arg2;
N_ARITH_SWITCH(result);
#endif
doufn:
ERROR_EXIT(tos);

View File

@@ -142,54 +142,6 @@
jmp *optable(,%eax,4)
.end
/////////////////////////////
//
// Arithmetic code speedups
//
// Assume edi & esi are arguments
//
// ebx is result.
//
////////////////////////////////
.inline Xiplus32,0
addl %edi,%esi
jo iplus_err
movl %esi,%eax
.end
.inline Xiplus32n,0
leal (%edi),%eax
addl %esi,%eax
jo iplusn_err
.end
.inline Xplus32,0
leal (%edi),%eax
addl %esi,%eax
jo plus_err
.end
.inline Xsub32,0
leal (%edi),%eax
subl %esi,%eax
jo diff_err
.end
.inline Xisub32,0
leal (%edi),%eax
subl %esi,%eax
jo idiff_err
.end
.inline Xisub32n,0
leal (%edi),%eax
subl %esi,%eax
jo idiffn_err
.end
.inline plus_err_label,0
plus_err:
.end

View File

@@ -131,80 +131,6 @@ done: ! else done;
nop
.end
/*
***************************************************************
Arithmetic Opcode Helpers
***************************************************************
*/
.inline _sub32,8
subcc %o0,%o1,%o0 ! result = arg0 - arg1
bvs diff_err
nop
.end
.inline _isub32,8
subcc %o0,%o1,%o0 ! result = arg0 - arg1
bvs idiff_err
nop
.end
.inline _sub32n,8
subcc %o0,%o1,%o0 ! result = arg0 - arg1
bvs diff_err2
nop
.end
.inline _mpy32,8
ba mpy_err
nop
.end
.inline _impy32,8
ba impy_err
nop
.end
.inline _quot32,8
ba quot_err
nop
.end
.inline _iquot32,8
ba iquot_err
nop
.end
.inline _rem32,8
ba rem_err
nop
.end
.inline _irem32,8
ba irem_err
nop
.end
.inline _plus32,8
addcc %o0,%o1,%o0 ! result = arg0 + arg1
bvs plus_err
nop
.end
.inline _iplus32,8
addcc %o0,%o1,%o0 ! result = arg0 + arg1
bvs iplus_err
nop
.end
.inline _iplus32n,8
addcc %o0,%o1,%o0 ! result = arg0 + arg1
bvs iplusn_err
nop
.end
/*
***************************************************************
Inline Assembly help for dispatcher.