Commit 66870070 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Compiler] Use conditional move / select to generate poison mask.

Replace bitwise arithmetic with conditional move / select instructions
on ia32, x64, Arm and Arm64. In local tests this improves --noopt Ignition
performance by between 2-5%.

BUG=chromium:798964

Change-Id: I82832e5d28469a574a575119c1a665b5c2c93bb2
Reviewed-on: https://chromium-review.googlesource.com/916561
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51444}
parent aa9843d7
...@@ -428,8 +428,7 @@ void TurboAssembler::Cset(const Register& rd, Condition cond) { ...@@ -428,8 +428,7 @@ void TurboAssembler::Cset(const Register& rd, Condition cond) {
cset(rd, cond); cset(rd, cond);
} }
void TurboAssembler::Csetm(const Register& rd, Condition cond) {
void MacroAssembler::Csetm(const Register& rd, Condition cond) {
DCHECK(allow_macro_instructions()); DCHECK(allow_macro_instructions());
DCHECK(!rd.IsZero()); DCHECK(!rd.IsZero());
DCHECK((cond != al) && (cond != nv)); DCHECK((cond != al) && (cond != nv));
......
...@@ -595,11 +595,8 @@ void TurboAssembler::ConditionalCompareMacro(const Register& rn, ...@@ -595,11 +595,8 @@ void TurboAssembler::ConditionalCompareMacro(const Register& rn,
} }
} }
void TurboAssembler::Csel(const Register& rd, const Register& rn,
void MacroAssembler::Csel(const Register& rd, const Operand& operand, Condition cond) {
const Register& rn,
const Operand& operand,
Condition cond) {
DCHECK(allow_macro_instructions()); DCHECK(allow_macro_instructions());
DCHECK(!rd.IsZero()); DCHECK(!rd.IsZero());
DCHECK((cond != al) && (cond != nv)); DCHECK((cond != al) && (cond != nv));
......
...@@ -645,6 +645,8 @@ class TurboAssembler : public Assembler { ...@@ -645,6 +645,8 @@ class TurboAssembler : public Assembler {
inline void Cmp(const Register& rn, const Operand& operand); inline void Cmp(const Register& rn, const Operand& operand);
inline void Subs(const Register& rd, const Register& rn, inline void Subs(const Register& rd, const Register& rn,
const Operand& operand); const Operand& operand);
void Csel(const Register& rd, const Register& rn, const Operand& operand,
Condition cond);
// Emits a runtime assert that the stack pointer is aligned. // Emits a runtime assert that the stack pointer is aligned.
void AssertSpAligned(); void AssertSpAligned();
...@@ -1011,6 +1013,7 @@ class TurboAssembler : public Assembler { ...@@ -1011,6 +1013,7 @@ class TurboAssembler : public Assembler {
void CanonicalizeNaN(const VRegister& reg) { CanonicalizeNaN(reg, reg); } void CanonicalizeNaN(const VRegister& reg) { CanonicalizeNaN(reg, reg); }
inline void Cset(const Register& rd, Condition cond); inline void Cset(const Register& rd, Condition cond);
inline void Csetm(const Register& rd, Condition cond);
inline void Fccmp(const VRegister& fn, const VRegister& fm, StatusFlags nzcv, inline void Fccmp(const VRegister& fn, const VRegister& fm, StatusFlags nzcv,
Condition cond); Condition cond);
inline void Csinc(const Register& rd, const Register& rn, const Register& rm, inline void Csinc(const Register& rd, const Register& rn, const Register& rm,
...@@ -1295,8 +1298,6 @@ class MacroAssembler : public TurboAssembler { ...@@ -1295,8 +1298,6 @@ class MacroAssembler : public TurboAssembler {
inline void Ccmn(const Register& rn, const Operand& operand, StatusFlags nzcv, inline void Ccmn(const Register& rn, const Operand& operand, StatusFlags nzcv,
Condition cond); Condition cond);
void Csel(const Register& rd, const Register& rn, const Operand& operand,
Condition cond);
#define DECLARE_FUNCTION(FN, OP) \ #define DECLARE_FUNCTION(FN, OP) \
inline void FN(const Register& rs, const Register& rt, const Register& rn); inline void FN(const Register& rs, const Register& rt, const Register& rn);
...@@ -1314,7 +1315,6 @@ class MacroAssembler : public TurboAssembler { ...@@ -1314,7 +1315,6 @@ class MacroAssembler : public TurboAssembler {
inline void Cinv(const Register& rd, const Register& rn, Condition cond); inline void Cinv(const Register& rd, const Register& rn, Condition cond);
inline void CzeroX(const Register& rd, Condition cond); inline void CzeroX(const Register& rd, Condition cond);
inline void CmovX(const Register& rd, const Register& rn, Condition cond); inline void CmovX(const Register& rd, const Register& rn, Condition cond);
inline void Csetm(const Register& rd, Condition cond);
inline void Csinv(const Register& rd, const Register& rn, const Register& rm, inline void Csinv(const Register& rd, const Register& rn, const Register& rm,
Condition cond); Condition cond);
inline void Csneg(const Register& rd, const Register& rn, const Register& rm, inline void Csneg(const Register& rd, const Register& rn, const Register& rm,
......
...@@ -624,21 +624,13 @@ void CodeGenerator::GenerateSpeculationPoison() { ...@@ -624,21 +624,13 @@ void CodeGenerator::GenerateSpeculationPoison() {
UseScratchRegisterScope temps(tasm()); UseScratchRegisterScope temps(tasm());
Register scratch = temps.Acquire(); Register scratch = temps.Acquire();
// Calculate a mask which has all bits set in the normal case, but has all // Set a mask which has all bits set in the normal case, but has all
// bits cleared if we are speculatively executing the wrong PC. // bits cleared if we are speculatively executing the wrong PC.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ ComputeCodeStartAddress(scratch); __ ComputeCodeStartAddress(scratch);
__ mov(kSpeculationPoisonRegister, scratch); __ cmp(kJavaScriptCallCodeStartRegister, scratch);
__ sub(kSpeculationPoisonRegister, kSpeculationPoisonRegister, __ mov(kSpeculationPoisonRegister, Operand(-1), SBit::LeaveCC, eq);
kJavaScriptCallCodeStartRegister); __ mov(kSpeculationPoisonRegister, Operand(0), SBit::LeaveCC, ne);
__ sub(kJavaScriptCallCodeStartRegister, kJavaScriptCallCodeStartRegister, __ csdb();
scratch);
__ orr(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ asr(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
Operand(kBitsPerPointer - 1));
__ mvn(kSpeculationPoisonRegister, Operand(kSpeculationPoisonRegister));
} }
// Assembles an instruction after register allocation, producing machine code. // Assembles an instruction after register allocation, producing machine code.
......
...@@ -568,21 +568,12 @@ void CodeGenerator::GenerateSpeculationPoison() { ...@@ -568,21 +568,12 @@ void CodeGenerator::GenerateSpeculationPoison() {
UseScratchRegisterScope temps(tasm()); UseScratchRegisterScope temps(tasm());
Register scratch = temps.AcquireX(); Register scratch = temps.AcquireX();
// Calculate a mask which has all bits set in the normal case, but has all // Set a mask which has all bits set in the normal case, but has all
// bits cleared if we are speculatively executing the wrong PC. // bits cleared if we are speculatively executing the wrong PC.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ ComputeCodeStartAddress(scratch); __ ComputeCodeStartAddress(scratch);
__ Mov(kSpeculationPoisonRegister, scratch); __ Cmp(kJavaScriptCallCodeStartRegister, scratch);
__ Sub(kSpeculationPoisonRegister, kSpeculationPoisonRegister, __ Csetm(kSpeculationPoisonRegister, eq);
kJavaScriptCallCodeStartRegister); __ Csdb();
__ Sub(kJavaScriptCallCodeStartRegister, kJavaScriptCallCodeStartRegister,
scratch);
__ Orr(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kJavaScriptCallCodeStartRegister);
__ Asr(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
kBitsPerPointer - 1);
__ Mvn(kSpeculationPoisonRegister, Operand(kSpeculationPoisonRegister));
} }
// Assembles an instruction after register allocation, producing machine code. // Assembles an instruction after register allocation, producing machine code.
......
...@@ -524,17 +524,13 @@ void CodeGenerator::BailoutIfDeoptimized() { ...@@ -524,17 +524,13 @@ void CodeGenerator::BailoutIfDeoptimized() {
void CodeGenerator::GenerateSpeculationPoison() { void CodeGenerator::GenerateSpeculationPoison() {
__ push(eax); // Push eax so we can use it as a scratch register. __ push(eax); // Push eax so we can use it as a scratch register.
// Calculate a mask which has all bits set in the normal case, but has all // Set a mask which has all bits set in the normal case, but has all
// bits cleared if we are speculatively executing the wrong PC. // bits cleared if we are speculatively executing the wrong PC.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ ComputeCodeStartAddress(eax); __ ComputeCodeStartAddress(eax);
__ mov(kSpeculationPoisonRegister, eax); __ mov(kSpeculationPoisonRegister, Immediate(0));
__ sub(kSpeculationPoisonRegister, kJavaScriptCallCodeStartRegister); __ cmp(kJavaScriptCallCodeStartRegister, eax);
__ sub(kJavaScriptCallCodeStartRegister, eax); __ mov(eax, Immediate(-1));
__ or_(kSpeculationPoisonRegister, kJavaScriptCallCodeStartRegister); __ cmov(equal, kSpeculationPoisonRegister, eax);
__ sar(kSpeculationPoisonRegister, kBitsPerPointer - 1);
__ not_(kSpeculationPoisonRegister);
__ pop(eax); // Restore eax. __ pop(eax); // Restore eax.
} }
......
...@@ -607,17 +607,13 @@ void CodeGenerator::BailoutIfDeoptimized() { ...@@ -607,17 +607,13 @@ void CodeGenerator::BailoutIfDeoptimized() {
} }
void CodeGenerator::GenerateSpeculationPoison() { void CodeGenerator::GenerateSpeculationPoison() {
// Calculate a mask which has all bits set in the normal case, but has all // Set a mask which has all bits set in the normal case, but has all
// bits cleared if we are speculatively executing the wrong PC. // bits cleared if we are speculatively executing the wrong PC.
// difference = (current - expected) | (expected - current)
// poison = ~(difference >> (kBitsPerPointer - 1))
__ ComputeCodeStartAddress(rbx); __ ComputeCodeStartAddress(rbx);
__ movp(kSpeculationPoisonRegister, rbx); __ movp(kSpeculationPoisonRegister, Immediate(0));
__ subq(kSpeculationPoisonRegister, kJavaScriptCallCodeStartRegister); __ cmpp(kJavaScriptCallCodeStartRegister, rbx);
__ subq(kJavaScriptCallCodeStartRegister, rbx); __ movp(rbx, Immediate(-1));
__ orq(kSpeculationPoisonRegister, kJavaScriptCallCodeStartRegister); __ cmovq(equal, kSpeculationPoisonRegister, rbx);
__ sarq(kSpeculationPoisonRegister, Immediate(kBitsPerPointer - 1));
__ notq(kSpeculationPoisonRegister);
} }
// Assembles an instruction after register allocation, producing machine code. // Assembles an instruction after register allocation, producing machine code.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment