From e765133481169b35521e3f2108a68dc8006e7741 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Fri, 29 Jul 2016 16:53:49 +0200 Subject: [PATCH] Bug 1289054 - Part 16: Implement the 64bit variant of Clz and Ctz on arm, r=bbouvier --- js/src/jit/MacroAssembler.h | 4 ++-- js/src/jit/arm/CodeGenerator-arm.cpp | 28 +++++++++++++++++++----- js/src/jit/arm/CodeGenerator-arm.h | 2 ++ js/src/jit/arm/MacroAssembler-arm-inl.h | 29 +++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 702082ec2a14..3ba68c393aa9 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -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. diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index f6c39af6e26d..149065be12fc 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -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); +} + diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index 6eb0c04d085a..a000d67d7368 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -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); diff --git a/js/src/jit/arm/MacroAssembler-arm-inl.h b/js/src/jit/arm/MacroAssembler-arm-inl.h index 41f98892674b..66980c3e9a27 100644 --- a/js/src/jit/arm/MacroAssembler-arm-inl.h +++ b/js/src/jit/arm/MacroAssembler-arm-inl.h @@ -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) {