Bug 1441521 : [MIPS] Optimize comparation with small constants

Tag: #1542
This commit is contained in:
Jiaxun Yang 2020-05-12 12:40:13 +08:00 • committed by Roy Tam
commit 9441c06a56
6 changed files with 170 additions and 74 deletions

View file

@ -740,9 +740,17 @@ MacroAssemblerMIPSShared::ma_b(Register lhs, Imm32 imm, Label* label, Condition
else else
branchWithCode(getBranchCode(lhs, c), label, jumpKind); branchWithCode(getBranchCode(lhs, c), label, jumpKind);
} else { } else {
MOZ_ASSERT(lhs != ScratchRegister); switch (c) {
ma_li(ScratchRegister, imm); case Equal:
ma_b(lhs, ScratchRegister, label, c, jumpKind); case NotEqual:
MOZ_ASSERT(lhs != ScratchRegister);
ma_li(ScratchRegister, imm);
ma_b(lhs, ScratchRegister, label, c, jumpKind);
break;
default:
Condition cond = ma_cmp(ScratchRegister, lhs, imm, c);
asMasm().branchWithCode(getBranchCode(ScratchRegister, cond), label, jumpKind);
}
} }
} }
@ -862,20 +870,59 @@ MacroAssemblerMIPSShared::ma_cmp(Register scratch, Register lhs, Register rhs, C
// beq at,$zero,offs // beq at,$zero,offs
as_slt(scratch, rhs, lhs); as_slt(scratch, rhs, lhs);
return Equal; return Equal;
case Equal :
case NotEqual:
case Zero:
case NonZero:
case Always:
case Signed:
case NotSigned:
MOZ_CRASH("There is a better way to compare for equality.");
break;
case Overflow:
MOZ_CRASH("Overflow condition not supported for MIPS.");
break;
default: default:
MOZ_CRASH("Invalid condition for branch."); MOZ_CRASH("Invalid condition.");
}
return Always;
}
Assembler::Condition
MacroAssemblerMIPSShared::ma_cmp(Register scratch, Register lhs, Imm32 imm, Condition c)
{
switch (c) {
case Above:
case BelowOrEqual:
if (Imm16::IsInSignedRange(imm.value + 1) && imm.value != -1) {
// lhs <= rhs via lhs < rhs + 1 if rhs + 1 does not overflow
as_sltiu(scratch, lhs, imm.value + 1);
return (c == BelowOrEqual ? NotEqual : Equal);
} else {
ma_li(scratch, imm);
as_sltu(scratch, scratch, lhs);
return (c == BelowOrEqual ? Equal : NotEqual);
}
case AboveOrEqual:
case Below:
if (Imm16::IsInSignedRange(imm.value)) {
as_sltiu(scratch, lhs, imm.value);
} else {
ma_li(scratch, imm);
as_sltu(scratch, lhs, scratch);
}
return (c == AboveOrEqual ? Equal : NotEqual);
case GreaterThan:
case LessThanOrEqual:
if (Imm16::IsInSignedRange(imm.value + 1)) {
// lhs <= rhs via lhs < rhs + 1.
as_slti(scratch, lhs, imm.value + 1);
return (c == LessThanOrEqual ? NotEqual : Equal);
} else {
ma_li(scratch, imm);
as_slt(scratch, scratch, lhs);
return (c == LessThanOrEqual ? Equal : NotEqual);
}
case GreaterThanOrEqual:
case LessThan:
if (Imm16::IsInSignedRange(imm.value)) {
as_slti(scratch, lhs, imm.value);
} else {
ma_li(scratch, imm);
as_slt(scratch, lhs, scratch);
}
return (c == GreaterThanOrEqual ? Equal : NotEqual);
default:
MOZ_CRASH("Invalid condition.");
} }
return Always; return Always;
} }
@ -947,22 +994,21 @@ MacroAssemblerMIPSShared::ma_cmp_set(Register rd, Register rs, Register rt, Cond
case Zero: case Zero:
MOZ_ASSERT(rs == rt); MOZ_ASSERT(rs == rt);
// seq d,s,$zero => // seq d,s,$zero =>
// xor d,s,$zero // sltiu d,s,1
// sltiu d,d,1 as_sltiu(rd, rs, 1);
as_xor(rd, rs, zero);
as_sltiu(rd, rd, 1);
break; break;
case NonZero: case NonZero:
MOZ_ASSERT(rs == rt);
// sne d,s,$zero => // sne d,s,$zero =>
// xor d,s,$zero // sltu d,$zero,s
// sltu d,$zero,d as_sltu(rd, zero, rs);
as_xor(rd, rs, zero);
as_sltu(rd, zero, rd);
break; break;
case Signed: case Signed:
MOZ_ASSERT(rs == rt);
as_slt(rd, rs, zero); as_slt(rd, rs, zero);
break; break;
case NotSigned: case NotSigned:
MOZ_ASSERT(rs == rt);
// sge d,s,$zero => // sge d,s,$zero =>
// slt d,s,$zero // slt d,s,$zero
// xori d,d,1 // xori d,d,1
@ -970,7 +1016,7 @@ MacroAssemblerMIPSShared::ma_cmp_set(Register rd, Register rs, Register rt, Cond
as_xori(rd, rd, 1); as_xori(rd, rd, 1);
break; break;
default: default:
MOZ_CRASH("Invalid condition for ma_cmp_set."); MOZ_CRASH("Invalid condition.");
} }
} }
@ -1067,39 +1113,102 @@ void
MacroAssemblerMIPSShared::ma_cmp_set_double(Register dest, FloatRegister lhs, FloatRegister rhs, MacroAssemblerMIPSShared::ma_cmp_set_double(Register dest, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c) DoubleCondition c)
{ {
ma_li(dest, Imm32(0));
ma_li(ScratchRegister, Imm32(1));
FloatTestKind moveCondition; FloatTestKind moveCondition;
compareFloatingPoint(DoubleFloat, lhs, rhs, c, &moveCondition); compareFloatingPoint(DoubleFloat, lhs, rhs, c, &moveCondition);
ma_li(dest, Imm32(1));
if (moveCondition == TestForTrue) if (moveCondition == TestForTrue)
as_movt(dest, ScratchRegister); as_movf(dest, zero);
else else
as_movf(dest, ScratchRegister); as_movt(dest, zero);
} }
void void
MacroAssemblerMIPSShared::ma_cmp_set_float32(Register dest, FloatRegister lhs, FloatRegister rhs, MacroAssemblerMIPSShared::ma_cmp_set_float32(Register dest, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c) DoubleCondition c)
{ {
ma_li(dest, Imm32(0));
ma_li(ScratchRegister, Imm32(1));
FloatTestKind moveCondition; FloatTestKind moveCondition;
compareFloatingPoint(SingleFloat, lhs, rhs, c, &moveCondition); compareFloatingPoint(SingleFloat, lhs, rhs, c, &moveCondition);
ma_li(dest, Imm32(1));
if (moveCondition == TestForTrue) if (moveCondition == TestForTrue)
as_movt(dest, ScratchRegister); as_movf(dest, zero);
else else
as_movf(dest, ScratchRegister); as_movt(dest, zero);
} }
void void
MacroAssemblerMIPSShared::ma_cmp_set(Register rd, Register rs, Imm32 imm, Condition c) MacroAssemblerMIPSShared::ma_cmp_set(Register rd, Register rs, Imm32 imm, Condition c)
{ {
ma_li(ScratchRegister, imm); if (imm.value == 0) {
ma_cmp_set(rd, rs, ScratchRegister, c); switch (c) {
case Equal :
case BelowOrEqual:
as_sltiu(rd, rs, 1);
break;
case NotEqual:
case Above:
as_sltu(rd, zero, rs);
break;
case AboveOrEqual:
case Below:
as_ori(rd, zero, c == AboveOrEqual ? 1: 0);
break;
case GreaterThan:
case LessThanOrEqual:
as_slt(rd, zero, rs);
if (c == LessThanOrEqual)
as_xori(rd, rd, 1);
break;
case LessThan:
case GreaterThanOrEqual:
as_slt(rd, rs, zero);
if (c == GreaterThanOrEqual)
as_xori(rd, rd, 1);
break;
case Zero:
as_sltiu(rd, rs, 1);
break;
case NonZero:
as_sltu(rd, zero, rs);
break;
case Signed:
as_slt(rd, rs, zero);
break;
case NotSigned:
as_slt(rd, rs, zero);
as_xori(rd, rd, 1);
break;
default:
MOZ_CRASH("Invalid condition.");
}
return;
}
switch (c) {
case Equal:
case NotEqual:
MOZ_ASSERT(rs != ScratchRegister);
ma_xor(rd, rs, imm);
if (c == Equal)
as_sltiu(rd, rd, 1);
else
as_sltu(rd, zero, rd);
break;
case Zero:
case NonZero:
case Signed:
case NotSigned:
MOZ_CRASH("Invalid condition.");
default:
Condition cond = ma_cmp(rd, rs, imm, c);
MOZ_ASSERT(cond == Equal || cond == NotEqual);
if(cond == Equal)
as_xori(rd, rd, 1);
}
} }
// fp instructions // fp instructions

View file

@ -54,6 +54,7 @@ class MacroAssemblerMIPSShared : public Assembler
const MacroAssembler& asMasm() const; const MacroAssembler& asMasm() const;
Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c); Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c);
Condition ma_cmp(Register rd, Register lhs, Imm32 imm, Condition c);
void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs, FloatRegister rhs, void compareFloatingPoint(FloatFormat fmt, FloatRegister lhs, FloatRegister rhs,
DoubleCondition c, FloatTestKind* testKind, DoubleCondition c, FloatTestKind* testKind,

View file

@ -503,19 +503,6 @@ MacroAssemblerMIPS::ma_b(Address addr, ImmGCPtr imm, Label* label, Condition c,
ma_b(SecondScratchReg, imm, label, c, jumpKind); ma_b(SecondScratchReg, imm, label, c, jumpKind);
} }
void
MacroAssemblerMIPS::ma_cmp_set(Register rd, Register rs, Address addr, Condition c)
{
ma_lw(ScratchRegister, addr);
ma_cmp_set(rd, rs, ScratchRegister, c);
}
void
MacroAssemblerMIPS::ma_cmp_set(Register dst, Address lhs, Register rhs, Condition c)
{
ma_lw(ScratchRegister, lhs);
ma_cmp_set(dst, ScratchRegister, rhs, c);
}
// fp instructions // fp instructions
void void

View file

@ -104,7 +104,7 @@ class MacroAssemblerMIPS : public MacroAssemblerMIPSShared
void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = MixedJump); void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = MixedJump);
void ma_b(Address addr, Register rhs, Label* l, Condition c, JumpKind jumpKind = MixedJump) { void ma_b(Address addr, Register rhs, Label* l, Condition c, JumpKind jumpKind = MixedJump) {
MOZ_ASSERT(rhs != ScratchRegister); MOZ_ASSERT(rhs != ScratchRegister);
ma_load(ScratchRegister, addr, SizeWord); ma_lw(ScratchRegister, addr);
ma_b(ScratchRegister, rhs, l, c, jumpKind); ma_b(ScratchRegister, rhs, l, c, jumpKind);
} }
@ -125,12 +125,19 @@ class MacroAssemblerMIPS : public MacroAssemblerMIPSShared
void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c) { void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c) {
ma_cmp_set(dst, lhs, Imm32(uint32_t(imm.value)), c); ma_cmp_set(dst, lhs, Imm32(uint32_t(imm.value)), c);
} }
void ma_cmp_set(Register rd, Register rs, Address addr, Condition c); void ma_cmp_set(Register dst, Register lhs, Address addr, Condition c) {
void ma_cmp_set(Register dst, Address lhs, Register rhs, Condition c); MOZ_ASSERT(lhs != ScratchRegister);
void ma_cmp_set(Register dst, Address lhs, ImmPtr imm, Condition c) { ma_lw(ScratchRegister, addr);
ma_cmp_set(dst, lhs, ScratchRegister, c);
}
void ma_cmp_set(Register dst, Address lhs, Register rhs, Condition c) {
MOZ_ASSERT(rhs != ScratchRegister);
ma_lw(ScratchRegister, lhs); ma_lw(ScratchRegister, lhs);
ma_li(SecondScratchReg, Imm32(uint32_t(imm.value))); ma_cmp_set(dst, ScratchRegister, rhs, c);
ma_cmp_set(dst, ScratchRegister, SecondScratchReg, c); }
void ma_cmp_set(Register dst, Address lhs, ImmPtr imm, Condition c) {
ma_lw(SecondScratchReg, lhs);
ma_cmp_set(dst, SecondScratchReg, imm, c);
} }
// These fuctions abstract the access to high part of the double precision // These fuctions abstract the access to high part of the double precision

View file

@ -726,9 +726,8 @@ inline void
MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, ImmPtr rhs, MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs, ImmPtr rhs,
Register dest) Register dest)
{ {
loadPtr(lhs, ScratchRegister); loadPtr(lhs, SecondScratchReg);
movePtr(rhs, SecondScratchReg); cmpPtrSet(cond, SecondScratchReg, rhs, dest);
cmpPtrSet(cond, ScratchRegister, SecondScratchReg, dest);
} }
template<> template<>

View file

@ -719,14 +719,8 @@ MacroAssemblerMIPS64::ma_push(Register r)
void void
MacroAssemblerMIPS64::ma_b(Register lhs, ImmWord imm, Label* label, Condition c, JumpKind jumpKind) MacroAssemblerMIPS64::ma_b(Register lhs, ImmWord imm, Label* label, Condition c, JumpKind jumpKind)
{ {
MOZ_ASSERT(c != Overflow); if (imm.value <= INT32_MAX) {
if (imm.value == 0) { ma_b(lhs, Imm32(uint32_t(imm.value)), label, c, jumpKind);
if (c == Always || c == AboveOrEqual)
ma_b(label, jumpKind);
else if (c == Below)
; // This condition is always false. No branch required.
else
branchWithCode(getBranchCode(lhs, c), label, jumpKind);
} else { } else {
MOZ_ASSERT(lhs != ScratchRegister); MOZ_ASSERT(lhs != ScratchRegister);
ma_li(ScratchRegister, imm); ma_li(ScratchRegister, imm);
@ -759,19 +753,18 @@ MacroAssemblerMIPS64::ma_b(Address addr, ImmGCPtr imm, Label* label, Condition c
void void
MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmWord imm, Condition c) MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmWord imm, Condition c)
{ {
if (imm.value == 0) { if (imm.value <= INT32_MAX) {
ma_cmp_set(rd, rs, zero, c); ma_cmp_set(rd, rs, Imm32(uint32_t(imm.value)), c);
return; } else {
ma_li(ScratchRegister, imm);
ma_cmp_set(rd, rs, ScratchRegister, c);
} }
ma_li(ScratchRegister, imm);
ma_cmp_set(rd, rs, ScratchRegister, c);
} }
void void
MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmPtr imm, Condition c) MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmPtr imm, Condition c)
{ {
ma_li(ScratchRegister, ImmWord(uintptr_t(imm.value))); ma_cmp_set(rd, rs, ImmWord(uintptr_t(imm.value)), c);
ma_cmp_set(rd, rs, ScratchRegister, c);
} }
// fp instructions // fp instructions