Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Vector64.Create for constants #101662

Merged
merged 3 commits into from May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 40 additions & 56 deletions src/coreclr/jit/codegenarm64.cpp
Expand Up @@ -2395,73 +2395,57 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre
{
#if defined(FEATURE_SIMD)
case TYP_SIMD8:
{
if (vecCon->IsAllBitsSet())
{
emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_2S);
}
else if (vecCon->IsZero())
{
emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_2S);
}
else
{
// Get a temp integer register to compute long address.
regNumber addrReg = internalRegisters.GetSingle(tree);

simd8_t constValue;
memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd8_t));

CORINFO_FIELD_HANDLE hnd = emit->emitSimd8Const(constValue);
emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0);
}
break;
}

case TYP_SIMD12:
{
if (vecCon->IsAllBitsSet())
{
emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_4S);
}
else if (vecCon->IsZero())
{
emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_4S);
}
else
{
// Get a temp integer register to compute long address.
regNumber addrReg = internalRegisters.GetSingle(tree);

simd16_t constValue = {};
memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd12_t));

CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue);
emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0);
}
break;
}

case TYP_SIMD16:
{
// We ignore any differences between SIMD12 and SIMD16 here if we can broadcast the value
// via mvni/movi.
const bool is8 = tree->TypeIs(TYP_SIMD8);
if (vecCon->IsAllBitsSet())
{
emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, INS_OPTS_4S);
emit->emitIns_R_I(INS_mvni, attr, targetReg, 0, is8 ? INS_OPTS_2S : INS_OPTS_4S);
}
else if (vecCon->IsZero())
{
emit->emitIns_R_I(INS_movi, attr, targetReg, 0, INS_OPTS_4S);
emit->emitIns_R_I(INS_movi, attr, targetReg, 0, is8 ? INS_OPTS_2S : INS_OPTS_4S);
}
else
{
// Get a temp integer register to compute long address.
regNumber addrReg = internalRegisters.GetSingle(tree);

simd16_t constValue;
memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd16_t));

CORINFO_FIELD_HANDLE hnd = emit->emitSimd16Const(constValue);
emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0);
simd16_t val = vecCon->gtSimd16Val;
if (ElementsAreSame(val.i32, is8 ? 2 : 4) &&
emitter::emitIns_valid_imm_for_movi(val.i32[0], EA_4BYTE))
{
emit->emitIns_R_I(INS_movi, attr, targetReg, val.i32[0], is8 ? INS_OPTS_2S : INS_OPTS_4S);
}
else if (ElementsAreSame(val.i16, is8 ? 4 : 8) &&
emitter::emitIns_valid_imm_for_movi(val.i16[0], EA_2BYTE))
{
emit->emitIns_R_I(INS_movi, attr, targetReg, val.i16[0], is8 ? INS_OPTS_4H : INS_OPTS_8H);
}
else if (ElementsAreSame(val.i8, is8 ? 8 : 16) &&
emitter::emitIns_valid_imm_for_movi(val.i8[0], EA_1BYTE))
{
emit->emitIns_R_I(INS_movi, attr, targetReg, val.i8[0], is8 ? INS_OPTS_8B : INS_OPTS_16B);
}
else
{
// Get a temp integer register to compute long address.
regNumber addrReg = internalRegisters.GetSingle(tree);
CORINFO_FIELD_HANDLE hnd;
if (is8)
{
simd8_t constValue;
memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd8_t));
hnd = emit->emitSimd8Const(constValue);
}
else
{
simd16_t constValue;
memcpy(&constValue, &vecCon->gtSimdVal, sizeof(simd16_t));
hnd = emit->emitSimd16Const(constValue);
}
emit->emitIns_R_C(INS_ldr, attr, targetReg, addrReg, hnd, 0);
}
}
break;
}
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/simd.h
Expand Up @@ -4,6 +4,17 @@
#ifndef _SIMD_H_
#define _SIMD_H_

template <typename T>
static bool ElementsAreSame(T* array, size_t size)
{
for (size_t i = 1; i < size; i++)
{
if (array[0] != array[i])
return false;
}
return true;
}

struct simd8_t
{
union
Expand Down