load 128 bit floating point constants from global (#21279)

This commit is contained in:
Walter Bright 2025-04-20 17:34:28 -07:00 committed by GitHub
parent ddb917f8e8
commit 4aa543a2a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 76 additions and 5 deletions

View file

@ -313,6 +313,7 @@ static if (0)
configv.vasm = vasm;
configv.verbose = verbose;
go.AArch64 = arm;
if (optimize)
go_flag(go, cast(char*)"-o".ptr);

View file

@ -1144,7 +1144,7 @@ int el_countCommas(const(elem)* e)
* Convert floating point constant to a read-only symbol.
* Needed iff floating point code can't load immediate constants.
*/
@trusted
private @trusted
elem* el_convfloat(ref GlobalOptimizer go, elem* e)
{
//printf("el_convfloat()\n"); elem_print(e);
@ -1232,12 +1232,75 @@ elem* el_convfloat(ref GlobalOptimizer go, elem* e)
return e;
}
/************************************
* Convert AArch64 128 bit floating point constant to a read-only symbol.
* Params:
* go = optimizer state
* e = floating point constant
* Returns:
* read-only constant variable
*/
private @trusted
elem* el_convreal(ref GlobalOptimizer go, elem* e)
{
//printf("el_convfloat()\n"); elem_print(e);
ubyte[32] buffer = void;
tym_t ty = e.Ety;
int sz = tysize(ty);
assert(sz <= buffer.length);
void* p;
switch (tybasic(ty))
{
case TYldouble:
case TYildouble:
/* The size, alignment, and padding of long doubles may be different
* from host to target
*/
p = buffer.ptr;
// TODO AArch64 these are supposed to be 128 bit floats, not 80 bit
memset(buffer.ptr, 0, sz); // ensure padding is 0
memcpy(buffer.ptr, &e.Vldouble, 10);
break;
case TYcldouble:
p = buffer.ptr;
memset(buffer.ptr, 0, sz);
memcpy(buffer.ptr, &e.Vcldouble.re, 10);
memcpy(buffer.ptr + tysize(TYldouble), &e.Vcldouble.im, 10);
break;
default:
return e; // not necessary
}
static if (0)
{
printf("%gL+%gLi\n", cast(double)e.Vcldouble.re, cast(double)e.Vcldouble.im);
printf("el_convfloat() %g %g sz=%d\n", e.Vcdouble.re, e.Vcdouble.im, sz);
printf("el_convfloat(): sz = %d\n", sz);
ushort* p = cast(ushort*)&e.Vcldouble;
for (int i = 0; i < sz/2; i++) printf("%04x ", p[i]);
printf("\n");
}
Symbol* s = out_readonly_sym(ty, p, sz);
el_free(e);
elem* ep = el_ptr(s);
elem* ec = el_una(OPind, ty, ep);
go.changes++;
//printf("s: %s %d:x%x\n", s.Sident, s.Sseg, s.Soffset);
return ec;
}
/************************************
* Convert vector constant to a read-only symbol.
* Needed iff vector code can't load immediate constants.
*/
@trusted
private @trusted
elem* el_convxmm(ref GlobalOptimizer go, elem* e)
{
// Do not convert if the constants can be loaded with the special XMM instructions
@ -1272,7 +1335,7 @@ elem* el_convxmm(ref GlobalOptimizer go, elem* e)
* stored in the static data segment.
*/
@trusted
private @trusted
elem* el_convstring(elem* e)
{
//printf("el_convstring()\n");
@ -1386,6 +1449,7 @@ void shrinkLongDoubleConstantIfPossible(elem* e)
/*************************
* Run through a tree converting it to CODGEN.
*/
public
@trusted
elem* el_convert(ref GlobalOptimizer go, elem* e)
{
@ -1400,8 +1464,13 @@ elem* el_convert(ref GlobalOptimizer go, elem* e)
case OPconst:
if (tyvector(e.Ety))
e = el_convxmm(go, e);
else if (tyfloating(e.Ety) && config.inline8087)
e = el_convfloat(go, e);
else if (tyfloating(e.Ety))
{
if (config.inline8087)
e = el_convfloat(go, e);
else if (go.AArch64)
e = el_convreal(go, e);
}
break;
case OPstring:

View file

@ -74,6 +74,7 @@ struct DefNode
*/
struct GlobalOptimizer
{
bool AArch64; // AArch64 is the target
mftype mfoptim;
uint changes; // # of optimizations performed