diff options
author | 2015-04-15 16:29:32 +0100 | |
---|---|---|
committer | 2015-04-16 11:09:55 +0100 | |
commit | 13b4718ecd52a674b25eac106e654d8e89872750 (patch) | |
tree | 34d6efd2cda3ceb233118e4d135c4a897f02ea12 | |
parent | da93333d568f3c5bd8eeb58341d10a332e1d42bf (diff) |
ART: Remove DCHECKs for boolean type
Since bool and int are interchangeable types, checking whether an
input is kPrimBoolean can fail when replaced with 0/1 constant or
a phi. This patch removes the problematic DCHECKs, adds a best-effort
verification into SSAChecker but leaves the phi case empty until a
suitable analysis is implemented.
Change-Id: I31e8daf27dd33d2fd74049b82bed1cb7c240c8c6
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.h | 3 | ||||
-rw-r--r-- | test/474-checker-boolean-input/expected.txt | 0 | ||||
-rw-r--r-- | test/474-checker-boolean-input/info.txt | 1 | ||||
-rw-r--r-- | test/474-checker-boolean-input/src/Main.java | 75 |
9 files changed, 102 insertions, 13 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 507b3cd021..2ea920310a 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -2673,7 +2673,6 @@ void LocationsBuilderARM::VisitBooleanNot(HBooleanNot* bool_not) { } void InstructionCodeGeneratorARM::VisitBooleanNot(HBooleanNot* bool_not) { - DCHECK_EQ(bool_not->InputAt(0)->GetType(), Primitive::kPrimBoolean); LocationSummary* locations = bool_not->GetLocations(); Location out = locations->Out(); Location in = locations->InAt(0); diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index f6ec729560..efc41e7c06 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -2286,7 +2286,6 @@ void LocationsBuilderARM64::VisitBooleanNot(HBooleanNot* instruction) { } void InstructionCodeGeneratorARM64::VisitBooleanNot(HBooleanNot* instruction) { - DCHECK_EQ(instruction->InputAt(0)->GetType(), Primitive::kPrimBoolean); __ Eor(OutputRegister(instruction), InputRegisterAt(instruction, 0), vixl::Operand(1)); } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 0cc377cf03..879216d59b 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -2931,7 +2931,6 @@ void LocationsBuilderX86::VisitBooleanNot(HBooleanNot* bool_not) { } void InstructionCodeGeneratorX86::VisitBooleanNot(HBooleanNot* bool_not) { - DCHECK_EQ(bool_not->InputAt(0)->GetType(), Primitive::kPrimBoolean); LocationSummary* locations = bool_not->GetLocations(); Location in = locations->InAt(0); Location out = locations->Out(); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index fb0f4ca06c..a3d3490357 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -2986,7 +2986,6 @@ void LocationsBuilderX86_64::VisitBooleanNot(HBooleanNot* bool_not) { } void InstructionCodeGeneratorX86_64::VisitBooleanNot(HBooleanNot* bool_not) { - DCHECK_EQ(bool_not->InputAt(0)->GetType(), Primitive::kPrimBoolean); LocationSummary* locations = bool_not->GetLocations(); DCHECK_EQ(locations->InAt(0).AsRegister<CpuRegister>().AsRegister(), locations->Out().AsRegister<CpuRegister>().AsRegister()); diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 7c3c2bf03d..906c8e8c76 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -369,26 +369,40 @@ void SSAChecker::VisitPhi(HPhi* phi) { } } -void SSAChecker::VisitIf(HIf* instruction) { - VisitInstruction(instruction); - HInstruction* input = instruction->InputAt(0); +void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) { + HInstruction* input = instruction->InputAt(input_index); if (input->IsIntConstant()) { - int value = input->AsIntConstant()->GetValue(); + int32_t value = input->AsIntConstant()->GetValue(); if (value != 0 && value != 1) { AddError(StringPrintf( - "If instruction %d has a non-Boolean constant input " - "whose value is: %d.", + "%s instruction %d has a non-Boolean constant input %d whose value is: %d.", + instruction->DebugName(), instruction->GetId(), + static_cast<int>(input_index), value)); } - } else if (instruction->InputAt(0)->GetType() != Primitive::kPrimBoolean) { + } else if (input->GetType() == Primitive::kPrimInt && input->IsPhi()) { + // TODO: We need a data-flow analysis which determines if the Phi is boolean. + } else if (input->GetType() != Primitive::kPrimBoolean) { AddError(StringPrintf( - "If instruction %d has a non-Boolean input type: %s.", + "%s instruction %d has a non-Boolean input %d whose type is: %s.", + instruction->DebugName(), instruction->GetId(), - Primitive::PrettyDescriptor(instruction->InputAt(0)->GetType()))); + static_cast<int>(input_index), + Primitive::PrettyDescriptor(input->GetType()))); } } +void SSAChecker::VisitIf(HIf* instruction) { + VisitInstruction(instruction); + HandleBooleanInput(instruction, 0); +} + +void SSAChecker::VisitBooleanNot(HBooleanNot* instruction) { + VisitInstruction(instruction); + HandleBooleanInput(instruction, 0); +} + void SSAChecker::VisitCondition(HCondition* op) { VisitInstruction(op); if (op->GetType() != Primitive::kPrimBoolean) { diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index 89fea0a07f..4568a5ef9d 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -107,8 +107,11 @@ class SSAChecker : public GraphChecker { void VisitBinaryOperation(HBinaryOperation* op) OVERRIDE; void VisitCondition(HCondition* op) OVERRIDE; void VisitIf(HIf* instruction) OVERRIDE; + void VisitBooleanNot(HBooleanNot* instruction) OVERRIDE; void VisitConstant(HConstant* instruction) OVERRIDE; + void HandleBooleanInput(HInstruction* instruction, size_t input_index); + private: DISALLOW_COPY_AND_ASSIGN(SSAChecker); }; diff --git a/test/474-checker-boolean-input/expected.txt b/test/474-checker-boolean-input/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/474-checker-boolean-input/expected.txt diff --git a/test/474-checker-boolean-input/info.txt b/test/474-checker-boolean-input/info.txt new file mode 100644 index 0000000000..8ec946bd19 --- /dev/null +++ b/test/474-checker-boolean-input/info.txt @@ -0,0 +1 @@ +Tests if zero/one constants and integer Phis are accepted as boolean values.
\ No newline at end of file diff --git a/test/474-checker-boolean-input/src/Main.java b/test/474-checker-boolean-input/src/Main.java new file mode 100644 index 0000000000..91e8d4f9df --- /dev/null +++ b/test/474-checker-boolean-input/src/Main.java @@ -0,0 +1,75 @@ +/* +* Copyright (C) 2015 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 { + + public static void assertBoolEquals(boolean expected, boolean result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + /* + * Test that zero/one constants are accepted as boolean inputs. + */ + + // CHECK-START: boolean Main.TestIntAsBoolean() inliner (before) + // CHECK-DAG: [[Invoke:z\d+]] InvokeStaticOrDirect + // CHECK-DAG: BooleanNot [ [[Invoke]] ] + + // CHECK-START: boolean Main.TestIntAsBoolean() inliner (after) + // CHECK-DAG: [[Const:i\d+]] IntConstant 1 + // CHECK-DAG: BooleanNot [ [[Const]] ] + + public static boolean InlineConst() { + return true; + } + + public static boolean TestIntAsBoolean() { + return InlineConst() != true ? true : false; + } + + /* + * Test that integer Phis are accepted as boolean inputs until we implement + * a suitable type analysis. + */ + + // CHECK-START: boolean Main.TestPhiAsBoolean(int) inliner (before) + // CHECK-DAG: [[Invoke:z\d+]] InvokeStaticOrDirect + // CHECK-DAG: BooleanNot [ [[Invoke]] ] + + // CHECK-START: boolean Main.TestPhiAsBoolean(int) inliner (after) + // CHECK-DAG: [[Phi:i\d+]] Phi + // CHECK-DAG: BooleanNot [ [[Phi]] ] + + public static boolean f1; + public static boolean f2; + + public static boolean InlinePhi(int x) { + return (x == 42) ? f1 : f2; + } + + public static boolean TestPhiAsBoolean(int x) { + return InlinePhi(x) != true ? true : false; + } + + public static void main(String[] args) { + f1 = true; + f2 = false; + assertBoolEquals(true, TestPhiAsBoolean(0)); + assertBoolEquals(false, TestPhiAsBoolean(42)); + } +} |