On Fri, Jan 31, 2020 at 04:59:18PM +0100, David Fetter wrote:
> On Wed, Jan 15, 2020 at 03:45:12PM -0800, Jesse Zhang wrote:
> > On Tue, Jan 14, 2020 at 2:09 PM David Fetter <da...@fetter.org> wrote:
> > > > The changes in hash AM and SIMPLEHASH do look like a net positive
> > > > improvement. My biggest cringe might be in pg_bitutils:
> > > >
> > > > 1. Is ceil_log2_64 dead code?
> > >
> > > Let's call it nascent code. I suspect there are places it could go, if
> > > I look for them.  Also, it seemed silly to have one without the other.
> > >
> > 
> > While not absolutely required, I'd like us to find at least one
> > place and start using it. (Clang also nags at me when we have
> > unused functions).
> 
> Done in the expanded patches attached.

These bit-rotted a little, so I've updated them.

Best,
David.
-- 
David Fetter <david(at)fetter(dot)org> http://fetter.org/
Phone: +1 415 235 3778

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
>From 90d3575b0716839b76953023bb63242b1d0698ef Mon Sep 17 00:00:00 2001
From: David Fetter <da...@fetter.org>
Date: Wed, 29 Jan 2020 02:09:59 -0800
Subject: [PATCH v5 1/3] de-long-ify
To: hackers
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.24.1"

This is a multi-part message in MIME format.
--------------2.24.1
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 4b562d8d3f..482a569814 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -34,11 +34,11 @@ static void gistPlaceItupToPage(GISTNodeBufferPage *pageBuffer,
 								IndexTuple item);
 static void gistGetItupFromPage(GISTNodeBufferPage *pageBuffer,
 								IndexTuple *item);
-static long gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb);
-static void gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum);
+static uint64 gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb);
+static void gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, uint64 blocknum);
 
-static void ReadTempFileBlock(BufFile *file, long blknum, void *ptr);
-static void WriteTempFileBlock(BufFile *file, long blknum, void *ptr);
+static void ReadTempFileBlock(BufFile *file, uint64 blknum, void *ptr);
+static void WriteTempFileBlock(BufFile *file, uint64 blknum, void *ptr);
 
 
 /*
@@ -64,7 +64,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	/* Initialize free page management. */
 	gfbb->nFreeBlocks = 0;
 	gfbb->freeBlocksLen = 32;
-	gfbb->freeBlocks = (long *) palloc(gfbb->freeBlocksLen * sizeof(long));
+	gfbb->freeBlocks = (int64 *) palloc(gfbb->freeBlocksLen * sizeof(int64));
 
 	/*
 	 * Current memory context will be used for all in-memory data structures
@@ -469,7 +469,7 @@ gistPopItupFromNodeBuffer(GISTBuildBuffers *gfbb, GISTNodeBuffer *nodeBuffer,
 /*
  * Select a currently unused block for writing to.
  */
-static long
+static uint64
 gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb)
 {
 	/*
@@ -487,7 +487,7 @@ gistBuffersGetFreeBlock(GISTBuildBuffers *gfbb)
  * Return a block# to the freelist.
  */
 static void
-gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum)
+gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, uint64 blocknum)
 {
 	int			ndx;
 
@@ -495,9 +495,9 @@ gistBuffersReleaseBlock(GISTBuildBuffers *gfbb, long blocknum)
 	if (gfbb->nFreeBlocks >= gfbb->freeBlocksLen)
 	{
 		gfbb->freeBlocksLen *= 2;
-		gfbb->freeBlocks = (long *) repalloc(gfbb->freeBlocks,
+		gfbb->freeBlocks = (int64 *) repalloc(gfbb->freeBlocks,
 											 gfbb->freeBlocksLen *
-											 sizeof(long));
+											 sizeof(uint64));
 	}
 
 	/* Add blocknum to array */
@@ -755,7 +755,7 @@ gistRelocateBuildBuffersOnSplit(GISTBuildBuffers *gfbb, GISTSTATE *giststate,
  */
 
 static void
-ReadTempFileBlock(BufFile *file, long blknum, void *ptr)
+ReadTempFileBlock(BufFile *file, uint64 blknum, void *ptr)
 {
 	if (BufFileSeekBlock(file, blknum) != 0)
 		elog(ERROR, "could not seek temporary file: %m");
@@ -764,7 +764,7 @@ ReadTempFileBlock(BufFile *file, long blknum, void *ptr)
 }
 
 static void
-WriteTempFileBlock(BufFile *file, long blknum, void *ptr)
+WriteTempFileBlock(BufFile *file, uint64 blknum, void *ptr)
 {
 	if (BufFileSeekBlock(file, blknum) != 0)
 		elog(ERROR, "could not seek temporary file: %m");
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index c46764bf42..4fc478640a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -70,7 +70,7 @@ static int	_SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount);
 static void _SPI_error_callback(void *arg);
 
 static void _SPI_cursor_operation(Portal portal,
-								  FetchDirection direction, long count,
+								  FetchDirection direction, uint64 count,
 								  DestReceiver *dest);
 
 static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan);
@@ -493,7 +493,7 @@ SPI_inside_nonatomic_context(void)
 
 /* Parse, plan, and execute a query string */
 int
-SPI_execute(const char *src, bool read_only, long tcount)
+SPI_execute(const char *src, bool read_only, int64 tcount)
 {
 	_SPI_plan	plan;
 	int			res;
@@ -521,7 +521,7 @@ SPI_execute(const char *src, bool read_only, long tcount)
 
 /* Obsolete version of SPI_execute */
 int
-SPI_exec(const char *src, long tcount)
+SPI_exec(const char *src, int64 tcount)
 {
 	return SPI_execute(src, false, tcount);
 }
@@ -529,7 +529,7 @@ SPI_exec(const char *src, long tcount)
 /* Execute a previously prepared plan */
 int
 SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
-				 bool read_only, long tcount)
+				 bool read_only, int64 tcount)
 {
 	int			res;
 
@@ -555,7 +555,7 @@ SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
 
 /* Obsolete version of SPI_execute_plan */
 int
-SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
+SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, int64 tcount)
 {
 	return SPI_execute_plan(plan, Values, Nulls, false, tcount);
 }
@@ -563,7 +563,7 @@ SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
 /* Execute a previously prepared plan */
 int
 SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params,
-								bool read_only, long tcount)
+								bool read_only, int64 tcount)
 {
 	int			res;
 
@@ -599,7 +599,7 @@ int
 SPI_execute_snapshot(SPIPlanPtr plan,
 					 Datum *Values, const char *Nulls,
 					 Snapshot snapshot, Snapshot crosscheck_snapshot,
-					 bool read_only, bool fire_triggers, long tcount)
+					 bool read_only, bool fire_triggers, int64 tcount)
 {
 	int			res;
 
@@ -633,7 +633,7 @@ int
 SPI_execute_with_args(const char *src,
 					  int nargs, Oid *argtypes,
 					  Datum *Values, const char *Nulls,
-					  bool read_only, long tcount)
+					  bool read_only, int64 tcount)
 {
 	int			res;
 	_SPI_plan	plan;
@@ -1530,7 +1530,7 @@ SPI_cursor_find(const char *name)
  *	Fetch rows in a cursor
  */
 void
-SPI_cursor_fetch(Portal portal, bool forward, long count)
+SPI_cursor_fetch(Portal portal, bool forward, int64 count)
 {
 	_SPI_cursor_operation(portal,
 						  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
@@ -1545,7 +1545,7 @@ SPI_cursor_fetch(Portal portal, bool forward, long count)
  *	Move in a cursor
  */
 void
-SPI_cursor_move(Portal portal, bool forward, long count)
+SPI_cursor_move(Portal portal, bool forward, int64 count)
 {
 	_SPI_cursor_operation(portal,
 						  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
@@ -1559,7 +1559,7 @@ SPI_cursor_move(Portal portal, bool forward, long count)
  *	Fetch rows in a scrollable cursor
  */
 void
-SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
+SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, int64 count)
 {
 	_SPI_cursor_operation(portal,
 						  direction, count,
@@ -1574,7 +1574,7 @@ SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)
  *	Move in a scrollable cursor
  */
 void
-SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)
+SPI_scroll_cursor_move(Portal portal, FetchDirection direction, int64 count)
 {
 	_SPI_cursor_operation(portal, direction, count, None_Receiver);
 }
@@ -2567,7 +2567,7 @@ _SPI_error_callback(void *arg)
  *	Do a FETCH or MOVE in a cursor
  */
 static void
-_SPI_cursor_operation(Portal portal, FetchDirection direction, long count,
+_SPI_cursor_operation(Portal portal, FetchDirection direction, uint64 count,
 					  DestReceiver *dest)
 {
 	uint64		nfetched;
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index 35e8f12e62..db73a9f159 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -749,7 +749,7 @@ BufFileTell(BufFile *file, int *fileno, off_t *offset)
  * impossible seek is attempted.
  */
 int
-BufFileSeekBlock(BufFile *file, long blknum)
+BufFileSeekBlock(BufFile *file, uint64 blknum)
 {
 	return BufFileSeek(file,
 					   (int) (blknum / BUFFILE_SEG_SIZE),
@@ -760,13 +760,11 @@ BufFileSeekBlock(BufFile *file, long blknum)
 #ifdef NOT_USED
 /*
  * BufFileTellBlock --- block-oriented tell
- *
- * Any fractional part of a block in the current seek position is ignored.
  */
-long
+uint64
 BufFileTellBlock(BufFile *file)
 {
-	long		blknum;
+	uint64		blknum;
 
 	blknum = (file->curOffset + file->pos) / BLCKSZ;
 	blknum += file->curFile * BUFFILE_SEG_SIZE;
@@ -820,10 +818,10 @@ BufFileSize(BufFile *file)
  * begins.  Caller should apply this as an offset when working off block
  * positions that are in terms of the original BufFile space.
  */
-long
+uint64
 BufFileAppend(BufFile *target, BufFile *source)
 {
-	long		startBlock = target->numFiles * BUFFILE_SEG_SIZE;
+	uint64		startBlock = target->numFiles * BUFFILE_SEG_SIZE;
 	int			newNumFiles = target->numFiles + source->numFiles;
 	int			i;
 
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index 046ca5c6c7..cb00c67303 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -349,7 +349,7 @@ DisownLatch(Latch *latch)
  * function returns immediately.
  *
  * The "timeout" is given in milliseconds. It must be >= 0 if WL_TIMEOUT flag
- * is given.  Although it is declared as "long", we don't actually support
+ * is given.  Although it is declared as "int64", we don't actually support
  * timeouts longer than INT_MAX milliseconds.  Note that some extra overhead
  * is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible.
  *
@@ -362,7 +362,7 @@ DisownLatch(Latch *latch)
  * we return all of them in one call, but we will return at least one.
  */
 int
-WaitLatch(Latch *latch, int wakeEvents, long timeout,
+WaitLatch(Latch *latch, int wakeEvents, int64 timeout,
 		  uint32 wait_event_info)
 {
 	return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
@@ -388,7 +388,7 @@ WaitLatch(Latch *latch, int wakeEvents, long timeout,
  */
 int
 WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
-				  long timeout, uint32 wait_event_info)
+				  int64 timeout, uint32 wait_event_info)
 {
 	int			ret = 0;
 	int			rc;
@@ -1155,14 +1155,14 @@ WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event)
  * values associated with the registered event.
  */
 int
-WaitEventSetWait(WaitEventSet *set, long timeout,
+WaitEventSetWait(WaitEventSet *set, int64 timeout,
 				 WaitEvent *occurred_events, int nevents,
 				 uint32 wait_event_info)
 {
 	int			returned_events = 0;
 	instr_time	start_time;
 	instr_time	cur_time;
-	long		cur_timeout = -1;
+	int64		cur_timeout = -1;
 
 	Assert(nevents > 0);
 
@@ -1247,7 +1247,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
 		{
 			INSTR_TIME_SET_CURRENT(cur_time);
 			INSTR_TIME_SUBTRACT(cur_time, start_time);
-			cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
+			cur_timeout = timeout - INSTR_TIME_GET_MILLISEC(cur_time);
 			if (cur_timeout <= 0)
 				break;
 		}
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 2892a573e4..582c63a5e6 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -335,8 +335,8 @@ InitShmemIndex(void)
  */
 HTAB *
 ShmemInitHash(const char *name,		/* table string name for shmem index */
-			  long init_size,	/* initial table size */
-			  long max_size,	/* max size of the table */
+			  uint64 init_size,	/* initial table size */
+			  uint64 max_size,	/* max size of the table */
 			  HASHCTL *infoP,	/* info about key and bucket size */
 			  int hash_flags)	/* info about infoP */
 {
diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c
index 37b6a4eecd..43c662aaeb 100644
--- a/src/backend/storage/lmgr/condition_variable.c
+++ b/src/backend/storage/lmgr/condition_variable.c
@@ -129,10 +129,10 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
  * See ConditionVariableSleep() for general usage.
  */
 bool
-ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
+ConditionVariableTimedSleep(ConditionVariable *cv, int64 timeout,
 							uint32 wait_event_info)
 {
-	long		cur_timeout = -1;
+	int64		cur_timeout = -1;
 	instr_time	start_time;
 	instr_time	cur_time;
 
@@ -217,7 +217,7 @@ ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
 		{
 			INSTR_TIME_SET_CURRENT(cur_time);
 			INSTR_TIME_SUBTRACT(cur_time, start_time);
-			cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
+			cur_timeout = timeout - (int64) INSTR_TIME_GET_MILLISEC(cur_time);
 
 			/* Have we crossed the timeout threshold? */
 			if (cur_timeout <= 0)
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 0a6f80963b..9bb9c1fda9 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -109,7 +109,7 @@ int			PostAuthDelay = 0;
  */
 
 /* max_stack_depth converted to bytes for speed of checking */
-static long max_stack_depth_bytes = 100 * 1024L;
+static uint64 max_stack_depth_bytes = 100 * 1024UL;
 
 /*
  * Stack base pointer -- initialized by PostmasterMain and inherited by
@@ -2016,7 +2016,7 @@ exec_bind_message(StringInfo input_message)
  * Process an "Execute" message for a portal
  */
 static void
-exec_execute_message(const char *portal_name, long max_rows)
+exec_execute_message(const char *portal_name, uint64 max_rows)
 {
 	CommandDest dest;
 	DestReceiver *receiver;
@@ -2302,7 +2302,7 @@ check_log_duration(char *msec_str, bool was_logged)
 	if (log_duration || log_min_duration_sample >= 0 ||
 		log_min_duration_statement >= 0 || xact_is_sampled)
 	{
-		long		secs;
+		int64		secs;
 		int			usecs;
 		int			msecs;
 		bool		exceeded_duration;
@@ -3302,12 +3302,12 @@ bool
 stack_is_too_deep(void)
 {
 	char		stack_top_loc;
-	long		stack_depth;
+	int64		stack_depth;
 
 	/*
 	 * Compute distance from reference point to my local variables
 	 */
-	stack_depth = (long) (stack_base_ptr - &stack_top_loc);
+	stack_depth = (int64) (stack_base_ptr - &stack_top_loc);
 
 	/*
 	 * Take abs value, since stacks grow up on some machines, down on others
@@ -3336,7 +3336,7 @@ stack_is_too_deep(void)
 	 * Note we assume that the same max_stack_depth applies to both stacks.
 	 */
 #if defined(__ia64__) || defined(__ia64)
-	stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
+	stack_depth = (int64) (ia64_get_bsp() - register_stack_base_ptr);
 
 	if (stack_depth > max_stack_depth_bytes &&
 		register_stack_base_ptr != NULL)
@@ -3350,8 +3350,8 @@ stack_is_too_deep(void)
 bool
 check_max_stack_depth(int *newval, void **extra, GucSource source)
 {
-	long		newval_bytes = *newval * 1024L;
-	long		stack_rlimit = get_stack_depth_rlimit();
+	uint64		newval_bytes = *newval * 1024UL;
+	uint64		stack_rlimit = get_stack_depth_rlimit();
 
 	if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
 	{
@@ -3367,7 +3367,7 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
 void
 assign_max_stack_depth(int newval, void *extra)
 {
-	long		newval_bytes = newval * 1024L;
+	uint64	newval_bytes = newval * 1024UL;
 
 	max_stack_depth_bytes = newval_bytes;
 }
@@ -4696,7 +4696,7 @@ static void
 log_disconnections(int code, Datum arg)
 {
 	Port	   *port = MyProcPort;
-	long		secs;
+	int64		secs;
 	int			usecs;
 	int			msecs;
 	int			hours,
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 0f5801e046..f519ce7def 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -44,7 +44,7 @@ static void ProcessQuery(PlannedStmt *plan,
 static void FillPortalStore(Portal portal, bool isTopLevel);
 static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count,
 						   DestReceiver *dest);
-static uint64 PortalRunSelect(Portal portal, bool forward, long count,
+static uint64 PortalRunSelect(Portal portal, bool forward, int64 count,
 							  DestReceiver *dest);
 static void PortalRunUtility(Portal portal, PlannedStmt *pstmt,
 							 bool isTopLevel, bool setHoldSnapshot,
@@ -55,7 +55,7 @@ static void PortalRunMulti(Portal portal,
 						   char *completionTag);
 static uint64 DoPortalRunFetch(Portal portal,
 							   FetchDirection fdirection,
-							   long count,
+							   int64 count,
 							   DestReceiver *dest);
 static void DoPortalRewind(Portal portal);
 
@@ -683,7 +683,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
  * suspended due to exhaustion of the count parameter.
  */
 bool
-PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
+PortalRun(Portal portal, int64 count, bool isTopLevel, bool run_once,
 		  DestReceiver *dest, DestReceiver *altdest,
 		  char *completionTag)
 {
@@ -871,7 +871,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, bool run_once,
 static uint64
 PortalRunSelect(Portal portal,
 				bool forward,
-				long count,
+				int64 count,
 				DestReceiver *dest)
 {
 	QueryDesc  *queryDesc;
@@ -1391,7 +1391,7 @@ PortalRunMulti(Portal portal,
 uint64
 PortalRunFetch(Portal portal,
 			   FetchDirection fdirection,
-			   long count,
+			   int64 count,
 			   DestReceiver *dest)
 {
 	uint64		result;
@@ -1493,7 +1493,7 @@ PortalRunFetch(Portal portal,
 static uint64
 DoPortalRunFetch(Portal portal,
 				 FetchDirection fdirection,
-				 long count,
+				 int64 count,
 				 DestReceiver *dest)
 {
 	bool		forward;
@@ -1531,7 +1531,7 @@ DoPortalRunFetch(Portal portal,
 				 * In practice, if the goal is less than halfway back to the
 				 * start, it's better to scan from where we are.
 				 *
-				 * Also, if current portalPos is outside the range of "long",
+				 * Also, if current portalPos is outside the range of "int64",
 				 * do it the hard way to avoid possible overflow of the count
 				 * argument to PortalRunSelect.  We must exclude exactly
 				 * LONG_MAX, as well, lest the count look like FETCH_ALL.
@@ -1549,7 +1549,7 @@ DoPortalRunFetch(Portal portal,
 				}
 				else
 				{
-					long		pos = (long) portal->portalPos;
+					int64		pos = (int64) portal->portalPos;
 
 					if (portal->atEnd)
 						pos++;	/* need one extra fetch if off end */
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 0b6c9d5ea8..ddd471c059 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -1655,7 +1655,7 @@ timeofday(PG_FUNCTION_ARGS)
  */
 void
 TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
-					long *secs, int *microsecs)
+					int64 *secs, int *microsecs)
 {
 	TimestampTz diff = stop_time - start_time;
 
@@ -1666,7 +1666,7 @@ TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
 	}
 	else
 	{
-		*secs = (long) (diff / USECS_PER_SEC);
+		*secs = (int64) (diff / USECS_PER_SEC);
 		*microsecs = (int) (diff % USECS_PER_SEC);
 	}
 }
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index d245e1aa12..6e98b61b2f 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -142,7 +142,7 @@ typedef HASHBUCKET *HASHSEGMENT;
 typedef struct
 {
 	slock_t		mutex;			/* spinlock for this freelist */
-	long		nentries;		/* number of entries in associated buckets */
+	uint64		nentries;		/* number of entries in associated buckets */
 	HASHELEMENT *freeList;		/* chain of free elements */
 } FreeListData;
 
@@ -170,8 +170,8 @@ struct HASHHDR
 
 	/* These fields can change, but not in a partitioned table */
 	/* Also, dsize can't change in a shared table, even if unpartitioned */
-	long		dsize;			/* directory size */
-	long		nsegs;			/* number of allocated segments (<= dsize) */
+	uint64		dsize;			/* directory size */
+	uint64		nsegs;			/* number of allocated segments (<= dsize) */
 	uint32		max_bucket;		/* ID of maximum bucket in use */
 	uint32		high_mask;		/* mask to modulo into entire table */
 	uint32		low_mask;		/* mask to modulo into lower half of table */
@@ -179,10 +179,10 @@ struct HASHHDR
 	/* These fields are fixed at hashtable creation */
 	Size		keysize;		/* hash key length in bytes */
 	Size		entrysize;		/* total user element size in bytes */
-	long		num_partitions; /* # partitions (must be power of 2), or 0 */
-	long		ffactor;		/* target fill factor */
-	long		max_dsize;		/* 'dsize' limit if directory is fixed size */
-	long		ssize;			/* segment size --- must be power of 2 */
+	uint64		num_partitions; /* # partitions (must be power of 2), or 0 */
+	uint64		ffactor;		/* target fill factor */
+	uint64		max_dsize;		/* 'dsize' limit if directory is fixed size */
+	uint64		ssize;			/* segment size --- must be power of 2 */
 	int			sshift;			/* segment shift = log2(ssize) */
 	int			nelem_alloc;	/* number of entries to allocate at once */
 
@@ -192,8 +192,8 @@ struct HASHHDR
 	 * Count statistics here.  NB: stats code doesn't bother with mutex, so
 	 * counts could be corrupted a bit in a partitioned table.
 	 */
-	long		accesses;
-	long		collisions;
+	uint64		accesses;
+	uint64		collisions;
 #endif
 };
 
@@ -224,7 +224,7 @@ struct HTAB
 
 	/* We keep local copies of these fixed values to reduce contention */
 	Size		keysize;		/* hash key length in bytes */
-	long		ssize;			/* segment size --- must be power of 2 */
+	uint64		ssize;			/* segment size --- must be power of 2 */
 	int			sshift;			/* segment shift = log2(ssize) */
 };
 
@@ -245,9 +245,9 @@ struct HTAB
 #define MOD(x,y)			   ((x) & ((y)-1))
 
 #ifdef HASH_STATISTICS
-static long hash_accesses,
-			hash_collisions,
-			hash_expansions;
+static uint64 hash_accesses,
+			  hash_collisions,
+			  hash_expansions;
 #endif
 
 /*
@@ -261,10 +261,10 @@ static bool expand_table(HTAB *hashp);
 static HASHBUCKET get_hash_entry(HTAB *hashp, int freelist_idx);
 static void hdefault(HTAB *hashp);
 static int	choose_nelem_alloc(Size entrysize);
-static bool init_htab(HTAB *hashp, long nelem);
+static bool init_htab(HTAB *hashp, uint64 nelem);
 static void hash_corrupted(HTAB *hashp);
-static long next_pow2_long(long num);
-static int	next_pow2_int(long num);
+static uint64 next_pow2_uint64(uint64 num);
+static int	next_pow2_int(uint64 num);
 static void register_seq_scan(HTAB *hashp);
 static void deregister_seq_scan(HTAB *hashp);
 static bool has_seq_scans(HTAB *hashp);
@@ -314,7 +314,7 @@ string_compare(const char *key1, const char *key2, Size keysize)
  * large nelem will penalize hash_seq_search speed without buying much.
  */
 HTAB *
-hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
+hash_create(const char *tabname, uint64 nelem, HASHCTL *info, int flags)
 {
 	HTAB	   *hashp;
 	HASHHDR    *hctl;
@@ -634,7 +634,7 @@ choose_nelem_alloc(Size entrysize)
  * arrays
  */
 static bool
-init_htab(HTAB *hashp, long nelem)
+init_htab(HTAB *hashp, uint64 nelem)
 {
 	HASHHDR    *hctl = hashp->hctl;
 	HASHSEGMENT *segp;
@@ -730,10 +730,10 @@ init_htab(HTAB *hashp, long nelem)
  * NB: assumes that all hash structure parameters have default values!
  */
 Size
-hash_estimate_size(long num_entries, Size entrysize)
+hash_estimate_size(uint64 num_entries, Size entrysize)
 {
 	Size		size;
-	long		nBuckets,
+	uint64		nBuckets,
 				nSegments,
 				nDirEntries,
 				nElementAllocs,
@@ -741,9 +741,9 @@ hash_estimate_size(long num_entries, Size entrysize)
 				elementAllocCnt;
 
 	/* estimate number of buckets wanted */
-	nBuckets = next_pow2_long((num_entries - 1) / DEF_FFACTOR + 1);
+	nBuckets = next_pow2_uint64((num_entries - 1) / DEF_FFACTOR + 1);
 	/* # of segments needed for nBuckets */
-	nSegments = next_pow2_long((nBuckets - 1) / DEF_SEGSIZE + 1);
+	nSegments = next_pow2_uint64((nBuckets - 1) / DEF_SEGSIZE + 1);
 	/* directory entries */
 	nDirEntries = DEF_DIRSIZE;
 	while (nDirEntries < nSegments)
@@ -776,17 +776,17 @@ hash_estimate_size(long num_entries, Size entrysize)
  *
  * XXX this had better agree with the behavior of init_htab()...
  */
-long
-hash_select_dirsize(long num_entries)
+uint64
+hash_select_dirsize(uint64 num_entries)
 {
-	long		nBuckets,
+	uint64		nBuckets,
 				nSegments,
 				nDirEntries;
 
 	/* estimate number of buckets wanted */
-	nBuckets = next_pow2_long((num_entries - 1) / DEF_FFACTOR + 1);
+	nBuckets = next_pow2_uint64((num_entries - 1) / DEF_FFACTOR + 1);
 	/* # of segments needed for nBuckets */
-	nSegments = next_pow2_long((nBuckets - 1) / DEF_SEGSIZE + 1);
+	nSegments = next_pow2_uint64((nBuckets - 1) / DEF_SEGSIZE + 1);
 	/* directory entries */
 	nDirEntries = DEF_DIRSIZE;
 	while (nDirEntries < nSegments)
@@ -837,8 +837,8 @@ hash_stats(const char *where, HTAB *hashp)
 	fprintf(stderr, "%s: this HTAB -- accesses %ld collisions %ld\n",
 			where, hashp->hctl->accesses, hashp->hctl->collisions);
 
-	fprintf(stderr, "hash_stats: entries %ld keysize %ld maxp %u segmentcount %ld\n",
-			hash_get_num_entries(hashp), (long) hashp->hctl->keysize,
+	fprintf(stderr, "hash_stats: entries %ld keysize %llu maxp %u segmentcount %ld\n",
+			hash_get_num_entries(hashp), (uint64) hashp->hctl->keysize,
 			hashp->hctl->max_bucket, hashp->hctl->nsegs);
 	fprintf(stderr, "%s: total accesses %ld total collisions %ld\n",
 			where, hash_accesses, hash_collisions);
@@ -927,8 +927,8 @@ hash_search_with_hash_value(HTAB *hashp,
 	int			freelist_idx = FREELIST_IDX(hctl, hashvalue);
 	Size		keysize;
 	uint32		bucket;
-	long		segment_num;
-	long		segment_ndx;
+	uint64		segment_num;
+	uint64		segment_ndx;
 	HASHSEGMENT segp;
 	HASHBUCKET	currBucket;
 	HASHBUCKET *prevBucketPtr;
@@ -955,7 +955,7 @@ hash_search_with_hash_value(HTAB *hashp,
 		 * order of these tests is to try to check cheaper conditions first.
 		 */
 		if (!IS_PARTITIONED(hctl) && !hashp->frozen &&
-			hctl->freeList[0].nentries / (long) (hctl->max_bucket + 1) >= hctl->ffactor &&
+			hctl->freeList[0].nentries / (uint64) (hctl->max_bucket + 1) >= hctl->ffactor &&
 			!has_seq_scans(hashp))
 			(void) expand_table(hashp);
 	}
@@ -1123,8 +1123,8 @@ hash_update_hash_key(HTAB *hashp,
 	Size		keysize;
 	uint32		bucket;
 	uint32		newbucket;
-	long		segment_num;
-	long		segment_ndx;
+	uint64		segment_num;
+	uint64		segment_ndx;
 	HASHSEGMENT segp;
 	HASHBUCKET	currBucket;
 	HASHBUCKET *prevBucketPtr;
@@ -1332,11 +1332,11 @@ get_hash_entry(HTAB *hashp, int freelist_idx)
 /*
  * hash_get_num_entries -- get the number of entries in a hashtable
  */
-long
+uint64
 hash_get_num_entries(HTAB *hashp)
 {
 	int			i;
-	long		sum = hashp->hctl->freeList[0].nentries;
+	uint64		sum = hashp->hctl->freeList[0].nentries;
 
 	/*
 	 * We currently don't bother with acquiring the mutexes; it's only
@@ -1392,9 +1392,9 @@ hash_seq_search(HASH_SEQ_STATUS *status)
 	HTAB	   *hashp;
 	HASHHDR    *hctl;
 	uint32		max_bucket;
-	long		ssize;
-	long		segment_num;
-	long		segment_ndx;
+	uint64		ssize;
+	uint64		segment_num;
+	uint64		segment_ndx;
 	HASHSEGMENT segp;
 	uint32		curBucket;
 	HASHELEMENT *curElem;
@@ -1505,11 +1505,11 @@ expand_table(HTAB *hashp)
 	HASHHDR    *hctl = hashp->hctl;
 	HASHSEGMENT old_seg,
 				new_seg;
-	long		old_bucket,
+	uint64		old_bucket,
 				new_bucket;
-	long		new_segnum,
+	uint64		new_segnum,
 				new_segndx;
-	long		old_segnum,
+	uint64		old_segnum,
 				old_segndx;
 	HASHBUCKET *oldlink,
 			   *newlink;
@@ -1577,7 +1577,7 @@ expand_table(HTAB *hashp)
 		 currElement = nextElement)
 	{
 		nextElement = currElement->link;
-		if ((long) calc_bucket(hctl, currElement->hashvalue) == old_bucket)
+		if ((uint64) calc_bucket(hctl, currElement->hashvalue) == old_bucket)
 		{
 			*oldlink = currElement;
 			oldlink = &currElement->link;
@@ -1601,9 +1601,9 @@ dir_realloc(HTAB *hashp)
 {
 	HASHSEGMENT *p;
 	HASHSEGMENT *old_p;
-	long		new_dsize;
-	long		old_dirsize;
-	long		new_dirsize;
+	uint64		new_dsize;
+	uint64		old_dirsize;
+	uint64		new_dirsize;
 
 	if (hashp->hctl->max_dsize != NO_MAX_DSIZE)
 		return false;
@@ -1716,10 +1716,10 @@ hash_corrupted(HTAB *hashp)
 
 /* calculate ceil(log base 2) of num */
 int
-my_log2(long num)
+my_log2(uint64 num)
 {
 	int			i;
-	long		limit;
+	uint64		limit;
 
 	/* guard against too-large input, which would put us into infinite loop */
 	if (num > LONG_MAX / 2)
@@ -1730,9 +1730,9 @@ my_log2(long num)
 	return i;
 }
 
-/* calculate first power of 2 >= num, bounded to what will fit in a long */
-static long
-next_pow2_long(long num)
+/* calculate first power of 2 >= num, bounded to what will fit in a uint64 */
+static uint64
+next_pow2_uint64(uint64 num)
 {
 	/* my_log2's internal range check is sufficient */
 	return 1L << my_log2(num);
@@ -1740,7 +1740,7 @@ next_pow2_long(long num)
 
 /* calculate first power of 2 >= num, bounded to what will fit in an int */
 static int
-next_pow2_int(long num)
+next_pow2_int(uint64 num)
 {
 	if (num > INT_MAX / 2)
 		num = INT_MAX / 2;
diff --git a/src/backend/utils/misc/sampling.c b/src/backend/utils/misc/sampling.c
index 361c15614e..05d2fd581c 100644
--- a/src/backend/utils/misc/sampling.c
+++ b/src/backend/utils/misc/sampling.c
@@ -37,7 +37,7 @@
  */
 BlockNumber
 BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize,
-				  long randseed)
+				  uint64 randseed)
 {
 	bs->N = nblocks;			/* measured table size */
 
@@ -230,7 +230,7 @@ reservoir_get_next_S(ReservoirState rs, double t, int n)
  *----------
  */
 void
-sampler_random_init_state(long seed, SamplerRandomState randstate)
+sampler_random_init_state(uint64 seed, SamplerRandomState randstate)
 {
 	randstate[0] = 0x330e;		/* same as pg_erand48, but could be anything */
 	randstate[1] = (unsigned short) seed;
diff --git a/src/backend/utils/sort/logtape.c b/src/backend/utils/sort/logtape.c
index 4f78b55fba..01396ca230 100644
--- a/src/backend/utils/sort/logtape.c
+++ b/src/backend/utils/sort/logtape.c
@@ -93,9 +93,9 @@
  */
 typedef struct TapeBlockTrailer
 {
-	long		prev;			/* previous block on this tape, or -1 on first
+	int64		prev;			/* previous block on this tape, or -1 on first
 								 * block */
-	long		next;			/* next block on this tape, or # of valid
+	int64		next;			/* next block on this tape, or # of valid
 								 * bytes on last block (if < 0) */
 } TapeBlockTrailer;
 
@@ -138,10 +138,10 @@ typedef struct LogicalTape
 	 * When concatenation of worker tape BufFiles is performed, an offset to
 	 * the first block in the unified BufFile space is applied during reads.
 	 */
-	long		firstBlockNumber;
-	long		curBlockNumber;
-	long		nextBlockNumber;
-	long		offsetBlockNumber;
+	int64		firstBlockNumber;
+	int64		curBlockNumber;
+	int64		nextBlockNumber;
+	int64		offsetBlockNumber;
 
 	/*
 	 * Buffer for current data block(s).
@@ -173,9 +173,9 @@ struct LogicalTapeSet
 	 * blocks that are in unused holes between worker spaces following BufFile
 	 * concatenation.
 	 */
-	long		nBlocksAllocated;	/* # of blocks allocated */
-	long		nBlocksWritten; /* # of blocks used in underlying file */
-	long		nHoleBlocks;	/* # of "hole" blocks left */
+	uint64		nBlocksAllocated;	/* # of blocks allocated */
+	uint64		nBlocksWritten; /* # of blocks used in underlying file */
+	uint64		nHoleBlocks;	/* # of "hole" blocks left */
 
 	/*
 	 * We store the numbers of recycled-and-available blocks in freeBlocks[].
@@ -186,19 +186,19 @@ struct LogicalTapeSet
 	 * LogicalTapeSetForgetFreeSpace().
 	 */
 	bool		forgetFreeSpace;	/* are we remembering free blocks? */
-	long	   *freeBlocks;		/* resizable array holding minheap */
-	long		nFreeBlocks;	/* # of currently free blocks */
-	Size		freeBlocksLen;	/* current allocated length of freeBlocks[] */
+	uint64	   *freeBlocks;		/* resizable array */
+	int			nFreeBlocks;	/* # of currently free blocks */
+	int			freeBlocksLen;	/* current allocated length of freeBlocks[] */
 
 	/* The array of logical tapes. */
 	int			nTapes;			/* # of logical tapes in set */
 	LogicalTape tapes[FLEXIBLE_ARRAY_MEMBER];	/* has nTapes nentries */
 };
 
-static void ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
-static void ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer);
-static long ltsGetFreeBlock(LogicalTapeSet *lts);
-static void ltsReleaseBlock(LogicalTapeSet *lts, long blocknum);
+static void ltsWriteBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer);
+static void ltsReadBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer);
+static int64 ltsGetFreeBlock(LogicalTapeSet *lts);
+static void ltsReleaseBlock(LogicalTapeSet *lts, int64 blocknum);
 static void ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared,
 								 SharedFileSet *fileset);
 static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt);
@@ -210,7 +210,7 @@ static void ltsInitReadBuffer(LogicalTapeSet *lts, LogicalTape *lt);
  * No need for an error return convention; we ereport() on any error.
  */
 static void
-ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
+ltsWriteBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer)
 {
 	/*
 	 * BufFile does not support "holes", so if we're about to write a block
@@ -258,7 +258,7 @@ ltsWriteBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
  * module should never attempt to read a block it doesn't know is there.
  */
 static void
-ltsReadBlock(LogicalTapeSet *lts, long blocknum, void *buffer)
+ltsReadBlock(LogicalTapeSet *lts, int64 blocknum, void *buffer)
 {
 	if (BufFileSeekBlock(lts->pfile, blocknum) != 0 ||
 		BufFileRead(lts->pfile, buffer, BLCKSZ) != BLCKSZ)
@@ -282,7 +282,7 @@ ltsReadFillBuffer(LogicalTapeSet *lts, LogicalTape *lt)
 	do
 	{
 		char	   *thisbuf = lt->buffer + lt->nbytes;
-		long		datablocknum = lt->nextBlockNumber;
+		int64		datablocknum = lt->nextBlockNumber;
 
 		/* Fetch next block number */
 		if (datablocknum == -1L)
@@ -344,7 +344,7 @@ parent_offset(unsigned long i)
  * Select the lowest currently unused block by taking the first element from
  * the freelist min heap.
  */
-static long
+static int64
 ltsGetFreeBlock(LogicalTapeSet *lts)
 {
 	long	*heap = lts->freeBlocks;
@@ -400,7 +400,7 @@ ltsGetFreeBlock(LogicalTapeSet *lts)
  * Return a block# to the freelist.
  */
 static void
-ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
+ltsReleaseBlock(LogicalTapeSet *lts, int64 blocknum)
 {
 	long	*heap;
 	unsigned long pos;
@@ -424,8 +424,8 @@ ltsReleaseBlock(LogicalTapeSet *lts, long blocknum)
 			return;
 
 		lts->freeBlocksLen *= 2;
-		lts->freeBlocks = (long *) repalloc(lts->freeBlocks,
-											lts->freeBlocksLen * sizeof(long));
+		lts->freeBlocks = (uint64 *) repalloc(lts->freeBlocks,
+											  lts->freeBlocksLen * sizeof(int64));
 	}
 
 	heap = lts->freeBlocks;
@@ -460,8 +460,8 @@ ltsConcatWorkerTapes(LogicalTapeSet *lts, TapeShare *shared,
 					 SharedFileSet *fileset)
 {
 	LogicalTape *lt = NULL;
-	long		tapeblocks = 0L;
-	long		nphysicalblocks = 0L;
+	int64		tapeblocks = 0L;
+	int64		nphysicalblocks = 0L;
 	int			i;
 
 	/* Should have at least one worker tape, plus leader's tape */
@@ -593,7 +593,7 @@ LogicalTapeSetCreate(int ntapes, TapeShare *shared, SharedFileSet *fileset,
 	lts->nHoleBlocks = 0L;
 	lts->forgetFreeSpace = false;
 	lts->freeBlocksLen = 32;	/* reasonable initial guess */
-	lts->freeBlocks = (long *) palloc(lts->freeBlocksLen * sizeof(long));
+	lts->freeBlocks = (uint64 *) palloc(lts->freeBlocksLen * sizeof(uint64));
 	lts->nFreeBlocks = 0;
 	lts->nTapes = ntapes;
 
@@ -719,7 +719,7 @@ LogicalTapeWrite(LogicalTapeSet *lts, int tapenum,
 		if (lt->pos >= TapeBlockPayloadSize)
 		{
 			/* Buffer full, dump it out */
-			long		nextBlockNumber;
+			int64		nextBlockNumber;
 
 			if (!lt->dirty)
 			{
@@ -1048,7 +1048,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
 	seekpos = (size_t) lt->pos; /* part within this block */
 	while (size > seekpos)
 	{
-		long		prev = TapeBlockGetTrailer(lt->buffer)->prev;
+		int64		prev = TapeBlockGetTrailer(lt->buffer)->prev;
 
 		if (prev == -1L)
 		{
@@ -1093,7 +1093,7 @@ LogicalTapeBackspace(LogicalTapeSet *lts, int tapenum, size_t size)
  */
 void
 LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
-				long blocknum, int offset)
+				int64 blocknum, int offset)
 {
 	LogicalTape *lt;
 
@@ -1127,7 +1127,7 @@ LogicalTapeSeek(LogicalTapeSet *lts, int tapenum,
  */
 void
 LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
-				long *blocknum, int *offset)
+				int64 *blocknum, int *offset)
 {
 	LogicalTape *lt;
 
@@ -1149,7 +1149,7 @@ LogicalTapeTell(LogicalTapeSet *lts, int tapenum,
 /*
  * Obtain total disk space currently used by a LogicalTapeSet, in blocks.
  */
-long
+int64
 LogicalTapeSetBlocks(LogicalTapeSet *lts)
 {
 	return lts->nBlocksAllocated - lts->nHoleBlocks;
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 62a342f77c..488f12dc6f 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -37,8 +37,8 @@ static bool still_sending = true;	/* feedback still needs to be sent? */
 
 static PGresult *HandleCopyStream(PGconn *conn, StreamCtl *stream,
 								  XLogRecPtr *stoppos);
-static int	CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket);
-static int	CopyStreamReceive(PGconn *conn, long timeout, pgsocket stop_socket,
+static int	CopyStreamPoll(PGconn *conn, int64 timeout_ms, pgsocket stop_socket);
+static int	CopyStreamReceive(PGconn *conn, int64 timeout, pgsocket stop_socket,
 							  char **buffer);
 static bool ProcessKeepaliveMsg(PGconn *conn, StreamCtl *stream, char *copybuf,
 								int len, XLogRecPtr blockpos, TimestampTz *last_status);
@@ -48,7 +48,7 @@ static PGresult *HandleEndOfCopyStream(PGconn *conn, StreamCtl *stream, char *co
 									   XLogRecPtr blockpos, XLogRecPtr *stoppos);
 static bool CheckCopyStreamStop(PGconn *conn, StreamCtl *stream, XLogRecPtr blockpos,
 								XLogRecPtr *stoppos);
-static long CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout,
+static int64 CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout,
 										 TimestampTz last_status);
 
 static bool ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos,
@@ -742,7 +742,7 @@ HandleCopyStream(PGconn *conn, StreamCtl *stream,
 	{
 		int			r;
 		TimestampTz now;
-		long		sleeptime;
+		int64		sleeptime;
 
 		/*
 		 * Check if we should continue streaming, or abort at this point.
@@ -858,7 +858,7 @@ error:
  * or interrupted by signal or stop_socket input, and -1 on an error.
  */
 static int
-CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket)
+CopyStreamPoll(PGconn *conn, int64 timeout_ms, pgsocket stop_socket)
 {
 	int			ret;
 	fd_set		input_mask;
@@ -920,7 +920,7 @@ CopyStreamPoll(PGconn *conn, long timeout_ms, pgsocket stop_socket)
  * -1 on error. -2 if the server ended the COPY.
  */
 static int
-CopyStreamReceive(PGconn *conn, long timeout, pgsocket stop_socket,
+CopyStreamReceive(PGconn *conn, int64 timeout, pgsocket stop_socket,
 				  char **buffer)
 {
 	char	   *copybuf = NULL;
@@ -1228,12 +1228,12 @@ CheckCopyStreamStop(PGconn *conn, StreamCtl *stream, XLogRecPtr blockpos,
 /*
  * Calculate how long send/receive loops should sleep
  */
-static long
+static int64
 CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout,
 							 TimestampTz last_status)
 {
 	TimestampTz status_targettime = 0;
-	long		sleeptime;
+	int64		sleeptime;
 
 	if (standby_message_timeout && still_sending)
 		status_targettime = last_status +
@@ -1241,7 +1241,7 @@ CalculateCopyStreamSleeptime(TimestampTz now, int standby_message_timeout,
 
 	if (status_targettime > 0)
 	{
-		long		secs;
+		int64		secs;
 		int			usecs;
 
 		feTimestampDifference(now,
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index 06de20ada5..e54c968aca 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -84,24 +84,24 @@ extern PGDLLIMPORT int SPI_result;
 extern int	SPI_connect(void);
 extern int	SPI_connect_ext(int options);
 extern int	SPI_finish(void);
-extern int	SPI_execute(const char *src, bool read_only, long tcount);
+extern int	SPI_execute(const char *src, bool read_only, int64 tcount);
 extern int	SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls,
-							 bool read_only, long tcount);
+							 bool read_only, int64 tcount);
 extern int	SPI_execute_plan_with_paramlist(SPIPlanPtr plan,
 											ParamListInfo params,
-											bool read_only, long tcount);
-extern int	SPI_exec(const char *src, long tcount);
+											bool read_only, int64 tcount);
+extern int	SPI_exec(const char *src, int64 tcount);
 extern int	SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls,
-					  long tcount);
+					  int64 tcount);
 extern int	SPI_execute_snapshot(SPIPlanPtr plan,
 								 Datum *Values, const char *Nulls,
 								 Snapshot snapshot,
 								 Snapshot crosscheck_snapshot,
-								 bool read_only, bool fire_triggers, long tcount);
+								 bool read_only, bool fire_triggers, int64 tcount);
 extern int	SPI_execute_with_args(const char *src,
 								  int nargs, Oid *argtypes,
 								  Datum *Values, const char *Nulls,
-								  bool read_only, long tcount);
+								  bool read_only, int64 tcount);
 extern SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes);
 extern SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes,
 									 int cursorOptions);
@@ -151,10 +151,10 @@ extern Portal SPI_cursor_open_with_args(const char *name,
 extern Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan,
 											 ParamListInfo params, bool read_only);
 extern Portal SPI_cursor_find(const char *name);
-extern void SPI_cursor_fetch(Portal portal, bool forward, long count);
-extern void SPI_cursor_move(Portal portal, bool forward, long count);
-extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, long count);
-extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, long count);
+extern void SPI_cursor_fetch(Portal portal, bool forward, int64 count);
+extern void SPI_cursor_move(Portal portal, bool forward, int64 count);
+extern void SPI_scroll_cursor_fetch(Portal, FetchDirection direction, int64 count);
+extern void SPI_scroll_cursor_move(Portal, FetchDirection direction, int64 count);
 extern void SPI_cursor_close(Portal portal);
 
 extern int	SPI_register_relation(EphemeralNamedRelation enr);
diff --git a/src/include/pgtime.h b/src/include/pgtime.h
index 0fc76d0e60..3d2fdedd89 100644
--- a/src/include/pgtime.h
+++ b/src/include/pgtime.h
@@ -33,7 +33,7 @@ struct pg_tm
 	int			tm_wday;
 	int			tm_yday;
 	int			tm_isdst;
-	long int	tm_gmtoff;
+	int64		tm_gmtoff;
 	const char *tm_zone;
 };
 
@@ -48,18 +48,18 @@ typedef struct pg_tzenum pg_tzenum;
 extern struct pg_tm *pg_localtime(const pg_time_t *timep, const pg_tz *tz);
 extern struct pg_tm *pg_gmtime(const pg_time_t *timep);
 extern int	pg_next_dst_boundary(const pg_time_t *timep,
-								 long int *before_gmtoff,
+								 int64 *before_gmtoff,
 								 int *before_isdst,
 								 pg_time_t *boundary,
-								 long int *after_gmtoff,
+								 int64 *after_gmtoff,
 								 int *after_isdst,
 								 const pg_tz *tz);
 extern bool pg_interpret_timezone_abbrev(const char *abbrev,
 										 const pg_time_t *timep,
-										 long int *gmtoff,
+										 int64 *gmtoff,
 										 int *isdst,
 										 const pg_tz *tz);
-extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff);
+extern bool pg_get_timezone_offset(const pg_tz *tz, int64 *gmtoff);
 extern const char *pg_get_timezone_name(pg_tz *tz);
 extern bool pg_tz_acceptable(pg_tz *tz);
 
@@ -75,7 +75,7 @@ extern pg_tz *log_timezone;
 
 extern void pg_timezone_initialize(void);
 extern pg_tz *pg_tzset(const char *tzname);
-extern pg_tz *pg_tzset_offset(long gmtoffset);
+extern pg_tz *pg_tzset_offset(int64 gmtoffset);
 
 extern pg_tzenum *pg_tzenumerate_start(void);
 extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir);
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h
index d6459327cc..0a51120fc4 100644
--- a/src/include/portability/instr_time.h
+++ b/src/include/portability/instr_time.h
@@ -136,7 +136,7 @@ typedef struct timespec instr_time;
 	(((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
 
 #define INSTR_TIME_GET_MILLISEC(t) \
-	(((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
+	(((int64) (t).tv_sec * 1000.0) + ((int64) (t).tv_nsec) / 1000000.0)
 
 #define INSTR_TIME_GET_MICROSEC(t) \
 	(((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) ((t).tv_nsec / 1000))
diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h
index 60433f35b4..7178247396 100644
--- a/src/include/storage/buffile.h
+++ b/src/include/storage/buffile.h
@@ -42,9 +42,9 @@ extern size_t BufFileRead(BufFile *file, void *ptr, size_t size);
 extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size);
 extern int	BufFileSeek(BufFile *file, int fileno, off_t offset, int whence);
 extern void BufFileTell(BufFile *file, int *fileno, off_t *offset);
-extern int	BufFileSeekBlock(BufFile *file, long blknum);
+extern int	BufFileSeekBlock(BufFile *file, uint64 blknum);
 extern int64 BufFileSize(BufFile *file);
-extern long BufFileAppend(BufFile *target, BufFile *source);
+extern uint64 BufFileAppend(BufFile *target, BufFile *source);
 
 extern BufFile *BufFileCreateShared(SharedFileSet *fileset, const char *name);
 extern void BufFileExportShared(BufFile *file);
diff --git a/src/include/storage/condition_variable.h b/src/include/storage/condition_variable.h
index bfe5c89b54..cb245c09c5 100644
--- a/src/include/storage/condition_variable.h
+++ b/src/include/storage/condition_variable.h
@@ -43,7 +43,7 @@ extern void ConditionVariableInit(ConditionVariable *cv);
  * the condition variable.
  */
 extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info);
-extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
+extern bool ConditionVariableTimedSleep(ConditionVariable *cv, int64 timeout,
 										uint32 wait_event_info);
 extern void ConditionVariableCancelSleep(void);
 
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index 46ae56cae3..3c013ca860 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -169,13 +169,13 @@ extern int	AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
 							  Latch *latch, void *user_data);
 extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
 
-extern int	WaitEventSetWait(WaitEventSet *set, long timeout,
+extern int	WaitEventSetWait(WaitEventSet *set, int64 timeout,
 							 WaitEvent *occurred_events, int nevents,
 							 uint32 wait_event_info);
-extern int	WaitLatch(Latch *latch, int wakeEvents, long timeout,
+extern int	WaitLatch(Latch *latch, int wakeEvents, int64 timeout,
 					  uint32 wait_event_info);
 extern int	WaitLatchOrSocket(Latch *latch, int wakeEvents,
-							  pgsocket sock, long timeout, uint32 wait_event_info);
+							  pgsocket sock, int64 timeout, uint32 wait_event_info);
 
 /*
  * Unix implementation uses SIGUSR1 for inter-process signaling.
diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h
index 0c1af89206..4b75f33be9 100644
--- a/src/include/storage/shmem.h
+++ b/src/include/storage/shmem.h
@@ -39,7 +39,7 @@ extern void *ShmemAllocNoError(Size size);
 extern void *ShmemAllocUnlocked(Size size);
 extern bool ShmemAddrIsValid(const void *addr);
 extern void InitShmemIndex(void);
-extern HTAB *ShmemInitHash(const char *name, long init_size, long max_size,
+extern HTAB *ShmemInitHash(const char *name, uint64 init_size, uint64 max_size,
 						   HASHCTL *infoP, int hash_flags);
 extern void *ShmemInitStruct(const char *name, Size size, bool *foundPtr);
 extern Size add_size(Size s1, Size s2);
diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h
index 4ad6324e2d..367c31cabb 100644
--- a/src/include/tcop/pquery.h
+++ b/src/include/tcop/pquery.h
@@ -33,13 +33,13 @@ extern void PortalStart(Portal portal, ParamListInfo params,
 extern void PortalSetResultFormat(Portal portal, int nFormats,
 								  int16 *formats);
 
-extern bool PortalRun(Portal portal, long count, bool isTopLevel,
+extern bool PortalRun(Portal portal, int64 count, bool isTopLevel,
 					  bool run_once, DestReceiver *dest, DestReceiver *altdest,
 					  char *completionTag);
 
 extern uint64 PortalRunFetch(Portal portal,
 							 FetchDirection fdirection,
-							 long count,
+							 int64 count,
 							 DestReceiver *dest);
 
 #endif							/* PQUERY_H */
diff --git a/src/include/utils/dynahash.h b/src/include/utils/dynahash.h
index 768b952176..0c75534897 100644
--- a/src/include/utils/dynahash.h
+++ b/src/include/utils/dynahash.h
@@ -14,6 +14,6 @@
 #ifndef DYNAHASH_H
 #define DYNAHASH_H
 
-extern int	my_log2(long num);
+extern int	my_log2(uint64 num);
 
 #endif							/* DYNAHASH_H */
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index f1deb9beab..dd0cd98962 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -64,11 +64,11 @@ typedef struct HTAB HTAB;
 /* Only those fields indicated by hash_flags need be set */
 typedef struct HASHCTL
 {
-	long		num_partitions; /* # partitions (must be power of 2) */
-	long		ssize;			/* segment size */
-	long		dsize;			/* (initial) directory size */
-	long		max_dsize;		/* limit to dsize if dir size is limited */
-	long		ffactor;		/* fill factor */
+	uint64		num_partitions; /* # partitions (must be power of 2) */
+	uint64		ssize;			/* segment size */
+	uint64		dsize;			/* (initial) directory size */
+	uint64		max_dsize;		/* limit to dsize if dir size is limited */
+	uint64		ffactor;		/* fill factor */
 	Size		keysize;		/* hash key length in bytes */
 	Size		entrysize;		/* total user element size in bytes */
 	HashValueFunc hash;			/* hash function */
@@ -123,7 +123,7 @@ typedef struct
  * string_hash, tag_hash, uint32_hash, or oid_hash.  Just set HASH_BLOBS or
  * not.  Use HASH_FUNCTION only when you want something other than those.
  */
-extern HTAB *hash_create(const char *tabname, long nelem,
+extern HTAB *hash_create(const char *tabname, uint64 nelem,
 						 HASHCTL *info, int flags);
 extern void hash_destroy(HTAB *hashp);
 extern void hash_stats(const char *where, HTAB *hashp);
@@ -135,13 +135,13 @@ extern void *hash_search_with_hash_value(HTAB *hashp, const void *keyPtr,
 										 bool *foundPtr);
 extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
 								 const void *newKeyPtr);
-extern long hash_get_num_entries(HTAB *hashp);
+extern uint64 hash_get_num_entries(HTAB *hashp);
 extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
 extern void *hash_seq_search(HASH_SEQ_STATUS *status);
 extern void hash_seq_term(HASH_SEQ_STATUS *status);
 extern void hash_freeze(HTAB *hashp);
-extern Size hash_estimate_size(long num_entries, Size entrysize);
-extern long hash_select_dirsize(long num_entries);
+extern Size hash_estimate_size(uint64 num_entries, Size entrysize);
+extern uint64 hash_select_dirsize(uint64 num_entries);
 extern Size hash_get_shared_size(HASHCTL *info, int flags);
 extern void AtEOXact_HashTables(bool isCommit);
 extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth);
diff --git a/src/include/utils/sampling.h b/src/include/utils/sampling.h
index 74646846b2..cbcbeb6fd7 100644
--- a/src/include/utils/sampling.h
+++ b/src/include/utils/sampling.h
@@ -19,7 +19,7 @@
 /* Random generator for sampling code */
 typedef unsigned short SamplerRandomState[3];
 
-extern void sampler_random_init_state(long seed,
+extern void sampler_random_init_state(uint64 seed,
 									  SamplerRandomState randstate);
 extern double sampler_random_fract(SamplerRandomState randstate);
 
@@ -38,7 +38,7 @@ typedef struct
 typedef BlockSamplerData *BlockSampler;
 
 extern BlockNumber BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
-									 int samplesize, long randseed);
+									 int samplesize, uint64 randseed);
 extern bool BlockSampler_HasMore(BlockSampler bs);
 extern BlockNumber BlockSampler_Next(BlockSampler bs);
 
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index 03a1de569f..78fdf05583 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -71,7 +71,7 @@ extern TimestampTz GetCurrentTimestamp(void);
 extern TimestampTz GetSQLCurrentTimestamp(int32 typmod);
 extern Timestamp GetSQLLocalTimestamp(int32 typmod);
 extern void TimestampDifference(TimestampTz start_time, TimestampTz stop_time,
-								long *secs, int *microsecs);
+								int64 *secs, int *microsecs);
 extern bool TimestampDifferenceExceeds(TimestampTz start_time,
 									   TimestampTz stop_time,
 									   int msec);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 5acf604f63..3ce5848247 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -358,7 +358,7 @@ static Datum exec_eval_expr(PLpgSQL_execstate *estate,
 							Oid *rettype,
 							int32 *rettypmod);
 static int	exec_run_select(PLpgSQL_execstate *estate,
-							PLpgSQL_expr *expr, long maxtuples, Portal *portalP);
+							PLpgSQL_expr *expr, uint64 maxtuples, Portal *portalP);
 static int	exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
 						   Portal portal, bool prefetch_ok);
 static ParamListInfo setup_param_list(PLpgSQL_execstate *estate,
@@ -4085,7 +4085,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
 				  PLpgSQL_stmt_execsql *stmt)
 {
 	ParamListInfo paramLI;
-	long		tcount;
+	int64		tcount;
 	int			rc;
 	PLpgSQL_expr *expr = stmt->sqlstmt;
 	int			too_many_rows_level = 0;
@@ -4683,7 +4683,7 @@ static int
 exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
 {
 	PLpgSQL_var *curvar;
-	long		how_many = stmt->how_many;
+	int64		how_many = stmt->how_many;
 	SPITupleTable *tuptab;
 	Portal		portal;
 	char	   *curname;
@@ -5831,7 +5831,7 @@ exec_eval_expr(PLpgSQL_execstate *estate,
  */
 static int
 exec_run_select(PLpgSQL_execstate *estate,
-				PLpgSQL_expr *expr, long maxtuples, Portal *portalP)
+				PLpgSQL_expr *expr, uint64 maxtuples, Portal *portalP)
 {
 	ParamListInfo paramLI;
 	int			rc;
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 69df3306fd..0cea7270cf 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -798,7 +798,7 @@ typedef struct PLpgSQL_stmt_fetch
 	PLpgSQL_variable *target;	/* target (record or row) */
 	int			curvar;			/* cursor variable to fetch from */
 	FetchDirection direction;	/* fetch direction */
-	long		how_many;		/* count, if constant (expr is NULL) */
+	int64		how_many;		/* count, if constant (expr is NULL) */
 	PLpgSQL_expr *expr;			/* count, if expression */
 	bool		is_move;		/* is this a fetch or move? */
 	bool		returns_multiple_rows;	/* can return more than one row? */
@@ -1027,7 +1027,7 @@ typedef struct PLpgSQL_function
 
 	/* these fields change when the function is used */
 	struct PLpgSQL_execstate *cur_estate;
-	unsigned long use_count;
+	uint64 use_count;
 } PLpgSQL_function;
 
 /*
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index 99c1b4f28f..91079f4c99 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -25,7 +25,7 @@
 #include "utils/memutils.h"
 #include "utils/syscache.h"
 
-static PyObject *PLy_spi_execute_query(char *query, long limit);
+static PyObject *PLy_spi_execute_query(char *query, uint64 limit);
 static PyObject *PLy_spi_execute_fetch_result(SPITupleTable *tuptable,
 											  uint64 rows, int status);
 static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata);
@@ -158,7 +158,7 @@ PLy_spi_execute(PyObject *self, PyObject *args)
 	char	   *query;
 	PyObject   *plan;
 	PyObject   *list = NULL;
-	long		limit = 0;
+	uint64		limit = 0;
 
 	if (PyArg_ParseTuple(args, "s|l", &query, &limit))
 		return PLy_spi_execute_query(query, limit);
@@ -174,7 +174,7 @@ PLy_spi_execute(PyObject *self, PyObject *args)
 }
 
 PyObject *
-PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
+PLy_spi_execute_plan(PyObject *ob, PyObject *list, uint64 limit)
 {
 	volatile int nargs;
 	int			i,
@@ -305,7 +305,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 }
 
 static PyObject *
-PLy_spi_execute_query(char *query, long limit)
+PLy_spi_execute_query(char *query, uint64 limit)
 {
 	int			rv;
 	volatile MemoryContext oldcontext;
diff --git a/src/pl/plpython/plpy_spi.h b/src/pl/plpython/plpy_spi.h
index a5e2e60da7..66e8a43aae 100644
--- a/src/pl/plpython/plpy_spi.h
+++ b/src/pl/plpython/plpy_spi.h
@@ -10,7 +10,7 @@
 
 extern PyObject *PLy_spi_prepare(PyObject *self, PyObject *args);
 extern PyObject *PLy_spi_execute(PyObject *self, PyObject *args);
-extern PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit);
+extern PyObject *PLy_spi_execute_plan(PyObject *ob, PyObject *list, uint64 limit);
 
 typedef struct PLyExceptionEntry
 {
diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c
index 333f27300a..926c677c41 100644
--- a/src/timezone/localtime.c
+++ b/src/timezone/localtime.c
@@ -1623,10 +1623,10 @@ increment_overflow_time(pg_time_t *tp, int32 j)
  */
 int
 pg_next_dst_boundary(const pg_time_t *timep,
-					 long int *before_gmtoff,
+					 int64 *before_gmtoff,
 					 int *before_isdst,
 					 pg_time_t *boundary,
-					 long int *after_gmtoff,
+					 int64 *after_gmtoff,
 					 int *after_isdst,
 					 const pg_tz *tz)
 {
@@ -1771,7 +1771,7 @@ pg_next_dst_boundary(const pg_time_t *timep,
 bool
 pg_interpret_timezone_abbrev(const char *abbrev,
 							 const pg_time_t *timep,
-							 long int *gmtoff,
+							 int64 *gmtoff,
 							 int *isdst,
 							 const pg_tz *tz)
 {
@@ -1863,7 +1863,7 @@ pg_interpret_timezone_abbrev(const char *abbrev,
  * into *gmtoff and return true, else return false.
  */
 bool
-pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
+pg_get_timezone_offset(const pg_tz *tz, int64 *gmtoff)
 {
 	/*
 	 * The zone could have more than one ttinfo, if it's historically used

--------------2.24.1--


>From a73cdc21d2d62df32bc087b2b4620e7c7f3f5b24 Mon Sep 17 00:00:00 2001
From: David Fetter <da...@fetter.org>
Date: Fri, 31 Jan 2020 07:08:48 -0800
Subject: [PATCH v5 2/3] Spread bitutils into hashing
To: hackers
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.24.1"

This is a multi-part message in MIME format.
--------------2.24.1
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 55d85644a4..29dca21be2 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -30,6 +30,7 @@
 
 #include "access/hash.h"
 #include "access/hash_xlog.h"
+#include "port/pg_bitutils.h"
 #include "miscadmin.h"
 #include "storage/lmgr.h"
 #include "storage/predicate.h"
@@ -502,7 +503,6 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
 	double		dnumbuckets;
 	uint32		num_buckets;
 	uint32		spare_index;
-	uint32		i;
 
 	/*
 	 * Choose the number of initial bucket pages to match the fill factor
@@ -543,14 +543,8 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
 	metap->hashm_ffactor = ffactor;
 	metap->hashm_bsize = HashGetMaxBitmapSize(page);
 	/* find largest bitmap array size that will fit in page size */
-	for (i = _hash_log2(metap->hashm_bsize); i > 0; --i)
-	{
-		if ((1 << i) <= metap->hashm_bsize)
-			break;
-	}
-	Assert(i > 0);
-	metap->hashm_bmsize = 1 << i;
-	metap->hashm_bmshift = i + BYTE_TO_BIT;
+	metap->hashm_bmsize = 1 << pg_leftmost_one_pos32(metap->hashm_bsize);
+	metap->hashm_bmshift = pg_leftmost_one_pos32(metap->hashm_bsize) + BYTE_TO_BIT;
 	Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1));
 
 	/*
@@ -570,7 +564,7 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
 	 * Set highmask as next immediate ((2 ^ x) - 1), which should be
 	 * sufficient to cover num_buckets.
 	 */
-	metap->hashm_highmask = (1 << (_hash_log2(num_buckets + 1))) - 1;
+	metap->hashm_highmask = next_power_of_2_32(num_buckets + 1) - 1;
 	metap->hashm_lowmask = (metap->hashm_highmask >> 1);
 
 	MemSet(metap->hashm_spares, 0, sizeof(metap->hashm_spares));
@@ -657,13 +651,12 @@ restart_expand:
 	 * Can't split anymore if maxbucket has reached its maximum possible
 	 * value.
 	 *
-	 * Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because
-	 * the calculation maxbucket+1 mustn't overflow).  Currently we restrict
-	 * to half that because of overflow looping in _hash_log2() and
-	 * insufficient space in hashm_spares[].  It's moot anyway because an
-	 * index with 2^32 buckets would certainly overflow BlockNumber and hence
-	 * _hash_alloc_buckets() would fail, but if we supported buckets smaller
-	 * than a disk block then this would be an independent constraint.
+	 * Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because the
+	 * calculation maxbucket+1 mustn't overflow).  Currently we restrict to half
+	 * that because of insufficient space in hashm_spares[].  It's moot anyway
+	 * because an index with 2^32 buckets would certainly overflow BlockNumber
+	 * and hence _hash_alloc_buckets() would fail, but if we supported buckets
+	 * smaller than a disk block then this would be an independent constraint.
 	 *
 	 * If you change this, see also the maximum initial number of buckets in
 	 * _hash_init().
diff --git a/src/backend/access/hash/hashsort.c b/src/backend/access/hash/hashsort.c
index 9cb41d62e7..322379788c 100644
--- a/src/backend/access/hash/hashsort.c
+++ b/src/backend/access/hash/hashsort.c
@@ -27,6 +27,7 @@
 
 #include "access/hash.h"
 #include "commands/progress.h"
+#include "port/pg_bitutils.h"
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "utils/tuplesort.h"
@@ -69,7 +70,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
 	 * NOTE : This hash mask calculation should be in sync with similar
 	 * calculation in _hash_init_metabuffer.
 	 */
-	hspool->high_mask = (((uint32) 1) << _hash_log2(num_buckets + 1)) - 1;
+	hspool->high_mask = next_power_of_2_32(num_buckets + 1) - 1;
 	hspool->low_mask = (hspool->high_mask >> 1);
 	hspool->max_buckets = num_buckets - 1;
 
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 9efc8016bc..738572ca40 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -17,6 +17,7 @@
 #include "access/hash.h"
 #include "access/reloptions.h"
 #include "access/relscan.h"
+#include "port/pg_bitutils.h"
 #include "storage/buf_internals.h"
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
@@ -134,21 +135,6 @@ _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
 	return bucket;
 }
 
-/*
- * _hash_log2 -- returns ceil(lg2(num))
- */
-uint32
-_hash_log2(uint32 num)
-{
-	uint32		i,
-				limit;
-
-	limit = 1;
-	for (i = 0; limit < num; limit <<= 1, i++)
-		;
-	return i;
-}
-
 /*
  * _hash_spareindex -- returns spare index / global splitpoint phase of the
  *					   bucket
@@ -159,7 +145,7 @@ _hash_spareindex(uint32 num_bucket)
 	uint32		splitpoint_group;
 	uint32		splitpoint_phases;
 
-	splitpoint_group = _hash_log2(num_bucket);
+	splitpoint_group = ceil_log2_32(num_bucket);
 
 	if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
 		return splitpoint_group;
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 6e98b61b2f..deef317520 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -86,6 +86,7 @@
 #include <limits.h>
 
 #include "access/xact.h"
+#include "port/pg_bitutils.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
 #include "utils/dynahash.h"
@@ -1718,16 +1719,11 @@ hash_corrupted(HTAB *hashp)
 int
 my_log2(uint64 num)
 {
-	int			i;
-	uint64		limit;
-
 	/* guard against too-large input, which would put us into infinite loop */
 	if (num > LONG_MAX / 2)
 		num = LONG_MAX / 2;
 
-	for (i = 0, limit = 1; limit < num; i++, limit <<= 1)
-		;
-	return i;
+	return ceil_log2_64(num);
 }
 
 /* calculate first power of 2 >= num, bounded to what will fit in a uint64 */
diff --git a/src/include/access/hash.h b/src/include/access/hash.h
index 9fc0696096..298c05e6fe 100644
--- a/src/include/access/hash.h
+++ b/src/include/access/hash.h
@@ -450,7 +450,6 @@ extern uint32 _hash_datum2hashkey(Relation rel, Datum key);
 extern uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype);
 extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
 								   uint32 highmask, uint32 lowmask);
-extern uint32 _hash_log2(uint32 num);
 extern uint32 _hash_spareindex(uint32 num_bucket);
 extern uint32 _hash_get_totalbuckets(uint32 splitpoint_phase);
 extern void _hash_checkpage(Relation rel, Buffer buf, int flags);
diff --git a/src/include/lib/simplehash.h b/src/include/lib/simplehash.h
index 5a6783f653..1a35a054d8 100644
--- a/src/include/lib/simplehash.h
+++ b/src/include/lib/simplehash.h
@@ -57,6 +57,8 @@
  *	  backwards, unless they're empty or already at their optimal position.
  */
 
+#include "port/pg_bitutils.h"
+
 /* helpers */
 #define SH_MAKE_PREFIX(a) CppConcat(a,_)
 #define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX),name)
@@ -215,27 +217,6 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
 #ifndef SIMPLEHASH_H
 #define SIMPLEHASH_H
 
-/* FIXME: can we move these to a central location? */
-
-/* calculate ceil(log base 2) of num */
-static inline uint64
-sh_log2(uint64 num)
-{
-	int			i;
-	uint64		limit;
-
-	for (i = 0, limit = 1; limit < num; i++, limit <<= 1)
-		;
-	return i;
-}
-
-/* calculate first power of 2 >= num */
-static inline uint64
-sh_pow2(uint64 num)
-{
-	return ((uint64) 1) << sh_log2(num);
-}
-
 #ifdef FRONTEND
 #define sh_error(...) pg_log_error(__VA_ARGS__)
 #define sh_log(...) pg_log_info(__VA_ARGS__)
@@ -259,7 +240,7 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint32 newsize)
 	size = Max(newsize, 2);
 
 	/* round up size to the next power of 2, that's how bucketing works */
-	size = sh_pow2(size);
+	size = next_power_of_2_64(size);
 	Assert(size <= SH_MAX_SIZE);
 
 	/*
@@ -434,7 +415,7 @@ SH_GROW(SH_TYPE * tb, uint32 newsize)
 	uint32		startelem = 0;
 	uint32		copyelem;
 
-	Assert(oldsize == sh_pow2(oldsize));
+	Assert(oldsize == next_power_of_2_64(oldsize));
 	Assert(oldsize != SH_MAX_SIZE);
 	Assert(oldsize < newsize);
 
diff --git a/src/include/port/pg_bitutils.h b/src/include/port/pg_bitutils.h
index 498e532308..88a9ea5b7f 100644
--- a/src/include/port/pg_bitutils.h
+++ b/src/include/port/pg_bitutils.h
@@ -20,19 +20,18 @@ extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
 /*
  * pg_leftmost_one_pos32
  *		Returns the position of the most significant set bit in "word",
- *		measured from the least significant bit.  word must not be 0.
+ *		measured from the least significant bit.
  */
 static inline int
 pg_leftmost_one_pos32(uint32 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
-	Assert(word != 0);
-
-	return 31 - __builtin_clz(word);
+	return word ? 31 - __builtin_clz(word) : 0;
 #else
 	int			shift = 32 - 8;
 
-	Assert(word != 0);
+	if (word == 0)
+		return 0;
 
 	while ((word >> shift) == 0)
 		shift -= 8;
@@ -49,19 +48,18 @@ static inline int
 pg_leftmost_one_pos64(uint64 word)
 {
 #ifdef HAVE__BUILTIN_CLZ
-	Assert(word != 0);
-
 #if defined(HAVE_LONG_INT_64)
-	return 63 - __builtin_clzl(word);
+	return word ? 63 - __builtin_clzl(word) : 0;
 #elif defined(HAVE_LONG_LONG_INT_64)
-	return 63 - __builtin_clzll(word);
+	return word ? 63 - __builtin_clzll(word) : 0;
 #else
 #error must have a working 64-bit integer datatype
 #endif
 #else							/* !HAVE__BUILTIN_CLZ */
 	int			shift = 64 - 8;
 
-	Assert(word != 0);
+	if (word == 0)
+		return 0;
 
 	while ((word >> shift) == 0)
 		shift -= 8;
@@ -73,19 +71,18 @@ pg_leftmost_one_pos64(uint64 word)
 /*
  * pg_rightmost_one_pos32
  *		Returns the position of the least significant set bit in "word",
- *		measured from the least significant bit.  word must not be 0.
+ *		measured from the least significant bit.
  */
 static inline int
 pg_rightmost_one_pos32(uint32 word)
 {
 #ifdef HAVE__BUILTIN_CTZ
-	Assert(word != 0);
-
-	return __builtin_ctz(word);
+	return word ? __builtin_ctz(word) : 32;
 #else
 	int			result = 0;
 
-	Assert(word != 0);
+	if (word == 0)
+		return 32;
 
 	while ((word & 255) == 0)
 	{
@@ -105,19 +102,18 @@ static inline int
 pg_rightmost_one_pos64(uint64 word)
 {
 #ifdef HAVE__BUILTIN_CTZ
-	Assert(word != 0);
-
 #if defined(HAVE_LONG_INT_64)
-	return __builtin_ctzl(word);
+	return word ? __builtin_ctzl(word) : 64;
 #elif defined(HAVE_LONG_LONG_INT_64)
-	return __builtin_ctzll(word);
+	return word ? __builtin_ctzll(word) : 64;
 #else
 #error must have a working 64-bit integer datatype
 #endif
 #else							/* !HAVE__BUILTIN_CTZ */
 	int			result = 0;
 
-	Assert(word != 0);
+	if (word == 0)
+		return 64;
 
 	while ((word & 255) == 0)
 	{
@@ -145,4 +141,34 @@ pg_rotate_right32(uint32 word, int n)
 	return (word >> n) | (word << (sizeof(word) * BITS_PER_BYTE - n));
 }
 
+/* ceil(lg2(num)) */
+static inline uint32
+ceil_log2_32(uint32 num)
+{
+	Assert(num > 0);
+	return pg_leftmost_one_pos32(num-1) + 1;
+}
+
+static inline uint64
+ceil_log2_64(uint64 num)
+{
+	Assert(num > 0);
+	return pg_leftmost_one_pos64(num-1) + 1;
+}
+
+/* Calculate the first power of 2 >= num */
+static inline uint32
+next_power_of_2_32(uint32 num)
+{
+	Assert(num > 0);
+	return ((uint32) 1) << (pg_leftmost_one_pos32(num-1) + 1);
+}
+
+static inline uint64
+next_power_of_2_64(uint64 num)
+{
+	Assert(num > 0);
+	return ((uint64) 1) << (pg_leftmost_one_pos64(num-1) + 1);
+}
+
 #endif							/* PG_BITUTILS_H */

--------------2.24.1--


>From f89be8307d945a636a1bb351372513ee4f4a7872 Mon Sep 17 00:00:00 2001
From: David Fetter <da...@fetter.org>
Date: Fri, 31 Jan 2020 08:32:26 -0800
Subject: [PATCH v5 3/3] Reduced operations in floor_log2
To: hackers
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------2.24.1"

This is a multi-part message in MIME format.
--------------2.24.1
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


diff --git a/src/backend/utils/adt/array_selfuncs.c b/src/backend/utils/adt/array_selfuncs.c
index d97e60a3ab..12170cb7f2 100644
--- a/src/backend/utils/adt/array_selfuncs.c
+++ b/src/backend/utils/adt/array_selfuncs.c
@@ -20,6 +20,7 @@
 #include "catalog/pg_collation.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_statistic.h"
+#include "port/pg_bitutils.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -1089,35 +1090,9 @@ calc_distr(const float *p, int n, int m, float rest)
 static int
 floor_log2(uint32 n)
 {
-	int			logval = 0;
-
 	if (n == 0)
 		return -1;
-	if (n >= (1 << 16))
-	{
-		n >>= 16;
-		logval += 16;
-	}
-	if (n >= (1 << 8))
-	{
-		n >>= 8;
-		logval += 8;
-	}
-	if (n >= (1 << 4))
-	{
-		n >>= 4;
-		logval += 4;
-	}
-	if (n >= (1 << 2))
-	{
-		n >>= 2;
-		logval += 2;
-	}
-	if (n >= (1 << 1))
-	{
-		logval += 1;
-	}
-	return logval;
+	return 1 << pg_leftmost_one_pos32(n);
 }
 
 /*

--------------2.24.1--


Reply via email to