Skip to content

Commit

Permalink
Add Word{S,U}<N>_{add,mul,neg,sub}AndCheck fns to Word-ops.h
Browse files Browse the repository at this point in the history
It appears that GCC (and, to a lesser extent) Clang/LLVM do not always
successfully fuse adjacent `Word<N>_<op>` and
`Word{S,U}<N>_<op>CheckP` primitives.  The performance results
reported at MLton#273 and
MLton#292 suggest that this does not
always have significant impact, but a close look at the `md5`
benchmark shows that the native codegen significantly outperforms the
C codegen with gcc-9 due to redundant arithmetic computations (one for
`Word{S,U}<N>_<op>CheckP` and another for `Word<N>_<op>`).

These functions compute both the arithmetic result and a boolean
indicating overflow (using `__builtin_<op>_overflow`).  They will be
used for explicit fusing of adjacent `Word<N>_<op>` and
`Word{S,U}<N>_<op>CheckP` primitives in the C codegen for
`-codegen-fuse-op-and-check true`.
  • Loading branch information
MatthewFluet committed Aug 8, 2019
1 parent 6b738b8 commit 3d1e89c
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions runtime/basis/Word/Word-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ binaryOvflOp (U##size, name)
binaryOvflChk (S##size, name) \
binaryOvflChk (U##size, name)

#define binaryOvflOpAndChk(kind, name) \
PRIVATE INLINE \
void Word##kind##_##name##AndCheck (Word##kind w1, Word##kind w2, Word##kind *rw, Bool *rb) { \
*rb = __builtin_##name##_overflow(w1, w2, rw); \
}

#define bothBinaryOvflOpAndChk(size, name) \
binaryOvflOpAndChk (S##size, name) \
binaryOvflOpAndChk (U##size, name)

#define compare(kind, name, op) \
PRIVATE INLINE \
Bool Word##kind##_##name (Word##kind w1, Word##kind w2) { \
Expand All @@ -60,6 +70,12 @@ compare (U##size, name, op)
return __builtin_sub_overflow(0, w, &res); \
}

#define negOvflOpAndChk(kind) \
PRIVATE INLINE \
void Word##kind##_negAndCheck (Word##kind w, Word##kind *rw, Bool *rb) { \
*rb = __builtin_sub_overflow(0, w, rw); \
}

#define rol(size) \
PRIVATE INLINE \
Word##size Word##size##_rol (Word##size w1, Word32 w2) { \
Expand All @@ -78,7 +94,7 @@ compare (U##size, name, op)
return (Word##kind)(w1 op w2); \
}

#define unary(kind, name, op) \
#define unary(kind, name, op) \
PRIVATE INLINE \
Word##kind Word##kind##_##name (Word##kind w) { \
return (Word##kind)(op w); \
Expand All @@ -105,6 +121,7 @@ compare (U##size, name, op)
#define all(size) \
binaryOvflOp (size, add) \
bothBinaryOvflChk (size, add) \
bothBinaryOvflOpAndChk (size, add) \
binary (size, andb, &) \
compare (size, equal, ==) \
bothCompare (size, ge, >=) \
Expand All @@ -114,9 +131,12 @@ shift (size, lshift, <<) \
bothCompare (size, lt, <) \
bothBinaryOvflOp (size, mul) \
bothBinaryOvflChk (size, mul) \
bothBinaryOvflOpAndChk (size, mul) \
negOvflOp (size) \
negOvflChk (S##size) \
negOvflChk (U##size) \
negOvflOpAndChk (S##size) \
negOvflOpAndChk (U##size) \
unary (size, notb, ~) \
bothBinary (size, quot, /) \
bothBinary (size, rem, %) \
Expand All @@ -134,6 +154,7 @@ shift (S##size, rshift, >>) \
shift (U##size, rshift, >>) \
binaryOvflOp (size, sub) \
bothBinaryOvflChk (size, sub) \
bothBinaryOvflOpAndChk (size, sub) \
binary (size, xorb, ^)

all (8)
Expand All @@ -149,12 +170,13 @@ misaligned(64)
#undef shift
#undef ror
#undef rol
#undef negOvfl
#undef negOvflOpAndChk
#undef negOvflChk
#undef negOvflOp
#undef bothCompare
#undef compare
#undef bothBinaryOvfl
#undef bothBinaryOvflOpAndChk
#undef binaryOvflOpAndChk
#undef bothBinaryOvflChk
#undef binaryOvflChk
#undef bothBinaryOvflOp
Expand Down

0 comments on commit 3d1e89c

Please sign in to comment.