diff src/cpu/x86/vm/x86_64.ad @ 747: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_64.ad	Tue May 05 11:02:10 2009 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Wed May 06 00:27:52 2009 -0700
@@ -1980,6 +1980,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
@@ -7656,6 +7663,121 @@
 %}
 
 
+//---------- Zeros Count Instructions ------------------------------------------
+
+instruct countLeadingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
+  predicate(UseCountLeadingZerosInstruction);
+  match(Set dst (CountLeadingZerosI src));
+  effect(KILL cr);
+
+  format %{ "lzcntl  $dst, $src\t# count leading zeros (int)" %}
+  ins_encode %{
+    __ lzcntl($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countLeadingZerosI_bsr(rRegI dst, rRegI src, rFlagsReg cr) %{
+  predicate(!UseCountLeadingZerosInstruction);
+  match(Set dst (CountLeadingZerosI src));
+  effect(KILL cr);
+
+  format %{ "bsrl    $dst, $src\t# count leading zeros (int)\n\t"
+            "jnz     skip\n\t"
+            "movl    $dst, -1\n"
+      "skip:\n\t"
+            "negl    $dst\n\t"
+            "addl    $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(rRegI dst, rRegL src, rFlagsReg cr) %{
+  predicate(UseCountLeadingZerosInstruction);
+  match(Set dst (CountLeadingZerosL src));
+  effect(KILL cr);
+
+  format %{ "lzcntq  $dst, $src\t# count leading zeros (long)" %}
+  ins_encode %{
+    __ lzcntq($dst$$Register, $src$$Register);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countLeadingZerosL_bsr(rRegI dst, rRegL src, rFlagsReg cr) %{
+  predicate(!UseCountLeadingZerosInstruction);
+  match(Set dst (CountLeadingZerosL src));
+  effect(KILL cr);
+
+  format %{ "bsrq    $dst, $src\t# count leading zeros (long)\n\t"
+            "jnz     skip\n\t"
+            "movl    $dst, -1\n"
+      "skip:\n\t"
+            "negl    $dst\n\t"
+            "addl    $dst, 63" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Register Rsrc = $src$$Register;
+    Label skip;
+    __ bsrq(Rdst, Rsrc);
+    __ jccb(Assembler::notZero, skip);
+    __ movl(Rdst, -1);
+    __ bind(skip);
+    __ negl(Rdst);
+    __ addl(Rdst, BitsPerLong - 1);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countTrailingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
+  match(Set dst (CountTrailingZerosI src));
+  effect(KILL cr);
+
+  format %{ "bsfl    $dst, $src\t# count trailing zeros (int)\n\t"
+            "jnz     done\n\t"
+            "movl    $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(rRegI dst, rRegL src, rFlagsReg cr) %{
+  match(Set dst (CountTrailingZerosL src));
+  effect(KILL cr);
+
+  format %{ "bsfq    $dst, $src\t# count trailing zeros (long)\n\t"
+            "jnz     done\n\t"
+            "movl    $dst, 64\n"
+      "done:" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Label done;
+    __ bsfq(Rdst, $src$$Register);
+    __ jccb(Assembler::notZero, done);
+    __ movl(Rdst, BitsPerLong);
+    __ bind(done);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+
 //---------- Population Count Instructions -------------------------------------
 
 instruct popCountI(rRegI dst, rRegI src) %{