diff options
| author | 2016-04-04 12:58:23 +0000 | |
|---|---|---|
| committer | 2016-04-04 12:58:23 +0000 | |
| commit | 75ee5c28ab583c532066b64d6337a5f78d6aa2ad (patch) | |
| tree | 21f4ff61cee75c35157366278641916786cfc58b | |
| parent | 7e168f65949e70069418148b0b60ac86d04339d0 (diff) | |
| parent | fa3912edfac60a9f0a9b95a5862c7361b403fcc2 (diff) | |
Merge "Fix BitCount intrinsics assertions."
| -rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 17 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 5 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 4 | ||||
| -rw-r--r-- | test/564-checker-bitcount/src/Main.java | 210 |
5 files changed, 179 insertions, 61 deletions
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 5de2306506..a589ef07e2 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -368,17 +368,16 @@ void IntrinsicCodeGeneratorARM64::VisitLongReverse(HInvoke* invoke) { 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 IntrinsicLocationsBuilderARM64::VisitLongBitCount(HInvoke* invoke) { } 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 IntrinsicLocationsBuilderARM64::VisitIntegerBitCount(HInvoke* invoke) { } 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 1280587276..19c6a225ac 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -614,8 +614,6 @@ static void GenBitCount(LocationSummary* locations, 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 @@ static void GenBitCount(LocationSummary* locations, __ 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 95fdb9b3f6..4aab3e2768 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -2387,10 +2387,10 @@ static void GenBitCount(X86Assembler* assembler, 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 9e568f7b4f..9ca4ef049a 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -2402,10 +2402,10 @@ static void GenBitCount(X86_64Assembler* assembler, 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 2683b2548f..aad9689a1e 100644 --- a/test/564-checker-bitcount/src/Main.java +++ b/test/564-checker-bitcount/src/Main.java @@ -20,67 +20,187 @@ public class Main { // 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.$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.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$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 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); + 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); - 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); + for (int i = 0; i < Character.SIZE; i++) { + expectEqualsInt($noinline$BitCountChar((char) (1 << i)), 1); } + } - System.out.println("passed"); + 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); + } } - private static void expectEquals32(int expected, int result) { - if (expected != result) { - throw new Error("Expected: " + expected + ", found: " + result); + 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); } } - private static void expectEquals64(long expected, long result) { + + public static void main(String args[]) { + testBitCountBoolean(); + testBitCountByte(); + testBitCountShort(); + testBitCountChar(); + testBitCountInt(); + testBitCountLong(); + + System.out.println("passed"); + } + + private static void expectEqualsInt(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } + + private static boolean doThrow = false; } |