MIPS64: ART Vectorizer

MIPS64 implementation which uses MSA extension. Also extended all
relevant checker tests to test MIPS64 implementation.

Test: booted MIPS64R6 in QEMU
Test: ./testrunner.py --target --optimizing -j1 in QEMU

Change-Id: I8b8a2f601076bca1925e21213db8ed1d41d79b52
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 94787c9..ae102f7 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -811,6 +811,11 @@
     }
     return true;
   } else if (instruction->IsArrayGet()) {
+    // Deal with vector restrictions.
+    if (instruction->AsArrayGet()->IsStringCharAt() &&
+        HasVectorRestrictions(restrictions, kNoStringCharAt)) {
+      return false;
+    }
     // Accept a right-hand-side array base[index] for
     // (1) exact matching vector type,
     // (2) loop-invariant base,
@@ -1072,9 +1077,36 @@
       }
       return false;
     case kMips:
-    case kMips64:
       // TODO: implement MIPS SIMD.
       return false;
+    case kMips64:
+      if (features->AsMips64InstructionSetFeatures()->HasMsa()) {
+        switch (type) {
+          case Primitive::kPrimBoolean:
+          case Primitive::kPrimByte:
+            *restrictions |= kNoDiv | kNoMinMax;
+            return TrySetVectorLength(16);
+          case Primitive::kPrimChar:
+          case Primitive::kPrimShort:
+            *restrictions |= kNoDiv | kNoMinMax | kNoStringCharAt;
+            return TrySetVectorLength(8);
+          case Primitive::kPrimInt:
+            *restrictions |= kNoDiv | kNoMinMax;
+            return TrySetVectorLength(4);
+          case Primitive::kPrimLong:
+            *restrictions |= kNoDiv | kNoMinMax;
+            return TrySetVectorLength(2);
+          case Primitive::kPrimFloat:
+            *restrictions |= kNoMinMax;
+            return TrySetVectorLength(4);
+          case Primitive::kPrimDouble:
+            *restrictions |= kNoMinMax;
+            return TrySetVectorLength(2);
+          default:
+            break;
+        }  // switch type
+      }
+      return false;
     default:
       return false;
   }  // switch instruction set