[Git][ghc/ghc][master] rts: use __builtin_mul_overflow for hs_mulIntMayOflo
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC Commits: 5729418c by Cheng Shao at 2025-12-18T13:22:29-05:00 rts: use __builtin_mul_overflow for hs_mulIntMayOflo This patch uses `__builtin_mul_overflow` to implement `hs_mulIntMayOflo`. This is a GNU C checked arithmetic builtin function supported by gcc/clang, is type-generic so works for both 32-bit/64-bit, and makes the code both more efficient and easier to read/maintain than the previous hand rolled logic. - - - - - 3 changed files: - compiler/GHC/CmmToC.hs - rts/include/Stg.h - rts/prim/mulIntMayOflo.c Changes: ===================================== compiler/GHC/CmmToC.hs ===================================== @@ -426,7 +426,7 @@ pprMachOpApp :: Platform -> MachOp -> [CmmExpr] -> SDoc pprMachOpApp platform op args | isMulMayOfloOp op - = text "mulIntMayOflo" <> parens (commafy (map (pprExpr platform) args)) + = text "hs_mulIntMayOflo" <> parens (commafy (map (pprExpr platform) args)) where isMulMayOfloOp (MO_S_MulMayOflo _) = True isMulMayOfloOp _ = False ===================================== rts/include/Stg.h ===================================== @@ -519,79 +519,3 @@ INLINE_HEADER StgInt64 PK_Int64(W_ p_src[]) } #endif /* SIZEOF_HSWORD == 4 */ - -/* ----------------------------------------------------------------------------- - Integer multiply with overflow - -------------------------------------------------------------------------- */ - -/* Multiply with overflow checking. - * - * This is tricky - the usual sign rules for add/subtract don't apply. - * - * On 32-bit machines we use gcc's 'long long' types, finding - * overflow with some careful bit-twiddling. - * - * On 64-bit machines where gcc's 'long long' type is also 64-bits, - * we use a crude approximation, testing whether either operand is - * larger than 32-bits; if neither is, then we go ahead with the - * multiplication. - * - * Return non-zero if there is any possibility that the signed multiply - * of a and b might overflow. Return zero only if you are absolutely sure - * that it won't overflow. If in doubt, return non-zero. - */ - -#if SIZEOF_VOID_P == 4 - -#if defined(WORDS_BIGENDIAN) -#define RTS_CARRY_IDX__ 0 -#define RTS_REM_IDX__ 1 -#else -#define RTS_CARRY_IDX__ 1 -#define RTS_REM_IDX__ 0 -#endif - -typedef union { - StgInt64 l; - StgInt32 i[2]; -} long_long_u ; - -#define mulIntMayOflo(a,b) \ -({ \ - StgInt32 r, c; \ - long_long_u z; \ - z.l = (StgInt64)a * (StgInt64)b; \ - r = z.i[RTS_REM_IDX__]; \ - c = z.i[RTS_CARRY_IDX__]; \ - if (c == 0 || c == -1) { \ - c = ((StgWord)((a^b) ^ r)) \ - >> (BITS_IN (I_) - 1); \ - } \ - c; \ -}) - -/* Careful: the carry calculation above is extremely delicate. Make sure - * you test it thoroughly after changing it. - */ - -#else - -/* Approximate version when we don't have long arithmetic (on 64-bit archs) */ - -/* If we have n-bit words then we have n-1 bits after accounting for the - * sign bit, so we can fit the result of multiplying 2 (n-1)/2-bit numbers */ -#define HALF_POS_INT (((I_)1) << ((BITS_IN (I_) - 1) / 2)) -#define HALF_NEG_INT (-HALF_POS_INT) - -#define mulIntMayOflo(a,b) \ -({ \ - I_ c; \ - if ((I_)a <= HALF_NEG_INT || a >= HALF_POS_INT \ - || (I_)b <= HALF_NEG_INT || b >= HALF_POS_INT) {\ - c = 1; \ - } else { \ - c = 0; \ - } \ - c; \ -}) -#endif ===================================== rts/prim/mulIntMayOflo.c ===================================== @@ -1,3 +1,6 @@ #include "Rts.h" -W_ hs_mulIntMayOflo(W_ a, W_ b) { return mulIntMayOflo(a, b); } +W_ hs_mulIntMayOflo(W_ a, W_ b) { + I_ r; + return (W_)__builtin_mul_overflow((I_)a, (I_)b, &r); +} View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5729418c5b017cff5e722ec42c91e73c... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5729418c5b017cff5e722ec42c91e73c... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)