From f07d474398e49647ff8aebfec494b447d8fc623a Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Tue, 1 Sep 2026 08:42:53 +0900 Subject: [PATCH v3] Use pg_neg_s{16,32,64}_overflow() for some overflow checks Extracted from a larger patch by the same author; these ones have proved to reduce the number of instructions generated overall for clang, gcc, with and without the builtin versions. --- src/backend/utils/adt/cash.c | 9 +++++---- src/backend/utils/adt/int.c | 11 +++++------ src/backend/utils/adt/int8.c | 12 ++++-------- src/backend/utils/adt/numeric.c | 3 +-- 4 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index 310b3bb3fca6..0820187b8e6a 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -156,6 +156,8 @@ cash_mul_int64(Cash c, int64 i) static inline Cash cash_div_int64(Cash c, int64 i) { + Cash res; + if (unlikely(i == 0)) ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO), @@ -169,11 +171,11 @@ cash_div_int64(Cash c, int64 i) */ if (i == -1) { - if (unlikely(c == PG_INT64_MIN)) + if (pg_neg_s64_overflow(c, &res)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("money out of range"))); - return -c; + return res; } /* No overflow is possible */ @@ -379,12 +381,11 @@ cash_in(PG_FUNCTION_ARGS) */ if (sgn > 0) { - if (value == PG_INT64_MIN) + if (pg_neg_s64_overflow(value, &result)) ereturn(escontext, (Datum) 0, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("value \"%s\" is out of range for type %s", str, "money"))); - result = -value; } else result = value; diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index 01608d8ca424..68fecbfe2ed3 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -800,12 +800,13 @@ Datum int4um(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); + int32 result; - if (unlikely(arg == PG_INT32_MIN)) + if (pg_neg_s32_overflow(arg, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); - PG_RETURN_INT32(-arg); + PG_RETURN_INT32(result); } Datum @@ -882,11 +883,10 @@ int4div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { - if (unlikely(arg1 == PG_INT32_MIN)) + if (pg_neg_s32_overflow(arg1, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); - result = -arg1; PG_RETURN_INT32(result); } @@ -1140,11 +1140,10 @@ int42div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { - if (unlikely(arg1 == PG_INT32_MIN)) + if (pg_neg_s32_overflow(arg1, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("integer out of range"))); - result = -arg1; PG_RETURN_INT32(result); } diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 1f59d831600f..1a8bddd6bb11 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -449,11 +449,10 @@ int8um(PG_FUNCTION_ARGS) int64 arg = PG_GETARG_INT64(0); int64 result; - if (unlikely(arg == PG_INT64_MIN)) + if (pg_neg_s64_overflow(arg, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); - result = -arg; PG_RETURN_INT64(result); } @@ -531,11 +530,10 @@ int8div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { - if (unlikely(arg1 == PG_INT64_MIN)) + if (pg_neg_s64_overflow(arg1, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); - result = -arg1; PG_RETURN_INT64(result); } @@ -991,11 +989,10 @@ int84div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { - if (unlikely(arg1 == PG_INT64_MIN)) + if (pg_neg_s64_overflow(arg1, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); - result = -arg1; PG_RETURN_INT64(result); } @@ -1133,11 +1130,10 @@ int82div(PG_FUNCTION_ARGS) */ if (arg2 == -1) { - if (unlikely(arg1 == PG_INT64_MIN)) + if (pg_neg_s64_overflow(arg1, &result)) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); - result = -arg1; PG_RETURN_INT64(result); } diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index 523cd3cd608e..37f24e33857f 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -7870,9 +7870,8 @@ numericvar_to_int64(const NumericVar *var, int64 *result) if (!neg) { - if (unlikely(val == PG_INT64_MIN)) + if (unlikely(pg_neg_s64_overflow(val, &val))) return false; - val = -val; } *result = val; -- 2.55.0