Bug 1289054 - Part 16: Implement the 64bit variant of Clz and Ctz on arm, r=bbouvier

This commit is contained in:
Hannes Verschore 2016-07-29 16:53:49 +02:00
parent 5ab976a487
commit e765133481
4 changed files with 55 additions and 8 deletions

View File

@ -909,8 +909,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void clz32(Register src, Register dest, bool knownNotZero) PER_SHARED_ARCH;
inline void ctz32(Register src, Register dest, bool knownNotZero) PER_SHARED_ARCH;
inline void clz64(Register64 src, Register dest) DEFINED_ON(x86, x64);
inline void ctz64(Register64 src, Register dest) DEFINED_ON(x86, x64);
inline void clz64(Register64 src, Register dest) DEFINED_ON(x86, x64, arm);
inline void ctz64(Register64 src, Register dest) DEFINED_ON(x86, x64, arm);
// On x86_shared, temp may be Invalid only if the chip has the POPCNT instruction.
// On ARM, temp may never be Invalid.

View File

@ -982,7 +982,7 @@ CodeGeneratorARM::visitClzI(LClzI* ins)
Register input = ToRegister(ins->input());
Register output = ToRegister(ins->output());
masm.ma_clz(input, output);
masm.clz32(input, output, /* knownNotZero = */ false);
}
void
@ -990,12 +990,8 @@ CodeGeneratorARM::visitCtzI(LCtzI* ins)
{
Register input = ToRegister(ins->input());
Register output = ToRegister(ins->output());
ScratchRegisterScope scratch(masm);
masm.ma_rsb(input, Imm32(0), scratch, SetCC);
masm.ma_and(input, scratch, input);
masm.ma_clz(input, output);
masm.ma_rsb(input, Imm32(0x1f), output, LeaveCC, Assembler::NotEqual);
masm.ctz32(input, output, /* knownNotZero = */ false);
}
void
@ -3420,3 +3416,23 @@ CodeGeneratorARM::visitPopcntI64(LPopcntI64* lir)
masm.popcnt64(input, output, temp);
}
void
CodeGeneratorARM::visitClzI64(LClzI64* lir)
{
Register64 input = ToRegister64(lir->getInt64Operand(0));
Register64 output = ToOutRegister64(lir);
masm.clz64(input, output.low);
masm.move32(Imm32(0), output.high);
}
void
CodeGeneratorARM::visitCtzI64(LCtzI64* lir)
{
Register64 input = ToRegister64(lir->getInt64Operand(0));
Register64 output = ToOutRegister64(lir);
masm.ctz64(input, output.low);
masm.move32(Imm32(0), output.high);
}

View File

@ -174,6 +174,8 @@ class CodeGeneratorARM : public CodeGeneratorShared
virtual void visitAsmReinterpretFromI64(LAsmReinterpretFromI64* lir);
virtual void visitAsmReinterpretToI64(LAsmReinterpretToI64* lir);
virtual void visitPopcntI64(LPopcntI64* ins);
virtual void visitClzI64(LClzI64* ins);
virtual void visitCtzI64(LCtzI64* ins);
// Out of line visitors.
void visitOutOfLineBailout(OutOfLineBailout* ool);

View File

@ -955,12 +955,41 @@ MacroAssembler::clz32(Register src, Register dest, bool knownNotZero)
ma_clz(src, dest);
}
void
MacroAssembler::clz64(Register64 src, Register dest)
{
ScratchRegisterScope scratch(*this);
ma_clz(src.high, scratch);
ma_cmp(scratch, Imm32(32));
ma_mov(scratch, dest, LeaveCC, NotEqual);
ma_clz(src.low, dest, Equal);
ma_add(Imm32(32), dest, LeaveCC, Equal);
}
void
MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero)
{
ma_ctz(src, dest);
}
void
MacroAssembler::ctz64(Register64 src, Register dest)
{
Label done, high;
ma_cmp(src.low, Imm32(0));
ma_b(&high, Equal);
ctz32(src.low, dest, /* knownNotZero = */ true);
ma_b(&done);
bind(&high);
ctz32(src.high, dest, /* knownNotZero = */ false);
ma_add(Imm32(32), dest);
bind(&done);
}
void
MacroAssembler::popcnt32(Register input, Register output, Register tmp)
{