changeset 3699:859c45fb8cea

7201026: add vector for shift count Summary: Add generation of vectors for scalar shift count. Reviewed-by: roland, twisti, dlong
author kvn
date Tue, 02 Oct 2012 12:25:13 -0700
parents f6b0eb4e44cf
children f13867c41f73
files src/cpu/sparc/vm/sparc.ad src/cpu/x86/vm/x86.ad src/share/vm/adlc/formssel.cpp src/share/vm/opto/classes.hpp src/share/vm/opto/matcher.hpp src/share/vm/opto/superword.cpp src/share/vm/opto/vectornode.cpp src/share/vm/opto/vectornode.hpp test/compiler/7200264/Test7200264.sh
diffstat 9 files changed, 178 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/sparc.ad	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Tue Oct 02 12:25:13 2012 -0700
@@ -1870,6 +1870,11 @@
   return Op_RegD;
 }
 
+const int Matcher::vector_shift_count_ideal_reg(int size) {
+  fatal("vector shift is not supported");
+  return Node::NotAMachineReg;
+}
+
 // Limits on vector size (number of elements) loaded into vector.
 const int Matcher::max_vector_size(const BasicType bt) {
   assert(is_java_primitive(bt), "only primitive type vectors");
--- a/src/cpu/x86/vm/x86.ad	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/cpu/x86/vm/x86.ad	Tue Oct 02 12:25:13 2012 -0700
@@ -571,6 +571,11 @@
   return 0;
 }
 
+// Only lowest bits of xmm reg are used for vector shift count.
+const int Matcher::vector_shift_count_ideal_reg(int size) {
+  return Op_VecS;
+}
+
 // x86 supports misaligned vectors store/load.
 const bool Matcher::misaligned_vectors_ok() {
   return !AlignVector; // can be changed by flag
@@ -3758,10 +3763,24 @@
   ins_pipe( pipe_slow );
 %}
 
+// ------------------------------ Shift ---------------------------------------
+
+// Left and right shift count vectors are the same on x86
+// (only lowest bits of xmm reg are used for count).
+instruct vshiftcnt(vecS dst, rRegI cnt) %{
+  match(Set dst (LShiftCntV cnt));
+  match(Set dst (RShiftCntV cnt));
+  format %{ "movd    $dst,$cnt\t! load shift count" %}
+  ins_encode %{
+    __ movdl($dst$$XMMRegister, $cnt$$Register);
+  %}
+  ins_pipe( pipe_slow );
+%}
+
 // ------------------------------ LeftShift -----------------------------------
 
 // Shorts/Chars vector left shift
-instruct vsll2S(vecS dst, regF shift) %{
+instruct vsll2S(vecS dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (LShiftVS dst shift));
   format %{ "psllw   $dst,$shift\t! left shift packed2S" %}
@@ -3781,7 +3800,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll2S_reg(vecS dst, vecS src, regF shift) %{
+instruct vsll2S_reg(vecS dst, vecS src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (LShiftVS src shift));
   format %{ "vpsllw  $dst,$src,$shift\t! left shift packed2S" %}
@@ -3803,7 +3822,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll4S(vecD dst, regF shift) %{
+instruct vsll4S(vecD dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 4);
   match(Set dst (LShiftVS dst shift));
   format %{ "psllw   $dst,$shift\t! left shift packed4S" %}
@@ -3823,7 +3842,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll4S_reg(vecD dst, vecD src, regF shift) %{
+instruct vsll4S_reg(vecD dst, vecD src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
   match(Set dst (LShiftVS src shift));
   format %{ "vpsllw  $dst,$src,$shift\t! left shift packed4S" %}
@@ -3845,7 +3864,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll8S(vecX dst, regF shift) %{
+instruct vsll8S(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 8);
   match(Set dst (LShiftVS dst shift));
   format %{ "psllw   $dst,$shift\t! left shift packed8S" %}
@@ -3865,7 +3884,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll8S_reg(vecX dst, vecX src, regF shift) %{
+instruct vsll8S_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 8);
   match(Set dst (LShiftVS src shift));
   format %{ "vpsllw  $dst,$src,$shift\t! left shift packed8S" %}
@@ -3887,7 +3906,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll16S_reg(vecY dst, vecY src, regF shift) %{
+instruct vsll16S_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 16);
   match(Set dst (LShiftVS src shift));
   format %{ "vpsllw  $dst,$src,$shift\t! left shift packed16S" %}
@@ -3910,7 +3929,7 @@
 %}
 
 // Integers vector left shift
-instruct vsll2I(vecD dst, regF shift) %{
+instruct vsll2I(vecD dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (LShiftVI dst shift));
   format %{ "pslld   $dst,$shift\t! left shift packed2I" %}
@@ -3930,7 +3949,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll2I_reg(vecD dst, vecD src, regF shift) %{
+instruct vsll2I_reg(vecD dst, vecD src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (LShiftVI src shift));
   format %{ "vpslld  $dst,$src,$shift\t! left shift packed2I" %}
@@ -3952,7 +3971,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll4I(vecX dst, regF shift) %{
+instruct vsll4I(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 4);
   match(Set dst (LShiftVI dst shift));
   format %{ "pslld   $dst,$shift\t! left shift packed4I" %}
@@ -3972,7 +3991,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll4I_reg(vecX dst, vecX src, regF shift) %{
+instruct vsll4I_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
   match(Set dst (LShiftVI src shift));
   format %{ "vpslld  $dst,$src,$shift\t! left shift packed4I" %}
@@ -3994,7 +4013,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll8I_reg(vecY dst, vecY src, regF shift) %{
+instruct vsll8I_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 8);
   match(Set dst (LShiftVI src shift));
   format %{ "vpslld  $dst,$src,$shift\t! left shift packed8I" %}
@@ -4017,7 +4036,7 @@
 %}
 
 // Longs vector left shift
-instruct vsll2L(vecX dst, regF shift) %{
+instruct vsll2L(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (LShiftVL dst shift));
   format %{ "psllq   $dst,$shift\t! left shift packed2L" %}
@@ -4037,7 +4056,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll2L_reg(vecX dst, vecX src, regF shift) %{
+instruct vsll2L_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (LShiftVL src shift));
   format %{ "vpsllq  $dst,$src,$shift\t! left shift packed2L" %}
@@ -4059,7 +4078,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsll4L_reg(vecY dst, vecY src, regF shift) %{
+instruct vsll4L_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 4);
   match(Set dst (LShiftVL src shift));
   format %{ "vpsllq  $dst,$src,$shift\t! left shift packed4L" %}
@@ -4088,7 +4107,7 @@
 // sign extension before a shift.
 
 // Integers vector logical right shift
-instruct vsrl2I(vecD dst, regF shift) %{
+instruct vsrl2I(vecD dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (URShiftVI dst shift));
   format %{ "psrld   $dst,$shift\t! logical right shift packed2I" %}
@@ -4108,7 +4127,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl2I_reg(vecD dst, vecD src, regF shift) %{
+instruct vsrl2I_reg(vecD dst, vecD src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (URShiftVI src shift));
   format %{ "vpsrld  $dst,$src,$shift\t! logical right shift packed2I" %}
@@ -4130,7 +4149,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl4I(vecX dst, regF shift) %{
+instruct vsrl4I(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 4);
   match(Set dst (URShiftVI dst shift));
   format %{ "psrld   $dst,$shift\t! logical right shift packed4I" %}
@@ -4150,7 +4169,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl4I_reg(vecX dst, vecX src, regF shift) %{
+instruct vsrl4I_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
   match(Set dst (URShiftVI src shift));
   format %{ "vpsrld  $dst,$src,$shift\t! logical right shift packed4I" %}
@@ -4172,7 +4191,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl8I_reg(vecY dst, vecY src, regF shift) %{
+instruct vsrl8I_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 8);
   match(Set dst (URShiftVI src shift));
   format %{ "vpsrld  $dst,$src,$shift\t! logical right shift packed8I" %}
@@ -4195,7 +4214,7 @@
 %}
 
 // Longs vector logical right shift
-instruct vsrl2L(vecX dst, regF shift) %{
+instruct vsrl2L(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (URShiftVL dst shift));
   format %{ "psrlq   $dst,$shift\t! logical right shift packed2L" %}
@@ -4215,7 +4234,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl2L_reg(vecX dst, vecX src, regF shift) %{
+instruct vsrl2L_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (URShiftVL src shift));
   format %{ "vpsrlq  $dst,$src,$shift\t! logical right shift packed2L" %}
@@ -4237,7 +4256,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsrl4L_reg(vecY dst, vecY src, regF shift) %{
+instruct vsrl4L_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 4);
   match(Set dst (URShiftVL src shift));
   format %{ "vpsrlq  $dst,$src,$shift\t! logical right shift packed4L" %}
@@ -4262,7 +4281,7 @@
 // ------------------- ArithmeticRightShift -----------------------------------
 
 // Shorts/Chars vector arithmetic right shift
-instruct vsra2S(vecS dst, regF shift) %{
+instruct vsra2S(vecS dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (RShiftVS dst shift));
   format %{ "psraw   $dst,$shift\t! arithmetic right shift packed2S" %}
@@ -4282,7 +4301,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra2S_reg(vecS dst, vecS src, regF shift) %{
+instruct vsra2S_reg(vecS dst, vecS src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (RShiftVS src shift));
   format %{ "vpsraw  $dst,$src,$shift\t! arithmetic right shift packed2S" %}
@@ -4304,7 +4323,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra4S(vecD dst, regF shift) %{
+instruct vsra4S(vecD dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 4);
   match(Set dst (RShiftVS dst shift));
   format %{ "psraw   $dst,$shift\t! arithmetic right shift packed4S" %}
@@ -4324,7 +4343,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra4S_reg(vecD dst, vecD src, regF shift) %{
+instruct vsra4S_reg(vecD dst, vecD src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
   match(Set dst (RShiftVS src shift));
   format %{ "vpsraw  $dst,$src,$shift\t! arithmetic right shift packed4S" %}
@@ -4346,7 +4365,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra8S(vecX dst, regF shift) %{
+instruct vsra8S(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 8);
   match(Set dst (RShiftVS dst shift));
   format %{ "psraw   $dst,$shift\t! arithmetic right shift packed8S" %}
@@ -4366,7 +4385,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra8S_reg(vecX dst, vecX src, regF shift) %{
+instruct vsra8S_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 8);
   match(Set dst (RShiftVS src shift));
   format %{ "vpsraw  $dst,$src,$shift\t! arithmetic right shift packed8S" %}
@@ -4388,7 +4407,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra16S_reg(vecY dst, vecY src, regF shift) %{
+instruct vsra16S_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 16);
   match(Set dst (RShiftVS src shift));
   format %{ "vpsraw  $dst,$src,$shift\t! arithmetic right shift packed16S" %}
@@ -4411,7 +4430,7 @@
 %}
 
 // Integers vector arithmetic right shift
-instruct vsra2I(vecD dst, regF shift) %{
+instruct vsra2I(vecD dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 2);
   match(Set dst (RShiftVI dst shift));
   format %{ "psrad   $dst,$shift\t! arithmetic right shift packed2I" %}
@@ -4431,7 +4450,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra2I_reg(vecD dst, vecD src, regF shift) %{
+instruct vsra2I_reg(vecD dst, vecD src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 2);
   match(Set dst (RShiftVI src shift));
   format %{ "vpsrad  $dst,$src,$shift\t! arithmetic right shift packed2I" %}
@@ -4453,7 +4472,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra4I(vecX dst, regF shift) %{
+instruct vsra4I(vecX dst, vecS shift) %{
   predicate(n->as_Vector()->length() == 4);
   match(Set dst (RShiftVI dst shift));
   format %{ "psrad   $dst,$shift\t! arithmetic right shift packed4I" %}
@@ -4473,7 +4492,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra4I_reg(vecX dst, vecX src, regF shift) %{
+instruct vsra4I_reg(vecX dst, vecX src, vecS shift) %{
   predicate(UseAVX > 0 && n->as_Vector()->length() == 4);
   match(Set dst (RShiftVI src shift));
   format %{ "vpsrad  $dst,$src,$shift\t! arithmetic right shift packed4I" %}
@@ -4495,7 +4514,7 @@
   ins_pipe( pipe_slow );
 %}
 
-instruct vsra8I_reg(vecY dst, vecY src, regF shift) %{
+instruct vsra8I_reg(vecY dst, vecY src, vecS shift) %{
   predicate(UseAVX > 1 && n->as_Vector()->length() == 8);
   match(Set dst (RShiftVI src shift));
   format %{ "vpsrad  $dst,$src,$shift\t! arithmetic right shift packed8I" %}
--- a/src/share/vm/adlc/formssel.cpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/adlc/formssel.cpp	Tue Oct 02 12:25:13 2012 -0700
@@ -4049,6 +4049,7 @@
     "MulVS","MulVI","MulVF","MulVD",
     "DivVF","DivVD",
     "AndV" ,"XorV" ,"OrV",
+    "LShiftCntV","RShiftCntV",
     "LShiftVB","LShiftVS","LShiftVI","LShiftVL",
     "RShiftVB","RShiftVS","RShiftVI","RShiftVL",
     "URShiftVB","URShiftVS","URShiftVI","URShiftVL",
--- a/src/share/vm/opto/classes.hpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/opto/classes.hpp	Tue Oct 02 12:25:13 2012 -0700
@@ -268,6 +268,8 @@
 macro(MulVD)
 macro(DivVF)
 macro(DivVD)
+macro(LShiftCntV)
+macro(RShiftCntV)
 macro(LShiftVB)
 macro(LShiftVS)
 macro(LShiftVI)
--- a/src/share/vm/opto/matcher.hpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/opto/matcher.hpp	Tue Oct 02 12:25:13 2012 -0700
@@ -261,6 +261,7 @@
 
   // Vector ideal reg
   static const int vector_ideal_reg(int len);
+  static const int vector_shift_count_ideal_reg(int len);
 
   // CPU supports misaligned vectors store/load.
   static const bool misaligned_vectors_ok();
--- a/src/share/vm/opto/superword.cpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/opto/superword.cpp	Tue Oct 02 12:25:13 2012 -0700
@@ -1436,10 +1436,9 @@
       return opd; // input is matching vector
     }
     if ((opd_idx == 2) && VectorNode::is_shift(p0)) {
-      // No vector is needed for shift count.
-      // Vector instructions do not mask shift count, do it here.
       Compile* C = _phase->C;
       Node* cnt = opd;
+      // Vector instructions do not mask shift count, do it here.
       juint mask = (p0->bottom_type() == TypeInt::INT) ? (BitsPerInt - 1) : (BitsPerLong - 1);
       const TypeInt* t = opd->find_int_type();
       if (t != NULL && t->is_con()) {
@@ -1456,8 +1455,8 @@
           _phase->set_ctrl(cnt, _phase->get_ctrl(opd));
         }
         assert(opd->bottom_type()->isa_int(), "int type only");
-        // Move non constant shift count into XMM register.
-        cnt = new (C) MoveI2FNode(cnt);
+        // Move non constant shift count into vector register.
+        cnt = VectorNode::shift_count(C, p0, cnt, vlen, velt_basic_type(p0));
       }
       if (cnt != opd) {
         _igvn.register_new_node_with_optimizer(cnt);
--- a/src/share/vm/opto/vectornode.cpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/opto/vectornode.cpp	Tue Oct 02 12:25:13 2012 -0700
@@ -243,6 +243,8 @@
 VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) {
   const TypeVect* vt = TypeVect::make(bt, vlen);
   int vopc = VectorNode::opcode(opc, bt);
+  // This method should not be called for unimplemented vectors.
+  guarantee(vopc > 0, err_msg_res("Vector for '%s' is not implemented", NodeClassNames[opc]));
 
   switch (vopc) {
   case Op_AddVB: return new (C) AddVBNode(n1, n2, vt);
@@ -286,7 +288,7 @@
   case Op_OrV:  return new (C) OrVNode (n1, n2, vt);
   case Op_XorV: return new (C) XorVNode(n1, n2, vt);
   }
-  ShouldNotReachHere();
+  fatal(err_msg_res("Missed vector creation for '%s'", NodeClassNames[vopc]));
   return NULL;
 
 }
@@ -312,7 +314,25 @@
   case T_DOUBLE:
     return new (C) ReplicateDNode(s, vt);
   }
-  ShouldNotReachHere();
+  fatal(err_msg_res("Type '%s' is not supported for vectors", type2name(bt)));
+  return NULL;
+}
+
+VectorNode* VectorNode::shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt) {
+  assert(VectorNode::is_shift(shift) && !cnt->is_Con(), "only variable shift count");
+  // Match shift count type with shift vector type.
+  const TypeVect* vt = TypeVect::make(bt, vlen);
+  switch (shift->Opcode()) {
+  case Op_LShiftI:
+  case Op_LShiftL:
+    return new (C) LShiftCntVNode(cnt, vt);
+  case Op_RShiftI:
+  case Op_RShiftL:
+  case Op_URShiftI:
+  case Op_URShiftL:
+    return new (C) RShiftCntVNode(cnt, vt);
+  }
+  fatal(err_msg_res("Missed vector creation for '%s'", NodeClassNames[shift->Opcode()]));
   return NULL;
 }
 
@@ -335,7 +355,7 @@
   case T_DOUBLE:
     return new (C) PackDNode(s, vt);
   }
-  ShouldNotReachHere();
+  fatal(err_msg_res("Type '%s' is not supported for vectors", type2name(bt)));
   return NULL;
 }
 
@@ -371,7 +391,7 @@
     case T_DOUBLE:
       return new (C) Pack2DNode(n1, n2, TypeVect::make(T_DOUBLE, 2));
     }
-    ShouldNotReachHere();
+    fatal(err_msg_res("Type '%s' is not supported for vectors", type2name(bt)));
   }
   return NULL;
 }
@@ -381,7 +401,6 @@
                                      Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) {
   const TypeVect* vt = TypeVect::make(bt, vlen);
   return new (C) LoadVectorNode(ctl, mem, adr, atyp, vt);
-  return NULL;
 }
 
 // Return the vector version of a scalar store node.
@@ -413,7 +432,7 @@
   case T_DOUBLE:
     return new (C) ExtractDNode(v, pos);
   }
-  ShouldNotReachHere();
+  fatal(err_msg_res("Type '%s' is not supported for vectors", type2name(bt)));
   return NULL;
 }
 
--- a/src/share/vm/opto/vectornode.hpp	Mon Oct 01 14:50:10 2012 -0700
+++ b/src/share/vm/opto/vectornode.hpp	Tue Oct 02 12:25:13 2012 -0700
@@ -29,7 +29,7 @@
 #include "opto/node.hpp"
 #include "opto/opcodes.hpp"
 
-//------------------------------VectorNode--------------------------------------
+//------------------------------VectorNode-------------------------------------
 // Vector Operation
 class VectorNode : public TypeNode {
  public:
@@ -53,7 +53,7 @@
   virtual uint ideal_reg() const { return Matcher::vector_ideal_reg(vect_type()->length_in_bytes()); }
 
   static VectorNode* scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t);
-
+  static VectorNode* shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt);
   static VectorNode* make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt);
 
   static int  opcode(int opc, BasicType bt);
@@ -64,9 +64,9 @@
   static void vector_operands(Node* n, uint* start, uint* end);
 };
 
-//===========================Vector=ALU=Operations====================================
+//===========================Vector=ALU=Operations=============================
 
-//------------------------------AddVBNode---------------------------------------
+//------------------------------AddVBNode--------------------------------------
 // Vector add byte
 class AddVBNode : public VectorNode {
  public:
@@ -74,7 +74,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------AddVSNode---------------------------------------
+//------------------------------AddVSNode--------------------------------------
 // Vector add char/short
 class AddVSNode : public VectorNode {
  public:
@@ -82,7 +82,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------AddVINode---------------------------------------
+//------------------------------AddVINode--------------------------------------
 // Vector add int
 class AddVINode : public VectorNode {
  public:
@@ -90,7 +90,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------AddVLNode---------------------------------------
+//------------------------------AddVLNode--------------------------------------
 // Vector add long
 class AddVLNode : public VectorNode {
  public:
@@ -98,7 +98,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------AddVFNode---------------------------------------
+//------------------------------AddVFNode--------------------------------------
 // Vector add float
 class AddVFNode : public VectorNode {
  public:
@@ -106,7 +106,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------AddVDNode---------------------------------------
+//------------------------------AddVDNode--------------------------------------
 // Vector add double
 class AddVDNode : public VectorNode {
  public:
@@ -114,7 +114,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVBNode---------------------------------------
+//------------------------------SubVBNode--------------------------------------
 // Vector subtract byte
 class SubVBNode : public VectorNode {
  public:
@@ -122,7 +122,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVSNode---------------------------------------
+//------------------------------SubVSNode--------------------------------------
 // Vector subtract short
 class SubVSNode : public VectorNode {
  public:
@@ -130,7 +130,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVINode---------------------------------------
+//------------------------------SubVINode--------------------------------------
 // Vector subtract int
 class SubVINode : public VectorNode {
  public:
@@ -138,7 +138,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVLNode---------------------------------------
+//------------------------------SubVLNode--------------------------------------
 // Vector subtract long
 class SubVLNode : public VectorNode {
  public:
@@ -146,7 +146,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVFNode---------------------------------------
+//------------------------------SubVFNode--------------------------------------
 // Vector subtract float
 class SubVFNode : public VectorNode {
  public:
@@ -154,7 +154,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------SubVDNode---------------------------------------
+//------------------------------SubVDNode--------------------------------------
 // Vector subtract double
 class SubVDNode : public VectorNode {
  public:
@@ -162,7 +162,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------MulVSNode---------------------------------------
+//------------------------------MulVSNode--------------------------------------
 // Vector multiply short
 class MulVSNode : public VectorNode {
  public:
@@ -170,7 +170,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------MulVINode---------------------------------------
+//------------------------------MulVINode--------------------------------------
 // Vector multiply int
 class MulVINode : public VectorNode {
  public:
@@ -178,7 +178,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------MulVFNode---------------------------------------
+//------------------------------MulVFNode--------------------------------------
 // Vector multiply float
 class MulVFNode : public VectorNode {
  public:
@@ -186,7 +186,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------MulVDNode---------------------------------------
+//------------------------------MulVDNode--------------------------------------
 // Vector multiply double
 class MulVDNode : public VectorNode {
  public:
@@ -194,7 +194,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------DivVFNode---------------------------------------
+//------------------------------DivVFNode--------------------------------------
 // Vector divide float
 class DivVFNode : public VectorNode {
  public:
@@ -202,7 +202,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------DivVDNode---------------------------------------
+//------------------------------DivVDNode--------------------------------------
 // Vector Divide double
 class DivVDNode : public VectorNode {
  public:
@@ -210,7 +210,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------LShiftVBNode---------------------------------------
+//------------------------------LShiftVBNode-----------------------------------
 // Vector left shift bytes
 class LShiftVBNode : public VectorNode {
  public:
@@ -218,7 +218,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------LShiftVSNode---------------------------------------
+//------------------------------LShiftVSNode-----------------------------------
 // Vector left shift shorts
 class LShiftVSNode : public VectorNode {
  public:
@@ -226,7 +226,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------LShiftVINode---------------------------------------
+//------------------------------LShiftVINode-----------------------------------
 // Vector left shift ints
 class LShiftVINode : public VectorNode {
  public:
@@ -234,7 +234,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------LShiftVLNode---------------------------------------
+//------------------------------LShiftVLNode-----------------------------------
 // Vector left shift longs
 class LShiftVLNode : public VectorNode {
  public:
@@ -242,7 +242,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------RShiftVBNode---------------------------------------
+//------------------------------RShiftVBNode-----------------------------------
 // Vector right arithmetic (signed) shift bytes
 class RShiftVBNode : public VectorNode {
  public:
@@ -250,7 +250,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------RShiftVSNode---------------------------------------
+//------------------------------RShiftVSNode-----------------------------------
 // Vector right arithmetic (signed) shift shorts
 class RShiftVSNode : public VectorNode {
  public:
@@ -258,7 +258,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------RShiftVINode---------------------------------------
+//------------------------------RShiftVINode-----------------------------------
 // Vector right arithmetic (signed) shift ints
 class RShiftVINode : public VectorNode {
  public:
@@ -266,7 +266,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------RShiftVLNode---------------------------------------
+//------------------------------RShiftVLNode-----------------------------------
 // Vector right arithmetic (signed) shift longs
 class RShiftVLNode : public VectorNode {
  public:
@@ -274,7 +274,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------URShiftVBNode---------------------------------------
+//------------------------------URShiftVBNode----------------------------------
 // Vector right logical (unsigned) shift bytes
 class URShiftVBNode : public VectorNode {
  public:
@@ -282,7 +282,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------URShiftVSNode---------------------------------------
+//------------------------------URShiftVSNode----------------------------------
 // Vector right logical (unsigned) shift shorts
 class URShiftVSNode : public VectorNode {
  public:
@@ -290,7 +290,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------URShiftVINode---------------------------------------
+//------------------------------URShiftVINode----------------------------------
 // Vector right logical (unsigned) shift ints
 class URShiftVINode : public VectorNode {
  public:
@@ -298,7 +298,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------URShiftVLNode---------------------------------------
+//------------------------------URShiftVLNode----------------------------------
 // Vector right logical (unsigned) shift longs
 class URShiftVLNode : public VectorNode {
  public:
@@ -306,6 +306,24 @@
   virtual int Opcode() const;
 };
 
+//------------------------------LShiftCntVNode---------------------------------
+// Vector left shift count
+class LShiftCntVNode : public VectorNode {
+ public:
+  LShiftCntVNode(Node* cnt, const TypeVect* vt) : VectorNode(cnt,vt) {}
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return Matcher::vector_shift_count_ideal_reg(vect_type()->length_in_bytes()); }
+};
+
+//------------------------------RShiftCntVNode---------------------------------
+// Vector right shift count
+class RShiftCntVNode : public VectorNode {
+ public:
+  RShiftCntVNode(Node* cnt, const TypeVect* vt) : VectorNode(cnt,vt) {}
+  virtual int Opcode() const;
+  virtual uint ideal_reg() const { return Matcher::vector_shift_count_ideal_reg(vect_type()->length_in_bytes()); }
+};
+
 
 //------------------------------AndVNode---------------------------------------
 // Vector and integer
@@ -452,7 +470,7 @@
   static PackNode* make(Compile* C, Node* s, uint vlen, BasicType bt);
 };
 
-//------------------------------PackBNode---------------------------------------
+//------------------------------PackBNode--------------------------------------
 // Pack byte scalars into vector
 class PackBNode : public PackNode {
  public:
@@ -460,7 +478,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------PackSNode---------------------------------------
+//------------------------------PackSNode--------------------------------------
 // Pack short scalars into a vector
 class PackSNode : public PackNode {
  public:
@@ -469,7 +487,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------PackINode---------------------------------------
+//------------------------------PackINode--------------------------------------
 // Pack integer scalars into a vector
 class PackINode : public PackNode {
  public:
@@ -478,7 +496,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------PackLNode---------------------------------------
+//------------------------------PackLNode--------------------------------------
 // Pack long scalars into a vector
 class PackLNode : public PackNode {
  public:
@@ -487,7 +505,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------Pack2LNode--------------------------------------
+//------------------------------Pack2LNode-------------------------------------
 // Pack 2 long scalars into a vector
 class Pack2LNode : public PackNode {
  public:
@@ -495,7 +513,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------PackFNode---------------------------------------
+//------------------------------PackFNode--------------------------------------
 // Pack float scalars into vector
 class PackFNode : public PackNode {
  public:
@@ -504,7 +522,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------PackDNode---------------------------------------
+//------------------------------PackDNode--------------------------------------
 // Pack double scalars into a vector
 class PackDNode : public PackNode {
  public:
@@ -513,7 +531,7 @@
   virtual int Opcode() const;
 };
 
-//------------------------------Pack2DNode--------------------------------------
+//------------------------------Pack2DNode-------------------------------------
 // Pack 2 double scalars into a vector
 class Pack2DNode : public PackNode {
  public:
@@ -522,9 +540,9 @@
 };
 
 
-//========================Extract_Scalar_from_Vector===============================
+//========================Extract_Scalar_from_Vector===========================
 
-//------------------------------ExtractNode---------------------------------------
+//------------------------------ExtractNode------------------------------------
 // Extract a scalar from a vector at position "pos"
 class ExtractNode : public Node {
  public:
@@ -537,7 +555,7 @@
   static Node* make(Compile* C, Node* v, uint position, BasicType bt);
 };
 
-//------------------------------ExtractBNode---------------------------------------
+//------------------------------ExtractBNode-----------------------------------
 // Extract a byte from a vector at position "pos"
 class ExtractBNode : public ExtractNode {
  public:
@@ -547,7 +565,7 @@
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------ExtractUBNode--------------------------------------
+//------------------------------ExtractUBNode----------------------------------
 // Extract a boolean from a vector at position "pos"
 class ExtractUBNode : public ExtractNode {
  public:
@@ -557,7 +575,7 @@
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------ExtractCNode---------------------------------------
+//------------------------------ExtractCNode-----------------------------------
 // Extract a char from a vector at position "pos"
 class ExtractCNode : public ExtractNode {
  public:
@@ -567,7 +585,7 @@
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------ExtractSNode---------------------------------------
+//------------------------------ExtractSNode-----------------------------------
 // Extract a short from a vector at position "pos"
 class ExtractSNode : public ExtractNode {
  public:
@@ -577,7 +595,7 @@
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------ExtractINode---------------------------------------
+//------------------------------ExtractINode-----------------------------------
 // Extract an int from a vector at position "pos"
 class ExtractINode : public ExtractNode {
  public:
@@ -587,7 +605,7 @@
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------ExtractLNode---------------------------------------
+//------------------------------ExtractLNode-----------------------------------
 // Extract a long from a vector at position "pos"
 class ExtractLNode : public ExtractNode {
  public:
@@ -597,7 +615,7 @@
   virtual uint ideal_reg() const { return Op_RegL; }
 };
 
-//------------------------------ExtractFNode---------------------------------------
+//------------------------------ExtractFNode-----------------------------------
 // Extract a float from a vector at position "pos"
 class ExtractFNode : public ExtractNode {
  public:
@@ -607,7 +625,7 @@
   virtual uint ideal_reg() const { return Op_RegF; }
 };
 
-//------------------------------ExtractDNode---------------------------------------
+//------------------------------ExtractDNode-----------------------------------
 // Extract a double from a vector at position "pos"
 class ExtractDNode : public ExtractNode {
  public:
--- a/test/compiler/7200264/Test7200264.sh	Mon Oct 01 14:50:10 2012 -0700
+++ b/test/compiler/7200264/Test7200264.sh	Tue Oct 02 12:25:13 2012 -0700
@@ -77,6 +77,16 @@
     exit 0
 fi
 
+# grep for support integer multiply vectors (cpu with SSE4.1)
+${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1"
+
+if [ $? != 0 ]
+then
+    SSE=2
+else
+    SSE=4
+fi
+
 cp ${TESTSRC}${FS}TestIntVect.java .
 ${TESTJAVA}${FS}bin${FS}javac -d . TestIntVect.java
 
@@ -97,6 +107,9 @@
     exit 1
 fi
 
+# MulVI is only supported with SSE4.1.
+if [ $SSE -gt 3 ]
+then
 # LShiftVI+SubVI is generated for test_mulc
 COUNT=`grep MulVI test.out | wc -l | awk '{print $1}'`
 if [ $COUNT -lt 2 ]
@@ -104,6 +117,7 @@
     echo "Test Failed: MulVI $COUNT < 2"
     exit 1
 fi
+fi
 
 COUNT=`grep AndV test.out | wc -l | awk '{print $1}'`
 if [ $COUNT -lt 3 ]
@@ -126,6 +140,7 @@
     exit 1
 fi
 
+# LShiftVI+SubVI is generated for test_mulc
 COUNT=`grep LShiftVI test.out | wc -l | awk '{print $1}'`
 if [ $COUNT -lt 5 ]
 then
@@ -133,11 +148,10 @@
     exit 1
 fi
 
-# RShiftVI + URShiftVI
-COUNT=`grep RShiftVI test.out | wc -l | awk '{print $1}'`
-if [ $COUNT -lt 6 ]
+COUNT=`grep RShiftVI test.out | sed '/URShiftVI/d' | wc -l | awk '{print $1}'`
+if [ $COUNT -lt 3 ]
 then
-    echo "Test Failed: RShiftVI $COUNT < 6"
+    echo "Test Failed: RShiftVI $COUNT < 3"
     exit 1
 fi