Mercurial > hg > truffle
diff src/cpu/x86/vm/x86_32.ad @ 775:93c14e5562c4
6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
Summary: These methods can be instrinsified by using bit scan, bit test, and population count instructions.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Wed, 06 May 2009 00:27:52 -0700 |
parents | fbde8ec322d0 |
children | 2056494941db |
line wrap: on
line diff
--- a/src/cpu/x86/vm/x86_32.ad Tue May 05 11:02:10 2009 -0700 +++ b/src/cpu/x86/vm/x86_32.ad Wed May 06 00:27:52 2009 -0700 @@ -1281,6 +1281,13 @@ } +const bool Matcher::match_rule_supported(int opcode) { + if (!has_match_rule(opcode)) + return false; + + return true; // Per default match rules are supported. +} + int Matcher::regnum_to_fpu_offset(int regnum) { return regnum - 32; // The FP registers are in the second chunk } @@ -6644,6 +6651,153 @@ %} +//---------- Zeros Count Instructions ------------------------------------------ + +instruct countLeadingZerosI(eRegI dst, eRegI src, eFlagsReg cr) %{ + predicate(UseCountLeadingZerosInstruction); + match(Set dst (CountLeadingZerosI src)); + effect(KILL cr); + + format %{ "LZCNT $dst, $src\t# count leading zeros (int)" %} + ins_encode %{ + __ lzcntl($dst$$Register, $src$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct countLeadingZerosI_bsr(eRegI dst, eRegI src, eFlagsReg cr) %{ + predicate(!UseCountLeadingZerosInstruction); + match(Set dst (CountLeadingZerosI src)); + effect(KILL cr); + + format %{ "BSR $dst, $src\t# count leading zeros (int)\n\t" + "JNZ skip\n\t" + "MOV $dst, -1\n" + "skip:\n\t" + "NEG $dst\n\t" + "ADD $dst, 31" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + Label skip; + __ bsrl(Rdst, Rsrc); + __ jccb(Assembler::notZero, skip); + __ movl(Rdst, -1); + __ bind(skip); + __ negl(Rdst); + __ addl(Rdst, BitsPerInt - 1); + %} + ins_pipe(ialu_reg); +%} + +instruct countLeadingZerosL(eRegI dst, eRegL src, eFlagsReg cr) %{ + predicate(UseCountLeadingZerosInstruction); + match(Set dst (CountLeadingZerosL src)); + effect(TEMP dst, KILL cr); + + format %{ "LZCNT $dst, $src.hi\t# count leading zeros (long)\n\t" + "JNC done\n\t" + "LZCNT $dst, $src.lo\n\t" + "ADD $dst, 32\n" + "done:" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + Label done; + __ lzcntl(Rdst, HIGH_FROM_LOW(Rsrc)); + __ jccb(Assembler::carryClear, done); + __ lzcntl(Rdst, Rsrc); + __ addl(Rdst, BitsPerInt); + __ bind(done); + %} + ins_pipe(ialu_reg); +%} + +instruct countLeadingZerosL_bsr(eRegI dst, eRegL src, eFlagsReg cr) %{ + predicate(!UseCountLeadingZerosInstruction); + match(Set dst (CountLeadingZerosL src)); + effect(TEMP dst, KILL cr); + + format %{ "BSR $dst, $src.hi\t# count leading zeros (long)\n\t" + "JZ msw_is_zero\n\t" + "ADD $dst, 32\n\t" + "JMP not_zero\n" + "msw_is_zero:\n\t" + "BSR $dst, $src.lo\n\t" + "JNZ not_zero\n\t" + "MOV $dst, -1\n" + "not_zero:\n\t" + "NEG $dst\n\t" + "ADD $dst, 63\n" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + Label msw_is_zero; + Label not_zero; + __ bsrl(Rdst, HIGH_FROM_LOW(Rsrc)); + __ jccb(Assembler::zero, msw_is_zero); + __ addl(Rdst, BitsPerInt); + __ jmpb(not_zero); + __ bind(msw_is_zero); + __ bsrl(Rdst, Rsrc); + __ jccb(Assembler::notZero, not_zero); + __ movl(Rdst, -1); + __ bind(not_zero); + __ negl(Rdst); + __ addl(Rdst, BitsPerLong - 1); + %} + ins_pipe(ialu_reg); +%} + +instruct countTrailingZerosI(eRegI dst, eRegI src, eFlagsReg cr) %{ + match(Set dst (CountTrailingZerosI src)); + effect(KILL cr); + + format %{ "BSF $dst, $src\t# count trailing zeros (int)\n\t" + "JNZ done\n\t" + "MOV $dst, 32\n" + "done:" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Label done; + __ bsfl(Rdst, $src$$Register); + __ jccb(Assembler::notZero, done); + __ movl(Rdst, BitsPerInt); + __ bind(done); + %} + ins_pipe(ialu_reg); +%} + +instruct countTrailingZerosL(eRegI dst, eRegL src, eFlagsReg cr) %{ + match(Set dst (CountTrailingZerosL src)); + effect(TEMP dst, KILL cr); + + format %{ "BSF $dst, $src.lo\t# count trailing zeros (long)\n\t" + "JNZ done\n\t" + "BSF $dst, $src.hi\n\t" + "JNZ msw_not_zero\n\t" + "MOV $dst, 32\n" + "msw_not_zero:\n\t" + "ADD $dst, 32\n" + "done:" %} + ins_encode %{ + Register Rdst = $dst$$Register; + Register Rsrc = $src$$Register; + Label msw_not_zero; + Label done; + __ bsfl(Rdst, Rsrc); + __ jccb(Assembler::notZero, done); + __ bsfl(Rdst, HIGH_FROM_LOW(Rsrc)); + __ jccb(Assembler::notZero, msw_not_zero); + __ movl(Rdst, BitsPerInt); + __ bind(msw_not_zero); + __ addl(Rdst, BitsPerInt); + __ bind(done); + %} + ins_pipe(ialu_reg); +%} + + //---------- Population Count Instructions ------------------------------------- instruct popCountI(eRegI dst, eRegI src) %{