Moved knowledge on masking shift operands to simplifier.

Rationale:
It is better to have a single place that simplifies shift
factors outside the 32-bit or 64-bit distance range, so
that other phases (induction variable analysis, loop optimizations,
etc.) do not have to know about that.

Test: test-art-target, test-art-host
Change-Id: Idfd90259cca085426cc3055eccb90f3c0976036b
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 2dcc12e..2cedde9 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -257,7 +257,8 @@
 
   if (shift_amount->IsConstant()) {
     int64_t cst = Int64FromConstant(shift_amount->AsConstant());
-    if ((cst & implicit_mask) == 0) {
+    int64_t masked_cst = cst & implicit_mask;
+    if (masked_cst == 0) {
       // Replace code looking like
       //    SHL dst, value, 0
       // with
@@ -266,6 +267,17 @@
       instruction->GetBlock()->RemoveInstruction(instruction);
       RecordSimplification();
       return;
+    } else if (masked_cst != cst) {
+      // Replace code looking like
+      //    SHL dst, value, cst
+      // where cst exceeds maximum distance with the equivalent
+      //    SHL dst, value, cst & implicit_mask
+      // (as defined by shift semantics). This ensures other
+      // optimizations do not need to special case for such situations.
+      DCHECK_EQ(shift_amount->GetType(), Primitive::kPrimInt);
+      instruction->ReplaceInput(GetGraph()->GetIntConstant(masked_cst), /* index */ 1);
+      RecordSimplification();
+      return;
     }
   }
 
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index bbc55dd..881802d 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -71,7 +71,7 @@
   // extension when represented in the *width* of the given narrower data type
   // (the fact that char normally zero extends does not matter here).
   int64_t value = 0;
-  if (IsInt64AndGet(instruction, &value)) {
+  if (IsInt64AndGet(instruction, /*out*/ &value)) {
     switch (type) {
       case Primitive::kPrimByte:
         if (std::numeric_limits<int8_t>::min() <= value &&
@@ -119,7 +119,7 @@
   // extension when represented in the *width* of the given narrower data type
   // (the fact that byte/short normally sign extend does not matter here).
   int64_t value = 0;
-  if (IsInt64AndGet(instruction, &value)) {
+  if (IsInt64AndGet(instruction, /*out*/ &value)) {
     switch (type) {
       case Primitive::kPrimByte:
         if (std::numeric_limits<uint8_t>::min() <= value &&
@@ -833,19 +833,14 @@
     // TODO: accept symbolic, albeit loop invariant shift factors.
     HInstruction* opa = instruction->InputAt(0);
     HInstruction* opb = instruction->InputAt(1);
-    int64_t value = 0;
-    if (VectorizeUse(node, opa, generate_code, type, restrictions) && IsInt64AndGet(opb, &value)) {
-      // Make sure shift distance only looks at lower bits, as defined for sequential shifts.
-      int64_t mask = (instruction->GetType() == Primitive::kPrimLong)
-          ? kMaxLongShiftDistance
-          : kMaxIntShiftDistance;
-      int64_t distance = value & mask;
+    int64_t distance = 0;
+    if (VectorizeUse(node, opa, generate_code, type, restrictions) &&
+        IsInt64AndGet(opb, /*out*/ &distance)) {
       // Restrict shift distance to packed data type width.
       int64_t max_distance = Primitive::ComponentSize(type) * 8;
       if (0 <= distance && distance < max_distance) {
         if (generate_code) {
-          HInstruction* s = graph_->GetIntConstant(distance);
-          GenerateVecOp(instruction, vector_map_->Get(opa), s, type);
+          GenerateVecOp(instruction, vector_map_->Get(opa), opb, type);
         }
         return true;
       }
@@ -1177,14 +1172,14 @@
   int64_t value = 0;
   if ((instruction->IsShr() ||
        instruction->IsUShr()) &&
-      IsInt64AndGet(instruction->InputAt(1), &value) && value == 1) {
+      IsInt64AndGet(instruction->InputAt(1), /*out*/ &value) && value == 1) {
     //
     // TODO: make following code less sensitive to associativity and commutativity differences.
     //
     HInstruction* x = instruction->InputAt(0);
     // Test for an optional rounding part (x + 1) >> 1.
     bool is_rounded = false;
-    if (x->IsAdd() && IsInt64AndGet(x->InputAt(1), &value) && value == 1) {
+    if (x->IsAdd() && IsInt64AndGet(x->InputAt(1), /*out*/ &value) && value == 1) {
       x = x->InputAt(0);
       is_rounded = true;
     }
diff --git a/test/551-checker-shifter-operand/src/Main.java b/test/551-checker-shifter-operand/src/Main.java
index e967398..bf09a6a 100644
--- a/test/551-checker-shifter-operand/src/Main.java
+++ b/test/551-checker-shifter-operand/src/Main.java
@@ -642,6 +642,123 @@
 
 
   // Each test line below should see one merge.
+  //
+  /// CHECK-START: void Main.$opt$validateShiftInt(int, int) instruction_simplifier$after_inlining (before)
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK-NOT:                        UShr
+  //
+  // Note: simplification after inlining removes `b << 32`, `b >> 32` and `b >>> 32`.
+  //
+  /// CHECK-START: void Main.$opt$validateShiftInt(int, int) instruction_simplifier$after_inlining (after)
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK-NOT:                        UShr
+  //
+  // Note: simplification followed by GVN exposes the common subexpressions between shifts with larger distance
+  //       `b << 62`, `b << 63` etc. and the equivalent smaller distances.
+  //
+  /// CHECK-START: void Main.$opt$validateShiftInt(int, int) GVN (after)
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK:                            Shl
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK:                            Shr
+  /// CHECK-NOT:                        Shl
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK:                            UShr
+  /// CHECK-NOT:                        UShr
+  //
   /// CHECK-START-ARM: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm (after)
   /// CHECK:                            DataProcWithShifterOp
   /// CHECK:                            DataProcWithShifterOp
@@ -670,14 +787,7 @@
   /// CHECK:                            DataProcWithShifterOp
   /// CHECK:                            DataProcWithShifterOp
   /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
   /// CHECK-NOT:                        DataProcWithShifterOp
-  // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier.
 
   /// CHECK-START-ARM: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm (after)
   /// CHECK-NOT:                        Shl
@@ -712,14 +822,7 @@
   /// CHECK:                            DataProcWithShifterOp
   /// CHECK:                            DataProcWithShifterOp
   /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
-  /// CHECK:                            DataProcWithShifterOp
   /// CHECK-NOT:                        DataProcWithShifterOp
-  // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier.
 
   /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
   /// CHECK-NOT:                        Shl
diff --git a/test/640-checker-int-simd/src/Main.java b/test/640-checker-int-simd/src/Main.java
index ba1e142..97048eb 100644
--- a/test/640-checker-int-simd/src/Main.java
+++ b/test/640-checker-int-simd/src/Main.java
@@ -76,6 +76,7 @@
   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START: void Main.div(int) loop_optimization (after)
+  /// CHECK-NOT: VecDiv
   //
   //  Not supported on any architecture.
   //
@@ -159,14 +160,81 @@
   // Shift sanity.
   //
 
+  // Expose constants to optimizing compiler, but not to front-end.
+  public static int $opt$inline$IntConstant32()       { return 32; }
+  public static int $opt$inline$IntConstant33()       { return 33; }
+  public static int $opt$inline$IntConstantMinus254() { return -254; }
+
+  /// CHECK-START: void Main.shr32() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 32                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shr32() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Phi:i\d+>> Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>> ArrayGet                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:              ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shr32() loop_optimization (after)
+  /// CHECK-DAG: <<Phi:i\d+>> Phi                                 loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>> VecLoad                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:              VecStore [{{l\d+}},<<Phi>>,<<Get>>] loop:<<Loop>>      outer_loop:none
   static void shr32() {
+    // TODO: remove a[i] = a[i] altogether?
     for (int i = 0; i < 128; i++)
-      a[i] >>>= 32;  // 0, since & 31
+      a[i] >>>= $opt$inline$IntConstant32();  // 0, since & 31
   }
 
+  /// CHECK-START: void Main.shr33() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 33                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shr33() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shr33() loop_optimization (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]           loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>>      outer_loop:none
   static void shr33() {
     for (int i = 0; i < 128; i++)
-      a[i] >>>= 33;  // 1, since & 31
+      a[i] >>>= $opt$inline$IntConstant33();  // 1, since & 31
+  }
+
+  /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant -254                      loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:i\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shrMinus254() loop_optimization (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]           loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>>      outer_loop:none
+  static void shrMinus254() {
+    for (int i = 0; i < 128; i++)
+      a[i] >>>= $opt$inline$IntConstantMinus254();  // 2, since & 31
   }
 
   //
@@ -240,9 +308,14 @@
     for (int i = 0; i < 128; i++) {
       expectEquals(0x1fffffff, a[i], "shr33");
     }
+    shrMinus254();
+    for (int i = 0; i < 128; i++) {
+      expectEquals(0x07ffffff, a[i], "shrMinus254");
+    }
+    // Bit-wise not operator.
     not();
     for (int i = 0; i < 128; i++) {
-      expectEquals(0xe0000000, a[i], "not");
+      expectEquals(0xf8000000, a[i], "not");
     }
     // Done.
     System.out.println("passed");
diff --git a/test/640-checker-long-simd/src/Main.java b/test/640-checker-long-simd/src/Main.java
index 5641182..e42c716 100644
--- a/test/640-checker-long-simd/src/Main.java
+++ b/test/640-checker-long-simd/src/Main.java
@@ -74,6 +74,7 @@
   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
   //
   /// CHECK-START: void Main.div(long) loop_optimization (after)
+  /// CHECK-NOT: VecDiv
   //
   //  Not supported on any architecture.
   //
@@ -157,14 +158,81 @@
   // Shift sanity.
   //
 
+  // Expose constants to optimizing compiler, but not to front-end.
+  public static int $opt$inline$IntConstant64()       { return 64; }
+  public static int $opt$inline$IntConstant65()       { return 65; }
+  public static int $opt$inline$IntConstantMinus254() { return -254; }
+
+  /// CHECK-START: void Main.shr64() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 64                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shr64() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Phi:i\d+>> Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>> ArrayGet                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:              ArraySet [{{l\d+}},{{i\d+}},<<Get>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shr64() loop_optimization (after)
+  /// CHECK-DAG: <<Phi:i\d+>> Phi                                 loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>> VecLoad                             loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:              VecStore [{{l\d+}},<<Phi>>,<<Get>>] loop:<<Loop>>      outer_loop:none
   static void shr64() {
+    // TODO: remove a[i] = a[i] altogether?
     for (int i = 0; i < 128; i++)
-      a[i] >>>= 64;  // 0, since & 63
+      a[i] >>>= $opt$inline$IntConstant64();  // 0, since & 63
   }
 
+  /// CHECK-START: void Main.shr65() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 65                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shr65() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shr65() loop_optimization (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 1                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]           loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>>      outer_loop:none
   static void shr65() {
     for (int i = 0; i < 128; i++)
-      a[i] >>>= 65;  // 1, since & 63
+      a[i] >>>= $opt$inline$IntConstant65();  // 1, since & 63
+  }
+
+  /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (before)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant -254                      loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START: void Main.shrMinus254() instruction_simplifier$after_inlining (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                         loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                   loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:j\d+>>  ArrayGet                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:j\d+>> UShr [<<Get>>,<<Dist>>]               loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<UShr>>] loop:<<Loop>>      outer_loop:none
+  //
+  /// CHECK-START-ARM64: void Main.shrMinus254() loop_optimization (after)
+  /// CHECK-DAG: <<Dist:i\d+>> IntConstant 2                        loop:none
+  /// CHECK-DAG: <<Phi:i\d+>>  Phi                                  loop:<<Loop:B\d+>> outer_loop:none
+  /// CHECK-DAG: <<Get:d\d+>>  VecLoad                              loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG: <<UShr:d\d+>> VecUShr [<<Get>>,<<Dist>>]           loop:<<Loop>>      outer_loop:none
+  /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<UShr>>] loop:<<Loop>>      outer_loop:none
+  static void shrMinus254() {
+    for (int i = 0; i < 128; i++)
+      a[i] >>>= $opt$inline$IntConstantMinus254();  // 2, since & 63
   }
 
   //
@@ -238,9 +306,14 @@
     for (int i = 0; i < 128; i++) {
       expectEquals(0x1fffffffffffffffL, a[i], "shr65");
     }
+    shrMinus254();
+    for (int i = 0; i < 128; i++) {
+      expectEquals(0x07ffffffffffffffL, a[i], "shrMinus254");
+    }
+    // Bit-wise not operator.
     not();
     for (int i = 0; i < 128; i++) {
-      expectEquals(0xe000000000000000L, a[i], "not");
+      expectEquals(0xf800000000000000L, a[i], "not");
     }
     // Done.
     System.out.println("passed");