Use pg_neg_s*_overflow() for open-coded negation overflow checks

From: Ewan Young <kdbase(dot)hack(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Cc: David Rowley <dgrowleyml(at)gmail(dot)com>, Dagfinn Ilmari Mannsåker <ilmari(at)ilmari(dot)org>, Daniel Gustafsson <daniel(at)yesql(dot)se>, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
Subject: Use pg_neg_s*_overflow() for open-coded negation overflow checks
Date: 2026-08-27 05:57:59
Message-ID: CAON2xHO4tTFiow2KKLbpiOEJNL4Th5p1QVTm4mSdEU+KW1rrfQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On the "Fix right() with the most negative integer" thread [1], Dagfinn
Ilmari Mannsåker noted that several places still guard negating the most
negative value with a hand-written "x == PG_INTnn_MIN" test rather than
the pg_neg_s{16,32,64}_overflow() helpers in int.h, and David Rowley
suggested cleaning them up separately. Here is that patch.

It converts the open-coded negation-overflow checks in the integer,
bigint and money types:

- unary minus: int2um, int4um, int8um
- abs: int2abs, int4abs, int8abs
- divide by -1: int2div, int4div, int42div, int8div, int84div, int82div
- lcm: int4lcm, int8lcm
- money: cash_div_int64, cash_in
- numeric: numericvar_to_int64

int?gcd_internal() is left alone: its "if (arg < 0) arg = -arg;" runs
only after INT_MIN has already been rejected. text_right() is another
such site but is being fixed as a bug on [1] (with the plain test, since
pg_neg_s32_overflow() only exists from v18); I'll fold it in once that
lands in master.

No behavioral change: each site keeps its existing hard- or soft-error
path.

On how the non-HAVE__BUILTIN_OP_OVERFLOW path was checked:
I built with that macro commented out in pg_config.h, so the
calls compile through int.h's #else fallback (objdump confirms int4um
then emits the explicit "cmp $0x80000000; je" rather than the builtin's
"jo"), and the int2/int4/int8/money/numeric regression tests pass on that
build. The fallback is byte-for-byte the "if (a == PG_INTnn_MIN) ...;
-a" it replaces, so those builds are unchanged.

Where the builtin is available the code is identical or one instruction
shorter (the negate sets OF, so "jo" replaces the separate compare), so
there is no performance downside.

[1] https://www.postgresql.org/message-id/flat/CAON2xHNnBz-AcPJgDmd5_39+8qR5AUKEZk4X3ZM-0zdsATn8kQ(at)mail(dot)gmail(dot)com

--
Regards,
Ewan Young

Attachment Content-Type Size
v1-0001-Use-pg_neg_s-16-32-64-_overflow-for-open-coded-negat.patch application/octet-stream 8.1 KB

Browse pgsql-hackers by date

  From Date Subject
Previous Message Rui Zhao 2026-08-27 05:55:04 Re: [PATCH] Preserve replication origin OIDs in pg_upgrade