6823354: Add intrinsics for {Integer,Long}.{numberOfLeadingZeros,numberOfTrailingZeros}()
authortwisti
Wed, 06 May 2009 00:27:52 -0700
changeset 2862 fad636edf18f
parent 2745 60853c6a93b7
child 2863 ef8439ec732b
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
hotspot/src/cpu/sparc/vm/sparc.ad
hotspot/src/cpu/x86/vm/assembler_x86.cpp
hotspot/src/cpu/x86/vm/assembler_x86.hpp
hotspot/src/cpu/x86/vm/vm_version_x86.cpp
hotspot/src/cpu/x86/vm/vm_version_x86.hpp
hotspot/src/cpu/x86/vm/x86_32.ad
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/opto/classes.hpp
hotspot/src/share/vm/opto/connode.cpp
hotspot/src/share/vm/opto/connode.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/matcher.hpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/test/compiler/6823354/Test6823354.java
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed May 06 00:27:52 2009 -0700
@@ -1712,6 +1712,23 @@
   return as_DoubleFloatRegister(register_encoding);
 }
 
+const bool Matcher::match_rule_supported(int opcode) {
+  if (!has_match_rule(opcode))
+    return false;
+
+  switch (opcode) {
+  case Op_CountLeadingZerosI:
+  case Op_CountLeadingZerosL:
+  case Op_CountTrailingZerosI:
+  case Op_CountTrailingZerosL:
+    if (!UsePopCountInstruction)
+      return false;
+    break;
+  }
+
+  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
 }
@@ -9188,6 +9205,145 @@
   ins_pipe(long_memory_op);
 %}
 
+
+//---------- Zeros Count Instructions ------------------------------------------
+
+instruct countLeadingZerosI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{
+  predicate(UsePopCountInstruction);  // See Matcher::match_rule_supported
+  match(Set dst (CountLeadingZerosI src));
+  effect(TEMP dst, TEMP tmp, KILL cr);
+
+  // x |= (x >> 1);
+  // x |= (x >> 2);
+  // x |= (x >> 4);
+  // x |= (x >> 8);
+  // x |= (x >> 16);
+  // return (WORDBITS - popc(x));
+  format %{ "SRL     $src,1,$dst\t! count leading zeros (int)\n\t"
+            "OR      $src,$tmp,$dst\n\t"
+            "SRL     $dst,2,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRL     $dst,4,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRL     $dst,8,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRL     $dst,16,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "POPC    $dst,$dst\n\t"
+            "MOV     32,$tmp\n\t"
+            "SUB     $tmp,$dst,$dst" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Register Rsrc = $src$$Register;
+    Register Rtmp = $tmp$$Register;
+    __ srl(Rsrc, 1, Rtmp);
+    __ or3(Rsrc, Rtmp, Rdst);
+    __ srl(Rdst, 2, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srl(Rdst, 4, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srl(Rdst, 8, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srl(Rdst, 16, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ popc(Rdst, Rdst);
+    __ mov(BitsPerInt, Rtmp);
+    __ sub(Rtmp, Rdst, Rdst);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countLeadingZerosL(iRegI dst, iRegL src, iRegL tmp, flagsReg cr) %{
+  predicate(UsePopCountInstruction);  // See Matcher::match_rule_supported
+  match(Set dst (CountLeadingZerosL src));
+  effect(TEMP dst, TEMP tmp, KILL cr);
+
+  // x |= (x >> 1);
+  // x |= (x >> 2);
+  // x |= (x >> 4);
+  // x |= (x >> 8);
+  // x |= (x >> 16);
+  // x |= (x >> 32);
+  // return (WORDBITS - popc(x));
+  format %{ "SRLX    $src,1,$dst\t! count leading zeros (long)\n\t"
+            "OR      $src,$tmp,$dst\n\t"
+            "SRLX    $dst,2,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRLX    $dst,4,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRLX    $dst,8,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRLX    $dst,16,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "SRLX    $dst,32,$tmp\n\t"
+            "OR      $dst,$tmp,$dst\n\t"
+            "POPC    $dst,$dst\n\t"
+            "MOV     64,$tmp\n\t"
+            "SUB     $tmp,$dst,$dst" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Register Rsrc = $src$$Register;
+    Register Rtmp = $tmp$$Register;
+    __ srlx(Rsrc, 1, Rtmp);
+    __ or3(Rsrc, Rtmp, Rdst);
+    __ srlx(Rdst, 2, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 4, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 8, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 16, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 32, Rtmp);
+    __ or3(Rdst, Rtmp, Rdst);
+    __ popc(Rdst, Rdst);
+    __ mov(BitsPerLong, Rtmp);
+    __ sub(Rtmp, Rdst, Rdst);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countTrailingZerosI(iRegI dst, iRegI src, flagsReg cr) %{
+  predicate(UsePopCountInstruction);  // See Matcher::match_rule_supported
+  match(Set dst (CountTrailingZerosI src));
+  effect(TEMP dst, KILL cr);
+
+  // return popc(~x & (x - 1));
+  format %{ "SUB     $src,1,$dst\t! count trailing zeros (int)\n\t"
+            "ANDN    $dst,$src,$dst\n\t"
+            "SRL     $dst,R_G0,$dst\n\t"
+            "POPC    $dst,$dst" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Register Rsrc = $src$$Register;
+    __ sub(Rsrc, 1, Rdst);
+    __ andn(Rdst, Rsrc, Rdst);
+    __ srl(Rdst, G0, Rdst);
+    __ popc(Rdst, Rdst);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+instruct countTrailingZerosL(iRegI dst, iRegL src, flagsReg cr) %{
+  predicate(UsePopCountInstruction);  // See Matcher::match_rule_supported
+  match(Set dst (CountTrailingZerosL src));
+  effect(TEMP dst, KILL cr);
+
+  // return popc(~x & (x - 1));
+  format %{ "SUB     $src,1,$dst\t! count trailing zeros (long)\n\t"
+            "ANDN    $dst,$src,$dst\n\t"
+            "POPC    $dst,$dst" %}
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Register Rsrc = $src$$Register;
+    __ sub(Rsrc, 1, Rdst);
+    __ andn(Rdst, Rsrc, Rdst);
+    __ popc(Rdst, Rdst);
+  %}
+  ins_pipe(ialu_reg);
+%}
+
+
 //---------- Population Count Instructions -------------------------------------
 
 instruct popCountI(iRegI dst, iRegI src) %{
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Wed May 06 00:27:52 2009 -0700
@@ -952,6 +952,21 @@
   emit_operand(dst, src);
 }
 
+void Assembler::bsfl(Register dst, Register src) {
+  int encode = prefix_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBC);
+  emit_byte(0xC0 | encode);
+}
+
+void Assembler::bsrl(Register dst, Register src) {
+  assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
+  int encode = prefix_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBD);
+  emit_byte(0xC0 | encode);
+}
+
 void Assembler::bswapl(Register reg) { // bswap
   int encode = prefix_and_encode(reg->encoding());
   emit_byte(0x0F);
@@ -1438,6 +1453,15 @@
   }
 }
 
+void Assembler::lzcntl(Register dst, Register src) {
+  assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR");
+  emit_byte(0xF3);
+  int encode = prefix_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBD);
+  emit_byte(0xC0 | encode);
+}
+
 // Emit mfence instruction
 void Assembler::mfence() {
   NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");)
@@ -3688,6 +3712,21 @@
   emit_arith(0x23, 0xC0, dst, src);
 }
 
+void Assembler::bsfq(Register dst, Register src) {
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBC);
+  emit_byte(0xC0 | encode);
+}
+
+void Assembler::bsrq(Register dst, Register src) {
+  assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBD);
+  emit_byte(0xC0 | encode);
+}
+
 void Assembler::bswapq(Register reg) {
   int encode = prefixq_and_encode(reg->encoding());
   emit_byte(0x0F);
@@ -3941,6 +3980,15 @@
   emit_data((int)imm32, rspec, narrow_oop_operand);
 }
 
+void Assembler::lzcntq(Register dst, Register src) {
+  assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR");
+  emit_byte(0xF3);
+  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0xBD);
+  emit_byte(0xC0 | encode);
+}
+
 void Assembler::movdq(XMMRegister dst, Register src) {
   // table D-1 says MMX/SSE2
   NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), ""));
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed May 06 00:27:52 2009 -0700
@@ -757,6 +757,14 @@
   void andpd(XMMRegister dst, Address src);
   void andpd(XMMRegister dst, XMMRegister src);
 
+  void bsfl(Register dst, Register src);
+  void bsrl(Register dst, Register src);
+
+#ifdef _LP64
+  void bsfq(Register dst, Register src);
+  void bsrq(Register dst, Register src);
+#endif
+
   void bswapl(Register reg);
 
   void bswapq(Register reg);
@@ -1061,6 +1069,12 @@
 
   void lock();
 
+  void lzcntl(Register dst, Register src);
+
+#ifdef _LP64
+  void lzcntq(Register dst, Register src);
+#endif
+
   enum Membar_mask_bits {
     StoreStore = 1 << 3,
     LoadStore  = 1 << 2,
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Wed May 06 00:27:52 2009 -0700
@@ -284,7 +284,7 @@
   }
 
   char buf[256];
-  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                cores_per_cpu(), threads_per_core(),
                cpu_family(), _model, _stepping,
                (supports_cmov() ? ", cmov" : ""),
@@ -301,6 +301,7 @@
                (supports_mmx_ext() ? ", mmxext" : ""),
                (supports_3dnow()   ? ", 3dnow"  : ""),
                (supports_3dnow2()  ? ", 3dnowext" : ""),
+               (supports_lzcnt()   ? ", lzcnt": ""),
                (supports_sse4a()   ? ", sse4a": ""),
                (supports_ht() ? ", ht": ""));
   _features_str = strdup(buf);
@@ -364,6 +365,13 @@
         UseXmmI2D = false;
       }
     }
+
+    // Use count leading zeros count instruction if available.
+    if (supports_lzcnt()) {
+      if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
+        UseCountLeadingZerosInstruction = true;
+      }
+    }
   }
 
   if( is_intel() ) { // Intel cpus specific settings
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Wed May 06 00:27:52 2009 -0700
@@ -120,7 +120,7 @@
       uint32_t LahfSahf     : 1,
                CmpLegacy    : 1,
                             : 4,
-               abm          : 1,
+               lzcnt        : 1,
                sse4a        : 1,
                misalignsse  : 1,
                prefetchw    : 1,
@@ -182,7 +182,8 @@
      CPU_SSE4A  = (1 << 10),
      CPU_SSE4_1 = (1 << 11),
      CPU_SSE4_2 = (1 << 12),
-     CPU_POPCNT = (1 << 13)
+     CPU_POPCNT = (1 << 13),
+     CPU_LZCNT  = (1 << 14)
    } cpuFeatureFlags;
 
   // cpuid information block.  All info derived from executing cpuid with
@@ -277,8 +278,6 @@
     if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || is_amd() &&
         _cpuid_info.ext_cpuid1_edx.bits.mmx != 0)
       result |= CPU_MMX;
-    if (is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow != 0)
-      result |= CPU_3DNOW;
     if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
       result |= CPU_SSE;
     if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0)
@@ -287,14 +286,23 @@
       result |= CPU_SSE3;
     if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0)
       result |= CPU_SSSE3;
-    if (is_amd() && _cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
-      result |= CPU_SSE4A;
     if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0)
       result |= CPU_SSE4_1;
     if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
       result |= CPU_SSE4_2;
     if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
       result |= CPU_POPCNT;
+
+    // AMD features.
+    if (is_amd()) {
+      if (_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0)
+        result |= CPU_3DNOW;
+      if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
+        result |= CPU_LZCNT;
+      if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
+        result |= CPU_SSE4A;
+    }
+
     return result;
   }
 
@@ -391,6 +399,7 @@
   static bool supports_3dnow()    { return (_cpuFeatures & CPU_3DNOW) != 0; }
   static bool supports_mmx_ext()  { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
   static bool supports_3dnow2()   { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; }
+  static bool supports_lzcnt()    { return (_cpuFeatures & CPU_LZCNT) != 0; }
   static bool supports_sse4a()    { return (_cpuFeatures & CPU_SSE4A) != 0; }
 
   static bool supports_compare_and_exchange() { return true; }
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/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) %{
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/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) %{
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Wed May 06 00:27:52 2009 -0700
@@ -313,6 +313,8 @@
   template(value_name,                                "value")                                    \
   template(frontCacheEnabled_name,                    "frontCacheEnabled")                        \
   template(stringCacheEnabled_name,                   "stringCacheEnabled")                       \
+  template(numberOfLeadingZeros_name,                 "numberOfLeadingZeros")                     \
+  template(numberOfTrailingZeros_name,                "numberOfTrailingZeros")                    \
   template(bitCount_name,                             "bitCount")                                 \
   template(profile_name,                              "profile")                                  \
   template(equals_name,                               "equals")                                   \
@@ -559,6 +561,12 @@
   do_intrinsic(_longBitsToDouble,         java_lang_Double,       longBitsToDouble_name,    long_double_signature, F_S) \
    do_name(     longBitsToDouble_name,                           "longBitsToDouble")                                    \
                                                                                                                         \
+  do_intrinsic(_numberOfLeadingZeros_i,   java_lang_Integer,      numberOfLeadingZeros_name,int_int_signature,   F_S)   \
+  do_intrinsic(_numberOfLeadingZeros_l,   java_lang_Long,         numberOfLeadingZeros_name,long_int_signature,  F_S)   \
+                                                                                                                        \
+  do_intrinsic(_numberOfTrailingZeros_i,  java_lang_Integer,      numberOfTrailingZeros_name,int_int_signature,  F_S)   \
+  do_intrinsic(_numberOfTrailingZeros_l,  java_lang_Long,         numberOfTrailingZeros_name,long_int_signature, F_S)   \
+                                                                                                                        \
   do_intrinsic(_bitCount_i,               java_lang_Integer,      bitCount_name,            int_int_signature,   F_S)   \
   do_intrinsic(_bitCount_l,               java_lang_Long,         bitCount_name,            long_int_signature,  F_S)   \
                                                                                                                         \
--- a/hotspot/src/share/vm/opto/classes.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp	Wed May 06 00:27:52 2009 -0700
@@ -104,6 +104,10 @@
 macro(CosD)
 macro(CountedLoop)
 macro(CountedLoopEnd)
+macro(CountLeadingZerosI)
+macro(CountLeadingZerosL)
+macro(CountTrailingZerosI)
+macro(CountTrailingZerosL)
 macro(CreateEx)
 macro(DecodeN)
 macro(DivD)
--- a/hotspot/src/share/vm/opto/connode.cpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/opto/connode.cpp	Wed May 06 00:27:52 2009 -0700
@@ -1255,3 +1255,93 @@
   v.set_jdouble(td->getd());
   return TypeLong::make( v.get_jlong() );
 }
+
+//------------------------------Value------------------------------------------
+const Type* CountLeadingZerosINode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeInt* ti = t->isa_int();
+  if (ti && ti->is_con()) {
+    jint i = ti->get_con();
+    // HD, Figure 5-6
+    if (i == 0)
+      return TypeInt::make(BitsPerInt);
+    int n = 1;
+    unsigned int x = i;
+    if (x >> 16 == 0) { n += 16; x <<= 16; }
+    if (x >> 24 == 0) { n +=  8; x <<=  8; }
+    if (x >> 28 == 0) { n +=  4; x <<=  4; }
+    if (x >> 30 == 0) { n +=  2; x <<=  2; }
+    n -= x >> 31;
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountLeadingZerosLNode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeLong* tl = t->isa_long();
+  if (tl && tl->is_con()) {
+    jlong l = tl->get_con();
+    // HD, Figure 5-6
+    if (l == 0)
+      return TypeInt::make(BitsPerLong);
+    int n = 1;
+    unsigned int x = (((julong) l) >> 32);
+    if (x == 0) { n += 32; x = (int) l; }
+    if (x >> 16 == 0) { n += 16; x <<= 16; }
+    if (x >> 24 == 0) { n +=  8; x <<=  8; }
+    if (x >> 28 == 0) { n +=  4; x <<=  4; }
+    if (x >> 30 == 0) { n +=  2; x <<=  2; }
+    n -= x >> 31;
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountTrailingZerosINode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeInt* ti = t->isa_int();
+  if (ti && ti->is_con()) {
+    jint i = ti->get_con();
+    // HD, Figure 5-14
+    int y;
+    if (i == 0)
+      return TypeInt::make(BitsPerInt);
+    int n = 31;
+    y = i << 16; if (y != 0) { n = n - 16; i = y; }
+    y = i <<  8; if (y != 0) { n = n -  8; i = y; }
+    y = i <<  4; if (y != 0) { n = n -  4; i = y; }
+    y = i <<  2; if (y != 0) { n = n -  2; i = y; }
+    y = i <<  1; if (y != 0) { n = n -  1; }
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
+
+//------------------------------Value------------------------------------------
+const Type* CountTrailingZerosLNode::Value(PhaseTransform* phase) const {
+  const Type* t = phase->type(in(1));
+  if (t == Type::TOP) return Type::TOP;
+  const TypeLong* tl = t->isa_long();
+  if (tl && tl->is_con()) {
+    jlong l = tl->get_con();
+    // HD, Figure 5-14
+    int x, y;
+    if (l == 0)
+      return TypeInt::make(BitsPerLong);
+    int n = 63;
+    y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32);
+    y = x << 16; if (y != 0) { n = n - 16; x = y; }
+    y = x <<  8; if (y != 0) { n = n -  8; x = y; }
+    y = x <<  4; if (y != 0) { n = n -  4; x = y; }
+    y = x <<  2; if (y != 0) { n = n -  2; x = y; }
+    y = x <<  1; if (y != 0) { n = n -  1; }
+    return TypeInt::make(n);
+  }
+  return TypeInt::INT;
+}
--- a/hotspot/src/share/vm/opto/connode.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/opto/connode.hpp	Wed May 06 00:27:52 2009 -0700
@@ -636,22 +636,62 @@
   virtual const Type* Value( PhaseTransform *phase ) const;
 };
 
-//---------- PopCountINode -----------------------------------------------------
-// Population count (bit count) of an integer.
-class PopCountINode : public Node {
+//---------- CountBitsNode -----------------------------------------------------
+class CountBitsNode : public Node {
 public:
-  PopCountINode(Node* in1) : Node(0, in1) {}
-  virtual int Opcode() const;
+  CountBitsNode(Node* in1) : Node(0, in1) {}
   const Type* bottom_type() const { return TypeInt::INT; }
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
+//---------- CountLeadingZerosINode --------------------------------------------
+// Count leading zeros (0-bit count starting from MSB) of an integer.
+class CountLeadingZerosINode : public CountBitsNode {
+public:
+  CountLeadingZerosINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountLeadingZerosLNode --------------------------------------------
+// Count leading zeros (0-bit count starting from MSB) of a long.
+class CountLeadingZerosLNode : public CountBitsNode {
+public:
+  CountLeadingZerosLNode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountTrailingZerosINode -------------------------------------------
+// Count trailing zeros (0-bit count starting from LSB) of an integer.
+class CountTrailingZerosINode : public CountBitsNode {
+public:
+  CountTrailingZerosINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- CountTrailingZerosLNode -------------------------------------------
+// Count trailing zeros (0-bit count starting from LSB) of a long.
+class CountTrailingZerosLNode : public CountBitsNode {
+public:
+  CountTrailingZerosLNode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+  virtual const Type* Value(PhaseTransform* phase) const;
+};
+
+//---------- PopCountINode -----------------------------------------------------
+// Population count (bit count) of an integer.
+class PopCountINode : public CountBitsNode {
+public:
+  PopCountINode(Node* in1) : CountBitsNode(in1) {}
+  virtual int Opcode() const;
+};
+
 //---------- PopCountLNode -----------------------------------------------------
 // Population count (bit count) of a long.
-class PopCountLNode : public Node {
+class PopCountLNode : public CountBitsNode {
 public:
-  PopCountLNode(Node* in1) : Node(0, in1) {}
+  PopCountLNode(Node* in1) : CountBitsNode(in1) {}
   virtual int Opcode() const;
-  const Type* bottom_type() const { return TypeInt::INT; }
-  virtual uint ideal_reg() const { return Op_RegI; }
 };
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed May 06 00:27:52 2009 -0700
@@ -222,6 +222,8 @@
   bool inline_unsafe_CAS(BasicType type);
   bool inline_unsafe_ordered_store(BasicType type);
   bool inline_fp_conversions(vmIntrinsics::ID id);
+  bool inline_numberOfLeadingZeros(vmIntrinsics::ID id);
+  bool inline_numberOfTrailingZeros(vmIntrinsics::ID id);
   bool inline_bitCount(vmIntrinsics::ID id);
   bool inline_reverseBytes(vmIntrinsics::ID id);
 };
@@ -630,6 +632,14 @@
   case vmIntrinsics::_longBitsToDouble:
     return inline_fp_conversions(intrinsic_id());
 
+  case vmIntrinsics::_numberOfLeadingZeros_i:
+  case vmIntrinsics::_numberOfLeadingZeros_l:
+    return inline_numberOfLeadingZeros(intrinsic_id());
+
+  case vmIntrinsics::_numberOfTrailingZeros_i:
+  case vmIntrinsics::_numberOfTrailingZeros_l:
+    return inline_numberOfTrailingZeros(intrinsic_id());
+
   case vmIntrinsics::_bitCount_i:
   case vmIntrinsics::_bitCount_l:
     return inline_bitCount(intrinsic_id());
@@ -1844,6 +1854,48 @@
   }
 }
 
+//-------------------inline_numberOfLeadingZeros_int/long-----------------------
+// inline int Integer.numberOfLeadingZeros(int)
+// inline int Long.numberOfLeadingZeros(long)
+bool LibraryCallKit::inline_numberOfLeadingZeros(vmIntrinsics::ID id) {
+  assert(id == vmIntrinsics::_numberOfLeadingZeros_i || id == vmIntrinsics::_numberOfLeadingZeros_l, "not numberOfLeadingZeros");
+  if (id == vmIntrinsics::_numberOfLeadingZeros_i && !Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false;
+  if (id == vmIntrinsics::_numberOfLeadingZeros_l && !Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false;
+  _sp += arg_size();  // restore stack pointer
+  switch (id) {
+  case vmIntrinsics::_numberOfLeadingZeros_i:
+    push(_gvn.transform(new (C, 2) CountLeadingZerosINode(pop())));
+    break;
+  case vmIntrinsics::_numberOfLeadingZeros_l:
+    push(_gvn.transform(new (C, 2) CountLeadingZerosLNode(pop_pair())));
+    break;
+  default:
+    ShouldNotReachHere();
+  }
+  return true;
+}
+
+//-------------------inline_numberOfTrailingZeros_int/long----------------------
+// inline int Integer.numberOfTrailingZeros(int)
+// inline int Long.numberOfTrailingZeros(long)
+bool LibraryCallKit::inline_numberOfTrailingZeros(vmIntrinsics::ID id) {
+  assert(id == vmIntrinsics::_numberOfTrailingZeros_i || id == vmIntrinsics::_numberOfTrailingZeros_l, "not numberOfTrailingZeros");
+  if (id == vmIntrinsics::_numberOfTrailingZeros_i && !Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false;
+  if (id == vmIntrinsics::_numberOfTrailingZeros_l && !Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false;
+  _sp += arg_size();  // restore stack pointer
+  switch (id) {
+  case vmIntrinsics::_numberOfTrailingZeros_i:
+    push(_gvn.transform(new (C, 2) CountTrailingZerosINode(pop())));
+    break;
+  case vmIntrinsics::_numberOfTrailingZeros_l:
+    push(_gvn.transform(new (C, 2) CountTrailingZerosLNode(pop_pair())));
+    break;
+  default:
+    ShouldNotReachHere();
+  }
+  return true;
+}
+
 //----------------------------inline_bitCount_int/long-----------------------
 // inline int Integer.bitCount(int)
 // inline int Long.bitCount(long)
--- a/hotspot/src/share/vm/opto/matcher.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/opto/matcher.hpp	Wed May 06 00:27:52 2009 -0700
@@ -225,10 +225,16 @@
   OptoRegPair *_parm_regs;        // Array of machine registers per argument
   RegMask *_calling_convention_mask; // Array of RegMasks per argument
 
-  // Does matcher support this ideal node?
+  // Does matcher have a match rule for this ideal node?
   static const bool has_match_rule(int opcode);
   static const bool _hasMatchRule[_last_opcode];
 
+  // Does matcher have a match rule for this ideal node and is the
+  // predicate (if there is one) true?
+  // NOTE: If this function is used more commonly in the future, ADLC
+  // should generate this one.
+  static const bool match_rule_supported(int opcode);
+
   // Used to determine if we have fast l2f conversion
   // USII has it, USIII doesn't
   static const bool convL2FSupported(void);
--- a/hotspot/src/share/vm/runtime/globals.hpp	Tue May 05 11:02:10 2009 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Wed May 06 00:27:52 2009 -0700
@@ -2185,6 +2185,9 @@
   diagnostic(bool, PrintIntrinsics, false,                                  \
           "prints attempted and successful inlining of intrinsics")         \
                                                                             \
+  product(bool, UseCountLeadingZerosInstruction, false,                     \
+          "Use count leading zeros instruction")                            \
+                                                                            \
   product(bool, UsePopCountInstruction, false,                              \
           "Use population count instruction")                               \
                                                                             \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6823354/Test6823354.java	Wed May 06 00:27:52 2009 -0700
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6823354
+ * @summary These methods can be instrinsified by using bit scan, bit test, and population count instructions.
+ *
+ * @run main/othervm -Xcomp -XX:CompileOnly=Test6823354.lzcomp,Test6823354.tzcomp,.dolzcomp,.dotzcomp Test6823354
+ */
+
+import java.net.URLClassLoader;
+
+public class Test6823354 {
+    // Arrays of corner case values.
+    static final int[]  ia = new int[]  { 0,  1,  -1,  Integer.MIN_VALUE, Integer.MAX_VALUE };
+    static final long[] la = new long[] { 0L, 1L, -1L, Long.MIN_VALUE,    Long.MAX_VALUE    };
+
+    public static void main(String[] args) throws Exception {
+        // Load the classes and the methods.
+        Integer.numberOfLeadingZeros(0);
+        Integer.numberOfTrailingZeros(0);
+        Long.numberOfLeadingZeros(0);
+        Long.numberOfTrailingZeros(0);
+
+        lz();
+        tz();
+    }
+
+    static void lz() throws Exception {
+        // int
+
+        // Test corner cases.
+        for (int i = 0; i < ia.length; i++) {
+            int x = ia[i];
+            check(x, lzcomp(x), lzint(x));
+        }
+
+        // Test all possible return values.
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int x = 1 << i;
+            check(x, lzcomp(x), lzint(x));
+        }
+
+        String classname = "Test6823354$lzconI";
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < ia.length; i++) {
+            testclass(classname, ia[i]);
+        }
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int x = 1 << i;
+            testclass(classname, x);
+        }
+
+
+        // long
+
+        // Test corner cases.
+        for (int i = 0; i < ia.length; i++) {
+            long x = la[i];
+            check(x, lzcomp(x), lzint(x));
+        }
+
+        // Test all possible return values.
+        for (int i = 0; i < Long.SIZE; i++) {
+            long x = 1L << i;
+            check(x, lzcomp(x), lzint(x));
+        }
+
+        classname = "Test6823354$lzconL";
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < la.length; i++) {
+            testclass(classname, la[i]);
+        }
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < Long.SIZE; i++) {
+            long x = 1L << i;
+            testclass(classname, x);
+        }
+    }
+
+    static void tz() throws Exception {
+        // int
+
+        // Test corner cases.
+        for (int i = 0; i < ia.length; i++) {
+            int x = ia[i];
+            check(x, tzcomp(x), tzint(x));
+        }
+
+        // Test all possible return values.
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int x = 1 << i;
+            check(x, tzcomp(x), tzint(x));
+        }
+
+        String classname = "Test6823354$tzconI";
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < ia.length; i++) {
+            testclass(classname, ia[i]);
+        }
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < Integer.SIZE; i++) {
+            int x = 1 << i;
+            testclass(classname, x);
+        }
+
+
+        // long
+
+        // Test corner cases.
+        for (int i = 0; i < la.length; i++) {
+            long x = la[i];
+            check(x, tzcomp(x), tzint(x));
+        }
+
+        // Test all possible return values.
+        for (int i = 0; i < Long.SIZE; i++) {
+            long x = 1L << i;
+            check(x, tzcomp(x), tzint(x));
+        }
+
+        classname = "Test6823354$tzconL";
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < la.length; i++) {
+            testclass(classname, la[i]);
+        }
+
+        // Test Ideal optimizations (constant values).
+        for (int i = 0; i < Long.SIZE; i++) {
+            long x = 1L << i;
+            testclass(classname, x);
+        }
+    }
+
+    static void check(int value, int result, int expected) {
+        //System.out.println(value + ": " + result + ", " + expected);
+        if (result != expected)
+            throw new InternalError(value + " failed: " + result + " != " + expected);
+    }
+
+    static void check(long value, long result, long expected) {
+        //System.out.println(value + ": " + result + ", " + expected);
+        if (result != expected)
+            throw new InternalError(value + " failed: " + result + " != " + expected);
+    }
+
+    static int lzint( int i)  { return Integer.numberOfLeadingZeros(i); }
+    static int lzcomp(int i)  { return Integer.numberOfLeadingZeros(i); }
+
+    static int lzint( long l) { return Long.numberOfLeadingZeros(l); }
+    static int lzcomp(long l) { return Long.numberOfLeadingZeros(l); }
+
+    static int tzint( int i)  { return Integer.numberOfTrailingZeros(i); }
+    static int tzcomp(int i)  { return Integer.numberOfTrailingZeros(i); }
+
+    static int tzint( long l) { return Long.numberOfTrailingZeros(l); }
+    static int tzcomp(long l) { return Long.numberOfTrailingZeros(l); }
+
+    static void testclass(String classname, int x) throws Exception {
+        System.setProperty("value", "" + x);
+        loadandrunclass(classname);
+    }
+
+    static void testclass(String classname, long x) throws Exception {
+        System.setProperty("value", "" + x);
+        loadandrunclass(classname);
+    }
+
+    static void loadandrunclass(String classname) throws Exception {
+        Class cl = Class.forName(classname);
+        URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
+        ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
+        Class c = loader.loadClass(classname);
+        Runnable r = (Runnable) c.newInstance();
+        r.run();
+    }
+
+    public static class lzconI implements Runnable {
+        static final int VALUE;
+
+        static {
+            int value = 0;
+            try {
+                value = Integer.decode(System.getProperty("value"));
+            } catch (Throwable e) {}
+            VALUE = value;
+        }
+
+        public void run() { check(VALUE, lzint(VALUE), dolzcomp()); }
+        static int dolzcomp() { return lzcomp(VALUE); }
+    }
+
+    public static class lzconL implements Runnable {
+        static final long VALUE;
+
+        static {
+            long value = 0;
+            try {
+                value = Long.decode(System.getProperty("value"));
+            } catch (Throwable e) {}
+            VALUE = value;
+        }
+
+        public void run() { check(VALUE, lzint(VALUE), dolzcomp()); }
+        static int dolzcomp() { return lzcomp(VALUE); }
+    }
+
+    public static class tzconI implements Runnable {
+        static final int VALUE;
+
+        static {
+            int value = 0;
+            try {
+                value = Integer.decode(System.getProperty("value"));
+            } catch (Throwable e) {}
+            VALUE = value;
+        }
+
+        public void run() { check(VALUE, tzint(VALUE), dotzcomp()); }
+        static int dotzcomp() { return tzcomp(VALUE); }
+    }
+
+    public static class tzconL implements Runnable {
+        static final long VALUE;
+
+        static {
+            long value = 0;
+            try {
+                value = Long.decode(System.getProperty("value"));
+            } catch (Throwable e) {}
+            VALUE = value;
+        }
+
+        public void run() { check(VALUE, tzint(VALUE), dotzcomp()); }
+        static int dotzcomp() { return tzcomp(VALUE); }
+    }
+}