- Revision
- 278846
- Author
- [email protected]
- Date
- 2021-06-14 12:44:02 -0700 (Mon, 14 Jun 2021)
Log Message
Add Air opcode sub32/64(Reg, Imm, Reg) form for ARM64 and select this instruction in Air
https://bugs.webkit.org/show_bug.cgi?id=226937
Patch by Yijia Huang <[email protected]> on 2021-06-14
Reviewed by Saam Barati.
Previously, Air arm64 sub32/64 utilize sub(Imm, Tmp) at optlevel = 0 and
add(Tmp, -Imm) at optlevel > 0 to perform and optimize sub(Tmp, Imm, Tmp).
The issue with this is that we were not eliding redundant operations.
For example:
// B3 IR
@0 = Trunc(ArgumentReg(0))
@1 = Const
@2 = Sub(@0, @1)
@3 = Return(@2)
// Old optimized Air IR
// OptLevel = 0
Move %x0, %tmp1, @0
Move $Const, %tmp2, @1
Move %tmp1, %tmp0, @2 // Redundant
Sub $Const, %tmp0, @2
Move %tmp0, %x0, @3
Ret32 %x0, @3
To remove those redundant instructions, Air arm64 sub32/64 opcode should
indicate a new form sub(Tmp, Imm, Tmp).
// New optimized Air IR
// OptLevel = 0
Move %x0, %tmp1, @0
Move $Const, %tmp2, @1
Sub %tmp1, $Const, %tmp0, @2
Move %tmp0, %x0, @3
Ret32 %x0, @3
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::sub32):
(JSC::MacroAssemblerARM64::sub64):
* assembler/testmasm.cpp:
(JSC::testSub32Args):
(JSC::testSub32Imm):
(JSC::testSub32ArgImm):
(JSC::testSub64Imm32):
(JSC::testSub64ArgImm32):
(JSC::testSub64Imm64):
(JSC::testSub64ArgImm64):
* b3/B3ReduceStrength.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.h:
* b3/testb3_2.cpp:
(testSubArgs32ZeroExtend):
* b3/testb3_3.cpp:
(addArgTests):
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (278845 => 278846)
--- trunk/Source/_javascript_Core/ChangeLog 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-06-14 19:44:02 UTC (rev 278846)
@@ -1,3 +1,60 @@
+2021-06-14 Yijia Huang <[email protected]>
+
+ Add Air opcode sub32/64(Reg, Imm, Reg) form for ARM64 and select this instruction in Air
+ https://bugs.webkit.org/show_bug.cgi?id=226937
+
+ Reviewed by Saam Barati.
+
+ Previously, Air arm64 sub32/64 utilize sub(Imm, Tmp) at optlevel = 0 and
+ add(Tmp, -Imm) at optlevel > 0 to perform and optimize sub(Tmp, Imm, Tmp).
+ The issue with this is that we were not eliding redundant operations.
+
+ For example:
+ // B3 IR
+ @0 = Trunc(ArgumentReg(0))
+ @1 = Const
+ @2 = Sub(@0, @1)
+ @3 = Return(@2)
+
+ // Old optimized Air IR
+ // OptLevel = 0
+ Move %x0, %tmp1, @0
+ Move $Const, %tmp2, @1
+ Move %tmp1, %tmp0, @2 // Redundant
+ Sub $Const, %tmp0, @2
+ Move %tmp0, %x0, @3
+ Ret32 %x0, @3
+
+ To remove those redundant instructions, Air arm64 sub32/64 opcode should
+ indicate a new form sub(Tmp, Imm, Tmp).
+
+ // New optimized Air IR
+ // OptLevel = 0
+ Move %x0, %tmp1, @0
+ Move $Const, %tmp2, @1
+ Sub %tmp1, $Const, %tmp0, @2
+ Move %tmp0, %x0, @3
+ Ret32 %x0, @3
+
+ * assembler/MacroAssemblerARM64.h:
+ (JSC::MacroAssemblerARM64::sub32):
+ (JSC::MacroAssemblerARM64::sub64):
+ * assembler/testmasm.cpp:
+ (JSC::testSub32Args):
+ (JSC::testSub32Imm):
+ (JSC::testSub32ArgImm):
+ (JSC::testSub64Imm32):
+ (JSC::testSub64ArgImm32):
+ (JSC::testSub64Imm64):
+ (JSC::testSub64ArgImm64):
+ * b3/B3ReduceStrength.cpp:
+ * b3/air/AirOpcode.opcodes:
+ * b3/testb3.h:
+ * b3/testb3_2.cpp:
+ (testSubArgs32ZeroExtend):
+ * b3/testb3_3.cpp:
+ (addArgTests):
+
2021-06-14 Commit Queue <[email protected]>
Unreviewed, reverting r278734.
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (278845 => 278846)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2021-06-14 19:44:02 UTC (rev 278846)
@@ -893,17 +893,24 @@
void sub32(TrustedImm32 imm, RegisterID dest)
{
- if (isUInt12(imm.m_value)) {
- m_assembler.sub<32>(dest, dest, UInt12(imm.m_value));
+ sub32(dest, imm, dest);
+ }
+
+ void sub32(RegisterID left, TrustedImm32 imm, RegisterID dest)
+ {
+ intptr_t immediate = imm.m_value;
+
+ if (isUInt12(immediate)) {
+ m_assembler.sub<32>(dest, left, UInt12(immediate));
return;
}
- if (isUInt12(-imm.m_value)) {
- m_assembler.add<32>(dest, dest, UInt12(-imm.m_value));
+ if (isUInt12(-immediate)) {
+ m_assembler.add<32>(dest, left, UInt12(-immediate));
return;
}
move(imm, getCachedDataTempRegisterIDAndInvalidate());
- m_assembler.sub<32>(dest, dest, dataTempRegister);
+ m_assembler.sub<32>(dest, left, dataTempRegister);
}
void sub32(TrustedImm32 imm, Address address)
@@ -954,41 +961,53 @@
m_assembler.sub<64>(dest, dest, src);
}
- void sub64(RegisterID a, RegisterID b, RegisterID dest)
+ void sub64(RegisterID left, RegisterID right, RegisterID dest)
{
- m_assembler.sub<64>(dest, a, b);
+ m_assembler.sub<64>(dest, left, right);
}
-
+
void sub64(TrustedImm32 imm, RegisterID dest)
{
- if (isUInt12(imm.m_value)) {
- m_assembler.sub<64>(dest, dest, UInt12(imm.m_value));
+ sub64(dest, imm, dest);
+ }
+
+ void sub64(RegisterID left, TrustedImm32 imm, RegisterID dest)
+ {
+ intptr_t immediate = imm.m_value;
+
+ if (isUInt12(immediate)) {
+ m_assembler.sub<64>(dest, left, UInt12(immediate));
return;
}
- if (isUInt12(-imm.m_value)) {
- m_assembler.add<64>(dest, dest, UInt12(-imm.m_value));
+ if (isUInt12(-immediate)) {
+ m_assembler.add<64>(dest, left, UInt12(-immediate));
return;
}
signExtend32ToPtr(imm, getCachedDataTempRegisterIDAndInvalidate());
- m_assembler.sub<64>(dest, dest, dataTempRegister);
+ m_assembler.sub<64>(dest, left, dataTempRegister);
}
-
+
void sub64(TrustedImm64 imm, RegisterID dest)
{
+ sub64(dest, imm, dest);
+ }
+
+ void sub64(RegisterID left, TrustedImm64 imm, RegisterID dest)
+ {
intptr_t immediate = imm.m_value;
if (isUInt12(immediate)) {
- m_assembler.sub<64>(dest, dest, UInt12(static_cast<int32_t>(immediate)));
+ m_assembler.sub<64>(dest, left, UInt12(static_cast<int32_t>(immediate)));
return;
}
if (isUInt12(-immediate)) {
- m_assembler.add<64>(dest, dest, UInt12(static_cast<int32_t>(-immediate)));
+ m_assembler.add<64>(dest, left, UInt12(static_cast<int32_t>(-immediate)));
return;
}
move(imm, getCachedDataTempRegisterIDAndInvalidate());
- m_assembler.sub<64>(dest, dest, dataTempRegister);
+ m_assembler.sub<64>(dest, left, dataTempRegister);
}
void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (278845 => 278846)
--- trunk/Source/_javascript_Core/assembler/testmasm.cpp 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp 2021-06-14 19:44:02 UTC (rev 278846)
@@ -920,6 +920,128 @@
CHECK_EQ(invoke<long int>(mul, value, value2), ((long int) value) * ((long int) value2));
}
}
+
+void testSub32Args()
+{
+ for (auto value : int32Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.sub32(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ for (auto value2 : int32Operands())
+ CHECK_EQ(invoke<uint32_t>(sub, value, value2), static_cast<uint32_t>(value - value2));
+ }
+}
+
+void testSub32Imm()
+{
+ for (auto immediate : int32Operands()) {
+ for (auto immediate2 : int32Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.move(CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
+ jit.sub32(CCallHelpers::TrustedImm32(immediate2), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+ CHECK_EQ(invoke<uint32_t>(sub), static_cast<uint32_t>(immediate - immediate2));
+ }
+ }
+}
+
+void testSub32ArgImm()
+{
+ for (auto immediate : int32Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.sub32(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ for (auto value : int32Operands())
+ CHECK_EQ(invoke<uint32_t>(sub, value), static_cast<uint32_t>(value - immediate));
+ }
+}
+
+void testSub64Imm32()
+{
+ for (auto immediate : int64Operands()) {
+ for (auto immediate2 : int32Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.move(CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
+ jit.sub64(CCallHelpers::TrustedImm32(immediate2), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+ CHECK_EQ(invoke<uint64_t>(sub), static_cast<uint64_t>(immediate - immediate2));
+ }
+ }
+}
+
+void testSub64ArgImm32()
+{
+ for (auto immediate : int32Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.sub64(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ for (auto value : int64Operands())
+ CHECK_EQ(invoke<int64_t>(sub, value), static_cast<int64_t>(value - immediate));
+ }
+}
+
+void testSub64Imm64()
+{
+ for (auto immediate : int64Operands()) {
+ for (auto immediate2 : int64Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.move(CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
+ jit.sub64(CCallHelpers::TrustedImm64(immediate2), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+ CHECK_EQ(invoke<uint64_t>(sub), static_cast<uint64_t>(immediate - immediate2));
+ }
+ }
+}
+
+void testSub64ArgImm64()
+{
+ for (auto immediate : int64Operands()) {
+ auto sub = compile([=] (CCallHelpers& jit) {
+ emitFunctionPrologue(jit);
+
+ jit.sub64(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
+
+ emitFunctionEpilogue(jit);
+ jit.ret();
+ });
+
+ for (auto value : int64Operands())
+ CHECK_EQ(invoke<int64_t>(sub, value), static_cast<int64_t>(value - immediate));
+ }
+}
#endif
#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
@@ -2640,6 +2762,13 @@
#if CPU(ARM64)
RUN(testMul32SignExtend());
+ RUN(testSub32Args());
+ RUN(testSub32Imm());
+ RUN(testSub32ArgImm());
+ RUN(testSub64Imm32());
+ RUN(testSub64ArgImm32());
+ RUN(testSub64Imm64());
+ RUN(testSub64ArgImm64());
#endif
#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (278845 => 278846)
--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2021-06-14 19:44:02 UTC (rev 278846)
@@ -633,7 +633,7 @@
Add, m_value->origin(), m_value->child(0), negatedConstant);
break;
}
-
+
// Turn this: Sub(0, value)
// Into this: Neg(value)
if (m_value->child(0)->isInt(0)) {
Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (278845 => 278846)
--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2021-06-14 19:44:02 UTC (rev 278846)
@@ -179,6 +179,7 @@
arm64: Sub32 U:G:32, U:G:32, ZD:G:32
Tmp, Tmp, Tmp
+ Tmp, Imm, Tmp
64: Sub64 U:G:64, UD:G:64
Tmp, Tmp
@@ -192,6 +193,7 @@
arm64: Sub64 U:G:64, U:G:64, D:G:64
Tmp, Tmp, Tmp
+ Tmp, Imm, Tmp
SubDouble U:F:64, U:F:64, D:F:64
arm64: Tmp, Tmp, Tmp
Modified: trunk/Source/_javascript_Core/b3/testb3.h (278845 => 278846)
--- trunk/Source/_javascript_Core/b3/testb3.h 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/b3/testb3.h 2021-06-14 19:44:02 UTC (rev 278846)
@@ -1027,6 +1027,7 @@
void testSubImmMem(int64_t, int64_t);
void testSubMemImm(int64_t, int64_t);
void testSubArgs32(int, int);
+void testSubArgs32ZeroExtend(int, int);
void testSubArgImm32(int, int);
void testSubImmArg32(int, int);
void testSubMemArg32(int32_t, int32_t);
Modified: trunk/Source/_javascript_Core/b3/testb3_2.cpp (278845 => 278846)
--- trunk/Source/_javascript_Core/b3/testb3_2.cpp 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/b3/testb3_2.cpp 2021-06-14 19:44:02 UTC (rev 278846)
@@ -2092,6 +2092,28 @@
CHECK(compileAndRun<int>(proc, a, b) == a - b);
}
+void testSubArgs32ZeroExtend(int a, int b)
+{
+ Procedure proc;
+ if (proc.optLevel() < 1)
+ return;
+ BasicBlock* root = proc.addBlock();
+ root->appendNewControlValue(
+ proc, Return, Origin(),
+ root->appendNew<Value>(
+ proc, ZExt32, Origin(),
+ root->appendNew<Value>(
+ proc, Sub, Origin(),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
+ root->appendNew<Value>(
+ proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))));
+
+ CHECK(compileAndRun<uint64_t>(proc, a, b) == static_cast<uint64_t>(static_cast<uint32_t>(a - b)));
+}
+
void testSubArgImm32(int a, int b)
{
Procedure proc;
Modified: trunk/Source/_javascript_Core/b3/testb3_3.cpp (278845 => 278846)
--- trunk/Source/_javascript_Core/b3/testb3_3.cpp 2021-06-14 19:20:10 UTC (rev 278845)
+++ trunk/Source/_javascript_Core/b3/testb3_3.cpp 2021-06-14 19:44:02 UTC (rev 278846)
@@ -3301,6 +3301,10 @@
RUN(testSubArgs32(1, 2));
RUN(testSubArgs32(13, -42));
RUN(testSubArgs32(-13, 42));
+ RUN(testSubArgs32ZeroExtend(1, 1));
+ RUN(testSubArgs32ZeroExtend(1, 2));
+ RUN(testSubArgs32ZeroExtend(13, -42));
+ RUN(testSubArgs32ZeroExtend(-13, 42));
RUN(testSubArgImm32(1, 1));
RUN(testSubArgImm32(1, 2));
RUN(testSubArgImm32(13, -42));