Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e3d41d0

Browse files
committed
Apply auto-vectorization to the inner loop of div_var_fast().
This loop is basically the same as the inner loop of mul_var(), which was auto-vectorized in commit 8870917, but the compiler will only consider auto-vectorizing the div_var_fast() loop if the assignment target div[qi + i] is replaced by div_qi[i], where div_qi = &div[qi]. Additionally, since the compiler doesn't know that qdigit is guaranteed to fit in a 16-bit NumericDigit, cast it to NumericDigit before multiplying to make the resulting auto-vectorized code more efficient (avoiding unnecessary multiplication of the high 16 bits). While at it, per suggestion from Tom Lane, change var1digit in mul_var() to be a NumericDigit rather than an int for the same reason. This actually makes no difference with modern gcc, but it might help other compilers generate more efficient assembly. Dean Rasheed, reviewed by Tom Lane. Discussion: https://postgr.es/m/CAEZATCVwsBi-ND-t82Cuuh1=8ee6jdOpzsmGN+CUZB6yjLg9jw@mail.gmail.com
1 parent 6b04abd commit e3d41d0

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/backend/utils/adt/numeric.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -8323,7 +8323,7 @@ mul_var(const NumericVar *var1, const NumericVar *var2, NumericVar *result,
83238323
*/
83248324
for (i1 = Min(var1ndigits - 1, res_ndigits - 3); i1 >= 0; i1--)
83258325
{
8326-
int var1digit = var1digits[i1];
8326+
NumericDigit var1digit = var1digits[i1];
83278327

83288328
if (var1digit == 0)
83298329
continue;
@@ -8908,13 +8908,22 @@ div_var_fast(const NumericVar *var1, const NumericVar *var2,
89088908
* which would make the new value simply div[qi] mod vardigits[0].
89098909
* The lower-order terms in qdigit can change this result by not
89108910
* more than about twice INT_MAX/NBASE, so overflow is impossible.
8911+
*
8912+
* This inner loop is the performance bottleneck for division, so
8913+
* code it in the same way as the inner loop of mul_var() so that
8914+
* it can be auto-vectorized. We cast qdigit to NumericDigit
8915+
* before multiplying to allow the compiler to generate more
8916+
* efficient code (using 16-bit multiplication), which is safe
8917+
* since we know that the quotient digit is off by at most one, so
8918+
* there is no overflow risk.
89118919
*/
89128920
if (qdigit != 0)
89138921
{
89148922
int istop = Min(var2ndigits, div_ndigits - qi + 1);
8923+
int *div_qi = &div[qi];
89158924

89168925
for (i = 0; i < istop; i++)
8917-
div[qi + i] -= qdigit * var2digits[i];
8926+
div_qi[i] -= ((NumericDigit) qdigit) * var2digits[i];
89188927
}
89198928
}
89208929

0 commit comments

Comments
 (0)