diff options
| -rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 13 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86.cc | 4 | ||||
| -rw-r--r-- | compiler/optimizing/intrinsics_x86_64.cc | 4 | ||||
| -rw-r--r-- | test/575-checker-isnan/expected.txt | 1 | ||||
| -rw-r--r-- | test/575-checker-isnan/info.txt | 1 | ||||
| -rw-r--r-- | test/575-checker-isnan/src/Main.java | 126 |
10 files changed, 153 insertions, 12 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index a48d06f3d0..c44815370e 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -92,6 +92,7 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { void SimplifySystemArrayCopy(HInvoke* invoke); void SimplifyStringEquals(HInvoke* invoke); void SimplifyCompare(HInvoke* invoke, bool has_zero_op); + void SimplifyIsNaN(HInvoke* invoke); OptimizingCompilerStats* stats_; bool simplification_occurred_ = false; @@ -1551,6 +1552,15 @@ void InstructionSimplifierVisitor::SimplifyCompare(HInvoke* invoke, bool is_sign invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, compare); } +void InstructionSimplifierVisitor::SimplifyIsNaN(HInvoke* invoke) { + DCHECK(invoke->IsInvokeStaticOrDirect()); + uint32_t dex_pc = invoke->GetDexPc(); + // IsNaN(x) is the same as x != x. + HInstruction* x = invoke->InputAt(0); + HCondition* condition = new (GetGraph()->GetArena()) HNotEqual(x, x, dex_pc); + invoke->GetBlock()->ReplaceAndRemoveInstructionWith(invoke, condition); +} + void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { if (instruction->GetIntrinsic() == Intrinsics::kStringEquals) { SimplifyStringEquals(instruction); @@ -1568,6 +1578,9 @@ void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) { } else if (instruction->GetIntrinsic() == Intrinsics::kIntegerSignum || instruction->GetIntrinsic() == Intrinsics::kLongSignum) { SimplifyCompare(instruction, /* is_signum */ true); + } else if (instruction->GetIntrinsic() == Intrinsics::kFloatIsNaN || + instruction->GetIntrinsic() == Intrinsics::kDoubleIsNaN) { + SimplifyIsNaN(instruction); } } diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 00a158b10a..ea8669fa18 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -1858,8 +1858,6 @@ UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit) UNIMPLEMENTED_INTRINSIC(LongHighestOneBit) @@ -1867,6 +1865,8 @@ UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit) UNIMPLEMENTED_INTRINSIC(LongLowestOneBit) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft) UNIMPLEMENTED_INTRINSIC(LongRotateLeft) UNIMPLEMENTED_INTRINSIC(IntegerRotateRight) diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 4140d94e17..8741fd284f 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1618,8 +1618,6 @@ UNIMPLEMENTED_INTRINSIC(StringGetCharsNoCheck) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit) UNIMPLEMENTED_INTRINSIC(LongHighestOneBit) @@ -1627,6 +1625,8 @@ UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit) UNIMPLEMENTED_INTRINSIC(LongLowestOneBit) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft) UNIMPLEMENTED_INTRINSIC(LongRotateLeft) UNIMPLEMENTED_INTRINSIC(IntegerRotateRight) diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 2294713a3e..e93b93951e 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1016,8 +1016,6 @@ UNIMPLEMENTED_INTRINSIC(MathTanh) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit) UNIMPLEMENTED_INTRINSIC(LongHighestOneBit) @@ -1025,6 +1023,8 @@ UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit) UNIMPLEMENTED_INTRINSIC(LongLowestOneBit) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerCompare) UNIMPLEMENTED_INTRINSIC(LongCompare) UNIMPLEMENTED_INTRINSIC(IntegerSignum) diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index ac2850342d..cf3a3657de 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1764,8 +1764,6 @@ UNIMPLEMENTED_INTRINSIC(MathTanh) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit) UNIMPLEMENTED_INTRINSIC(LongHighestOneBit) @@ -1773,6 +1771,8 @@ UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit) UNIMPLEMENTED_INTRINSIC(LongLowestOneBit) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerCompare) UNIMPLEMENTED_INTRINSIC(LongCompare) UNIMPLEMENTED_INTRINSIC(IntegerSignum) diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index 22cefe8aa5..260a8773fb 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -2635,8 +2635,6 @@ UNIMPLEMENTED_INTRINSIC(SystemArrayCopy) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerHighestOneBit) UNIMPLEMENTED_INTRINSIC(LongHighestOneBit) @@ -2644,6 +2642,8 @@ UNIMPLEMENTED_INTRINSIC(IntegerLowestOneBit) UNIMPLEMENTED_INTRINSIC(LongLowestOneBit) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft) UNIMPLEMENTED_INTRINSIC(LongRotateLeft) UNIMPLEMENTED_INTRINSIC(IntegerRotateRight) diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index c9a43442b3..93e8c00e5a 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -2717,10 +2717,10 @@ UNIMPLEMENTED_INTRINSIC(ReferenceGetReferent) UNIMPLEMENTED_INTRINSIC(FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(DoubleIsInfinite) -UNIMPLEMENTED_INTRINSIC(FloatIsNaN) -UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) // Handled as HIR instructions. +UNIMPLEMENTED_INTRINSIC(FloatIsNaN) +UNIMPLEMENTED_INTRINSIC(DoubleIsNaN) UNIMPLEMENTED_INTRINSIC(IntegerRotateLeft) UNIMPLEMENTED_INTRINSIC(LongRotateLeft) UNIMPLEMENTED_INTRINSIC(IntegerRotateRight) diff --git a/test/575-checker-isnan/expected.txt b/test/575-checker-isnan/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/575-checker-isnan/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/575-checker-isnan/info.txt b/test/575-checker-isnan/info.txt new file mode 100644 index 0000000000..5c48a6a877 --- /dev/null +++ b/test/575-checker-isnan/info.txt @@ -0,0 +1 @@ +Unit test for float/double isNaN() operation. diff --git a/test/575-checker-isnan/src/Main.java b/test/575-checker-isnan/src/Main.java new file mode 100644 index 0000000000..cc71e5e27d --- /dev/null +++ b/test/575-checker-isnan/src/Main.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class Main { + + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (before) + /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after) + /// CHECK-DAG: <<Result:z\d+>> NotEqual + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN32(float) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + private static boolean isNaN32(float x) { + return Float.isNaN(x); + } + + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (before) + /// CHECK-DAG: <<Result:z\d+>> InvokeStaticOrDirect + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after) + /// CHECK-DAG: <<Result:z\d+>> NotEqual + /// CHECK-DAG: Return [<<Result>>] + // + /// CHECK-START: boolean Main.isNaN64(double) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + private static boolean isNaN64(double x) { + return Double.isNaN(x); + } + + public static void main(String args[]) { + // A few distinct numbers. + expectFalse(isNaN32(Float.NEGATIVE_INFINITY)); + expectFalse(isNaN32(-1.0f)); + expectFalse(isNaN32(-0.0f)); + expectFalse(isNaN32(0.0f)); + expectFalse(isNaN32(1.0f)); + expectFalse(isNaN32(Float.POSITIVE_INFINITY)); + + // A few distinct subnormal numbers. + expectFalse(isNaN32(Float.intBitsToFloat(0x00400000))); + expectFalse(isNaN32(Float.intBitsToFloat(0x80400000))); + expectFalse(isNaN32(Float.intBitsToFloat(0x00000001))); + expectFalse(isNaN32(Float.intBitsToFloat(0x80000001))); + + // A few NaN numbers. + expectTrue(isNaN32(Float.NaN)); + expectTrue(isNaN32(0.0f / 0.0f)); + expectTrue(isNaN32((float)Math.sqrt(-1.0f))); + float[] fvals = { + Float.intBitsToFloat(0x7f800001), + Float.intBitsToFloat(0x7fa00000), + Float.intBitsToFloat(0x7fc00000), + Float.intBitsToFloat(0x7fffffff), + Float.intBitsToFloat(0xff800001), + Float.intBitsToFloat(0xffa00000), + Float.intBitsToFloat(0xffc00000), + Float.intBitsToFloat(0xffffffff) + }; + for (int i = 0; i < fvals.length; i++) { + expectTrue(isNaN32(fvals[i])); + } + + // A few distinct numbers. + expectFalse(isNaN64(Double.NEGATIVE_INFINITY)); + expectFalse(isNaN32(-1.0f)); + expectFalse(isNaN64(-0.0d)); + expectFalse(isNaN64(0.0d)); + expectFalse(isNaN64(1.0d)); + expectFalse(isNaN64(Double.POSITIVE_INFINITY)); + + // A few distinct subnormal numbers. + expectFalse(isNaN64(Double.longBitsToDouble(0x0008000000000000l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x8008000000000000l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x0000000000000001l))); + expectFalse(isNaN64(Double.longBitsToDouble(0x8000000000000001l))); + + // A few NaN numbers. + expectTrue(isNaN64(Double.NaN)); + expectTrue(isNaN64(0.0d / 0.0d)); + expectTrue(isNaN64(Math.sqrt(-1.0d))); + double[] dvals = { + Double.longBitsToDouble(0x7ff0000000000001L), + Double.longBitsToDouble(0x7ff4000000000000L), + Double.longBitsToDouble(0x7ff8000000000000L), + Double.longBitsToDouble(0x7fffffffffffffffL), + Double.longBitsToDouble(0xfff0000000000001L), + Double.longBitsToDouble(0xfff4000000000000L), + Double.longBitsToDouble(0xfff8000000000000L), + Double.longBitsToDouble(0xffffffffffffffffL) + }; + for (int i = 0; i < dvals.length; i++) { + expectTrue(isNaN64(dvals[i])); + } + + System.out.println("passed"); + } + + private static void expectTrue(boolean value) { + if (!value) { + throw new Error("Expected True"); + } + } + + private static void expectFalse(boolean value) { + if (value) { + throw new Error("Expected False"); + } + } +} |