[JIT] Rewrite CNTLZ and remove one branch

This commit is contained in:
DrChat 2018-02-16 12:51:39 -06:00
parent e4bc596887
commit 43f9cebb0c

View file

@ -6484,24 +6484,17 @@ struct CNTLZ_I8 : Sequence<CNTLZ_I8, I<OPCODE_CNTLZ, I8Op, I8Op>> {
e.lzcnt(i.dest.reg().cvt16(), i.dest.reg().cvt16()); e.lzcnt(i.dest.reg().cvt16(), i.dest.reg().cvt16());
e.sub(i.dest, 8); e.sub(i.dest, 8);
} else { } else {
Xbyak::Label jz, jend; Xbyak::Label end;
e.inLocalLabel(); e.inLocalLabel();
// BSR: searches $2 until MSB 1 found, stores idx (from bit 0) in $1 e.bsr(e.rax, i.src1); // ZF set if i.src1 is 0
// if input is 0, results are undefined (and ZF is set) e.mov(i.dest, 0x8);
e.bsr(i.dest, i.src1); e.jz(end);
e.jz(jz); // Jump if zero
// Invert the result (7 - i.dest) e.xor_(e.rax, 0x7);
e.xor_(i.dest, 0x7); e.mov(i.dest, e.rax);
e.jmp(jend); // Jmp to end
// src1 was zero, so write 8 to the dest reg e.L(end);
e.L(jz);
e.mov(i.dest, 8);
e.L(jend);
e.outLocalLabel(); e.outLocalLabel();
} }
} }
@ -6512,24 +6505,17 @@ struct CNTLZ_I16 : Sequence<CNTLZ_I16, I<OPCODE_CNTLZ, I8Op, I16Op>> {
// LZCNT: searches $2 until MSB 1 found, stores idx (from last bit) in $1 // LZCNT: searches $2 until MSB 1 found, stores idx (from last bit) in $1
e.lzcnt(i.dest.reg().cvt32(), i.src1); e.lzcnt(i.dest.reg().cvt32(), i.src1);
} else { } else {
Xbyak::Label jz, jend; Xbyak::Label end;
e.inLocalLabel(); e.inLocalLabel();
// BSR: searches $2 until MSB 1 found, stores idx (from bit 0) in $1 e.bsr(e.rax, i.src1); // ZF set if i.src1 is 0
// if input is 0, results are undefined (and ZF is set) e.mov(i.dest, 0x10);
e.bsr(i.dest, i.src1); e.jz(end);
e.jz(jz); // Jump if zero
// Invert the result (15 - i.dest) e.xor_(e.rax, 0x0F);
e.xor_(i.dest, 0xF); e.mov(i.dest, e.rax);
e.jmp(jend); // Jmp to end
// src1 was zero, so write 16 to the dest reg e.L(end);
e.L(jz);
e.mov(i.dest, 16);
e.L(jend);
e.outLocalLabel(); e.outLocalLabel();
} }
} }
@ -6539,24 +6525,17 @@ struct CNTLZ_I32 : Sequence<CNTLZ_I32, I<OPCODE_CNTLZ, I8Op, I32Op>> {
if (e.IsFeatureEnabled(kX64EmitLZCNT)) { if (e.IsFeatureEnabled(kX64EmitLZCNT)) {
e.lzcnt(i.dest.reg().cvt32(), i.src1); e.lzcnt(i.dest.reg().cvt32(), i.src1);
} else { } else {
Xbyak::Label jz, jend; Xbyak::Label end;
e.inLocalLabel(); e.inLocalLabel();
// BSR: searches $2 until MSB 1 found, stores idx (from bit 0) in $1 e.bsr(e.rax, i.src1); // ZF set if i.src1 is 0
// if input is 0, results are undefined (and ZF is set) e.mov(i.dest, 0x20);
e.bsr(i.dest, i.src1); e.jz(end);
e.jz(jz); // Jump if zero
// Invert the result (31 - i.dest) e.xor_(e.rax, 0x1F);
e.xor_(i.dest, 0x1F); e.mov(i.dest, e.rax);
e.jmp(jend); // Jmp to end
// src1 was zero, so write 32 to the dest reg e.L(end);
e.L(jz);
e.mov(i.dest, 32);
e.L(jend);
e.outLocalLabel(); e.outLocalLabel();
} }
} }
@ -6566,24 +6545,17 @@ struct CNTLZ_I64 : Sequence<CNTLZ_I64, I<OPCODE_CNTLZ, I8Op, I64Op>> {
if (e.IsFeatureEnabled(kX64EmitLZCNT)) { if (e.IsFeatureEnabled(kX64EmitLZCNT)) {
e.lzcnt(i.dest.reg().cvt64(), i.src1); e.lzcnt(i.dest.reg().cvt64(), i.src1);
} else { } else {
Xbyak::Label jz, jend; Xbyak::Label end;
e.inLocalLabel(); e.inLocalLabel();
// BSR: searches $2 until MSB 1 found, stores idx (from bit 0) in $1 e.bsr(e.rax, i.src1); // ZF set if i.src1 is 0
// if input is 0, results are undefined (and ZF is set) e.mov(i.dest, 0x40);
e.bsr(i.dest, i.src1); e.jz(end);
e.jz(jz); // Jump if zero
// Invert the result (63 - i.dest) e.xor_(e.rax, 0x3F);
e.xor_(i.dest, 0x3F); e.mov(i.dest, e.rax);
e.jmp(jend); // Jmp to end
// src1 was zero, so write 64 to the dest reg e.L(end);
e.L(jz);
e.mov(i.dest, 64);
e.L(jend);
e.outLocalLabel(); e.outLocalLabel();
} }
} }