]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid using unsigned 64-bit integer division on platforms that do not support
authordrh <>
Sun, 29 Mar 2026 19:06:36 +0000 (19:06 +0000)
committerdrh <>
Sun, 29 Mar 2026 19:06:36 +0000 (19:06 +0000)
it in hardware.

FossilOrigin-Name: 2197677491dfc5ec87b57bbf807776875248a250f80ce9a5ce94ae385bb1d2bc

Makefile.msc
main.mk
manifest
manifest.uuid
src/sqliteInt.h
src/util.c

index 76b9ddfc3bbbe546ecb1c95c11c378afa845d39c..8e06c11cb68ccc5156f8561b1695676a18b932d2 100644 (file)
@@ -2630,8 +2630,8 @@ smoketest:        $(TESTPROGS)
 # Measure the performance of floating-point conversions.
 #
 fp-speed-test: fp-speed-1.exe fp-speed-2.exe
-       fp-speed-1 10000000
-       fp-speed-2 10000000
+       fp-speed-1 1000000
+       fp-speed-2 1000000
 
 shelltest:
        $(TCLSH_CMD) $(TOP)\test\testrunner.tcl release shell
diff --git a/main.mk b/main.mk
index fa6d35c8ae9d52f2662dac7d64b007899f31ceab..0b13b7da6d2691abdd42cda0c4590ed78e6b6174 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -1923,8 +1923,8 @@ shelltest:
 # Test performance of floating-point conversions.
 #
 fp-speed-test: fp-speed-1$(T.exe) fp-speed-2$(T.exe)
-       ./fp-speed-1 10000000
-       ./fp-speed-2 10000000
+       ./fp-speed-1 1000000
+       ./fp-speed-2 1000000
 
 #
 # sqlite3_analyzer.c build depends on $(LINK_TOOLS_DYNAMICALLY).
index 32e98013221d236e8d1a0ff599c35e64869fae67..94a5edf85b565e987045795f8478c6dfce551507 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,12 +1,12 @@
-C The\s_umulh()\sintrinsic\sfunction\sis\snot\savailable\son\s32-bit\swindows.\s\sSo\sdon't\nuse\sit\sthere.
-D 2026-03-29T10:32:25.815
+C Avoid\susing\sunsigned\s64-bit\sinteger\sdivision\son\splatforms\sthat\sdo\snot\ssupport\nit\sin\shardware.
+D 2026-03-29T19:06:36.213
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
 F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
 F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
-F Makefile.msc 05dffae7914a3e3accd6056d71ec2bf5dff563a728592373b828882a52141067
+F Makefile.msc 92391304cf70f4c178b127aa83b88637abd28d1b83ede451616144037ea1d3dd
 F README.md 3fa51fc7ababc32edd175ae8b2986c86d5ea120c1cb1e57c7f7849492d1405ec
 F VERSION 31435e19ded2aae3c1c67dacf06a995a37fd1b253baec5899b78d64cd29db4f7
 F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -655,7 +655,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
 F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
 F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk ac1cafc6f08d108f99cf74f686f1a7f8a08569279341f9d6ffb7745c1fba66f6
+F main.mk 0ed98e9faa3a8e2ce40ec5b55781101048c13c6970bc50d456d4c2834e74f4ea
 F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -738,7 +738,7 @@ F src/shell.c.in 91ee40ec3f75192362cbaa0ad85316140b8dde00a184113d73a837fb6173dbc
 F src/sqlite.h.in e7acbb01518f05c5a342149ec1eeb1afcdccf9b90a6e9770a4893ae9a3c756ae
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
-F src/sqliteInt.h 9716721fb57e32938a1d30a84560ce7633c63860a2209e188c87afad15d4b464
+F src/sqliteInt.h 9d6e04c079cade18c32bcf615552ac5dfba6a151b29abd2319c368764a5d297e
 F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092
 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -798,7 +798,7 @@ F src/trigger.c 4bf3bfb3851d165e4404a9f9e69357345f3f7103378c07e07139fdd8aeb7bd20
 F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
 F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
 F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
-F src/util.c 1fe895c652b3b1b9f4a298b95ebfcfd95e3383952dd26a5baf1c47655c483e5d
+F src/util.c f264a84eda716ae009089f1d788b55718062810792b0bfa331e7899f2add39c6
 F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
 F src/vdbe.c 6c57525d7db0232d52687d30da1093db0c152f14206c2ef1adf0c19a09d863e3
 F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
@@ -2196,8 +2196,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P ff9008e7615d877e6cc852c60097777006b274971646d368eaa56b99a7acf6c7
-R ff4274da2fda9408dbca94e175d79321
+P e75f30c7e66e725a2f3f46c7d4d69a2ff925e2de9a86c3a6ec38897545b43a58
+R afdcaa646f7e2c48f9521367d5bf245b
 U drh
-Z 399684f83892f09fa733c31059114ff6
+Z d27904683472a5531629ef5a5e64c8f1
 # Remove this line to create a well-formed Fossil manifest.
index f5219e16ef08c120ec03ce5642ff36eb70814bd5..8946699b1f42647ef417c9da89c9f258e7f5108f 100644 (file)
@@ -1 +1 @@
-e75f30c7e66e725a2f3f46c7d4d69a2ff925e2de9a86c3a6ec38897545b43a58
+2197677491dfc5ec87b57bbf807776875248a250f80ce9a5ce94ae385bb1d2bc
index 26a194782415427cbe4432f739dda5e5e036b8fa..5aa8972035e4417a749703c16dc70b01d5586bac 100644 (file)
@@ -4828,17 +4828,22 @@ struct PrintfArguments {
   sqlite3_value **apArg;   /* The argument values */
 };
 
+/*
+** Maxium number of base-10 digits in an unsigned 64-bit integer
+*/
+#define SQLITE_U64_DIGITS 20
+
 /*
 ** An instance of this object receives the decoding of a floating point
 ** value into an approximate decimal representation.
 */
 struct FpDecode {
-  int n;               /* Significant digits in the decode */
-  int iDP;             /* Location of the decimal point */
-  char *z;             /* Start of significant digits */
-  char zBuf[20];       /* Storage for significant digits */
-  char sign;           /* '+' or '-' */
-  char isSpecial;      /* 1: Infinity  2: NaN */
+  int n;                           /* Significant digits in the decode */
+  int iDP;                         /* Location of the decimal point */
+  char *z;                         /* Start of significant digits */
+  char zBuf[SQLITE_U64_DIGITS+1];  /* Storage for significant digits */
+  char sign;                       /* '+' or '-' */
+  char isSpecial;                  /* 1: Infinity  2: NaN */
 };
 
 void sqlite3FpDecode(FpDecode*,double,int,int);
index eae618da310051b3e579440f3e4299d6491cae91..9a0456f214098db0feefa5fd2bf2105756ddc1c6 100644 (file)
@@ -998,6 +998,69 @@ static const union {
   "90919293949596979899"
 };
 
+/*
+** ARMv6, ARMv7, PPC32 are known to not support hardware u64 division.
+*/
+#if (defined(__arm__) && !defined(__aarch64__)) || \
+    (defined(__ppc__) && !defined(__ppc64__))
+# define SQLITE_AVOID_U64_DIVIDE 1
+#endif
+
+#ifdef SQLITE_AVOID_U64_DIVIDE
+/*
+** Render an unsigned 64-bit integer as text onto the end of a 2-byte
+** aligned buffer that is SQLITE_U64_DIGIT+1 bytes long.  The last byte
+** of the buffer will be filled with a \000 byte.
+**
+** Return the index into the buffer of the first byte.
+**
+** This routine is used on platforms where u64-division is slow because
+** it is not available in hardware and has to be emulated in software.
+** It seeks to minimize the number of u64 divisions and use u32 divisions
+** instead.  It is slower on platforms that have hardware u64 division,
+** but much faster on platforms that do not.
+*/
+static int sqlite3UInt64ToText(u64 v, char *zOut){
+  u32 x32, kk;
+  int i;
+  zOut[SQLITE_U64_DIGITS] = 0;
+  i = SQLITE_U64_DIGITS;
+  assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[0]) );
+  assert( TWO_BYTE_ALIGNMENT(zOut) );
+  while( (v>>32)!=0 ){
+    u32 y, x0, x1, y0, y1;
+    x32 = v % 100000000;
+    v   = v / 100000000;
+    y = x32 % 10000;
+    x32 /= 10000;
+    x1 = x32 / 100;
+    x0 = x32 % 100;
+    y1 = y / 100;
+    y0 = y % 100;
+    assert( i>=8 );
+    i -= 8;
+    *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[x1*2];
+    *(u16*)(&zOut[i+2]) = *(u16*)&sqlite3DigitPairs.a[x0*2];
+    *(u16*)(&zOut[i+4]) = *(u16*)&sqlite3DigitPairs.a[y1*2];
+    *(u16*)(&zOut[i+6]) = *(u16*)&sqlite3DigitPairs.a[y0*2];
+  }
+  x32 = v;
+  while( x32>=10 ){
+    kk  = x32 % 100;
+    x32 = x32 / 100;
+    assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk*2]) );
+    assert( i>=2 );
+    i -= 2;
+    assert( TWO_BYTE_ALIGNMENT(&zOut[i]) );
+    *(u16*)(&zOut[i]) = *(u16*)&sqlite3DigitPairs.a[kk*2];
+  }
+  if( x32 ){
+    assert( i>0 );
+    zOut[--i] = x32 + '0';
+  }
+  return i;
+}
+#endif /* defined(SQLITE_AVOID_U64_DIVIDE) */
 
 /*
 ** Render an signed 64-bit integer as text.  Store the result in zOut[] and
@@ -1011,7 +1074,7 @@ int sqlite3Int64ToText(i64 v, char *zOut){
   int i;
   u64 x;
   union {
-    char a[23];
+    char a[SQLITE_U64_DIGITS+1];
     u16 forceAlignment;
   } u;
   if( v>0 ){
@@ -1023,6 +1086,9 @@ int sqlite3Int64ToText(i64 v, char *zOut){
   }else{
     x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
   }
+#ifdef SQLITE_AVOID_U64_DIVIDE
+  i = sqlite3UInt64ToText(x, u.a);
+#else
   i = sizeof(u.a)-1;
   u.a[i] = 0;
   while( x>=10 ){
@@ -1036,6 +1102,7 @@ int sqlite3Int64ToText(i64 v, char *zOut){
   if( x ){
     u.a[--i] = x + '0';
   }
+#endif /* SQLITE_AVOID_U64_DIVIDE */
   if( v<0 ) u.a[--i] = '-';
   memcpy(zOut, &u.a[i], sizeof(u.a)-i);
   return sizeof(u.a)-1-i;
@@ -1355,37 +1422,43 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
   /* Extract significant digits, start at the right-most slot in p->zBuf
   ** and working back to the right.  "i" keeps track of the next slot in
   ** which to store a digit. */
-  i = sizeof(p->zBuf)-1;
-  zBuf = p->zBuf;
+  assert( sizeof(p->zBuf)==SQLITE_U64_DIGITS+1 );
   assert( v>0 );
+  zBuf = p->zBuf;
+#ifdef SQLITE_AVOID_U64_DIVIDE
+  i = sqlite3UInt64ToText(v, zBuf);
+#else
+  i = SQLITE_U64_DIGITS;
   while( v>=10 ){
     int kk = (v%100)*2;
     assert( TWO_BYTE_ALIGNMENT(&sqlite3DigitPairs.a[kk]) );
-    assert( TWO_BYTE_ALIGNMENT(&zBuf[i-1]) );
-    *(u16*)(&zBuf[i-1]) = *(u16*)&sqlite3DigitPairs.a[kk];
+    assert( TWO_BYTE_ALIGNMENT(&zBuf[i]) );
+    assert( i-2>=0 );
+    *(u16*)(&zBuf[i-2]) = *(u16*)&sqlite3DigitPairs.a[kk];
     i -= 2;
     v /= 100;
   }
   if( v ){
     assert( v<10 );
-    zBuf[i--] = v + '0';
+    assert( i>0 );
+    zBuf[--i] = v + '0';
   }
-  assert( i>=0 && i<sizeof(p->zBuf)-1 );
-  n = sizeof(p->zBuf) - 1 - i;  /* Total number of digits extracted */
+#endif /* SQLITE_AVOID_U64_DIVIDE */
+  assert( i>=0 && i<SQLITE_U64_DIGITS );
+  n = SQLITE_U64_DIGITS - i;  /* Total number of digits extracted */
   assert( n>0 );
-  assert( n<sizeof(p->zBuf) );
-  testcase( n==sizeof(p->zBuf)-1 );
+  assert( n<=SQLITE_U64_DIGITS );
   p->iDP = n + exp;
   if( iRound<=0 ){
     iRound = p->iDP - iRound;
-    if( iRound==0 && zBuf[i+1]>='5' ){
+    if( iRound==0 && zBuf[i]>='5' ){
       iRound = 1;
-      zBuf[i--] = '0';
+      zBuf[--i] = '0';
       n++;
       p->iDP++;
     }
   }
-  z = &zBuf[i+1];  /* z points to the first digit */
+  z = &zBuf[i];  /* z points to the first digit */
   if( iRound>0 && (iRound<n || n>mxRound) ){
     if( iRound>mxRound ) iRound = mxRound;
     if( iRound==17 ){