mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-26 05:00:13 +01:00
Arm64: Optimize SVE VInsElement
This can be done without storing any data to memory and also compressing the amount of instructions being used. Thanks to @dougallj for the optimization suggestions.
This commit is contained in:
1 parent
ed7f1b017d
commit
398a70312e
5 files changed
+1091
-2563
No files matched your search
@@ -2555,59 +2555,33 @@ DEF_OP(VInsElement) {
|
||||
ElementSize == 4 ? ARMEmitter::SubRegSize::i32Bit :
|
||||
ElementSize == 8 ? ARMEmitter::SubRegSize::i64Bit : ARMEmitter::SubRegSize::i128Bit;
|
||||
|
||||
// We're going to use this to create our predicate register literal.
|
||||
// On an SVE 256-bit capable system, the predicate register will be
|
||||
// 32-bit in size. We want to set up only the element corresponding
|
||||
// to the destination index, since we're going to copy over the equivalent
|
||||
// indexed element from the source vector.
|
||||
const auto Data = [ElementSize, DestIdx]() -> uint32_t {
|
||||
const auto Log2ElementSize = FEXCore::ilog2(ElementSize);
|
||||
|
||||
[[maybe_unused]] const auto MaxIndex = (32U >> Log2ElementSize) - 1;
|
||||
LOGMAN_THROW_AA_FMT(DestIdx <= MaxIndex, "DestIdx ({}) out of range. Must be within [0, {}]",
|
||||
DestIdx, MaxIndex);
|
||||
|
||||
const auto ShiftAmount = DestIdx << Log2ElementSize;
|
||||
|
||||
switch (ElementSize) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
return 1U << ShiftAmount;
|
||||
case 16:
|
||||
// Predicates can't be subdivided into the Q format, so we can just set up
|
||||
// the predicate to select the two adjacent doublewords.
|
||||
return 0x101U << ShiftAmount;
|
||||
default:
|
||||
FEX_UNREACHABLE;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
}();
|
||||
|
||||
// Load our predicate register.
|
||||
const auto Predicate = ARMEmitter::PReg::p0;
|
||||
ARMEmitter::ForwardLabel DataLocation;
|
||||
adr(TMP1, &DataLocation);
|
||||
ldr(Predicate, TMP1);
|
||||
|
||||
// Broadcast our source value across a temporary,
|
||||
// then combine with the destination.
|
||||
dup(SubRegSize, VTMP2.Z(), SrcVector.Z(), SrcIdx);
|
||||
mov(Dst.Z(), Reg.Z());
|
||||
if (ElementSize == 16) {
|
||||
mov(ARMEmitter::SubRegSize::i64Bit, Dst.Z(), Predicate.Merging(), VTMP2.Z());
|
||||
}
|
||||
else {
|
||||
mov(SubRegSize, Dst.Z(), Predicate.Merging(), VTMP2.Z());
|
||||
|
||||
// We don't need to move the data unnecessarily if
|
||||
// DestVector just so happens to also be the IR op
|
||||
// destination.
|
||||
if (Dst != Reg) {
|
||||
mov(Dst.Z(), Reg.Z());
|
||||
}
|
||||
|
||||
// Set up a label to jump over the data we inserted, so we don't try and execute it.
|
||||
ARMEmitter::ForwardLabel PastConstant;
|
||||
b(&PastConstant);
|
||||
Bind(&DataLocation);
|
||||
dc32(Data);
|
||||
Bind(&PastConstant);
|
||||
constexpr auto Predicate = ARMEmitter::PReg::p0;
|
||||
|
||||
if (ElementSize == 16) {
|
||||
if (DestIdx == 0) {
|
||||
mov(ARMEmitter::SubRegSize::i8Bit, Dst.Z(), PRED_TMP_16B.Merging(), VTMP2.Z());
|
||||
} else {
|
||||
not_(Predicate, PRED_TMP_32B.Zeroing(), PRED_TMP_16B);
|
||||
mov(ARMEmitter::SubRegSize::i8Bit, Dst.Z(), Predicate.Merging(), VTMP2.Z());
|
||||
}
|
||||
} else {
|
||||
const auto UpperBound = 16 >> FEXCore::ilog2(ElementSize);
|
||||
const auto TargetElement = static_cast<int>(DestIdx) - UpperBound;
|
||||
index(SubRegSize, VTMP1.Z(), -UpperBound, 1);
|
||||
cmpeq(SubRegSize, Predicate, PRED_TMP_32B.Zeroing(), VTMP1.Z(), TargetElement);
|
||||
mov(SubRegSize, Dst.Z(), Predicate.Merging(), VTMP2.Z());
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOGMAN_THROW_AA_FMT(ElementSize == 1 || ElementSize == 2 || ElementSize == 4 || ElementSize == 8, "Invalid size");
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -24,7 +24,7 @@
|
||||
]
|
||||
},
|
||||
"vpshufb ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 21,
|
||||
"ExpectedInstructionCount": 13,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x00 256-bit"
|
||||
@@ -35,21 +35,13 @@
|
||||
"mov z6.b, #-113",
|
||||
"and z5.d, z5.d, z6.d",
|
||||
"tbl v6.16b, {v4.16b}, v5.16b",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, z4.q[1]",
|
||||
"mov z4.d, z4.d",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x101",
|
||||
"mov z4.b, p6/m, z1.b",
|
||||
"tbl v4.16b, {v4.16b}, v5.16b",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, q4",
|
||||
"mov z4.d, z6.d",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"not p0.b, p7/z, p6.b",
|
||||
"mov z4.b, p0/m, z1.b",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -69,7 +61,7 @@
|
||||
]
|
||||
},
|
||||
"vphaddw ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 22,
|
||||
"ExpectedInstructionCount": 18,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x01 256-bit"
|
||||
@@ -82,20 +74,16 @@
|
||||
"uzp1 z4.h, z0.h, z0.h",
|
||||
"uzp2 z1.h, z0.h, z0.h",
|
||||
"splice z4.d, p6, z4.d, z1.d",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -115,7 +103,7 @@
|
||||
]
|
||||
},
|
||||
"vphaddd ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 22,
|
||||
"ExpectedInstructionCount": 18,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x02 256-bit"
|
||||
@@ -128,20 +116,16 @@
|
||||
"uzp1 z4.s, z0.s, z0.s",
|
||||
"uzp2 z1.s, z0.s, z0.s",
|
||||
"splice z4.d, p6, z4.d, z1.d",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -162,7 +146,7 @@
|
||||
]
|
||||
},
|
||||
"vphaddsw ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 20,
|
||||
"ExpectedInstructionCount": 16,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x03 256-bit"
|
||||
@@ -173,20 +157,16 @@
|
||||
"uzp1 z6.h, z4.h, z5.h",
|
||||
"uzp2 z4.h, z4.h, z5.h",
|
||||
"sqadd z4.h, z6.h, z4.h",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -251,7 +231,7 @@
|
||||
]
|
||||
},
|
||||
"vphsubw ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 20,
|
||||
"ExpectedInstructionCount": 16,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x05 256-bit"
|
||||
@@ -262,20 +242,16 @@
|
||||
"uzp1 z6.h, z4.h, z5.h",
|
||||
"uzp2 z4.h, z4.h, z5.h",
|
||||
"sub z4.h, z6.h, z4.h",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -297,7 +273,7 @@
|
||||
]
|
||||
},
|
||||
"vphsubd ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 20,
|
||||
"ExpectedInstructionCount": 16,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x06 256-bit"
|
||||
@@ -308,20 +284,16 @@
|
||||
"uzp1 z6.s, z4.s, z5.s",
|
||||
"uzp2 z4.s, z4.s, z5.s",
|
||||
"sub z4.s, z6.s, z4.s",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -342,7 +314,7 @@
|
||||
]
|
||||
},
|
||||
"vphsubsw ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 20,
|
||||
"ExpectedInstructionCount": 16,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x07 256-bit"
|
||||
@@ -353,20 +325,16 @@
|
||||
"uzp1 z6.h, z4.h, z5.h",
|
||||
"uzp2 z4.h, z4.h, z5.h",
|
||||
"sqsub z4.h, z6.h, z4.h",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -549,7 +517,7 @@
|
||||
]
|
||||
},
|
||||
"vpermilps ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 24,
|
||||
"ExpectedInstructionCount": 20,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x0c 256-bit"
|
||||
@@ -568,13 +536,9 @@
|
||||
"mov z6.s, w20",
|
||||
"mov z7.d, #0",
|
||||
"mov z8.b, #16",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, q8",
|
||||
"mov z7.d, z7.d",
|
||||
"mov z7.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"not p0.b, p7/z, p6.b",
|
||||
"mov z7.b, p0/m, z1.b",
|
||||
"add z6.b, z6.b, z7.b",
|
||||
"add z5.b, z6.b, z5.b",
|
||||
"tbl z4.b, {z4.b}, z5.b",
|
||||
@@ -610,7 +574,7 @@
|
||||
]
|
||||
},
|
||||
"vpermilpd ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 29,
|
||||
"ExpectedInstructionCount": 25,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x0d 256-bit"
|
||||
@@ -634,13 +598,9 @@
|
||||
"mov z6.d, x20",
|
||||
"mov z7.d, #0",
|
||||
"mov z8.b, #16",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, q8",
|
||||
"mov z7.d, z7.d",
|
||||
"mov z7.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"not p0.b, p7/z, p6.b",
|
||||
"mov z7.b, p0/m, z1.b",
|
||||
"add z6.b, z6.b, z7.b",
|
||||
"add z5.b, z6.b, z5.b",
|
||||
"tbl z4.b, {z4.b}, z5.b",
|
||||
@@ -1319,7 +1279,7 @@
|
||||
]
|
||||
},
|
||||
"vpackusdw ymm0, ymm1, ymm2": {
|
||||
"ExpectedInstructionCount": 23,
|
||||
"ExpectedInstructionCount": 19,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map 2 0b01 0x2b 256-bit"
|
||||
@@ -1333,20 +1293,16 @@
|
||||
"uzp1 z1.h, z1.h, z1.h",
|
||||
"movprfx z4, z4",
|
||||
"splice z4.h, p6, z4.h, z1.h",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[1]",
|
||||
"mov z5.d, z4.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #0",
|
||||
"mov z5.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.d, z4.d[2]",
|
||||
"mov z4.d, z5.d",
|
||||
"index z0.d, #-2, #1",
|
||||
"cmpeq p0.d, p7/z, z0.d, #-1",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"udf #0x100",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -598,7 +598,7 @@
|
||||
]
|
||||
},
|
||||
"vpsrldq ymm0, ymm1, 15": {
|
||||
"ExpectedInstructionCount": 14,
|
||||
"ExpectedInstructionCount": 11,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map group 14 0b011 256-bit"
|
||||
@@ -610,13 +610,10 @@
|
||||
"movprfx z1, z4",
|
||||
"ext z1.b, z1.b, z5.b, #31",
|
||||
"mov z4.d, z1.d",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, q4",
|
||||
"mov z4.d, z6.d",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"not p0.b, p7/z, p6.b",
|
||||
"mov z4.b, p0/m, z1.b",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
@@ -758,7 +755,7 @@
|
||||
]
|
||||
},
|
||||
"vpslldq ymm0, ymm1, 15": {
|
||||
"ExpectedInstructionCount": 14,
|
||||
"ExpectedInstructionCount": 11,
|
||||
"Optimal": "No",
|
||||
"Comment": [
|
||||
"Map group 14 0b111 256-bit"
|
||||
@@ -770,13 +767,10 @@
|
||||
"movprfx z1, z5",
|
||||
"ext z1.b, z1.b, z4.b, #17",
|
||||
"mov z4.d, z1.d",
|
||||
"adr x0, #+0x18",
|
||||
"ldr p0, [x0]",
|
||||
"mov z1.q, q4",
|
||||
"mov z4.d, z6.d",
|
||||
"mov z4.d, p0/m, z1.d",
|
||||
"b #+0x8",
|
||||
"unallocated (Unallocated)",
|
||||
"not p0.b, p7/z, p6.b",
|
||||
"mov z4.b, p0/m, z1.b",
|
||||
"mov z16.d, p7/m, z4.d"
|
||||
]
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user