OSDN Git Service

Ensure art::HRor support boolean, byte, short and char inputs.
authorRoland Levillain <rpl@google.com>
Fri, 18 Mar 2016 14:04:28 +0000 (14:04 +0000)
committerRoland Levillain <rpl@google.com>
Fri, 18 Mar 2016 14:04:28 +0000 (14:04 +0000)
Also extend tests covering the IntegerRotateLeft,
LongRotateLeft, IntegerRotateRight and LongRotateRight
intrinsics and their translation into an art::HRor
instruction.

Bug: 27682579
Change-Id: I89f6ea6a7315659a172482bf09875cfb7e7422a1

compiler/optimizing/code_generator_arm.cc
compiler/optimizing/code_generator_arm.h
compiler/optimizing/code_generator_x86.cc
compiler/optimizing/common_arm64.h
compiler/optimizing/graph_checker.cc
compiler/optimizing/instruction_simplifier.cc
compiler/optimizing/nodes.h
test/565-checker-rotate/src/Main.java

index 34fd9ff..c164f2b 100644 (file)
@@ -3273,7 +3273,8 @@ void InstructionCodeGeneratorARM::HandleLongRotate(LocationSummary* locations) {
     __ Bind(&end);
   }
 }
-void LocationsBuilderARM::HandleRotate(HRor* ror) {
+
+void LocationsBuilderARM::VisitRor(HRor* ror) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(ror, LocationSummary::kNoCall);
   switch (ror->GetResultType()) {
@@ -3300,7 +3301,7 @@ void LocationsBuilderARM::HandleRotate(HRor* ror) {
   }
 }
 
-void InstructionCodeGeneratorARM::HandleRotate(HRor* ror) {
+void InstructionCodeGeneratorARM::VisitRor(HRor* ror) {
   LocationSummary* locations = ror->GetLocations();
   Primitive::Type type = ror->GetResultType();
   switch (type) {
@@ -3318,14 +3319,6 @@ void InstructionCodeGeneratorARM::HandleRotate(HRor* ror) {
   }
 }
 
-void LocationsBuilderARM::VisitRor(HRor* op) {
-  HandleRotate(op);
-}
-
-void InstructionCodeGeneratorARM::VisitRor(HRor* op) {
-  HandleRotate(op);
-}
-
 void LocationsBuilderARM::HandleShift(HBinaryOperation* op) {
   DCHECK(op->IsShl() || op->IsShr() || op->IsUShr());
 
index 5c0f31c..cc4aa14 100644 (file)
@@ -174,7 +174,6 @@ class LocationsBuilderARM : public HGraphVisitor {
   void HandleCondition(HCondition* condition);
   void HandleIntegerRotate(LocationSummary* locations);
   void HandleLongRotate(LocationSummary* locations);
-  void HandleRotate(HRor* ror);
   void HandleShift(HBinaryOperation* operation);
   void HandleFieldSet(HInstruction* instruction, const FieldInfo& field_info);
   void HandleFieldGet(HInstruction* instruction, const FieldInfo& field_info);
@@ -222,7 +221,6 @@ class InstructionCodeGeneratorARM : public InstructionCodeGenerator {
   void HandleCondition(HCondition* condition);
   void HandleIntegerRotate(LocationSummary* locations);
   void HandleLongRotate(LocationSummary* locations);
-  void HandleRotate(HRor* ror);
   void HandleShift(HBinaryOperation* operation);
 
   void GenerateWideAtomicStore(Register addr, uint32_t offset,
index 9acaa1d..68c10d4 100644 (file)
@@ -3981,8 +3981,7 @@ void InstructionCodeGeneratorX86::VisitRor(HRor* ror) {
     __ cmovl(kNotEqual, first_reg_hi, first_reg_lo);
     __ cmovl(kNotEqual, first_reg_lo, temp_reg);
   } else {
-    int32_t shift_amt =
-      CodeGenerator::GetInt64ValueOf(second.GetConstant()) & kMaxLongShiftValue;
+    int32_t shift_amt = CodeGenerator::GetInt64ValueOf(second.GetConstant()) & kMaxLongShiftValue;
     if (shift_amt == 0) {
       // Already fine.
       return;
index 10d8343..6c55194 100644 (file)
@@ -194,7 +194,8 @@ static inline vixl::Operand OperandFromMemOperand(const vixl::MemOperand& mem_op
 }
 
 static bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* instr) {
-  DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant());
+  DCHECK(constant->IsIntConstant() || constant->IsLongConstant() || constant->IsNullConstant())
+      << constant->DebugName();
 
   // For single uses we let VIXL handle the constant generation since it will
   // use registers that are not managed by the register allocator (wip0, wip1).
@@ -221,7 +222,8 @@ static bool CanEncodeConstantAsImmediate(HConstant* constant, HInstruction* inst
            instr->IsBoundsCheck() ||
            instr->IsCompare() ||
            instr->IsCondition() ||
-           instr->IsSub());
+           instr->IsSub())
+        << instr->DebugName();
     // Uses aliases of ADD/SUB instructions.
     // If `value` does not fit but `-value` does, VIXL will automatically use
     // the 'opposite' instruction.
index 1fbb2d5..11e3689 100644 (file)
@@ -945,7 +945,7 @@ void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) {
                             Primitive::PrettyDescriptor(result_type)));
     }
   } else {
-    // Use the first input, so that we can also make this check for shift operations.
+    // Use the first input, so that we can also make this check for shift and rotate operations.
     if (Primitive::PrimitiveKind(result_type) != Primitive::PrimitiveKind(lhs_type)) {
       AddError(StringPrintf("Binary operation %s %d has a result kind different "
                             "from its input kind: %s vs %s.",
index dd2977f..4a8186a 100644 (file)
@@ -96,7 +96,7 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor {
 
   bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const;
 
-  void SimplifyRotate(HInvoke* invoke, bool is_left);
+  void SimplifyRotate(HInvoke* invoke, bool is_left, Primitive::Type type);
   void SimplifySystemArrayCopy(HInvoke* invoke);
   void SimplifyStringEquals(HInvoke* invoke);
   void SimplifyCompare(HInvoke* invoke, bool is_signum, Primitive::Type type);
@@ -262,10 +262,8 @@ static bool IsSubRegBitsMinusOther(HSub* sub, size_t reg_bits, HInstruction* oth
 bool InstructionSimplifierVisitor::ReplaceRotateWithRor(HBinaryOperation* op,
                                                         HUShr* ushr,
                                                         HShl* shl) {
-  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr());
-  HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(),
-                                                ushr->GetLeft(),
-                                                ushr->GetRight());
+  DCHECK(op->IsAdd() || op->IsXor() || op->IsOr()) << op->DebugName();
+  HRor* ror = new (GetGraph()->GetArena()) HRor(ushr->GetType(), ushr->GetLeft(), ushr->GetRight());
   op->GetBlock()->ReplaceAndRemoveInstructionWith(op, ror);
   if (!ushr->HasUses()) {
     ushr->GetBlock()->RemoveInstruction(ushr);
@@ -1232,7 +1230,7 @@ void InstructionSimplifierVisitor::VisitMul(HMul* instruction) {
       // with
       //    SHL dst, src, log2(pow_of_2)
       HIntConstant* shift = GetGraph()->GetIntConstant(WhichPowerOf2(factor));
-      HShl* shl = new(allocator) HShl(type, input_other, shift);
+      HShl* shl = new (allocator) HShl(type, input_other, shift);
       block->ReplaceAndRemoveInstructionWith(instruction, shl);
       RecordSimplification();
     } else if (IsPowerOfTwo(factor - 1)) {
@@ -1531,7 +1529,9 @@ void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
   }
 }
 
-void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, bool is_left) {
+void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke,
+                                                  bool is_left,
+                                                  Primitive::Type type) {
   DCHECK(invoke->IsInvokeStaticOrDirect());
   DCHECK_EQ(invoke->GetOriginalInvokeType(), InvokeType::kStatic);
   HInstruction* value = invoke->InputAt(0);
@@ -1541,7 +1541,7 @@ void InstructionSimplifierVisitor::SimplifyRotate(HInvoke* invoke, bool is_left)
     distance = new (GetGraph()->GetArena()) HNeg(distance->GetType(), distance);
     invoke->GetBlock()->InsertInstructionBefore(distance, invoke);
   }
-  HRor* ror = new (GetGraph()->GetArena()) HRor(value->GetType(), value, distance);
+  HRor* ror = new (GetGraph()->GetArena()) HRor(type, value, distance);
   invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, ror);
   // Remove ClinitCheck and LoadClass, if possible.
   HInstruction* clinit = invoke->InputAt(invoke->InputCount() - 1);
@@ -1694,12 +1694,16 @@ void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
       SimplifySystemArrayCopy(instruction);
       break;
     case Intrinsics::kIntegerRotateRight:
+      SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimInt);
+      break;
     case Intrinsics::kLongRotateRight:
-      SimplifyRotate(instruction, false);
+      SimplifyRotate(instruction, /* is_left */ false, Primitive::kPrimLong);
       break;
     case Intrinsics::kIntegerRotateLeft:
+      SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimInt);
+      break;
     case Intrinsics::kLongRotateLeft:
-      SimplifyRotate(instruction, true);
+      SimplifyRotate(instruction, /* is_left */ true, Primitive::kPrimLong);
       break;
     case Intrinsics::kIntegerCompare:
       SimplifyCompare(instruction, /* is_signum */ false, Primitive::kPrimInt);
index e2a54f4..46377ee 100644 (file)
@@ -4689,7 +4689,12 @@ class HXor : public HBinaryOperation {
 class HRor : public HBinaryOperation {
  public:
   HRor(Primitive::Type result_type, HInstruction* value, HInstruction* distance)
-    : HBinaryOperation(result_type, value, distance) {}
+    : HBinaryOperation(result_type, value, distance) {
+    if (kIsDebugBuild) {
+      DCHECK_EQ(result_type, Primitive::PrimitiveKind(value->GetType()));
+      DCHECK_EQ(Primitive::kPrimInt, Primitive::PrimitiveKind(distance->GetType()));
+    }
+  }
 
   template <typename T, typename U, typename V>
   T Compute(T x, U y, V max_shift_value) const {
index 33bbe02..d7f57d8 100644 (file)
 
 public class Main {
 
-  /// CHECK-START: int Main.rotateLeft32(int, int) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerRotateLeft
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static int rotateLeft32(int x, int y) {
-    return Integer.rotateLeft(x, y);
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) select_generator (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) select_generator (after)
+  /// CHECK-NOT:                      Phi
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier_after_bce (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftBoolean(boolean, int) instruction_simplifier_after_bce (after)
+  /// CHECK-NOT:                      Select
+
+  private static int rotateLeftBoolean(boolean value, int distance) {
+    return Integer.rotateLeft(value ? 1 : 0, distance);
   }
 
-  /// CHECK-START: long Main.rotateLeft64(long, int) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongRotateLeft
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static long rotateLeft64(long x, int y) {
-    return Long.rotateLeft(x, y);
+  /// CHECK-START: int Main.rotateLeftByte(byte, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftByte(byte, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftByte(byte value, int distance) {
+    return Integer.rotateLeft(value, distance);
   }
 
-  /// CHECK-START: int Main.rotateRight32(int, int) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerRotateRight
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static int rotateRight32(int x, int y) {
-    return Integer.rotateRight(x, y);
+  /// CHECK-START: int Main.rotateLeftShort(short, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftShort(short, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftShort(short value, int distance) {
+    return Integer.rotateLeft(value, distance);
   }
 
-  /// CHECK-START: long Main.rotateRight64(long, int) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect intrinsic:LongRotateRight
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static long rotateRight64(long x, int y) {
-    return Long.rotateRight(x, y);
+  /// CHECK-START: int Main.rotateLeftChar(char, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftChar(char, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftChar(char value, int distance) {
+    return Integer.rotateLeft(value, distance);
   }
 
-  public static void main(String args[]) {
-    expectEquals32(0x00000001, rotateLeft32(0x00000001, 0));
-    expectEquals32(0x00000002, rotateLeft32(0x00000001, 1));
-    expectEquals32(0x80000000, rotateLeft32(0x00000001, 31));
-    expectEquals32(0x00000001, rotateLeft32(0x00000001, 32));  // overshoot
-    expectEquals32(0x00000003, rotateLeft32(0x80000001, 1));
-    expectEquals32(0x00000006, rotateLeft32(0x80000001, 2));
-    expectEquals32(0x23456781, rotateLeft32(0x12345678, 4));
-    expectEquals32(0xBCDEF09A, rotateLeft32(0x9ABCDEF0, 8));
+  /// CHECK-START: int Main.rotateLeftInt(int, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateLeftInt(int, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateLeftInt(int value, int distance) {
+    return Integer.rotateLeft(value, distance);
+  }
+
+  /// CHECK-START: long Main.rotateLeftLong(long, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:j\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateLeft
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<NegDist:i\d+>> Neg [<<ArgDist>>]
+  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<NegDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long Main.rotateLeftLong(long, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static long rotateLeftLong(long value, int distance) {
+    return Long.rotateLeft(value, distance);
+  }
+
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<Val>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+  /// CHECK-DAG:                     Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<Val:i\d+>>     Phi [<<One>>,<<Zero>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<Val>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) select_generator (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Zero:i\d+>>    IntConstant 0
+  /// CHECK-DAG:     <<One:i\d+>>     IntConstant 1
+  /// CHECK-DAG:     <<SelVal:i\d+>>  Select [<<Zero>>,<<One>>,<<ArgVal>>]
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<SelVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) select_generator (after)
+  /// CHECK-NOT:                     Phi
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier_after_bce (after)
+  /// CHECK:         <<ArgVal:z\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightBoolean(boolean, int) instruction_simplifier_after_bce (after)
+  /// CHECK-NOT:                     Select
+
+  private static int rotateRightBoolean(boolean value, int distance) {
+    return Integer.rotateRight(value ? 1 : 0, distance);
+  }
+
+  /// CHECK-START: int Main.rotateRightByte(byte, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:b\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightByte(byte, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightByte(byte value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int Main.rotateRightShort(short, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:s\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightShort(short, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightShort(short value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int Main.rotateRightChar(char, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:c\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightChar(char, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightChar(char value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: int Main.rotateRightInt(int, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:IntegerRotateRight
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:i\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:i\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: int Main.rotateRightInt(int, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static int rotateRightInt(int value, int distance) {
+    return Integer.rotateRight(value, distance);
+  }
+
+  /// CHECK-START: long Main.rotateRightLong(long, int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Method:[ij]\d+>> CurrentMethod
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:j\d+>>  InvokeStaticOrDirect [<<ArgVal>>,<<ArgDist>>,<<Method>>] intrinsic:LongRotateRight
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
+  /// CHECK:         <<ArgVal:j\d+>>  ParameterValue
+  /// CHECK:         <<ArgDist:i\d+>> ParameterValue
+  /// CHECK-DAG:     <<Result:j\d+>>  Ror [<<ArgVal>>,<<ArgDist>>]
+  /// CHECK-DAG:                      Return [<<Result>>]
+
+  /// CHECK-START: long Main.rotateRightLong(long, int) instruction_simplifier (after)
+  /// CHECK-NOT:                      InvokeStaticOrDirect
+
+  private static long rotateRightLong(long value, int distance) {
+    return Long.rotateRight(value, distance);
+  }
+
+
+  public static void testRotateLeftBoolean() {
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0, rotateLeftBoolean(false, i));
+      expectEqualsInt(1 << i, rotateLeftBoolean(true, i));
+    }
+  }
+
+  public static void testRotateLeftByte() {
+    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 0));
+    expectEqualsInt(0x00000002, rotateLeftByte((byte)0x01, 1));
+    expectEqualsInt(0x80000000, rotateLeftByte((byte)0x01, 31));
+    expectEqualsInt(0x00000001, rotateLeftByte((byte)0x01, 32));  // overshoot
+    expectEqualsInt(0xFFFFFF03, rotateLeftByte((byte)0x81, 1));
+    expectEqualsInt(0xFFFFFE07, rotateLeftByte((byte)0x81, 2));
+    expectEqualsInt(0x00000120, rotateLeftByte((byte)0x12, 4));
+    expectEqualsInt(0xFFFF9AFF, rotateLeftByte((byte)0x9A, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftByte((byte)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftByte((byte)0xFFFF, i));
+      expectEqualsInt((1 << j), rotateLeftByte((byte)0x0001, i));
+      expectEqualsInt((0x12 << j) | (0x12 >>> -j), rotateLeftByte((byte)0x12, i));
+    }
+  }
+
+  public static void testRotateLeftShort() {
+    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 0));
+    expectEqualsInt(0x00000002, rotateLeftShort((short)0x0001, 1));
+    expectEqualsInt(0x80000000, rotateLeftShort((short)0x0001, 31));
+    expectEqualsInt(0x00000001, rotateLeftShort((short)0x0001, 32));  // overshoot
+    expectEqualsInt(0xFFFF0003, rotateLeftShort((short)0x8001, 1));
+    expectEqualsInt(0xFFFE0007, rotateLeftShort((short)0x8001, 2));
+    expectEqualsInt(0x00012340, rotateLeftShort((short)0x1234, 4));
+    expectEqualsInt(0xFF9ABCFF, rotateLeftShort((short)0x9ABC, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftShort((short)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftShort((short)0xFFFF, i));
+      expectEqualsInt((1 << j), rotateLeftShort((short)0x0001, i));
+      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftShort((short)0x1234, i));
+    }
+  }
+
+  public static void testRotateLeftChar() {
+    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 0));
+    expectEqualsInt(0x00000002, rotateLeftChar((char)0x0001, 1));
+    expectEqualsInt(0x80000000, rotateLeftChar((char)0x0001, 31));
+    expectEqualsInt(0x00000001, rotateLeftChar((char)0x0001, 32));  // overshoot
+    expectEqualsInt(0x00010002, rotateLeftChar((char)0x8001, 1));
+    expectEqualsInt(0x00020004, rotateLeftChar((char)0x8001, 2));
+    expectEqualsInt(0x00012340, rotateLeftChar((char)0x1234, 4));
+    expectEqualsInt(0x009ABC00, rotateLeftChar((char)0x9ABC, 8));
+    expectEqualsInt(0x00FF0000, rotateLeftChar((char)0xFF00, 8));
     for (int i = 0; i < 40; i++) {  // overshoot a bit
       int j = i & 31;
-      expectEquals32(0x00000000, rotateLeft32(0x00000000, i));
-      expectEquals32(0xFFFFFFFF, rotateLeft32(0xFFFFFFFF, i));
-      expectEquals32(1 << j, rotateLeft32(0x00000001, i));
-      expectEquals32((0x12345678 << j) | (0x12345678 >>> -j),
-                     rotateLeft32(0x12345678, i));
+      expectEqualsInt(0x00000000, rotateLeftChar((char)0x0000, i));
+      expectEqualsInt((1 << j), rotateLeftChar((char)0x0001, i));
+      expectEqualsInt((0x1234 << j) | (0x1234 >>> -j), rotateLeftChar((char)0x1234, i));
     }
+  }
 
-    expectEquals64(0x0000000000000001L, rotateLeft64(0x0000000000000001L, 0));
-    expectEquals64(0x0000000000000002L, rotateLeft64(0x0000000000000001L, 1));
-    expectEquals64(0x8000000000000000L, rotateLeft64(0x0000000000000001L, 63));
-    expectEquals64(0x0000000000000001L, rotateLeft64(0x0000000000000001L, 64));  // overshoot
-    expectEquals64(0x0000000000000003L, rotateLeft64(0x8000000000000001L, 1));
-    expectEquals64(0x0000000000000006L, rotateLeft64(0x8000000000000001L, 2));
-    expectEquals64(0x23456789ABCDEF01L, rotateLeft64(0x123456789ABCDEF0L, 4));
-    expectEquals64(0x3456789ABCDEF012L, rotateLeft64(0x123456789ABCDEF0L, 8));
+  public static void testRotateLeftInt() {
+    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 0));
+    expectEqualsInt(0x00000002, rotateLeftInt(0x00000001, 1));
+    expectEqualsInt(0x80000000, rotateLeftInt(0x00000001, 31));
+    expectEqualsInt(0x00000001, rotateLeftInt(0x00000001, 32));  // overshoot
+    expectEqualsInt(0x00000003, rotateLeftInt(0x80000001, 1));
+    expectEqualsInt(0x00000006, rotateLeftInt(0x80000001, 2));
+    expectEqualsInt(0x23456781, rotateLeftInt(0x12345678, 4));
+    expectEqualsInt(0xBCDEF09A, rotateLeftInt(0x9ABCDEF0, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateLeftInt(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateLeftInt(0xFFFFFFFF, i));
+      expectEqualsInt(1 << j, rotateLeftInt(0x00000001, i));
+      expectEqualsInt((0x12345678 << j) | (0x12345678 >>> -j), rotateLeftInt(0x12345678, i));
+    }
+  }
+
+  public static void testRotateLeftLong() {
+    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 0));
+    expectEqualsLong(0x0000000000000002L, rotateLeftLong(0x0000000000000001L, 1));
+    expectEqualsLong(0x8000000000000000L, rotateLeftLong(0x0000000000000001L, 63));
+    expectEqualsLong(0x0000000000000001L, rotateLeftLong(0x0000000000000001L, 64));  // overshoot
+    expectEqualsLong(0x0000000000000003L, rotateLeftLong(0x8000000000000001L, 1));
+    expectEqualsLong(0x0000000000000006L, rotateLeftLong(0x8000000000000001L, 2));
+    expectEqualsLong(0x23456789ABCDEF01L, rotateLeftLong(0x123456789ABCDEF0L, 4));
+    expectEqualsLong(0x3456789ABCDEF012L, rotateLeftLong(0x123456789ABCDEF0L, 8));
     for (int i = 0; i < 70; i++) {  // overshoot a bit
       int j = i & 63;
-      expectEquals64(0x0000000000000000L, rotateLeft64(0x0000000000000000L, i));
-      expectEquals64(0xFFFFFFFFFFFFFFFFL, rotateLeft64(0xFFFFFFFFFFFFFFFFL, i));
-      expectEquals64(1L << j, rotateLeft64(0x0000000000000001, i));
-      expectEquals64((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
-                     rotateLeft64(0x123456789ABCDEF0L, i));
+      expectEqualsLong(0x0000000000000000L, rotateLeftLong(0x0000000000000000L, i));
+      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateLeftLong(0xFFFFFFFFFFFFFFFFL, i));
+      expectEqualsLong(1L << j, rotateLeftLong(0x0000000000000001, i));
+      expectEqualsLong((0x123456789ABCDEF0L << j) | (0x123456789ABCDEF0L >>> -j),
+                       rotateLeftLong(0x123456789ABCDEF0L, i));
+    }
+  }
+
+  public static void testRotateRightBoolean() {
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0, rotateRightBoolean(false, i));
+      expectEqualsInt(1 << (32 - i), rotateRightBoolean(true, i));
+    }
+  }
+
+  public static void testRotateRightByte() {
+    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 0));
+    expectEqualsInt(0x7FFFFFC0, rotateRightByte((byte)0x80, 1));
+    expectEqualsInt(0xFFFFFF01, rotateRightByte((byte)0x80, 31));
+    expectEqualsInt(0xFFFFFF80, rotateRightByte((byte)0x80, 32));  // overshoot
+    expectEqualsInt(0xFFFFFFC0, rotateRightByte((byte)0x81, 1));
+    expectEqualsInt(0x7FFFFFE0, rotateRightByte((byte)0x81, 2));
+    expectEqualsInt(0x20000001, rotateRightByte((byte)0x12, 4));
+    expectEqualsInt(0x9AFFFFFF, rotateRightByte((byte)0x9A, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightByte((byte)0x00, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightByte((byte)0xFF, i));
+      expectEqualsInt(1 << (32 - j), rotateRightByte((byte)0x01, i));
+      expectEqualsInt((0x12 >>> j) | (0x12 << -j), rotateRightByte((byte)0x12, i));
+    }
+  }
+
+  public static void testRotateRightShort() {
+    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 0));
+    expectEqualsInt(0x7FFFC000, rotateRightShort((short)0x8000, 1));
+    expectEqualsInt(0xFFFF0001, rotateRightShort((short)0x8000, 31));
+    expectEqualsInt(0xFFFF8000, rotateRightShort((short)0x8000, 32));  // overshoot
+    expectEqualsInt(0xFFFFC000, rotateRightShort((short)0x8001, 1));
+    expectEqualsInt(0x7FFFE000, rotateRightShort((short)0x8001, 2));
+    expectEqualsInt(0x40000123, rotateRightShort((short)0x1234, 4));
+    expectEqualsInt(0xBCFFFF9A, rotateRightShort((short)0x9ABC, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightShort((short)0x0000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightShort((short)0xFFFF, i));
+      expectEqualsInt(1 << (32 - j), rotateRightShort((short)0x0001, i));
+      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightShort((short)0x1234, i));
     }
+  }
 
-    expectEquals32(0x80000000, rotateRight32(0x80000000, 0));
-    expectEquals32(0x40000000, rotateRight32(0x80000000, 1));
-    expectEquals32(0x00000001, rotateRight32(0x80000000, 31));
-    expectEquals32(0x80000000, rotateRight32(0x80000000, 32));  // overshoot
-    expectEquals32(0xC0000000, rotateRight32(0x80000001, 1));
-    expectEquals32(0x60000000, rotateRight32(0x80000001, 2));
-    expectEquals32(0x81234567, rotateRight32(0x12345678, 4));
-    expectEquals32(0xF09ABCDE, rotateRight32(0x9ABCDEF0, 8));
+  public static void testRotateRightChar() {
+    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 0));
+    expectEqualsInt(0x00004000, rotateRightChar((char)0x8000, 1));
+    expectEqualsInt(0x00010000, rotateRightChar((char)0x8000, 31));
+    expectEqualsInt(0x00008000, rotateRightChar((char)0x8000, 32));  // overshoot
+    expectEqualsInt(0x80004000, rotateRightChar((char)0x8001, 1));
+    expectEqualsInt(0x40002000, rotateRightChar((char)0x8001, 2));
+    expectEqualsInt(0x40000123, rotateRightChar((char)0x1234, 4));
+    expectEqualsInt(0xBC00009A, rotateRightChar((char)0x9ABC, 8));
     for (int i = 0; i < 40; i++) {  // overshoot a bit
       int j = i & 31;
-      expectEquals32(0x00000000, rotateRight32(0x00000000, i));
-      expectEquals32(0xFFFFFFFF, rotateRight32(0xFFFFFFFF, i));
-      expectEquals32(0x80000000 >>> j, rotateRight32(0x80000000, i));
-      expectEquals32((0x12345678 >>> j) | (0x12345678 << -j),
-                     rotateRight32(0x12345678, i));
+      expectEqualsInt(0x00000000, rotateRightChar((char)0x0000, i));
+      expectEqualsInt(1 << (32 - j), rotateRightChar((char)0x0001, i));
+      expectEqualsInt((0x1234 >>> j) | (0x1234 << -j), rotateRightChar((char)0x1234, i));
     }
+  }
+
+  public static void testRotateRightInt() {
+    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 0));
+    expectEqualsInt(0x40000000, rotateRightInt(0x80000000, 1));
+    expectEqualsInt(0x00000001, rotateRightInt(0x80000000, 31));
+    expectEqualsInt(0x80000000, rotateRightInt(0x80000000, 32));  // overshoot
+    expectEqualsInt(0xC0000000, rotateRightInt(0x80000001, 1));
+    expectEqualsInt(0x60000000, rotateRightInt(0x80000001, 2));
+    expectEqualsInt(0x81234567, rotateRightInt(0x12345678, 4));
+    expectEqualsInt(0xF09ABCDE, rotateRightInt(0x9ABCDEF0, 8));
+    for (int i = 0; i < 40; i++) {  // overshoot a bit
+      int j = i & 31;
+      expectEqualsInt(0x00000000, rotateRightInt(0x00000000, i));
+      expectEqualsInt(0xFFFFFFFF, rotateRightInt(0xFFFFFFFF, i));
+      expectEqualsInt(0x80000000 >>> j, rotateRightInt(0x80000000, i));
+      expectEqualsInt((0x12345678 >>> j) | (0x12345678 << -j), rotateRightInt(0x12345678, i));
+    }
+  }
 
-    expectEquals64(0x8000000000000000L, rotateRight64(0x8000000000000000L, 0));
-    expectEquals64(0x4000000000000000L, rotateRight64(0x8000000000000000L, 1));
-    expectEquals64(0x0000000000000001L, rotateRight64(0x8000000000000000L, 63));
-    expectEquals64(0x8000000000000000L, rotateRight64(0x8000000000000000L, 64));  // overshoot
-    expectEquals64(0xC000000000000000L, rotateRight64(0x8000000000000001L, 1));
-    expectEquals64(0x6000000000000000L, rotateRight64(0x8000000000000001L, 2));
-    expectEquals64(0x0123456789ABCDEFL, rotateRight64(0x123456789ABCDEF0L, 4));
-    expectEquals64(0xF0123456789ABCDEL, rotateRight64(0x123456789ABCDEF0L, 8));
+  public static void testRotateRightLong() {
+    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 0));
+    expectEqualsLong(0x4000000000000000L, rotateRightLong(0x8000000000000000L, 1));
+    expectEqualsLong(0x0000000000000001L, rotateRightLong(0x8000000000000000L, 63));
+    expectEqualsLong(0x8000000000000000L, rotateRightLong(0x8000000000000000L, 64));  // overshoot
+    expectEqualsLong(0xC000000000000000L, rotateRightLong(0x8000000000000001L, 1));
+    expectEqualsLong(0x6000000000000000L, rotateRightLong(0x8000000000000001L, 2));
+    expectEqualsLong(0x0123456789ABCDEFL, rotateRightLong(0x123456789ABCDEF0L, 4));
+    expectEqualsLong(0xF0123456789ABCDEL, rotateRightLong(0x123456789ABCDEF0L, 8));
     for (int i = 0; i < 70; i++) {  // overshoot a bit
       int j = i & 63;
-      expectEquals64(0x0000000000000000L, rotateRight64(0x0000000000000000L, i));
-      expectEquals64(0xFFFFFFFFFFFFFFFFL, rotateRight64(0xFFFFFFFFFFFFFFFFL, i));
-      expectEquals64(0x8000000000000000L >>> j, rotateRight64(0x8000000000000000L, i));
-      expectEquals64((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
-                     rotateRight64(0x123456789ABCDEF0L, i));
+      expectEqualsLong(0x0000000000000000L, rotateRightLong(0x0000000000000000L, i));
+      expectEqualsLong(0xFFFFFFFFFFFFFFFFL, rotateRightLong(0xFFFFFFFFFFFFFFFFL, i));
+      expectEqualsLong(0x8000000000000000L >>> j, rotateRightLong(0x8000000000000000L, i));
+      expectEqualsLong((0x123456789ABCDEF0L >>> j) | (0x123456789ABCDEF0L << -j),
+                       rotateRightLong(0x123456789ABCDEF0L, i));
     }
+  }
+
+
+  public static void main(String args[]) {
+    testRotateLeftBoolean();
+    testRotateLeftByte();
+    testRotateLeftShort();
+    testRotateLeftChar();
+    testRotateLeftInt();
+    testRotateLeftLong();
+
+    testRotateRightBoolean();
+    testRotateRightByte();
+    testRotateRightShort();
+    testRotateRightChar();
+    testRotateRightInt();
+    testRotateRightLong();
 
     System.out.println("passed");
   }
 
-  private static void expectEquals32(int expected, int result) {
+
+  private static void expectEqualsInt(int expected, int result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
     }
   }
-  private static void expectEquals64(long expected, long result) {
+
+  private static void expectEqualsLong(long expected, long result) {
     if (expected != result) {
       throw new Error("Expected: " + expected + ", found: " + result);
     }