8252188: Crash in OrINode::Ideal(PhaseGVN*, bool)+0x8b9

Reviewed-by: vlivanov, thartmann, jbhateja
diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp
index f83938a..1ac85cc 100644
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -743,41 +743,47 @@
   return AddNode::Identity(phase);
 }
 
-Node *OrINode::Ideal(PhaseGVN *phase, bool can_reshape) {
+// Find shift value for Integer or Long OR.
+Node* rotate_shift(PhaseGVN* phase, Node* lshift, Node* rshift, int mask) {
+  // val << norm_con_shift | val >> ({32|64} - norm_con_shift) => rotate_left val, norm_con_shift
+  const TypeInt* lshift_t = phase->type(lshift)->isa_int();
+  const TypeInt* rshift_t = phase->type(rshift)->isa_int();
+  if (lshift_t != NULL && lshift_t->is_con() &&
+      rshift_t != NULL && rshift_t->is_con() &&
+      ((lshift_t->get_con() & mask) == ((mask + 1) - (rshift_t->get_con() & mask)))) {
+    return phase->intcon(lshift_t->get_con() & mask);
+  }
+  // val << var_shift | val >> ({0|32|64} - var_shift) => rotate_left val, var_shift
+  if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift && rshift->in(1)->is_Con()){
+    const TypeInt* shift_t = phase->type(rshift->in(1))->isa_int();
+    if (shift_t != NULL && shift_t->is_con() &&
+        (shift_t->get_con() == 0 || shift_t->get_con() == (mask + 1))) {
+      return lshift;
+    }
+  }
+  return NULL;
+}
+
+Node* OrINode::Ideal(PhaseGVN* phase, bool can_reshape) {
   int lopcode = in(1)->Opcode();
   int ropcode = in(2)->Opcode();
   if (Matcher::match_rule_supported(Op_RotateLeft) &&
       lopcode == Op_LShiftI && ropcode == Op_URShiftI && in(1)->in(1) == in(2)->in(1)) {
-     Node *lshift = in(1)->in(2);
-     Node *rshift = in(2)->in(2);
-     // val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val , norm_con_shift
-     if (lshift->is_Con() && rshift->is_Con() &&
-         ((lshift->get_int() & 0x1F) == (32 - (rshift->get_int() & 0x1F)))) {
-       return  new RotateLeftNode(in(1)->in(1),
-                 phase->intcon(lshift->get_int() & 0x1F), TypeInt::INT);
+     Node* lshift = in(1)->in(2);
+     Node* rshift = in(2)->in(2);
+     Node* shift = rotate_shift(phase, lshift, rshift, 0x1F);
+     if (shift != NULL) {
+       return new RotateLeftNode(in(1)->in(1), shift, TypeInt::INT);
      }
-     // val << var_shift | val >> (0/32 - var_shift) => rotate_left val , var_shift
-     if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
-         rshift->in(1)->is_Con() &&
-         (rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 32)) {
-       return  new RotateLeftNode(in(1)->in(1), lshift, TypeInt::INT);
-     }
+     return NULL;
   }
   if (Matcher::match_rule_supported(Op_RotateRight) &&
       lopcode == Op_URShiftI && ropcode == Op_LShiftI && in(1)->in(1) == in(2)->in(1)) {
      Node *rshift = in(1)->in(2);
      Node *lshift = in(2)->in(2);
-     // val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val , norm_con_shift
-     if (rshift->is_Con() && lshift->is_Con() &&
-         ((rshift->get_int() & 0x1F) == (32 - (lshift->get_int() & 0x1F)))) {
-       return  new RotateRightNode(in(1)->in(1),
-                 phase->intcon(rshift->get_int() & 0x1F), TypeInt::INT);
-     }
-     // val >> var_shift | val << (0/32 - var_shift) => rotate_right val , var_shift
-     if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
-         lshift->in(1)->is_Con() &&
-         (lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 32)) {
-       return  new RotateRightNode(in(1)->in(1), rshift, TypeInt::INT);
+     Node* shift = rotate_shift(phase, rshift, lshift, 0x1F);
+     if (shift != NULL) {
+       return new RotateRightNode(in(1)->in(1), shift, TypeInt::INT);
      }
   }
   return NULL;
@@ -824,42 +830,27 @@
   return AddNode::Identity(phase);
 }
 
-Node *OrLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+Node* OrLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
   int lopcode = in(1)->Opcode();
   int ropcode = in(2)->Opcode();
   if (Matcher::match_rule_supported(Op_RotateLeft) &&
       lopcode == Op_LShiftL && ropcode == Op_URShiftL && in(1)->in(1) == in(2)->in(1)) {
-     Node *lshift = in(1)->in(2);
-     Node *rshift = in(2)->in(2);
-     // val << norm_con_shift | val >> (64 - norm_con_shift) => rotate_left val , norm_con_shift
-     if (lshift->is_Con() && rshift->is_Con() &&
-         ((lshift->get_int() & 0x3F) == (64 - (rshift->get_int() & 0x3F)))) {
-       return  new RotateLeftNode(in(1)->in(1),
-                 phase->intcon(lshift->get_int() & 0x3F), TypeLong::LONG);
-     }
-     // val << var_shift | val >> (0/64 - var_shift) => rotate_left val , var_shift
-     if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
-         rshift->in(1)->is_Con() &&
-         (rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 64)) {
-       return  new RotateLeftNode(in(1)->in(1), lshift, TypeLong::LONG);
-     }
+    Node* lshift = in(1)->in(2);
+    Node* rshift = in(2)->in(2);
+    Node* shift = rotate_shift(phase, lshift, rshift, 0x3F);
+    if (shift != NULL) {
+      return new RotateLeftNode(in(1)->in(1), shift, TypeLong::LONG);
+    }
+    return NULL;
   }
   if (Matcher::match_rule_supported(Op_RotateRight) &&
       lopcode == Op_URShiftL && ropcode == Op_LShiftL && in(1)->in(1) == in(2)->in(1)) {
-     Node *rshift = in(1)->in(2);
-     Node *lshift = in(2)->in(2);
-     // val >> norm_con_shift | val << (64 - norm_con_shift) => rotate_right val , norm_con_shift
-     if (rshift->is_Con() && lshift->is_Con() &&
-         ((rshift->get_int() & 0x3F) == (64 - (lshift->get_int() & 0x3F)))) {
-       return  new RotateRightNode(in(1)->in(1),
-                 phase->intcon(rshift->get_int() & 0x3F), TypeLong::LONG);
-     }
-     // val >> var_shift | val << (0/64 - var_shift) => rotate_right val , var_shift
-     if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
-         lshift->in(1)->is_Con() &&
-         (lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 64)) {
-       return  new RotateRightNode(in(1)->in(1), rshift, TypeLong::LONG);
-     }
+    Node* rshift = in(1)->in(2);
+    Node* lshift = in(2)->in(2);
+    Node* shift = rotate_shift(phase, rshift, lshift, 0x3F);
+    if (shift != NULL) {
+      return new RotateRightNode(in(1)->in(1), shift, TypeLong::LONG);
+    }
   }
   return NULL;
 }
diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp
index d94f3a5..b3703e1 100644
--- a/src/hotspot/share/opto/vectornode.cpp
+++ b/src/hotspot/share/opto/vectornode.cpp
@@ -835,46 +835,33 @@
 
 Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_left,
                                            int vlen, BasicType bt, PhaseGVN* phase) {
-  int shiftLOpc;
-  int shiftROpc;
-  Node* shiftLCnt = NULL;
-  Node* shiftRCnt = NULL;
+  assert(bt == T_INT || bt == T_LONG, "sanity");
   const TypeVect* vt = TypeVect::make(bt, vlen);
 
+  int shift_mask = (bt == T_INT) ? 0x1F : 0x3F;
+  int shiftLOpc = (bt == T_INT) ? Op_LShiftI : Op_LShiftL;
+  int shiftROpc = (bt == T_INT) ? Op_URShiftI: Op_URShiftL;
+
   // Compute shift values for right rotation and
   // later swap them in case of left rotation.
-  if (cnt->is_Con()) {
+  Node* shiftRCnt = NULL;
+  Node* shiftLCnt = NULL;
+  if (cnt->is_Con() && cnt->bottom_type()->isa_int()) {
     // Constant shift case.
-    if (bt == T_INT) {
-      int shift = cnt->get_int() & 31;
-      shiftRCnt = phase->intcon(shift);
-      shiftLCnt = phase->intcon(32 - shift);
-      shiftLOpc = Op_LShiftI;
-      shiftROpc = Op_URShiftI;
-    } else {
-      int shift = cnt->get_int() & 63;
-      shiftRCnt = phase->intcon(shift);
-      shiftLCnt = phase->intcon(64 - shift);
-      shiftLOpc = Op_LShiftL;
-      shiftROpc = Op_URShiftL;
-    }
+    int shift = cnt->get_int() & shift_mask;
+    shiftRCnt = phase->intcon(shift);
+    shiftLCnt = phase->intcon(shift_mask + 1 - shift);
   } else {
     // Variable shift case.
     assert(VectorNode::is_invariant_vector(cnt), "Broadcast expected");
     cnt = cnt->in(1);
-    if (bt == T_INT) {
-      shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(31)));
-      shiftLCnt = phase->transform(new SubINode(phase->intcon(32), shiftRCnt));
-      shiftLOpc = Op_LShiftI;
-      shiftROpc = Op_URShiftI;
-    } else {
+    if (bt == T_LONG) {
+      // Shift count vector for Rotate vector has long elements too.
       assert(cnt->Opcode() == Op_ConvI2L, "ConvI2L expected");
       cnt = cnt->in(1);
-      shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(63)));
-      shiftLCnt = phase->transform(new SubINode(phase->intcon(64), shiftRCnt));
-      shiftLOpc = Op_LShiftL;
-      shiftROpc = Op_URShiftL;
     }
+    shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(shift_mask)));
+    shiftLCnt = phase->transform(new SubINode(phase->intcon(shift_mask + 1), shiftRCnt));
   }
 
   // Swap the computed left and right shift counts.
@@ -908,86 +895,3 @@
   return NULL;
 }
 
-Node* OrVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
-  int lopcode = in(1)->Opcode();
-  int ropcode = in(2)->Opcode();
-  const TypeVect* vt = bottom_type()->is_vect();
-  int vec_len = vt->length();
-  BasicType bt = vt->element_basic_type();
-
-  // Vector Rotate operations inferencing, this will be useful when vector
-  // operations are created via non-SLP route i.e. (VectorAPI).
-  if (Matcher::match_rule_supported_vector(Op_RotateLeftV, vec_len, bt) &&
-      ((ropcode == Op_LShiftVI && lopcode == Op_URShiftVI) ||
-       (ropcode == Op_LShiftVL && lopcode == Op_URShiftVL)) &&
-      in(1)->in(1) == in(2)->in(1)) {
-    assert(Op_RShiftCntV == in(1)->in(2)->Opcode(), "LShiftCntV operand expected");
-    assert(Op_LShiftCntV == in(2)->in(2)->Opcode(), "RShiftCntV operand expected");
-    Node* lshift = in(1)->in(2)->in(1);
-    Node* rshift = in(2)->in(2)->in(1);
-    int mod_val = bt == T_LONG ? 64 : 32;
-    int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
-    // val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val ,
-    // norm_con_shift
-    if (lshift->is_Con() && rshift->is_Con() &&
-        ((lshift->get_int() & shift_mask) ==
-         (mod_val - (rshift->get_int() & shift_mask)))) {
-      return new RotateRightVNode(
-          in(1)->in(1), phase->intcon(lshift->get_int() & shift_mask), vt);
-    }
-    if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
-        lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
-        lshift->in(2)->get_int() == (mod_val - 1) &&
-        rshift->in(2)->get_int() == (mod_val - 1)) {
-      lshift = lshift->in(1);
-      rshift = rshift->in(1);
-      // val << var_shift | val >> (0/32 - var_shift) => rotate_left val ,
-      // var_shift
-      if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
-          lshift->in(1)->is_Con() &&
-          (lshift->in(1)->get_int() == 0 ||
-           lshift->in(1)->get_int() == mod_val)) {
-        Node* rotate_cnt = phase->transform(new ReplicateINode(rshift, vt));
-        return new RotateLeftVNode(in(1)->in(1), rotate_cnt, vt);
-      }
-    }
-  }
-
-  if (Matcher::match_rule_supported_vector(Op_RotateRightV, vec_len, bt) &&
-      ((ropcode == Op_URShiftVI && lopcode == Op_LShiftVI) ||
-       (ropcode == Op_URShiftVL && lopcode == Op_LShiftVL)) &&
-      in(1)->in(1) == in(2)->in(1)) {
-    assert(Op_LShiftCntV == in(1)->in(2)->Opcode(), "RShiftCntV operand expected");
-    assert(Op_RShiftCntV == in(2)->in(2)->Opcode(), "LShiftCntV operand expected");
-    Node* rshift = in(1)->in(2)->in(1);
-    Node* lshift = in(2)->in(2)->in(1);
-    int mod_val = bt == T_LONG ? 64 : 32;
-    int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
-    // val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val
-    // , norm_con_shift
-    if (rshift->is_Con() && lshift->is_Con() &&
-        ((rshift->get_int() & shift_mask) ==
-         (mod_val - (lshift->get_int() & shift_mask)))) {
-      return new RotateLeftVNode(
-          in(1)->in(1), phase->intcon(rshift->get_int() & shift_mask), vt);
-    }
-    if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
-        lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
-        rshift->in(2)->get_int() == (mod_val - 1) &&
-        lshift->in(2)->get_int() == (mod_val - 1)) {
-      rshift = rshift->in(1);
-      lshift = lshift->in(1);
-      // val >> var_shift | val << (0/32 - var_shift) => rotate_right val ,
-      // var_shift
-      if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
-          rshift->in(1)->is_Con() &&
-          (rshift->in(1)->get_int() == 0 ||
-           rshift->in(1)->get_int() == mod_val)) {
-        Node* rotate_cnt = phase->transform(new ReplicateINode(lshift, vt));
-        return new RotateRightVNode(in(1)->in(1), rotate_cnt, vt);
-      }
-    }
-  }
-  return NULL;
-}
-
diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp
index 570f064..719070f 100644
--- a/src/hotspot/share/opto/vectornode.hpp
+++ b/src/hotspot/share/opto/vectornode.hpp
@@ -624,7 +624,6 @@
  public:
   OrVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {}
   virtual int Opcode() const;
-  Node* Ideal(PhaseGVN* phase, bool can_reshape);
 };
 
 //------------------------------XorVNode---------------------------------------
diff --git a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java
index 1c71293..2ba6a29 100644
--- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java
+++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. 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
@@ -42,8 +42,6 @@
   private static final int BIT_MASK = 0xEC80F731;
   private static final int VALUE = 15;
   private static final int SHIFT = 32;
-  private static final int SHIFT_LT_IMM8 = -128;
-  private static final int SHIFT_GT_IMM8 = 128;
 
   public static void main(String args[]) {
     System.out.println("Testing Integer vectors");
@@ -151,13 +149,6 @@
       test_srac_and(a0, a1);
       test_srav_and(a0, a1, BIT_MASK);
 
-      test1_ror(a0, a1);
-      test1_rol(a0, a1);
-      test2_ror(a0, a1);
-      test2_rol(a0, a1);
-      test3_ror(a0, a1, SHIFT);
-      test3_rol(a0, a1, SHIFT);
-
       test_pack2(p2, a1);
       test_unpack2(a0, p2);
       test_pack2_swap(p2, a1);
@@ -385,30 +376,6 @@
       for (int i=0; i<ARRLEN; i++) {
         errn += verify("test_srav_o: ", i, a0[i], (int)((int)(ADD_INIT+i)>>SHIFT));
       }
-      test1_ror(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test1_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
-      }
-      test1_rol(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test1_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
-      }
-      test2_ror(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test2_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
-      }
-      test2_rol(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test2_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
-      }
-      test3_rol(a0, a1, SHIFT);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test3_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT) | (int)(ADD_INIT+i)>>>-SHIFT));
-      }
-      test3_ror(a0, a1, SHIFT);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test3_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT) | (int)(ADD_INIT+i)<<-SHIFT));
-      }
 
       test_sllc_on(a0, a1);
       for (int i=0; i<ARRLEN; i++) {
@@ -939,48 +906,6 @@
 
     start = System.currentTimeMillis();
     for (int i=0; i<ITERS; i++) {
-      test1_rol(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test1_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test1_ror(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test1_ror: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test2_rol(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test2_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test2_ror(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test2_ror: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test3_rol(a0, a1, SHIFT);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test3_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test3_ror(a0, a1, SHIFT);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test3_ror: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
       test_srlv_and(a0, a1, BIT_MASK);
     }
     end = System.currentTimeMillis();
@@ -999,7 +924,6 @@
     end = System.currentTimeMillis();
     System.out.println("test_srav_and: " + (end - start));
 
-
     start = System.currentTimeMillis();
     for (int i=0; i<ITERS; i++) {
       test_pack2(p2, a1);
@@ -1175,36 +1099,7 @@
       a0[i] = (int)(~a1[i]);
     }
   }
-  static void test1_rol(int[] a0, int[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_GT_IMM8));
-    }
-  }
-  static void test1_ror(int[] a0, int[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_GT_IMM8));
-    }
-  }
-  static void test2_rol(int[] a0, int[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_LT_IMM8));
-    }
-  }
-  static void test2_ror(int[] a0, int[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_LT_IMM8));
-    }
-  }
-  static void test3_rol(int[] a0, int[] a1, int shift) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateLeft(a1[i], shift));
-    }
-  }
-  static void test3_ror(int[] a0, int[] a1, int shift) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (int)(Integer.rotateRight(a1[i], shift));
-    }
-  }
+
   static void test_sllc(int[] a0, int[] a1) {
     for (int i = 0; i < a0.length; i+=1) {
       a0[i] = (int)(a1[i]<<VALUE);
diff --git a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java
new file mode 100644
index 0000000..cc03d0b
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVectRotate.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8248830
+ * @summary Implement Rotate vectorization optimizations in hotspot-server
+ *
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m compiler.c2.cr6340864.TestIntVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=8 compiler.c2.cr6340864.TestIntVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=16 compiler.c2.cr6340864.TestIntVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=32 compiler.c2.cr6340864.TestIntVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=3 compiler.c2.cr6340864.TestIntVectRotate
+ */
+
+package compiler.c2.cr6340864;
+
+public class TestIntVectRotate {
+  private static final int ARRLEN = 997;
+  private static final int ITERS  = 11000;
+  private static final int ADD_INIT = Integer.MAX_VALUE-500;
+  private static final int VALUE = 15;
+  private static final int SHIFT = 32;
+  private static final int SHIFT_LT_IMM8 = -128;
+  private static final int SHIFT_GT_IMM8 = 128;
+
+  public static void main(String args[]) {
+    System.out.println("Testing Integer Rotate vectors");
+    test();
+    int errn = verify();
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    times();
+    System.out.println("PASSED");
+  }
+
+  static int[] a0 = new int[ARRLEN];
+  static int[] a1 = new int[ARRLEN];
+
+  static void test() {
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      int val = (int)(ADD_INIT+i);
+      a1[i] = val;
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test1_ror(a0, a1);
+      test1_rol(a0, a1);
+      test2_ror(a0, a1);
+      test2_rol(a0, a1);
+      test3_ror(a0, a1, SHIFT);
+      test3_rol(a0, a1, SHIFT);
+
+      test_rolc(a0, a1);
+      test_rolv(a0, a1, VALUE);
+      test_rorc(a0, a1);
+      test_rorv(a0, a1, VALUE);
+
+      test_rolc_n(a0, a1);
+      test_rolv(a0, a1, -VALUE);
+      test_rorc_n(a0, a1);
+      test_rorv(a0, a1, -VALUE);
+
+      test_rolc_o(a0, a1);
+      test_rolv(a0, a1, SHIFT);
+      test_rorc_o(a0, a1);
+      test_rorv(a0, a1, SHIFT);
+
+      test_rolc_on(a0, a1);
+      test_rolv(a0, a1, -SHIFT);
+      test_rorc_on(a0, a1);
+      test_rorv(a0, a1, -SHIFT);
+    }
+  }
+
+  // Test and verify results
+  static int verify() {
+    System.out.println("Verification");
+    int errn = 0;
+
+    test1_ror(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test1_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
+    }
+    test1_rol(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test1_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
+    }
+    test2_ror(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test2_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (int)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
+    }
+    test2_rol(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test2_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (int)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
+    }
+    test3_rol(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test3_rol: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT) | (int)(ADD_INIT+i)>>>-SHIFT));
+    }
+    test3_ror(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test3_ror: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT) | (int)(ADD_INIT+i)<<-SHIFT));
+    }
+
+    test_rolc(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<VALUE) | (int)(ADD_INIT+i)>>>(-VALUE)));
+    }
+    test_rolv(a0, a1, VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<VALUE) | (int)(ADD_INIT+i)>>>(-VALUE)));
+    }
+
+    test_rorc(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>VALUE) | (int)(ADD_INIT+i)<<(-VALUE)));
+    }
+    test_rorv(a0, a1, VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>VALUE) | (int)(ADD_INIT+i)<<(-VALUE)));
+    }
+
+    test_rolc_n(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_n: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<(-VALUE)) | (int)(ADD_INIT+i)>>>VALUE));
+    }
+    test_rolv(a0, a1, -VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_n: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<(-VALUE)) | (int)(ADD_INIT+i)>>>VALUE));
+    }
+
+    test_rorc_n(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_n: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>(-VALUE)) | (int)(ADD_INIT+i)<<VALUE));
+    }
+    test_rorv(a0, a1, -VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv_n: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>(-VALUE)) | (int)(ADD_INIT+i)<<VALUE));
+    }
+
+    test_rolc_o(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_o: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT) | (int)(ADD_INIT+i)>>>(-SHIFT)));
+    }
+    test_rolv(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_o: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<SHIFT) | (int)(ADD_INIT+i)>>>(-SHIFT)));
+    }
+
+    test_rorc_o(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_o: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT) | (int)(ADD_INIT+i)<<(-SHIFT)));
+    }
+    test_rorv(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv_o: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>SHIFT) | (int)(ADD_INIT+i)<<(-SHIFT)));
+    }
+
+    test_rolc_on(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_on: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<(-SHIFT)) | (int)(ADD_INIT+i)>>>SHIFT));
+    }
+    test_rolv(a0, a1, -SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_on: ", i, a0[i], (int)(((int)(ADD_INIT+i)<<(-SHIFT)) | (int)(ADD_INIT+i)>>>SHIFT));
+    }
+
+    test_rorc_on(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_on: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>(-SHIFT)) | (int)(ADD_INIT+i)<<SHIFT));
+    }
+    test_rorv(a0, a1, -SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_on: ", i, a0[i], (int)(((int)(ADD_INIT+i)>>>(-SHIFT)) | (int)(ADD_INIT+i)<<SHIFT));
+    }
+
+    return errn;
+  }
+
+  static void times() {
+    System.out.println("Time");
+    long start, end;
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test1_rol(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test1_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test1_ror(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test1_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test2_rol(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test2_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test2_ror(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test2_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test3_rol(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test3_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test3_ror(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test3_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_n(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, -VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_n(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, -VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_o(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_o(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_on(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, -SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_on(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, -SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_on: " + (end - start));
+  }
+
+  static void test_rolc(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], VALUE));
+    }
+  }
+
+  static void test_rolc_n(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], (-VALUE)));
+    }
+  }
+
+  static void test_rolc_o(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT));
+    }
+  }
+
+  static void test_rolc_on(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], (-SHIFT)));
+    }
+  }
+
+  static void test_rolv(int[] a0, int[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], shift));
+    }
+  }
+
+  static void test_rorc(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], VALUE));
+    }
+  }
+
+  static void test_rorc_n(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], (-VALUE)));
+    }
+  }
+
+  static void test_rorc_o(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT));
+    }
+  }
+
+  static void test_rorc_on(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], (-SHIFT)));
+    }
+  }
+
+  static void test_rorv(int[] a0, int[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], shift));
+    }
+  }
+
+  static void test1_rol(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_GT_IMM8));
+    }
+  }
+
+  static void test1_ror(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_GT_IMM8));
+    }
+  }
+
+  static void test2_rol(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], SHIFT_LT_IMM8));
+    }
+  }
+
+  static void test2_ror(int[] a0, int[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], SHIFT_LT_IMM8));
+    }
+  }
+
+  static void test3_rol(int[] a0, int[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateLeft(a1[i], shift));
+    }
+  }
+
+  static void test3_ror(int[] a0, int[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (int)(Integer.rotateRight(a1[i], shift));
+    }
+  }
+
+  static int verify(String text, int i, int elem, int val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+
+}
diff --git a/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVect.java b/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVect.java
index b26e073..bff2436 100644
--- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVect.java
+++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVect.java
@@ -42,8 +42,6 @@
   private static final long BIT_MASK = 0xEC80F731EC80F731L;
   private static final int VALUE = 31;
   private static final int SHIFT = 64;
-  private static final int SHIFT_LT_IMM8 = -128;
-  private static final int SHIFT_GT_IMM8 = 128;
 
   public static void main(String args[]) {
     System.out.println("Testing Long vectors");
@@ -145,13 +143,6 @@
       test_srlv_and(a0, a1, BIT_MASK);
       test_srac_and(a0, a1);
       test_srav_and(a0, a1, BIT_MASK);
-
-      test1_ror(a0, a1);
-      test1_rol(a0, a1);
-      test2_ror(a0, a1);
-      test2_rol(a0, a1);
-      test3_ror(a0, a1, SHIFT);
-      test3_rol(a0, a1, SHIFT);
     }
     // Test and verify results
     System.out.println("Verification");
@@ -442,30 +433,6 @@
         errn += verify("test_srav_and: ", i, a0[i], (long)(((long)(ADD_INIT+i) & BIT_MASK)>>VALUE));
       }
 
-      test1_ror(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test1_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
-      }
-      test1_rol(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test1_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
-      }
-      test2_ror(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test2_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
-      }
-      test2_rol(a0, a1);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test2_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
-      }
-      test3_rol(a0, a1, SHIFT);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test3_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT) | (long)(ADD_INIT+i)>>>-SHIFT));
-      }
-      test3_ror(a0, a1, SHIFT);
-      for (int i=0; i<ARRLEN; i++) {
-        errn += verify("test3_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT) | (long)(ADD_INIT+i)<<-SHIFT));
-      }
     }
 
     if (errn > 0)
@@ -886,48 +853,6 @@
     end = System.currentTimeMillis();
     System.out.println("test_srav_and: " + (end - start));
 
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test1_rol(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test1_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test1_ror(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test1_ror: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test2_rol(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test2_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test2_ror(a0, a1);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test2_ror: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test3_rol(a0, a1, SHIFT);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test3_rol: " + (end - start));
-
-    start = System.currentTimeMillis();
-    for (int i=0; i<ITERS; i++) {
-      test3_ror(a0, a1, SHIFT);
-    }
-    end = System.currentTimeMillis();
-    System.out.println("test3_ror: " + (end - start));
-
     return errn;
   }
 
@@ -1198,36 +1123,6 @@
       a0[i] = (long)((a1[i] & b)>>VALUE);
     }
   }
-  static void test1_rol(long[] a0, long[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_GT_IMM8));
-    }
-  }
-  static void test1_ror(long[] a0, long[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_GT_IMM8));
-    }
-  }
-  static void test2_rol(long[] a0, long[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_LT_IMM8));
-    }
-  }
-  static void test2_ror(long[] a0, long[] a1) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_LT_IMM8));
-    }
-  }
-  static void test3_rol(long[] a0, long[] a1, int shift) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateLeft(a1[i], shift));
-    }
-  }
-  static void test3_ror(long[] a0, long[] a1, int shift) {
-    for (int i = 0; i < a0.length; i+=1) {
-      a0[i] = (long)(Long.rotateRight(a1[i], shift));
-    }
-  }
 
   static int verify(String text, int i, long elem, long val) {
     if (elem != val) {
diff --git a/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVectRotate.java b/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVectRotate.java
new file mode 100644
index 0000000..d926df1
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestLongVectRotate.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8248830
+ * @summary Implement Rotate vectorization optimizations in hotspot-server
+ *
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m compiler.c2.cr6340864.TestLongVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=8 compiler.c2.cr6340864.TestLongVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=16 compiler.c2.cr6340864.TestLongVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=32 compiler.c2.cr6340864.TestLongVectRotate
+ * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:+IgnoreUnrecognizedVMOptions -XX:UseAVX=3 compiler.c2.cr6340864.TestLongVectRotate
+ */
+
+package compiler.c2.cr6340864;
+
+public class TestLongVectRotate {
+  private static final int ARRLEN = 997;
+  private static final int ITERS  = 11000;
+  private static final long ADD_INIT = Long.MAX_VALUE-500;
+  private static final int VALUE = 31;
+  private static final int SHIFT = 64;
+  private static final int SHIFT_LT_IMM8 = -128;
+  private static final int SHIFT_GT_IMM8 = 128;
+
+  public static void main(String args[]) {
+    System.out.println("Testing Long Rotate vectors");
+    test();
+    int errn = verify();
+    if (errn > 0) {
+      System.err.println("FAILED: " + errn + " errors");
+      System.exit(97);
+    }
+    times();
+    System.out.println("PASSED");
+  }
+
+  static long[] a0 = new long[ARRLEN];
+  static long[] a1 = new long[ARRLEN];
+
+  static void test() {
+    // Initialize
+    for (int i=0; i<ARRLEN; i++) {
+      long val = (long)(ADD_INIT+i);
+      a1[i] = val;
+    }
+    System.out.println("Warmup");
+    for (int i=0; i<ITERS; i++) {
+      test1_ror(a0, a1);
+      test1_rol(a0, a1);
+      test2_ror(a0, a1);
+      test2_rol(a0, a1);
+      test3_ror(a0, a1, SHIFT);
+      test3_rol(a0, a1, SHIFT);
+
+      test_rolc(a0, a1);
+      test_rolv(a0, a1, VALUE);
+      test_rorc(a0, a1);
+      test_rorv(a0, a1, VALUE);
+
+      test_rolc_n(a0, a1);
+      test_rolv(a0, a1, -VALUE);
+      test_rorc_n(a0, a1);
+      test_rorv(a0, a1, -VALUE);
+
+      test_rolc_o(a0, a1);
+      test_rolv(a0, a1, SHIFT);
+      test_rorc_o(a0, a1);
+      test_rorv(a0, a1, SHIFT);
+
+      test_rolc_on(a0, a1);
+      test_rolv(a0, a1, -SHIFT);
+      test_rorc_on(a0, a1);
+      test_rorv(a0, a1, -SHIFT);
+    }
+  }
+
+  // Test and verify results
+  static int verify() {
+    System.out.println("Verification");
+    int errn = 0;
+
+    test1_ror(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test1_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_GT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_GT_IMM8));
+    }
+    test1_rol(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test1_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_GT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_GT_IMM8));
+    }
+    test2_ror(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test2_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT_LT_IMM8) | (long)(ADD_INIT+i)<<-SHIFT_LT_IMM8));
+    }
+    test2_rol(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test2_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT_LT_IMM8) | (long)(ADD_INIT+i)>>>-SHIFT_LT_IMM8));
+    }
+    test3_rol(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test3_rol: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT) | (long)(ADD_INIT+i)>>>-SHIFT));
+    }
+    test3_ror(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test3_ror: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT) | (long)(ADD_INIT+i)<<-SHIFT));
+    }
+
+    test_rolc(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<VALUE) | (long)(ADD_INIT+i)>>>(-VALUE)));
+    }
+    test_rolv(a0, a1, VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<VALUE) | (long)(ADD_INIT+i)>>>(-VALUE)));
+    }
+
+    test_rorc(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>VALUE) | (long)(ADD_INIT+i)<<(-VALUE)));
+    }
+    test_rorv(a0, a1, VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>VALUE) | (long)(ADD_INIT+i)<<(-VALUE)));
+    }
+
+    test_rolc_n(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_n: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<(-VALUE)) | (long)(ADD_INIT+i)>>>VALUE));
+    }
+    test_rolv(a0, a1, -VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_n: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<(-VALUE)) | (long)(ADD_INIT+i)>>>VALUE));
+    }
+
+    test_rorc_n(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_n: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>(-VALUE)) | (long)(ADD_INIT+i)<<VALUE));
+    }
+    test_rorv(a0, a1, -VALUE);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv_n: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>(-VALUE)) | (long)(ADD_INIT+i)<<VALUE));
+    }
+
+    test_rolc_o(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_o: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT) | (long)(ADD_INIT+i)>>>(-SHIFT)));
+    }
+    test_rolv(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_o: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<SHIFT) | (long)(ADD_INIT+i)>>>(-SHIFT)));
+    }
+
+    test_rorc_o(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_o: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT) | (long)(ADD_INIT+i)<<(-SHIFT)));
+    }
+    test_rorv(a0, a1, SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorv_o: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>SHIFT) | (long)(ADD_INIT+i)<<(-SHIFT)));
+    }
+
+    test_rolc_on(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolc_on: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<(-SHIFT)) | (long)(ADD_INIT+i)>>>SHIFT));
+    }
+    test_rolv(a0, a1, -SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rolv_on: ", i, a0[i], (long)(((long)(ADD_INIT+i)<<(-SHIFT)) | (long)(ADD_INIT+i)>>>SHIFT));
+    }
+
+    test_rorc_on(a0, a1);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_on: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>(-SHIFT)) | (long)(ADD_INIT+i)<<SHIFT));
+    }
+    test_rorv(a0, a1, -SHIFT);
+    for (int i=0; i<ARRLEN; i++) {
+      errn += verify("test_rorc_on: ", i, a0[i], (long)(((long)(ADD_INIT+i)>>>(-SHIFT)) | (long)(ADD_INIT+i)<<SHIFT));
+    }
+
+    return errn;
+  }
+
+  static void times() {
+    System.out.println("Time");
+    long start, end;
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test1_rol(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test1_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test1_ror(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test1_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test2_rol(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test2_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test2_ror(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test2_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test3_rol(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test3_rol: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test3_ror(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test3_ror: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_n(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, -VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_n(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, -VALUE);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_n: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_o(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_o(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_o: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolc_on(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolc_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rolv(a0, a1, -SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rolv_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorc_on(a0, a1);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorc_on: " + (end - start));
+
+    start = System.currentTimeMillis();
+    for (int i=0; i<ITERS; i++) {
+      test_rorv(a0, a1, -SHIFT);
+    }
+    end = System.currentTimeMillis();
+    System.out.println("test_rorv_on: " + (end - start));
+  }
+
+  static void test_rolc(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], VALUE));
+    }
+  }
+
+  static void test_rolc_n(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], (-VALUE)));
+    }
+  }
+
+  static void test_rolc_o(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT));
+    }
+  }
+
+  static void test_rolc_on(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], (-SHIFT)));
+    }
+  }
+
+  static void test_rolv(long[] a0, long[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], shift));
+    }
+  }
+
+  static void test_rorc(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], VALUE));
+    }
+  }
+
+  static void test_rorc_n(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], (-VALUE)));
+    }
+  }
+
+  static void test_rorc_o(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], SHIFT));
+    }
+  }
+
+  static void test_rorc_on(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], (-SHIFT)));
+    }
+  }
+
+  static void test_rorv(long[] a0, long[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], shift));
+    }
+  }
+
+  static void test1_rol(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_GT_IMM8));
+    }
+  }
+
+  static void test1_ror(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_GT_IMM8));
+    }
+  }
+
+  static void test2_rol(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], SHIFT_LT_IMM8));
+    }
+  }
+
+  static void test2_ror(long[] a0, long[] a1) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], SHIFT_LT_IMM8));
+    }
+  }
+
+  static void test3_rol(long[] a0, long[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateLeft(a1[i], shift));
+    }
+  }
+
+  static void test3_ror(long[] a0, long[] a1, int shift) {
+    for (int i = 0; i < a0.length; i+=1) {
+      a0[i] = (long)(Long.rotateRight(a1[i], shift));
+    }
+  }
+
+  static int verify(String text, int i, long elem, long val) {
+    if (elem != val) {
+      System.err.println(text + "[" + i + "] = " + elem + " != " + val);
+      return 1;
+    }
+    return 0;
+  }
+
+}