Fix BitCount intrinsics assertions.

Bug: 27852035
Change-Id: Iba43039aadd9ba288b476d53cc2306a58356465f
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 5de2306..a589ef0 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -368,17 +368,16 @@
   GenReverse(invoke->GetLocations(), Primitive::kPrimLong, GetVIXLAssembler());
 }
 
-static void GenBitCount(HInvoke* instr, bool is_long, vixl::MacroAssembler* masm) {
-  DCHECK(instr->GetType() == Primitive::kPrimInt);
-  DCHECK((is_long && instr->InputAt(0)->GetType() == Primitive::kPrimLong) ||
-         (!is_long && instr->InputAt(0)->GetType() == Primitive::kPrimInt));
+static void GenBitCount(HInvoke* instr, Primitive::Type type, vixl::MacroAssembler* masm) {
+  DCHECK(Primitive::IsIntOrLongType(type)) << type;
+  DCHECK_EQ(instr->GetType(), Primitive::kPrimInt);
+  DCHECK_EQ(Primitive::PrimitiveKind(instr->InputAt(0)->GetType()), type);
 
-  Location out = instr->GetLocations()->Out();
   UseScratchRegisterScope temps(masm);
 
   Register src = InputRegisterAt(instr, 0);
-  Register dst = is_long ? XRegisterFrom(out) : WRegisterFrom(out);
-  FPRegister fpr = is_long ? temps.AcquireD() : temps.AcquireS();
+  Register dst = RegisterFrom(instr->GetLocations()->Out(), type);
+  FPRegister fpr = (type == Primitive::kPrimLong) ? temps.AcquireD() : temps.AcquireS();
 
   __ Fmov(fpr, src);
   __ Cnt(fpr.V8B(), fpr.V8B());
@@ -391,7 +390,7 @@
 }
 
 void IntrinsicCodeGeneratorARM64::VisitLongBitCount(HInvoke* invoke) {
-  GenBitCount(invoke, /* is_long */ true, GetVIXLAssembler());
+  GenBitCount(invoke, Primitive::kPrimLong, GetVIXLAssembler());
 }
 
 void IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) {
@@ -399,7 +398,7 @@
 }
 
 void IntrinsicCodeGeneratorARM64::VisitIntegerBitCount(HInvoke* invoke) {
-  GenBitCount(invoke, /* is_long */ false, GetVIXLAssembler());
+  GenBitCount(invoke, Primitive::kPrimInt, GetVIXLAssembler());
 }
 
 static void CreateFPToFPLocations(ArenaAllocator* arena, HInvoke* invoke) {
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc
index 1280587..19c6a22 100644
--- a/compiler/optimizing/intrinsics_mips.cc
+++ b/compiler/optimizing/intrinsics_mips.cc
@@ -614,8 +614,6 @@
                         Primitive::Type type,
                         bool isR6,
                         MipsAssembler* assembler) {
-  DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
-
   Register out = locations->Out().AsRegister<Register>();
 
   // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
@@ -663,7 +661,8 @@
       __ MulR2(out, out, TMP);
     }
     __ Srl(out, out, 24);
-  } else if (type == Primitive::kPrimLong) {
+  } else {
+    DCHECK_EQ(type, Primitive::kPrimLong);
     Register in_lo = locations->InAt(0).AsRegisterPairLow<Register>();
     Register in_hi = locations->InAt(0).AsRegisterPairHigh<Register>();
     Register tmp_hi = locations->GetTemp(0).AsRegister<Register>();
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 95fdb9b..4aab3e2 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -2387,10 +2387,10 @@
   if (invoke->InputAt(0)->IsConstant()) {
     // Evaluate this at compile time.
     int64_t value = Int64FromConstant(invoke->InputAt(0)->AsConstant());
-    value = is_long
+    int32_t result = is_long
         ? POPCOUNT(static_cast<uint64_t>(value))
         : POPCOUNT(static_cast<uint32_t>(value));
-    codegen->Load32BitValue(out, value);
+    codegen->Load32BitValue(out, result);
     return;
   }
 
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 9e568f7..9ca4ef0 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2402,10 +2402,10 @@
   if (invoke->InputAt(0)->IsConstant()) {
     // Evaluate this at compile time.
     int64_t value = Int64FromConstant(invoke->InputAt(0)->AsConstant());
-    value = is_long
+    int32_t result = is_long
         ? POPCOUNT(static_cast<uint64_t>(value))
         : POPCOUNT(static_cast<uint32_t>(value));
-    codegen->Load32BitValue(out, value);
+    codegen->Load32BitValue(out, result);
     return;
   }
 
diff --git a/test/564-checker-bitcount/src/Main.java b/test/564-checker-bitcount/src/Main.java
index 2683b25..aad9689 100644
--- a/test/564-checker-bitcount/src/Main.java
+++ b/test/564-checker-bitcount/src/Main.java
@@ -20,67 +20,187 @@
   // CHECK-START-X86_64: int Main.bits32(int) disassembly (after)
   // CHECK-DAG: popcnt
 
-  /// CHECK-START: int Main.bits32(int) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:IntegerBitCount
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static int bits32(int x) {
+
+  /// CHECK-START: int Main.$noinline$BitCountBoolean(boolean) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:IntegerBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountBoolean(boolean x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
+    return Integer.bitCount(x ? 1 : 0);
+  }
+
+  /// CHECK-START: int Main.$noinline$BitCountByte(byte) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:IntegerBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountByte(byte x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
     return Integer.bitCount(x);
   }
 
-  /// CHECK-START: int Main.bits64(long) intrinsics_recognition (after)
-  /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect intrinsic:LongBitCount
-  /// CHECK-DAG:                 Return [<<Result>>]
-  private static int bits64(long x) {
+  /// CHECK-START: int Main.$noinline$BitCountShort(short) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:IntegerBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountShort(short x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
+    return Integer.bitCount(x);
+  }
+
+  /// CHECK-START: int Main.$noinline$BitCountChar(char) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:IntegerBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountChar(char x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
+    return Integer.bitCount(x);
+  }
+
+  /// CHECK-START: int Main.$noinline$BitCountInt(int) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:IntegerBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountInt(int x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
+    return Integer.bitCount(x);
+  }
+
+  /// CHECK-START: int Main.$noinline$BitCountLong(long) intrinsics_recognition (after)
+  /// CHECK-DAG:     <<Result:i\d+>>  InvokeStaticOrDirect intrinsic:LongBitCount
+  /// CHECK-DAG:                      Return [<<Result>>]
+  private static int $noinline$BitCountLong(long x) {
+    if (doThrow) { throw new Error(); }  // Try defeating inlining.
     return Long.bitCount(x);
   }
 
+  public static void testBitCountBoolean() {
+    expectEqualsInt($noinline$BitCountBoolean(false), 0);
+    expectEqualsInt($noinline$BitCountBoolean(true), 1);
+  }
+
+  public static void testBitCountByte() {
+    // Number of bits in an 32-bit integer representing the sign
+    // extension of a byte value widened to an int.
+    int signExtensionSize = Integer.SIZE - Byte.SIZE;
+    // Sign bit position in a byte.
+    int signBit = Byte.SIZE - 1;
+
+    expectEqualsInt($noinline$BitCountByte((byte) 0x00), 0);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x01), 1);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x10), 1);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x11), 2);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x03), 2);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x70), 3);
+    expectEqualsInt($noinline$BitCountByte((byte) 0xF0), 4 + signExtensionSize);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x0F), 4);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x12), 2);
+    expectEqualsInt($noinline$BitCountByte((byte) 0x9A), 4 + signExtensionSize);
+    expectEqualsInt($noinline$BitCountByte((byte) 0xFF), 8 + signExtensionSize);
+
+    for (int i = 0; i < Byte.SIZE; i++) {
+      expectEqualsInt($noinline$BitCountByte((byte) (1 << i)),
+                      (i < signBit) ? 1 : 1 + signExtensionSize);
+    }
+  }
+
+  public static void testBitCountShort() {
+    // Number of bits in an 32-bit integer representing the sign
+    // extension of a short value widened to an int.
+    int signExtensionSize = Integer.SIZE - Short.SIZE;
+    // Sign bit position in a short.
+    int signBit = Short.SIZE - 1;
+
+    expectEqualsInt($noinline$BitCountShort((short) 0x0000), 0);
+    expectEqualsInt($noinline$BitCountShort((short) 0x0001), 1);
+    expectEqualsInt($noinline$BitCountShort((short) 0x1000), 1);
+    expectEqualsInt($noinline$BitCountShort((short) 0x1001), 2);
+    expectEqualsInt($noinline$BitCountShort((short) 0x0003), 2);
+    expectEqualsInt($noinline$BitCountShort((short) 0x7000), 3);
+    expectEqualsInt($noinline$BitCountShort((short) 0x0F00), 4);
+    expectEqualsInt($noinline$BitCountShort((short) 0x0011), 2);
+    expectEqualsInt($noinline$BitCountShort((short) 0x1100), 2);
+    expectEqualsInt($noinline$BitCountShort((short) 0x1111), 4);
+    expectEqualsInt($noinline$BitCountShort((short) 0x1234), 5);
+    expectEqualsInt($noinline$BitCountShort((short) 0x9ABC), 9 + signExtensionSize);
+    expectEqualsInt($noinline$BitCountShort((short) 0xFFFF), 16 + signExtensionSize);
+
+    for (int i = 0; i < Short.SIZE; i++) {
+      expectEqualsInt($noinline$BitCountShort((short) (1 << i)),
+                      (i < signBit) ? 1 : 1 + signExtensionSize);
+    }
+  }
+
+  public static void testBitCountChar() {
+    expectEqualsInt($noinline$BitCountChar((char) 0x0000), 0);
+    expectEqualsInt($noinline$BitCountChar((char) 0x0001), 1);
+    expectEqualsInt($noinline$BitCountChar((char) 0x1000), 1);
+    expectEqualsInt($noinline$BitCountChar((char) 0x1001), 2);
+    expectEqualsInt($noinline$BitCountChar((char) 0x0003), 2);
+    expectEqualsInt($noinline$BitCountChar((char) 0x7000), 3);
+    expectEqualsInt($noinline$BitCountChar((char) 0x0F00), 4);
+    expectEqualsInt($noinline$BitCountChar((char) 0x0011), 2);
+    expectEqualsInt($noinline$BitCountChar((char) 0x1100), 2);
+    expectEqualsInt($noinline$BitCountChar((char) 0x1111), 4);
+    expectEqualsInt($noinline$BitCountChar((char) 0x1234), 5);
+    expectEqualsInt($noinline$BitCountChar((char) 0x9ABC), 9);
+    expectEqualsInt($noinline$BitCountChar((char) 0xFFFF), 16);
+
+    for (int i = 0; i < Character.SIZE; i++) {
+      expectEqualsInt($noinline$BitCountChar((char) (1 << i)), 1);
+    }
+  }
+
+  public static void testBitCountInt() {
+    expectEqualsInt($noinline$BitCountInt(0x00000000), 0);
+    expectEqualsInt($noinline$BitCountInt(0x00000001), 1);
+    expectEqualsInt($noinline$BitCountInt(0x10000000), 1);
+    expectEqualsInt($noinline$BitCountInt(0x10000001), 2);
+    expectEqualsInt($noinline$BitCountInt(0x00000003), 2);
+    expectEqualsInt($noinline$BitCountInt(0x70000000), 3);
+    expectEqualsInt($noinline$BitCountInt(0x000F0000), 4);
+    expectEqualsInt($noinline$BitCountInt(0x00001111), 4);
+    expectEqualsInt($noinline$BitCountInt(0x11110000), 4);
+    expectEqualsInt($noinline$BitCountInt(0x11111111), 8);
+    expectEqualsInt($noinline$BitCountInt(0x12345678), 13);
+    expectEqualsInt($noinline$BitCountInt(0x9ABCDEF0), 19);
+    expectEqualsInt($noinline$BitCountInt(0xFFFFFFFF), 32);
+
+    for (int i = 0; i < Integer.SIZE; i++) {
+      expectEqualsInt($noinline$BitCountInt(1 << i), 1);
+    }
+  }
+
+  public static void testBitCountLong() {
+    expectEqualsInt($noinline$BitCountLong(0x0000000000000000L), 0);
+    expectEqualsInt($noinline$BitCountLong(0x0000000000000001L), 1);
+    expectEqualsInt($noinline$BitCountLong(0x1000000000000000L), 1);
+    expectEqualsInt($noinline$BitCountLong(0x1000000000000001L), 2);
+    expectEqualsInt($noinline$BitCountLong(0x0000000000000003L), 2);
+    expectEqualsInt($noinline$BitCountLong(0x7000000000000000L), 3);
+    expectEqualsInt($noinline$BitCountLong(0x000F000000000000L), 4);
+    expectEqualsInt($noinline$BitCountLong(0x0000000011111111L), 8);
+    expectEqualsInt($noinline$BitCountLong(0x1111111100000000L), 8);
+    expectEqualsInt($noinline$BitCountLong(0x1111111111111111L), 16);
+    expectEqualsInt($noinline$BitCountLong(0x123456789ABCDEF1L), 33);
+    expectEqualsInt($noinline$BitCountLong(0xFFFFFFFFFFFFFFFFL), 64);
+
+    for (int i = 0; i < Long.SIZE; i++) {
+      expectEqualsInt($noinline$BitCountLong(1L << i), 1);
+    }
+  }
+
   public static void main(String args[]) {
-    expectEquals32(bits32(0x00000000), 0);
-    expectEquals32(bits32(0x00000001), 1);
-    expectEquals32(bits32(0x10000000), 1);
-    expectEquals32(bits32(0x10000001), 2);
-    expectEquals32(bits32(0x00000003), 2);
-    expectEquals32(bits32(0x70000000), 3);
-    expectEquals32(bits32(0x000F0000), 4);
-    expectEquals32(bits32(0x00001111), 4);
-    expectEquals32(bits32(0x11110000), 4);
-    expectEquals32(bits32(0x11111111), 8);
-    expectEquals32(bits32(0x12345678), 13);
-    expectEquals32(bits32(0x9ABCDEF0), 19);
-    expectEquals32(bits32(0xFFFFFFFF), 32);
-
-    for (int i = 0; i < 32; i++) {
-      expectEquals32(bits32(1 << i), 1);
-    }
-
-    expectEquals64(bits64(0x0000000000000000L), 0);
-    expectEquals64(bits64(0x0000000000000001L), 1);
-    expectEquals64(bits64(0x1000000000000000L), 1);
-    expectEquals64(bits64(0x1000000000000001L), 2);
-    expectEquals64(bits64(0x0000000000000003L), 2);
-    expectEquals64(bits64(0x7000000000000000L), 3);
-    expectEquals64(bits64(0x000F000000000000L), 4);
-    expectEquals64(bits64(0x0000000011111111L), 8);
-    expectEquals64(bits64(0x1111111100000000L), 8);
-    expectEquals64(bits64(0x1111111111111111L), 16);
-    expectEquals64(bits64(0x123456789ABCDEF1L), 33);
-    expectEquals64(bits64(0xFFFFFFFFFFFFFFFFL), 64);
-
-    for (int i = 0; i < 64; i++) {
-      expectEquals64(bits64(1L << i), 1);
-    }
+    testBitCountBoolean();
+    testBitCountByte();
+    testBitCountShort();
+    testBitCountChar();
+    testBitCountInt();
+    testBitCountLong();
 
     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) {
-    if (expected != result) {
-      throw new Error("Expected: " + expected + ", found: " + result);
-    }
-  }
+
+  private static boolean doThrow = false;
 }