Skip to content
Permalink
Browse files
Add SMNEGL, UMNEGL, UMADDL, and UMSUBL for ARM64 and select this inst…
…ruction in Air

https://bugs.webkit.org/show_bug.cgi?id=227857

Reviewed by Robin Morisset.

The previous patches have already added MNEG, MADD, MSUB, SMADDL, and SMSUBL.
This patch completes the corresponding signed or unsigned variants (SMNEGL,
UMNEGL, UMADDL, and UMSUBL) of them. In addition, this patch refactors
the implementation and the associative test cases of MADD, MSUB, and MNEG
to be more readable and maintainable w.r.t their variants.

------------------------------
### SMNEGL/UMNEGL Xd Wn Wm ###
------------------------------
Signed/Unsigned Multiply-Negate Long multiplies two 32-bit register values,
negates the product, and writes the result to the 64-bit destination register.
The equivalent patterns are

d = -(SExt32(n) * SExt32(m)) and d = -(ZExt32(n) * ZExt32(m)) respectively.

Given B3 IR:
Int @0 = S/ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = S/ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = Mul(@0, @1)
Int @3 = Neg(@2)
Void@4 = Return(@3, Terminal)

// Old optimized AIR
Move32      %x0, %x0,      @0
Move32      %x1, %x1,      @1
MultiplyNeg %x0, %x1, %x0, @3
Ret         %x0,           @4

// New optimized AIR
MultiplyNegSign/ZeroExtend  %x0, %x1, %x0, @3
Ret                         %x0,           @4

--------------------------
### UMADDL Xd Wn Wm Xa ###
--------------------------
Unsigned Multiply-Add Long multiplies two 32-bit register values, adds a 64-bit
register value, and writes the result to the 64-bit destination register. The
equivalent patterns are

d = ZExt32(n) * ZExt32(m) + a or d = a + ZExt32(n) * ZExt32(m)

Given B3 IR:
Int @0 = ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = ArgumentReg(%x2)
Int @3 = Mul(@0, @1)
Int @4 = Add(@3, @2)
Void@5 = Return(@4, Terminal)

// Old optimized AIR
Move32        %x0, %x0,           @1
Move32        %x1, %x1,           @2
MultiplyAdd   %x0, %x1, %x2, %x0, @4
Ret64         %x0,                @5

// New optimized AIR
MultiplyAddZeroExtend %x0, %x1, %x2, %x0, @8
Ret                   %x0,                @9

--------------------------
### UMSUBL Xd Wn Wm Xa ###
--------------------------
Unsigned Multiply-Subtract Long multiplies two 32-bit register values, subtracts
the product from a 64-bit register value, and writes the result to the 64-bit
destination register. The equivalent patterns are

d = a - ZExt32(n) * ZExt32(m)

Given B3 IR:
Int @0 = ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = ArgumentReg(%x2)
Int @3 = Mul(@0, @1)
Int @4 = Sub(@2, @3)
Void@5 = Return(@4, Terminal)

// Old optimized AIR
Move32        %x0, %x0,           @1
Move32        %x1, %x1,           @2
MultiplySub   %x0, %x1, %x2, %x0, @4
Ret64         %x0,                @5

// New optimized AIR
MultiplySubZeroExtend %x0, %x1, %x2, %x0, @8
Ret                   %x0,                @9

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::multiplyNeg32):
(JSC::MacroAssemblerARM64::multiplyAddZeroExtend32):
(JSC::MacroAssemblerARM64::multiplySubZeroExtend32):
(JSC::MacroAssemblerARM64::multiplyNeg64):
(JSC::MacroAssemblerARM64::multiplyNegSignExtend32):
(JSC::MacroAssemblerARM64::multiplyNegZeroExtend32):
* assembler/testmasm.cpp:
(JSC::testMultiplyAddSignExtend32):
(JSC::testMultiplyAddZeroExtend32):
(JSC::testMultiplySubSignExtend32):
(JSC::testMultiplySubZeroExtend32):
(JSC::testMultiplyNegSignExtend32):
(JSC::testMultiplyNegZeroExtend32):
(JSC::testMultiplyAddSignExtend32Left): Deleted.
(JSC::testMultiplyAddSignExtend32Right): Deleted.
* b3/B3LowerToAir.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.h:
* b3/testb3_2.cpp:
(testMulAddArgsLeft):
(testMulAddArgsRight):
(testMulAddSignExtend32ArgsLeft):
(testMulAddZeroExtend32ArgsLeft):
(testMulAddZeroExtend32ArgsRight):
(testMulSubArgsLeft):
(testMulSubArgsRight):
(testMulSubArgsRight32):
(testMulSubSignExtend32):
(testMulSubZeroExtend32):
(testMulNegArgArg):
(testMulNegArgs):
(testMulNegArgs32):
(testMulNegSignExtend32):
(testMulNegZeroExtend32):
(testMulSubSignExtend32Args): Deleted.
* b3/testb3_3.cpp:
(addArgTests):


Canonical link: https://commits.webkit.org/239605@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@279850 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Yijia Huang committed Jul 12, 2021
1 parent 170e395 commit 69730619f253477743e3b99399c8c8f665a124d5
Showing 8 changed files with 628 additions and 164 deletions.
@@ -1,3 +1,135 @@
2021-07-12 Yijia Huang <yijia_huang@apple.com>

Add SMNEGL, UMNEGL, UMADDL, and UMSUBL for ARM64 and select this instruction in Air
https://bugs.webkit.org/show_bug.cgi?id=227857

Reviewed by Robin Morisset.

The previous patches have already added MNEG, MADD, MSUB, SMADDL, and SMSUBL.
This patch completes the corresponding signed or unsigned variants (SMNEGL,
UMNEGL, UMADDL, and UMSUBL) of them. In addition, this patch refactors
the implementation and the associative test cases of MADD, MSUB, and MNEG
to be more readable and maintainable w.r.t their variants.

------------------------------
### SMNEGL/UMNEGL Xd Wn Wm ###
------------------------------
Signed/Unsigned Multiply-Negate Long multiplies two 32-bit register values,
negates the product, and writes the result to the 64-bit destination register.
The equivalent patterns are

d = -(SExt32(n) * SExt32(m)) and d = -(ZExt32(n) * ZExt32(m)) respectively.

Given B3 IR:
Int @0 = S/ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = S/ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = Mul(@0, @1)
Int @3 = Neg(@2)
Void@4 = Return(@3, Terminal)

// Old optimized AIR
Move32 %x0, %x0, @0
Move32 %x1, %x1, @1
MultiplyNeg %x0, %x1, %x0, @3
Ret %x0, @4

// New optimized AIR
MultiplyNegSign/ZeroExtend %x0, %x1, %x0, @3
Ret %x0, @4

--------------------------
### UMADDL Xd Wn Wm Xa ###
--------------------------
Unsigned Multiply-Add Long multiplies two 32-bit register values, adds a 64-bit
register value, and writes the result to the 64-bit destination register. The
equivalent patterns are

d = ZExt32(n) * ZExt32(m) + a or d = a + ZExt32(n) * ZExt32(m)

Given B3 IR:
Int @0 = ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = ArgumentReg(%x2)
Int @3 = Mul(@0, @1)
Int @4 = Add(@3, @2)
Void@5 = Return(@4, Terminal)

// Old optimized AIR
Move32 %x0, %x0, @1
Move32 %x1, %x1, @2
MultiplyAdd %x0, %x1, %x2, %x0, @4
Ret64 %x0, @5

// New optimized AIR
MultiplyAddZeroExtend %x0, %x1, %x2, %x0, @8
Ret %x0, @9

--------------------------
### UMSUBL Xd Wn Wm Xa ###
--------------------------
Unsigned Multiply-Subtract Long multiplies two 32-bit register values, subtracts
the product from a 64-bit register value, and writes the result to the 64-bit
destination register. The equivalent patterns are

d = a - ZExt32(n) * ZExt32(m)

Given B3 IR:
Int @0 = ZExt32(Trunc(ArgumentReg(%x0)))
Int @1 = ZExt32(Trunc(ArgumentReg(%x1)))
Int @2 = ArgumentReg(%x2)
Int @3 = Mul(@0, @1)
Int @4 = Sub(@2, @3)
Void@5 = Return(@4, Terminal)

// Old optimized AIR
Move32 %x0, %x0, @1
Move32 %x1, %x1, @2
MultiplySub %x0, %x1, %x2, %x0, @4
Ret64 %x0, @5

// New optimized AIR
MultiplySubZeroExtend %x0, %x1, %x2, %x0, @8
Ret %x0, @9

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::multiplyNeg32):
(JSC::MacroAssemblerARM64::multiplyAddZeroExtend32):
(JSC::MacroAssemblerARM64::multiplySubZeroExtend32):
(JSC::MacroAssemblerARM64::multiplyNeg64):
(JSC::MacroAssemblerARM64::multiplyNegSignExtend32):
(JSC::MacroAssemblerARM64::multiplyNegZeroExtend32):
* assembler/testmasm.cpp:
(JSC::testMultiplyAddSignExtend32):
(JSC::testMultiplyAddZeroExtend32):
(JSC::testMultiplySubSignExtend32):
(JSC::testMultiplySubZeroExtend32):
(JSC::testMultiplyNegSignExtend32):
(JSC::testMultiplyNegZeroExtend32):
(JSC::testMultiplyAddSignExtend32Left): Deleted.
(JSC::testMultiplyAddSignExtend32Right): Deleted.
* b3/B3LowerToAir.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.h:
* b3/testb3_2.cpp:
(testMulAddArgsLeft):
(testMulAddArgsRight):
(testMulAddSignExtend32ArgsLeft):
(testMulAddZeroExtend32ArgsLeft):
(testMulAddZeroExtend32ArgsRight):
(testMulSubArgsLeft):
(testMulSubArgsRight):
(testMulSubArgsRight32):
(testMulSubSignExtend32):
(testMulSubZeroExtend32):
(testMulNegArgArg):
(testMulNegArgs):
(testMulNegArgs32):
(testMulNegSignExtend32):
(testMulNegZeroExtend32):
(testMulSubSignExtend32Args): Deleted.
* b3/testb3_3.cpp:
(addArgTests):

2021-07-12 Yusuke Suzuki <ysuzuki@apple.com>

[JSC] JITCage already includes guard pages
@@ -770,7 +770,7 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler<Assembler> {

void multiplyNeg32(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
{
m_assembler.msub<32>(dest, mulLeft, mulRight, ARM64Registers::zr);
m_assembler.mneg<32>(dest, mulLeft, mulRight);
}

void multiplyAdd64(RegisterID mulLeft, RegisterID mulRight, RegisterID summand, RegisterID dest)
@@ -783,6 +783,11 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler<Assembler> {
m_assembler.smaddl(dest, mulLeft, mulRight, summand);
}

void multiplyAddZeroExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID summand, RegisterID dest)
{
m_assembler.umaddl(dest, mulLeft, mulRight, summand);
}

void multiplySub64(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
{
m_assembler.msub<64>(dest, mulLeft, mulRight, minuend);
@@ -793,9 +798,24 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler<Assembler> {
m_assembler.smsubl(dest, mulLeft, mulRight, minuend);
}

void multiplySubZeroExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
{
m_assembler.umsubl(dest, mulLeft, mulRight, minuend);
}

void multiplyNeg64(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
{
m_assembler.msub<64>(dest, mulLeft, mulRight, ARM64Registers::zr);
m_assembler.mneg<64>(dest, mulLeft, mulRight);
}

void multiplyNegSignExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
{
m_assembler.smnegl(dest, mulLeft, mulRight);
}

void multiplyNegZeroExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
{
m_assembler.umnegl(dest, mulLeft, mulRight);
}

void multiplySignExtend32(RegisterID left, RegisterID right, RegisterID dest)
@@ -921,7 +921,7 @@ void testMultiplySignExtend32()
}
}

void testMultiplyAddSignExtend32Left()
void testMultiplyAddSignExtend32()
{
// d = SExt32(n) * SExt32(m) + a
auto add = compile([=] (CCallHelpers& jit) {
@@ -944,25 +944,28 @@ void testMultiplyAddSignExtend32Left()
}
}

void testMultiplyAddSignExtend32Right()
void testMultiplyAddZeroExtend32()
{
// d = a + SExt32(n) * SExt32(m)
// d = ZExt32(n) * ZExt32(m) + a
auto add = compile([=] (CCallHelpers& jit) {
emitFunctionPrologue(jit);

jit.multiplyAddSignExtend32(GPRInfo::argumentGPR1,
jit.multiplyAddZeroExtend32(GPRInfo::argumentGPR0,
GPRInfo::argumentGPR1,
GPRInfo::argumentGPR2,
GPRInfo::argumentGPR0,
GPRInfo::returnValueGPR);

emitFunctionEpilogue(jit);
jit.ret();
});

for (auto a : int64Operands()) {
for (auto n : int32Operands()) {
for (auto m : int32Operands())
CHECK_EQ(invoke<int64_t>(add, a, n, m), a + static_cast<int64_t>(n) * static_cast<int64_t>(m));
for (auto n : int32Operands()) {
for (auto m : int32Operands()) {
for (auto a : int64Operands()) {
uint32_t un = n;
uint32_t um = m;
CHECK_EQ(invoke<int64_t>(add, n, m, a), static_cast<int64_t>(un) * static_cast<int64_t>(um) + a);
}
}
}
}
@@ -1091,7 +1094,7 @@ void testSub64ArgImm64()

void testMultiplySubSignExtend32()
{
// d = a - SExt32(n) * SExt32(m)
// d = a - SExt32(n) * SExt32(m)
auto sub = compile([=] (CCallHelpers& jit) {
emitFunctionPrologue(jit);

@@ -1112,6 +1115,71 @@ void testMultiplySubSignExtend32()
}
}

void testMultiplySubZeroExtend32()
{
// d = a - (ZExt32(n) * ZExt32(m))
auto sub = compile([=] (CCallHelpers& jit) {
emitFunctionPrologue(jit);

jit.multiplySubZeroExtend32(GPRInfo::argumentGPR1,
GPRInfo::argumentGPR2,
GPRInfo::argumentGPR0,
GPRInfo::returnValueGPR);

emitFunctionEpilogue(jit);
jit.ret();
});

for (auto a : int64Operands()) {
for (auto n : int32Operands()) {
for (auto m : int32Operands()) {
uint32_t un = n;
uint32_t um = m;
CHECK_EQ(invoke<int64_t>(sub, a, n, m), a - static_cast<int64_t>(un) * static_cast<int64_t>(um));
}
}
}
}

void testMultiplyNegSignExtend32()
{
// d = - (SExt32(n) * SExt32(m))
auto neg = compile([=] (CCallHelpers& jit) {
emitFunctionPrologue(jit);

jit.multiplyNegSignExtend32(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::returnValueGPR);

emitFunctionEpilogue(jit);
jit.ret();
});

for (auto n : int32Operands()) {
for (auto m : int32Operands())
CHECK_EQ(invoke<int64_t>(neg, n, m), -(static_cast<int64_t>(n) * static_cast<int64_t>(m)));
}
}

void testMultiplyNegZeroExtend32()
{
// d = - ZExt32(n) * ZExt32(m)
auto neg = compile([=] (CCallHelpers& jit) {
emitFunctionPrologue(jit);

jit.multiplyNegZeroExtend32(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::returnValueGPR);

emitFunctionEpilogue(jit);
jit.ret();
});

for (auto n : int32Operands()) {
for (auto m : int32Operands()) {
uint32_t un = n;
uint32_t um = m;
CHECK_EQ(invoke<uint64_t>(neg, n, m), -(static_cast<uint64_t>(un) * static_cast<uint64_t>(um)));
}
}
}

void testExtractUnsignedBitfield32()
{
uint32_t src = 0xf0f0f0f0;
@@ -4164,9 +4232,12 @@ void run(const char* filter) WTF_IGNORES_THREAD_SAFETY_ANALYSIS
RUN(testSub64Imm64());
RUN(testSub64ArgImm64());

RUN(testMultiplyAddSignExtend32Left());
RUN(testMultiplyAddSignExtend32Right());
RUN(testMultiplyAddSignExtend32());
RUN(testMultiplyAddZeroExtend32());
RUN(testMultiplySubSignExtend32());
RUN(testMultiplySubZeroExtend32());
RUN(testMultiplyNegSignExtend32());
RUN(testMultiplyNegZeroExtend32());

RUN(testExtractUnsignedBitfield32());
RUN(testExtractUnsignedBitfield64());

0 comments on commit 6973061

Please sign in to comment.