[a64] Use LoadV128Const for OPCODE_SPLAT(constant)
Should allow certain splats to opportunistically emit the best assembly when possible. Also use `std::bit_cast` rather than an inline `union` type to directly cast a `float` into a `uint32_t`.
This commit is contained in:
@@ -31,8 +31,7 @@ volatile int anchor_vector = 0;
|
|||||||
struct SPLAT_I8 : Sequence<SPLAT_I8, I<OPCODE_SPLAT, V128Op, I8Op>> {
|
struct SPLAT_I8 : Sequence<SPLAT_I8, I<OPCODE_SPLAT, V128Op, I8Op>> {
|
||||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.movi(VReg(i.dest.reg().getIdx()).b16,
|
LoadV128Const(e, i.dest.reg().getIdx(), vec128b(i.src1.constant()));
|
||||||
static_cast<uint8_t>(i.src1.constant()));
|
|
||||||
} else {
|
} else {
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).b16, i.src1);
|
e.dup(VReg(i.dest.reg().getIdx()).b16, i.src1);
|
||||||
}
|
}
|
||||||
@@ -41,8 +40,7 @@ struct SPLAT_I8 : Sequence<SPLAT_I8, I<OPCODE_SPLAT, V128Op, I8Op>> {
|
|||||||
struct SPLAT_I16 : Sequence<SPLAT_I16, I<OPCODE_SPLAT, V128Op, I16Op>> {
|
struct SPLAT_I16 : Sequence<SPLAT_I16, I<OPCODE_SPLAT, V128Op, I16Op>> {
|
||||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
e.mov(e.w0, static_cast<uint64_t>(i.src1.constant() & 0xFFFF));
|
LoadV128Const(e, i.dest.reg().getIdx(), vec128s(i.src1.constant()));
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).h8, e.w0);
|
|
||||||
} else {
|
} else {
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).h8, i.src1);
|
e.dup(VReg(i.dest.reg().getIdx()).h8, i.src1);
|
||||||
}
|
}
|
||||||
@@ -51,10 +49,7 @@ struct SPLAT_I16 : Sequence<SPLAT_I16, I<OPCODE_SPLAT, V128Op, I16Op>> {
|
|||||||
struct SPLAT_I32 : Sequence<SPLAT_I32, I<OPCODE_SPLAT, V128Op, I32Op>> {
|
struct SPLAT_I32 : Sequence<SPLAT_I32, I<OPCODE_SPLAT, V128Op, I32Op>> {
|
||||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
uint32_t val = static_cast<uint32_t>(i.src1.constant());
|
LoadV128Const(e, i.dest.reg().getIdx(), vec128i(i.src1.constant()));
|
||||||
// Use movz/movn via mov(xreg, uint64) for full 32-bit range.
|
|
||||||
e.mov(e.x0, static_cast<uint64_t>(val));
|
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).s4, e.w0);
|
|
||||||
} else {
|
} else {
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).s4, i.src1);
|
e.dup(VReg(i.dest.reg().getIdx()).s4, i.src1);
|
||||||
}
|
}
|
||||||
@@ -63,13 +58,8 @@ struct SPLAT_I32 : Sequence<SPLAT_I32, I<OPCODE_SPLAT, V128Op, I32Op>> {
|
|||||||
struct SPLAT_F32 : Sequence<SPLAT_F32, I<OPCODE_SPLAT, V128Op, F32Op>> {
|
struct SPLAT_F32 : Sequence<SPLAT_F32, I<OPCODE_SPLAT, V128Op, F32Op>> {
|
||||||
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
static void Emit(A64Emitter& e, const EmitArgType& i) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
union {
|
LoadV128Const(e, i.dest.reg().getIdx(),
|
||||||
float f;
|
vec128i(std::bit_cast<uint32_t, float>(i.src1.constant())));
|
||||||
uint32_t u;
|
|
||||||
} c;
|
|
||||||
c.f = i.src1.constant();
|
|
||||||
e.mov(e.w0, static_cast<uint64_t>(c.u));
|
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).s4, e.w0);
|
|
||||||
} else {
|
} else {
|
||||||
int src_idx = i.src1.reg().getIdx();
|
int src_idx = i.src1.reg().getIdx();
|
||||||
e.dup(VReg(i.dest.reg().getIdx()).s4, VReg(src_idx).s4[0]);
|
e.dup(VReg(i.dest.reg().getIdx()).s4, VReg(src_idx).s4[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user