6946040: add intrinsic for short and char reverseBytes
authornever
Mon, 26 Apr 2010 11:27:21 -0700
changeset 5352 cee8f7acb7bc
parent 5341 290a02b4adb3
child 5353 30f4b75f8005
6946040: add intrinsic for short and char reverseBytes Reviewed-by: never, twisti Contributed-by: Hiroshi Yamauchi <yamauchi@google.com>
hotspot/make/linux/makefiles/adlc.make
hotspot/make/solaris/makefiles/adlc.make
hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
hotspot/src/cpu/sparc/vm/sparc.ad
hotspot/src/cpu/x86/vm/x86_32.ad
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/share/vm/adlc/formssel.cpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/opto/classes.hpp
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/subnode.hpp
hotspot/test/compiler/6431242/Test.java
hotspot/test/compiler/6946040/TestCharShortByteSwap.java
--- a/hotspot/make/linux/makefiles/adlc.make	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/make/linux/makefiles/adlc.make	Mon Apr 26 11:27:21 2010 -0700
@@ -127,6 +127,9 @@
 # Note that product files are updated via "mv", which is atomic.
 TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
 
+# Debuggable by default
+CFLAGS += -g
+
 # Pass -D flags into ADLC.
 ADLCFLAGS += $(SYSDEFS)
 
@@ -135,7 +138,7 @@
 
 # Normally, debugging is done directly on the ad_<arch>*.cpp files.
 # But -g will put #line directives in those files pointing back to <arch>.ad.
-#ADLCFLAGS += -g
+ADLCFLAGS += -g
 
 ifdef LP64
 ADLCFLAGS += -D_LP64
--- a/hotspot/make/solaris/makefiles/adlc.make	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/make/solaris/makefiles/adlc.make	Mon Apr 26 11:27:21 2010 -0700
@@ -147,6 +147,9 @@
 # Note that product files are updated via "mv", which is atomic.
 TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
 
+# Debuggable by default
+CFLAGS += -g
+
 # Pass -D flags into ADLC.
 ADLCFLAGS += $(SYSDEFS)
 
@@ -155,7 +158,7 @@
 
 # Normally, debugging is done directly on the ad_<arch>*.cpp files.
 # But -g will put #line directives in those files pointing back to <arch>.ad.
-#ADLCFLAGS += -g
+ADLCFLAGS += -g
 
 ifdef LP64
 ADLCFLAGS += -D_LP64
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Mon Apr 26 11:27:21 2010 -0700
@@ -661,9 +661,6 @@
     stx_op3      = 0x0e,
     swap_op3     = 0x0f,
 
-    lduwa_op3    = 0x10,
-    ldxa_op3     = 0x1b,
-
     stwa_op3     = 0x14,
     stxa_op3     = 0x1e,
 
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Mon Apr 26 11:27:21 2010 -0700
@@ -923,38 +923,6 @@
 #endif
 }
 
-void emit_form3_mem_reg_asi(CodeBuffer &cbuf, const MachNode* n, int primary, int tertiary,
-                        int src1_enc, int disp32, int src2_enc, int dst_enc, int asi) {
-
-  uint instr;
-  instr = (Assembler::ldst_op << 30)
-        | (dst_enc        << 25)
-        | (primary        << 19)
-        | (src1_enc       << 14);
-
-  int disp = disp32;
-  int index    = src2_enc;
-
-  if (src1_enc == R_SP_enc || src1_enc == R_FP_enc)
-    disp += STACK_BIAS;
-
-  // We should have a compiler bailout here rather than a guarantee.
-  // Better yet would be some mechanism to handle variable-size matches correctly.
-  guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" );
-
-  if( disp != 0 ) {
-    // use reg-reg form
-    // set src2=R_O7 contains offset
-    index = R_O7_enc;
-    emit3_simm13( cbuf, Assembler::arith_op, index, Assembler::or_op3, 0, disp);
-  }
-  instr |= (asi << 5);
-  instr |= index;
-  uint *code = (uint*)cbuf.code_end();
-  *code = instr;
-  cbuf.set_code_end(cbuf.code_end() + BytesPerInstWord);
-}
-
 void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) {
   // The method which records debug information at every safepoint
   // expects the call to be the first instruction in the snippet as
@@ -1954,11 +1922,6 @@
                        $mem$$base, $mem$$disp, $mem$$index, $dst$$reg);
   %}
 
-  enc_class form3_mem_reg_little( memory mem, iRegI dst) %{
-    emit_form3_mem_reg_asi(cbuf, this, $primary, -1,
-                     $mem$$base, $mem$$disp, $mem$$index, $dst$$reg, Assembler::ASI_PRIMARY_LITTLE);
-  %}
-
   enc_class form3_mem_prefetch_read( memory mem ) %{
     emit_form3_mem_reg(cbuf, this, $primary, -1,
                        $mem$$base, $mem$$disp, $mem$$index, 0/*prefetch function many-reads*/);
@@ -4311,8 +4274,8 @@
 // instructions for every form of operand when the instruction accepts
 // multiple operand types with the same basic encoding and format.  The classic
 // case of this is memory operands.
-// Indirect is not included since its use is limited to Compare & Swap
 opclass memory( indirect, indOffset13, indIndex );
+opclass indIndexMemory( indIndex );
 
 //----------PIPELINE-----------------------------------------------------------
 pipeline %{
@@ -9666,84 +9629,179 @@
 
 instruct bytes_reverse_int(iRegI dst, stackSlotI src) %{
   match(Set dst (ReverseBytesI src));
-  effect(DEF dst, USE src);
+
+  // Op cost is artificially doubled to make sure that load or store
+  // instructions are preferred over this one which requires a spill
+  // onto a stack slot.
+  ins_cost(2*DEFAULT_COST + MEMORY_REF_COST);
+  format %{ "LDUWA  $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ set($src$$disp + STACK_BIAS, O7);
+    __ lduwa($src$$base$$Register, O7, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
+  ins_pipe( iload_mem );
+%}
+
+instruct bytes_reverse_long(iRegL dst, stackSlotL src) %{
+  match(Set dst (ReverseBytesL src));
 
   // Op cost is artificially doubled to make sure that load or store
   // instructions are preferred over this one which requires a spill
   // onto a stack slot.
   ins_cost(2*DEFAULT_COST + MEMORY_REF_COST);
-  size(8);
-  format %{ "LDUWA  $src, $dst\t!asi=primary_little" %}
-  opcode(Assembler::lduwa_op3);
-  ins_encode( form3_mem_reg_little(src, dst) );
+  format %{ "LDXA   $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ set($src$$disp + STACK_BIAS, O7);
+    __ ldxa($src$$base$$Register, O7, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
   ins_pipe( iload_mem );
 %}
 
-instruct bytes_reverse_long(iRegL dst, stackSlotL src) %{
-  match(Set dst (ReverseBytesL src));
-  effect(DEF dst, USE src);
+instruct bytes_reverse_unsigned_short(iRegI dst, stackSlotI src) %{
+  match(Set dst (ReverseBytesUS src));
+
+  // Op cost is artificially doubled to make sure that load or store
+  // instructions are preferred over this one which requires a spill
+  // onto a stack slot.
+  ins_cost(2*DEFAULT_COST + MEMORY_REF_COST);
+  format %{ "LDUHA  $src, $dst\t!asi=primary_little\n\t" %}
+
+  ins_encode %{
+    // the value was spilled as an int so bias the load
+    __ set($src$$disp + STACK_BIAS + 2, O7);
+    __ lduha($src$$base$$Register, O7, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
+  ins_pipe( iload_mem );
+%}
+
+instruct bytes_reverse_short(iRegI dst, stackSlotI src) %{
+  match(Set dst (ReverseBytesS src));
 
   // Op cost is artificially doubled to make sure that load or store
   // instructions are preferred over this one which requires a spill
   // onto a stack slot.
   ins_cost(2*DEFAULT_COST + MEMORY_REF_COST);
-  size(8);
-  format %{ "LDXA   $src, $dst\t!asi=primary_little" %}
-
-  opcode(Assembler::ldxa_op3);
-  ins_encode( form3_mem_reg_little(src, dst) );
+  format %{ "LDSHA  $src, $dst\t!asi=primary_little\n\t" %}
+
+  ins_encode %{
+    // the value was spilled as an int so bias the load
+    __ set($src$$disp + STACK_BIAS + 2, O7);
+    __ ldsha($src$$base$$Register, O7, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
   ins_pipe( iload_mem );
 %}
 
 // Load Integer reversed byte order
-instruct loadI_reversed(iRegI dst, memory src) %{
+instruct loadI_reversed(iRegI dst, indIndexMemory src) %{
   match(Set dst (ReverseBytesI (LoadI src)));
 
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
-  size(8);
+  size(4);
   format %{ "LDUWA  $src, $dst\t!asi=primary_little" %}
 
-  opcode(Assembler::lduwa_op3);
-  ins_encode( form3_mem_reg_little( src, dst) );
+  ins_encode %{
+    __ lduwa($src$$base$$Register, $src$$index$$Register, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
   ins_pipe(iload_mem);
 %}
 
 // Load Long - aligned and reversed
-instruct loadL_reversed(iRegL dst, memory src) %{
+instruct loadL_reversed(iRegL dst, indIndexMemory src) %{
   match(Set dst (ReverseBytesL (LoadL src)));
 
-  ins_cost(DEFAULT_COST + MEMORY_REF_COST);
-  size(8);
+  ins_cost(MEMORY_REF_COST);
+  size(4);
   format %{ "LDXA   $src, $dst\t!asi=primary_little" %}
 
-  opcode(Assembler::ldxa_op3);
-  ins_encode( form3_mem_reg_little( src, dst ) );
+  ins_encode %{
+    __ ldxa($src$$base$$Register, $src$$index$$Register, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
+  ins_pipe(iload_mem);
+%}
+
+// Load unsigned short / char reversed byte order
+instruct loadUS_reversed(iRegI dst, indIndexMemory src) %{
+  match(Set dst (ReverseBytesUS (LoadUS src)));
+
+  ins_cost(MEMORY_REF_COST);
+  size(4);
+  format %{ "LDUHA  $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ lduha($src$$base$$Register, $src$$index$$Register, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
+  ins_pipe(iload_mem);
+%}
+
+// Load short reversed byte order
+instruct loadS_reversed(iRegI dst, indIndexMemory src) %{
+  match(Set dst (ReverseBytesS (LoadS src)));
+
+  ins_cost(MEMORY_REF_COST);
+  size(4);
+  format %{ "LDSHA  $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ ldsha($src$$base$$Register, $src$$index$$Register, Assembler::ASI_PRIMARY_LITTLE, $dst$$Register);
+  %}
   ins_pipe(iload_mem);
 %}
 
 // Store Integer reversed byte order
-instruct storeI_reversed(memory dst, iRegI src) %{
+instruct storeI_reversed(indIndexMemory dst, iRegI src) %{
   match(Set dst (StoreI dst (ReverseBytesI src)));
 
   ins_cost(MEMORY_REF_COST);
-  size(8);
+  size(4);
   format %{ "STWA   $src, $dst\t!asi=primary_little" %}
 
-  opcode(Assembler::stwa_op3);
-  ins_encode( form3_mem_reg_little( dst, src) );
+  ins_encode %{
+    __ stwa($src$$Register, $dst$$base$$Register, $dst$$index$$Register, Assembler::ASI_PRIMARY_LITTLE);
+  %}
   ins_pipe(istore_mem_reg);
 %}
 
 // Store Long reversed byte order
-instruct storeL_reversed(memory dst, iRegL src) %{
+instruct storeL_reversed(indIndexMemory dst, iRegL src) %{
   match(Set dst (StoreL dst (ReverseBytesL src)));
 
   ins_cost(MEMORY_REF_COST);
-  size(8);
+  size(4);
   format %{ "STXA   $src, $dst\t!asi=primary_little" %}
 
-  opcode(Assembler::stxa_op3);
-  ins_encode( form3_mem_reg_little( dst, src) );
+  ins_encode %{
+    __ stxa($src$$Register, $dst$$base$$Register, $dst$$index$$Register, Assembler::ASI_PRIMARY_LITTLE);
+  %}
+  ins_pipe(istore_mem_reg);
+%}
+
+// Store unsighed short/char reversed byte order
+instruct storeUS_reversed(indIndexMemory dst, iRegI src) %{
+  match(Set dst (StoreC dst (ReverseBytesUS src)));
+
+  ins_cost(MEMORY_REF_COST);
+  size(4);
+  format %{ "STHA   $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ stha($src$$Register, $dst$$base$$Register, $dst$$index$$Register, Assembler::ASI_PRIMARY_LITTLE);
+  %}
+  ins_pipe(istore_mem_reg);
+%}
+
+// Store short reversed byte order
+instruct storeS_reversed(indIndexMemory dst, iRegI src) %{
+  match(Set dst (StoreC dst (ReverseBytesS src)));
+
+  ins_cost(MEMORY_REF_COST);
+  size(4);
+  format %{ "STHA   $src, $dst\t!asi=primary_little" %}
+
+  ins_encode %{
+    __ stha($src$$Register, $dst$$base$$Register, $dst$$index$$Register, Assembler::ASI_PRIMARY_LITTLE);
+  %}
   ins_pipe(istore_mem_reg);
 %}
 
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 //
-// Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+// Copyright 1997-2010 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
@@ -6272,6 +6272,30 @@
   ins_pipe( ialu_reg_reg);
 %}
 
+instruct bytes_reverse_unsigned_short(eRegI dst) %{
+  match(Set dst (ReverseBytesUS dst));
+
+  format %{ "BSWAP  $dst\n\t" 
+            "SHR    $dst,16\n\t" %}
+  ins_encode %{
+    __ bswapl($dst$$Register);
+    __ shrl($dst$$Register, 16); 
+  %}
+  ins_pipe( ialu_reg );
+%}
+
+instruct bytes_reverse_short(eRegI dst) %{
+  match(Set dst (ReverseBytesS dst));
+
+  format %{ "BSWAP  $dst\n\t" 
+            "SAR    $dst,16\n\t" %}
+  ins_encode %{
+    __ bswapl($dst$$Register);
+    __ sarl($dst$$Register, 16); 
+  %}
+  ins_pipe( ialu_reg );
+%}
+
 
 //---------- Zeros Count Instructions ------------------------------------------
 
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 //
-// Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
+// Copyright 2003-2010 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
@@ -7371,6 +7371,30 @@
   ins_pipe( ialu_reg);
 %}
 
+instruct bytes_reverse_unsigned_short(rRegI dst) %{
+  match(Set dst (ReverseBytesUS dst));
+
+  format %{ "bswapl  $dst\n\t" 
+            "shrl    $dst,16\n\t" %}
+  ins_encode %{
+    __ bswapl($dst$$Register);
+    __ shrl($dst$$Register, 16); 
+  %}
+  ins_pipe( ialu_reg );
+%}
+
+instruct bytes_reverse_short(rRegI dst) %{
+  match(Set dst (ReverseBytesS dst));
+
+  format %{ "bswapl  $dst\n\t" 
+            "sar     $dst,16\n\t" %}
+  ins_encode %{
+    __ bswapl($dst$$Register);
+    __ sarl($dst$$Register, 16); 
+  %}
+  ins_pipe( ialu_reg );
+%}
+
 instruct loadI_reversed(rRegI dst, memory src) %{
   match(Set dst (ReverseBytesI (LoadI src)));
 
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2010 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
@@ -3861,6 +3861,8 @@
         strcmp(opType,"RoundFloat")==0 ||
         strcmp(opType,"ReverseBytesI")==0 ||
         strcmp(opType,"ReverseBytesL")==0 ||
+        strcmp(opType,"ReverseBytesUS")==0 ||
+        strcmp(opType,"ReverseBytesS")==0 ||
         strcmp(opType,"Replicate16B")==0 ||
         strcmp(opType,"Replicate8B")==0 ||
         strcmp(opType,"Replicate4B")==0 ||
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 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
@@ -357,6 +357,8 @@
   template(void_double_signature,                     "()D")                                      \
   template(int_void_signature,                        "(I)V")                                     \
   template(int_int_signature,                         "(I)I")                                     \
+  template(char_char_signature,                       "(C)C")                                     \
+  template(short_short_signature,                     "(S)S")                                     \
   template(int_bool_signature,                        "(I)Z")                                     \
   template(float_int_signature,                       "(F)I")                                     \
   template(double_long_signature,                     "(D)J")                                     \
@@ -585,6 +587,10 @@
    do_name(     reverseBytes_name,                               "reverseBytes")                                        \
   do_intrinsic(_reverseBytes_l,           java_lang_Long,         reverseBytes_name,        long_long_signature, F_S)   \
     /*  (symbol reverseBytes_name defined above) */                                                                     \
+  do_intrinsic(_reverseBytes_c,           java_lang_Character,    reverseBytes_name,        char_char_signature, F_S)   \
+    /*  (symbol reverseBytes_name defined above) */                                                                     \
+  do_intrinsic(_reverseBytes_s,           java_lang_Short,        reverseBytes_name,        short_short_signature, F_S) \
+    /*  (symbol reverseBytes_name defined above) */                                                                     \
                                                                                                                         \
   do_intrinsic(_identityHashCode,         java_lang_System,       identityHashCode_name, object_int_signature,   F_S)   \
    do_name(     identityHashCode_name,                           "identityHashCode")                                    \
--- a/hotspot/src/share/vm/opto/classes.hpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 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
@@ -44,6 +44,8 @@
 macro(BoxLock)
 macro(ReverseBytesI)
 macro(ReverseBytesL)
+macro(ReverseBytesUS)
+macro(ReverseBytesS)
 macro(CProj)
 macro(CallDynamicJava)
 macro(CallJava)
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Mon Apr 26 11:27:21 2010 -0700
@@ -636,6 +636,8 @@
 
   case vmIntrinsics::_reverseBytes_i:
   case vmIntrinsics::_reverseBytes_l:
+  case vmIntrinsics::_reverseBytes_s:
+  case vmIntrinsics::_reverseBytes_c:
     return inline_reverseBytes((vmIntrinsics::ID) intrinsic_id());
 
   case vmIntrinsics::_get_AtomicLong:
@@ -2010,13 +2012,19 @@
   return true;
 }
 
-//----------------------------inline_reverseBytes_int/long-------------------
+//----------------------------inline_reverseBytes_int/long/char/short-------------------
 // inline Integer.reverseBytes(int)
 // inline Long.reverseBytes(long)
+// inline Character.reverseBytes(char)
+// inline Short.reverseBytes(short)
 bool LibraryCallKit::inline_reverseBytes(vmIntrinsics::ID id) {
-  assert(id == vmIntrinsics::_reverseBytes_i || id == vmIntrinsics::_reverseBytes_l, "not reverse Bytes");
-  if (id == vmIntrinsics::_reverseBytes_i && !Matcher::has_match_rule(Op_ReverseBytesI)) return false;
-  if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL)) return false;
+  assert(id == vmIntrinsics::_reverseBytes_i || id == vmIntrinsics::_reverseBytes_l ||
+         id == vmIntrinsics::_reverseBytes_c || id == vmIntrinsics::_reverseBytes_s,
+         "not reverse Bytes");
+  if (id == vmIntrinsics::_reverseBytes_i && !Matcher::has_match_rule(Op_ReverseBytesI))  return false;
+  if (id == vmIntrinsics::_reverseBytes_l && !Matcher::has_match_rule(Op_ReverseBytesL))  return false;
+  if (id == vmIntrinsics::_reverseBytes_c && !Matcher::has_match_rule(Op_ReverseBytesUS)) return false;
+  if (id == vmIntrinsics::_reverseBytes_s && !Matcher::has_match_rule(Op_ReverseBytesS))  return false;
   _sp += arg_size();        // restore stack pointer
   switch (id) {
   case vmIntrinsics::_reverseBytes_i:
@@ -2025,6 +2033,12 @@
   case vmIntrinsics::_reverseBytes_l:
     push_pair(_gvn.transform(new (C, 2) ReverseBytesLNode(0, pop_pair())));
     break;
+  case vmIntrinsics::_reverseBytes_c:
+    push(_gvn.transform(new (C, 2) ReverseBytesUSNode(0, pop())));
+    break;
+  case vmIntrinsics::_reverseBytes_s:
+    push(_gvn.transform(new (C, 2) ReverseBytesSNode(0, pop())));
+    break;
   default:
     ;
   }
--- a/hotspot/src/share/vm/opto/subnode.hpp	Tue Apr 20 13:26:33 2010 -0700
+++ b/hotspot/src/share/vm/opto/subnode.hpp	Mon Apr 26 11:27:21 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 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
@@ -509,3 +509,23 @@
   const Type *bottom_type() const { return TypeLong::LONG; }
   virtual uint ideal_reg() const { return Op_RegL; }
 };
+
+//-------------------------------ReverseBytesUSNode--------------------------------
+// reverse bytes of an unsigned short / char
+class ReverseBytesUSNode : public Node {
+public:
+  ReverseBytesUSNode(Node *c, Node *in1) : Node(c, in1) {}
+  virtual int Opcode() const;
+  const Type *bottom_type() const { return TypeInt::CHAR; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//-------------------------------ReverseBytesSNode--------------------------------
+// reverse bytes of a short
+class ReverseBytesSNode : public Node {
+public:
+  ReverseBytesSNode(Node *c, Node *in1) : Node(c, in1) {}
+  virtual int Opcode() const;
+  const Type *bottom_type() const { return TypeInt::SHORT; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6431242/Test.java	Mon Apr 26 11:27:21 2010 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2006 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 6431242
+ * @run main/othervm -server -XX:+PrintCompilation Test
+ */
+
+public class Test{
+
+  int    _len      = 8;
+  int[]  _arr_i    = new int[_len];
+  long[] _arr_l    = new long[_len];
+
+  int[]  _arr_i_cp = new int [_len];
+  long[] _arr_l_cp = new long [_len];
+
+  int _k     = 0x12345678;
+  int _j     = 0;
+  int _ir    = 0x78563412;
+  int _ir1   = 0x78563413;
+  int _ir2   = 0x79563412;
+
+  long _m    = 0x123456789abcdef0L;
+  long _l    = 0L;
+  long _lr   = 0xf0debc9a78563412L;
+  long _lr1  = 0xf0debc9a78563413L;
+  long _lr2  = 0xf1debc9a78563412L;
+
+  void init() {
+    for (int i=0; i<_arr_i.length; i++) {
+      _arr_i[i] = _k;
+      _arr_l[i] = _m;
+    }
+  }
+
+  public int test_int_reversed(int i) {
+    return Integer.reverseBytes(i);
+  }
+
+  public long test_long_reversed(long i) {
+    return Long.reverseBytes(i);
+  }
+
+  public void test_copy_ints(int[] dst, int[] src) {
+    for(int i=0; i<src.length; i++) {
+      dst[i] = Integer.reverseBytes(src[i]);
+    }
+  }
+
+  public void test_copy_ints_reversed(int[] dst, int[] src) {
+    for (int i=0; i<src.length; i++) {
+      dst[i] = 1 + Integer.reverseBytes(src[i]);
+    }
+  }
+
+  public void test_copy_ints_store_reversed(int[] dst, int[] src) {
+    for(int i=0; i<src.length; i++) {
+      dst[i] = Integer.reverseBytes(1 + src[i]);
+    }
+  }
+
+  public void test_copy_longs(long[] dst, long[] src) {
+    for(int i=0; i<src.length; i++) {
+      dst[i] = Long.reverseBytes(src[i]);
+    }
+  }
+
+  public void test_copy_longs_reversed(long[] dst, long[] src) {
+    for (int i=0; i<src.length; i++) {
+      dst[i] = 1 + Long.reverseBytes(src[i]);
+    }
+  }
+
+  public void test_copy_longs_store_reversed(long[] dst, long[] src) {
+    for(int i=0; i<src.length; i++) {
+      dst[i] = Long.reverseBytes(1 + src[i]);
+    }
+  }
+
+  public void test() throws Exception {
+    int up_limit=90000;
+
+
+    //test single
+
+    for (int loop=0; loop<up_limit; loop++) {
+      _j = test_int_reversed(_k);
+      if (_j != _ir ) {
+        throw new Exception("Interger.reverseBytes failed " + _j + " iter " + loop);
+      }
+      _l = test_long_reversed(_m);
+      if (_l != _lr ) {
+        throw new Exception("Long.reverseBytes failed " + _l + " iter " + loop);
+      }
+    }
+
+    // test scalar load/store
+    for (int loop=0; loop<up_limit; loop++) {
+
+      test_copy_ints(_arr_i_cp, _arr_i);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_i_cp[j] != _ir) {
+          throw new Exception("Interger.reverseBytes failed test_copy_ints iter " + loop);
+        }
+      }
+
+      test_copy_ints_reversed(_arr_i_cp, _arr_i);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_i_cp[j] != _ir1) {
+          throw new Exception("Interger.reverseBytes failed test_copy_ints_reversed iter " + loop);
+        }
+      }
+      test_copy_ints_store_reversed(_arr_i_cp, _arr_i);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_i_cp[j] != _ir2) {
+          throw new Exception("Interger.reverseBytes failed test_copy_ints_store_reversed iter " + loop);
+        }
+      }
+
+      test_copy_longs(_arr_l_cp, _arr_l);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_l_cp[j] != _lr) {
+          throw new Exception("Long.reverseBytes failed test_copy_longs iter " + loop);
+        }
+      }
+      test_copy_longs_reversed(_arr_l_cp, _arr_l);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_l_cp[j] != _lr1) {
+          throw new Exception("Long.reverseBytes failed test_copy_longs_reversed iter " + loop);
+        }
+      }
+      test_copy_longs_store_reversed(_arr_l_cp, _arr_l);
+      for (int j=0; j< _arr_i.length; j++) {
+        if (_arr_l_cp[j] != _lr2) {
+          throw new Exception("Long.reverseBytes failed test_copy_longs_store_reversed iter " + loop);
+        }
+      }
+
+    }
+  }
+
+  public static void main(String args[]) {
+    try {
+      Test t = new Test();
+      t.init();
+      t.test();
+      System.out.println("Passed");
+    }catch (Exception e) {
+      e.printStackTrace();
+      System.out.println("Failed");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6946040/TestCharShortByteSwap.java	Mon Apr 26 11:27:21 2010 -0700
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2010 Google, 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 6946040
+ * @summary Tests Character/Short.reverseBytes and their intrinsics implementation in the server compiler
+ * @run main/othervm -Xbatch -server -XX:CompileOnly=.testChar,.testShort TestCharShortByteSwap
+ */
+
+// This test must run without any command line arguments.
+
+public class TestCharShortByteSwap {
+
+  private static short initShort(String[] args, short v) {
+    if (args.length > 0) {
+      try {
+        return (short) Integer.valueOf(args[0]).intValue();
+      } catch (NumberFormatException e) { }
+    }
+    return v;
+  }
+
+  private static char initChar(String[] args, char v) {
+    if (args.length > 0) {
+      try {
+        return (char) Integer.valueOf(args[0]).intValue();
+      } catch (NumberFormatException e) { }
+    }
+    return v;
+  }
+
+  private static void testChar(char a, char b) {
+    if (a != Character.reverseBytes(b)) {
+      throw new RuntimeException("FAIL: " + (int)a + " != Character.reverseBytes(" + (int)b + ")");
+    }
+    if (b != Character.reverseBytes(a)) {
+      throw new RuntimeException("FAIL: " + (int)b + " != Character.reverseBytes(" + (int)a + ")");
+    }
+  }
+
+  private static void testShort(short a, short b) {
+    if (a != Short.reverseBytes(b)) {
+      throw new RuntimeException("FAIL: " + (int)a + " != Short.reverseBytes(" + (int)b + ")");
+    }
+    if (b != Short.reverseBytes(a)) {
+      throw new RuntimeException("FAIL: " + (int)b + " != Short.reverseBytes(" + (int)a + ")");
+    }
+  }
+
+  public static void main(String[] args) {
+    for (int i = 0; i < 100000; ++i) { // Trigger compilation
+      char c1 = initChar(args, (char) 0x0123);
+      char c2 = initChar(args, (char) 0x2301);
+      char c3 = initChar(args, (char) 0xaabb);
+      char c4 = initChar(args, (char) 0xbbaa);
+      short s1 = initShort(args, (short) 0x0123);
+      short s2 = initShort(args, (short) 0x2301);
+      short s3 = initShort(args, (short) 0xaabb);
+      short s4 = initShort(args, (short) 0xbbaa);
+      testChar(c1, c2);
+      testChar(c3, c4);
+      testShort(s1, s2);
+      testShort(s3, s4);
+    }
+  }
+}