Merge "Move the linear order to the HGraph."
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 73d7210..5abd204 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -350,8 +350,9 @@
 class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
  public:
   InitCodeMethodVisitor(OatWriter* writer, size_t offset)
-    : OatDexMethodVisitor(writer, offset) {
-    text_absolute_patch_locations_ = writer->GetAbsolutePatchLocationsFor(".text");
+    : OatDexMethodVisitor(writer, offset),
+      text_absolute_patch_locations_(writer->GetAbsolutePatchLocationsFor(".text")),
+      debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) {
     text_absolute_patch_locations_->reserve(
         writer_->compiler_driver_->GetNonRelativeLinkerPatchCount());
   }
@@ -379,20 +380,19 @@
       CHECK_NE(code_size, 0U);
       uint32_t thumb_offset = compiled_method->CodeDelta();
 
-      // Deduplicate code arrays.
+      // Deduplicate code arrays if we are not producing debuggable code.
       bool deduped = false;
-      auto lb = dedupe_map_.lower_bound(compiled_method);
-      if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(compiled_method, lb->first)) {
-        quick_code_offset = lb->second;
-        deduped = true;
+      if (debuggable_) {
+        quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
       } else {
-        offset_ = writer_->relative_patcher_->ReserveSpace(
-            offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
-        offset_ = compiled_method->AlignCode(offset_);
-        DCHECK_ALIGNED_PARAM(offset_,
-                             GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
-        quick_code_offset = offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
-        dedupe_map_.PutBefore(lb, compiled_method, quick_code_offset);
+        auto lb = dedupe_map_.lower_bound(compiled_method);
+        if (lb != dedupe_map_.end() && !dedupe_map_.key_comp()(compiled_method, lb->first)) {
+          quick_code_offset = lb->second;
+          deduped = true;
+        } else {
+          quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset);
+          dedupe_map_.PutBefore(lb, compiled_method, quick_code_offset);
+        }
       }
 
       MethodReference method_ref(dex_file_, it.GetMemberIndex());
@@ -532,12 +532,26 @@
     }
   };
 
+  uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method,
+                              const ClassDataItemIterator& it,
+                              uint32_t thumb_offset) {
+    offset_ = writer_->relative_patcher_->ReserveSpace(
+              offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
+    offset_ = compiled_method->AlignCode(offset_);
+    DCHECK_ALIGNED_PARAM(offset_,
+                         GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
+    return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
+  }
+
   // Deduplication is already done on a pointer basis by the compiler driver,
   // so we can simply compare the pointers to find out if things are duplicated.
   SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
 
   // Patch locations for the .text section.
-  std::vector<uintptr_t>* text_absolute_patch_locations_;
+  std::vector<uintptr_t>* const text_absolute_patch_locations_;
+
+  // Cache of compiler's --debuggable option.
+  const bool debuggable_;
 };
 
 template <typename DataAccess>
diff --git a/compiler/optimizing/boolean_simplifier.cc b/compiler/optimizing/boolean_simplifier.cc
index be432c5..06328f2 100644
--- a/compiler/optimizing/boolean_simplifier.cc
+++ b/compiler/optimizing/boolean_simplifier.cc
@@ -73,8 +73,8 @@
     }
   } else {
     // General case when 'cond' is another instruction of type boolean.
-    // Negate with 'cond == 0'.
-    return new (allocator) HEqual(cond, graph->GetIntConstant(0));
+    DCHECK_EQ(cond->GetType(), Primitive::Type::kPrimBoolean);
+    return new (allocator) HBooleanNot(cond);
   }
 }
 
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 332c99a..72b07cd 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2657,6 +2657,21 @@
   }
 }
 
+void LocationsBuilderARM::VisitBooleanNot(HBooleanNot* bool_not) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(bool_not, LocationSummary::kNoCall);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+}
+
+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);
+  __ eor(out.AsRegister<Register>(), in.AsRegister<Register>(), ShifterOperand(1));
+}
+
 void LocationsBuilderARM::VisitCompare(HCompare* compare) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index a5ddd6b..7dfb595 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2279,6 +2279,17 @@
   }
 }
 
+void LocationsBuilderARM64::VisitBooleanNot(HBooleanNot* instruction) {
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+}
+
+void InstructionCodeGeneratorARM64::VisitBooleanNot(HBooleanNot* instruction) {
+  DCHECK_EQ(instruction->InputAt(0)->GetType(), Primitive::kPrimBoolean);
+  __ Eor(OutputRegister(instruction), InputRegisterAt(instruction, 0), vixl::Operand(1));
+}
+
 void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 38f9ef8..79c00ba 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -2915,6 +2915,22 @@
   }
 }
 
+void LocationsBuilderX86::VisitBooleanNot(HBooleanNot* bool_not) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(bool_not, LocationSummary::kNoCall);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+}
+
+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();
+  DCHECK(in.Equals(out));
+  __ xorl(out.AsRegister<Register>(), Immediate(1));
+}
+
 void LocationsBuilderX86::VisitCompare(HCompare* compare) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(compare, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 7a928d4..0dd4423 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -2974,6 +2974,22 @@
   }
 }
 
+void LocationsBuilderX86_64::VisitBooleanNot(HBooleanNot* bool_not) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(bool_not, LocationSummary::kNoCall);
+  locations->SetInAt(0, Location::RequiresRegister());
+  locations->SetOut(Location::SameAsFirstInput());
+}
+
+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());
+  Location out = locations->Out();
+  __ xorl(out.AsRegister<CpuRegister>(), Immediate(1));
+}
+
 void LocationsBuilderX86_64::VisitPhi(HPhi* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index b36e574..de876be 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -486,17 +486,11 @@
 
   void SetOut(Location location, Location::OutputOverlap overlaps = Location::kOutputOverlap) {
     DCHECK(output_.IsInvalid());
-    if (kIsDebugBuild && location.IsUnallocated()) {
-      if ((location.GetPolicy() == Location::kSameAsFirstInput) && InAt(0).IsUnallocated()) {
-        DCHECK_NE(InAt(0).GetPolicy(), Location::kAny);
-      }
-    }
     output_overlaps_ = overlaps;
     output_ = location;
   }
 
   void UpdateOut(Location location) {
-    DCHECK(!location.IsUnallocated());
     // There are two reasons for updating an output:
     // 1) Parameters, where we only know the exact stack slot after
     //    doing full register allocation.
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index b406cbb..539e0b5 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -685,6 +685,7 @@
   M(ArrayGet, Instruction)                                              \
   M(ArrayLength, Instruction)                                           \
   M(ArraySet, Instruction)                                              \
+  M(BooleanNot, UnaryOperation)                                         \
   M(BoundsCheck, Instruction)                                           \
   M(BoundType, Instruction)                                             \
   M(CheckCast, Instruction)                                             \
@@ -2652,6 +2653,33 @@
   DISALLOW_COPY_AND_ASSIGN(HNot);
 };
 
+class HBooleanNot : public HUnaryOperation {
+ public:
+  explicit HBooleanNot(HInstruction* input)
+      : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
+
+  bool CanBeMoved() const OVERRIDE { return true; }
+  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+    UNUSED(other);
+    return true;
+  }
+
+  int32_t Evaluate(int32_t x) const OVERRIDE {
+    DCHECK(IsUint<1>(x));
+    return !x;
+  }
+
+  int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
+    LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
+    UNREACHABLE();
+  }
+
+  DECLARE_INSTRUCTION(BooleanNot);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
+};
+
 class HTypeConversion : public HExpression<1> {
  public:
   // Instantiate a type conversion of `input` to `result_type`.
diff --git a/test/468-bool-simplifier-regression/expected.txt b/test/468-checker-bool-simplifier-regression/expected.txt
similarity index 100%
rename from test/468-bool-simplifier-regression/expected.txt
rename to test/468-checker-bool-simplifier-regression/expected.txt
diff --git a/test/468-bool-simplifier-regression/info.txt b/test/468-checker-bool-simplifier-regression/info.txt
similarity index 100%
rename from test/468-bool-simplifier-regression/info.txt
rename to test/468-checker-bool-simplifier-regression/info.txt
diff --git a/test/468-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
similarity index 100%
rename from test/468-bool-simplifier-regression/smali/TestCase.smali
rename to test/468-checker-bool-simplifier-regression/smali/TestCase.smali
diff --git a/test/468-bool-simplifier-regression/src/Main.java b/test/468-checker-bool-simplifier-regression/src/Main.java
similarity index 64%
rename from test/468-bool-simplifier-regression/src/Main.java
rename to test/468-checker-bool-simplifier-regression/src/Main.java
index 1dd27c9..65f20b3 100644
--- a/test/468-bool-simplifier-regression/src/Main.java
+++ b/test/468-checker-bool-simplifier-regression/src/Main.java
@@ -17,6 +17,20 @@
 import java.lang.reflect.*;
 
 public class Main {
+  
+  // CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
+  // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
+  // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
+  // CHECK-DAG:     [[Value:z\d+]]    StaticFieldGet
+  // CHECK-DAG:                       If [ [[Value]] ]
+  // CHECK-DAG:     [[Phi:i\d+]]      Phi [ [[Const1]] [[Const0]] ]
+  // CHECK-DAG:                       Return [ [[Phi]] ]
+
+  // CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
+  // CHECK-DAG:     [[Value:z\d+]]    StaticFieldGet
+  // CHECK-DAG:     [[Not:z\d+]]      BooleanNot [ [[Value]] ]
+  // CHECK-DAG:                       Return [ [[Not]] ]
+  
   public static boolean runTest(boolean input) throws Exception {
     Class<?> c = Class.forName("TestCase");
     Method m = c.getMethod("testCase");