Use static inline functions for float <-> Datum conversions.

Now that we are OK with using static inline functions, we can use them
to avoid function call overhead of pass-by-val versions of Float4GetDatum,
DatumGetFloat8, and Float8GetDatum. Those functions are only a few CPU
instructions long, but they could not be written into macros previously,
because we need a local union variable for the conversion.

I kept the pass-by-ref versions as regular functions. They are very simple
too, but they call palloc() anyway, so shaving a few instructions from the
function call doesn't seem so important there.

Discussion: <dbb82a4a-2c15-ba27-dd0a-009d2aa72b77@iki.fi>
This commit is contained in:
Heikki Linnakangas 2016-08-31 16:00:28 +03:00
parent 0e0f43d6fd
commit 14cca1bf8e
2 changed files with 67 additions and 59 deletions

View File

@ -2126,10 +2126,7 @@ fmgr(Oid procedureId,...)
*
* int8, float4, and float8 can be passed by value if Datum is wide enough.
* (For backwards-compatibility reasons, we allow pass-by-ref to be chosen
* at compile time even if pass-by-val is possible.) For the float types,
* we need a support routine even if we are passing by value, because many
* machines pass int and float function parameters/results differently;
* so we need to play weird games with unions.
* at compile time even if pass-by-val is possible.)
*
* Note: there is only one switch controlling the pass-by-value option for
* both int8 and float8; this is to avoid making things unduly complicated
@ -2149,77 +2146,29 @@ Int64GetDatum(int64 X)
}
#endif /* USE_FLOAT8_BYVAL */
#ifndef USE_FLOAT4_BYVAL
Datum
Float4GetDatum(float4 X)
{
#ifdef USE_FLOAT4_BYVAL
union
{
float4 value;
int32 retval;
} myunion;
myunion.value = X;
return SET_4_BYTES(myunion.retval);
#else
float4 *retval = (float4 *) palloc(sizeof(float4));
*retval = X;
return PointerGetDatum(retval);
}
#endif
}
#ifdef USE_FLOAT4_BYVAL
float4
DatumGetFloat4(Datum X)
{
union
{
int32 value;
float4 retval;
} myunion;
myunion.value = GET_4_BYTES(X);
return myunion.retval;
}
#endif /* USE_FLOAT4_BYVAL */
#ifndef USE_FLOAT8_BYVAL
Datum
Float8GetDatum(float8 X)
{
#ifdef USE_FLOAT8_BYVAL
union
{
float8 value;
int64 retval;
} myunion;
myunion.value = X;
return SET_8_BYTES(myunion.retval);
#else
float8 *retval = (float8 *) palloc(sizeof(float8));
*retval = X;
return PointerGetDatum(retval);
}
#endif
}
#ifdef USE_FLOAT8_BYVAL
float8
DatumGetFloat8(Datum X)
{
union
{
int64 value;
float8 retval;
} myunion;
myunion.value = GET_8_BYTES(X);
return myunion.retval;
}
#endif /* USE_FLOAT8_BYVAL */
/*-------------------------------------------------------------------------

View File

@ -656,6 +656,14 @@ extern Datum Int64GetDatum(int64 X);
#define UInt64GetDatum(X) Int64GetDatum((int64) (X))
#endif
/*
* Float <-> Datum conversions
*
* These have to be implemented as inline functions rather than macros, when
* passing by value, because many machines pass int and float function
* parameters/results differently; so we need to play weird games with unions.
*/
/*
* DatumGetFloat4
* Returns 4-byte floating point value of a datum.
@ -664,7 +672,18 @@ extern Datum Int64GetDatum(int64 X);
*/
#ifdef USE_FLOAT4_BYVAL
extern float4 DatumGetFloat4(Datum X);
static inline float4
DatumGetFloat4(Datum X)
{
union
{
int32 value;
float4 retval;
} myunion;
myunion.value = GET_4_BYTES(X);
return myunion.retval;
}
#else
#define DatumGetFloat4(X) (* ((float4 *) DatumGetPointer(X)))
#endif
@ -676,8 +695,22 @@ extern float4 DatumGetFloat4(Datum X);
* Note: if float4 is pass by reference, this function returns a reference
* to palloc'd space.
*/
#ifdef USE_FLOAT4_BYVAL
static inline Datum
Float4GetDatum(float4 X)
{
union
{
float4 value;
int32 retval;
} myunion;
myunion.value = X;
return SET_4_BYTES(myunion.retval);
}
#else
extern Datum Float4GetDatum(float4 X);
#endif
/*
* DatumGetFloat8
@ -687,7 +720,18 @@ extern Datum Float4GetDatum(float4 X);
*/
#ifdef USE_FLOAT8_BYVAL
extern float8 DatumGetFloat8(Datum X);
static inline float8
DatumGetFloat8(Datum X)
{
union
{
int64 value;
float8 retval;
} myunion;
myunion.value = GET_8_BYTES(X);
return myunion.retval;
}
#else
#define DatumGetFloat8(X) (* ((float8 *) DatumGetPointer(X)))
#endif
@ -700,7 +744,22 @@ extern float8 DatumGetFloat8(Datum X);
* to palloc'd space.
*/
#ifdef USE_FLOAT8_BYVAL
static inline Datum
Float8GetDatum(float8 X)
{
union
{
float8 value;
int64 retval;
} myunion;
myunion.value = X;
return SET_8_BYTES(myunion.retval);
}
#else
extern Datum Float8GetDatum(float8 X);
#endif
/*