Merge "Implement InexpensiveConstantInt(., opcode) for ARM."
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index e8b363b..523d143 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -44,6 +44,9 @@
   core_pic_infix :=
   core_dex2oat_dependency := $(DEX2OAT_DEPENDENCY)
 
+  ifeq ($(1),default)
+    core_compile_options += --compiler-backend=Quick
+  endif
   ifeq ($(1),optimizing)
     core_compile_options += --compiler-backend=Optimizing
     # With the optimizing compiler, we want to rerun dex2oat whenever there is
@@ -137,6 +140,9 @@
   core_pic_infix :=
   core_dex2oat_dependency := $(DEX2OAT_DEPENDENCY)
 
+  ifeq ($(1),default)
+    core_compile_options += --compiler-backend=Quick
+  endif
   ifeq ($(1),optimizing)
     ifeq ($($(3)TARGET_ARCH),arm64)
       # TODO: Enable image generation on arm64 once the backend
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 23c3b39..eb6181c 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -1108,6 +1108,11 @@
       break;
     }
 
+    case Instruction::FLOAT_TO_INT: {
+      Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt);
+      break;
+    }
+
     case Instruction::INT_TO_BYTE: {
       Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte);
       break;
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 4c0d3ea..7c8f6a2 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -35,6 +35,9 @@
 // Binary encoding of 2^31 for type double.
 static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000);
 
+// Maximum value for a primitive integer.
+static int32_t constexpr kPrimIntMax = 0x7fffffff;
+
 class Assembler;
 class CodeGenerator;
 class DexCompilationUnit;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 5b2be2e..448a5a0 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1406,6 +1406,12 @@
           break;
 
         case Primitive::kPrimFloat:
+          // Processing a Dex `float-to-int' instruction.
+          locations->SetInAt(0, Location::RequiresFpuRegister());
+          locations->SetOut(Location::RequiresRegister());
+          locations->AddTemp(Location::RequiresFpuRegister());
+          break;
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
@@ -1580,7 +1586,15 @@
           }
           break;
 
-        case Primitive::kPrimFloat:
+        case Primitive::kPrimFloat: {
+          // Processing a Dex `float-to-int' instruction.
+          SRegister temp = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>();
+          __ vmovs(temp, in.AsFpuRegister<SRegister>());
+          __ vcvtis(temp, temp);
+          __ vmovrs(out.AsRegister<Register>(), temp);
+          break;
+        }
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index fd794f9..6f83d9f 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1373,6 +1373,12 @@
           break;
 
         case Primitive::kPrimFloat:
+          // Processing a Dex `float-to-int' instruction.
+          locations->SetInAt(0, Location::RequiresFpuRegister());
+          locations->SetOut(Location::RequiresRegister());
+          locations->AddTemp(Location::RequiresFpuRegister());
+          break;
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
@@ -1559,7 +1565,31 @@
           }
           break;
 
-        case Primitive::kPrimFloat:
+        case Primitive::kPrimFloat: {
+          // Processing a Dex `float-to-int' instruction.
+          XmmRegister input = in.AsFpuRegister<XmmRegister>();
+          Register output = out.AsRegister<Register>();
+          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+          Label done, nan;
+
+          __ movl(output, Immediate(kPrimIntMax));
+          // temp = int-to-float(output)
+          __ cvtsi2ss(temp, output);
+          // if input >= temp goto done
+          __ comiss(input, temp);
+          __ j(kAboveEqual, &done);
+          // if input == NaN goto nan
+          __ j(kUnordered, &nan);
+          // output = float-to-int-truncate(input)
+          __ cvttss2si(output, input);
+          __ jmp(&done);
+          __ Bind(&nan);
+          //  output = 0
+          __ xorl(output, output);
+          __ Bind(&done);
+          break;
+        }
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 4d70efc..47fd304 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1363,6 +1363,12 @@
           break;
 
         case Primitive::kPrimFloat:
+          // Processing a Dex `float-to-int' instruction.
+          locations->SetInAt(0, Location::RequiresFpuRegister());
+          locations->SetOut(Location::RequiresRegister());
+          locations->AddTemp(Location::RequiresFpuRegister());
+          break;
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
@@ -1550,7 +1556,31 @@
           }
           break;
 
-        case Primitive::kPrimFloat:
+        case Primitive::kPrimFloat: {
+          // Processing a Dex `float-to-int' instruction.
+          XmmRegister input = in.AsFpuRegister<XmmRegister>();
+          CpuRegister output = out.AsRegister<CpuRegister>();
+          XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+          Label done, nan;
+
+          __ movl(output, Immediate(kPrimIntMax));
+          // temp = int-to-float(output)
+          __ cvtsi2ss(temp, output);
+          // if input >= temp goto done
+          __ comiss(input, temp);
+          __ j(kAboveEqual, &done);
+          // if input == NaN goto nan
+          __ j(kUnordered, &nan);
+          // output = float-to-int-truncate(input)
+          __ cvttss2si(output, input);
+          __ jmp(&done);
+          __ Bind(&nan);
+          //  output = 0
+          __ xorl(output, output);
+          __ Bind(&done);
+          break;
+        }
+
         case Primitive::kPrimDouble:
           LOG(FATAL) << "Type conversion from " << input_type
                      << " to " << result_type << " not yet implemented";
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 7584f1b..ba4dccf 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -30,6 +30,36 @@
   VisitBlockForBackEdges(entry_block_, visited, &visiting);
 }
 
+static void RemoveAsUser(HInstruction* instruction) {
+  for (size_t i = 0; i < instruction->InputCount(); i++) {
+    instruction->InputAt(i)->RemoveUser(instruction, i);
+  }
+
+  HEnvironment* environment = instruction->GetEnvironment();
+  if (environment != nullptr) {
+    for (size_t i = 0, e = environment->Size(); i < e; ++i) {
+      HInstruction* vreg = environment->GetInstructionAt(i);
+      if (vreg != nullptr) {
+        vreg->RemoveEnvironmentUser(environment, i);
+      }
+    }
+  }
+}
+
+void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const {
+  for (size_t i = 0; i < blocks_.Size(); ++i) {
+    if (!visited.IsBitSet(i)) {
+      HBasicBlock* block = blocks_.Get(i);
+      for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
+        RemoveAsUser(it.Current());
+      }
+      for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+        RemoveAsUser(it.Current());
+      }
+    }
+  }
+}
+
 void HGraph::RemoveDeadBlocks(const ArenaBitVector& visited) const {
   for (size_t i = 0; i < blocks_.Size(); ++i) {
     if (!visited.IsBitSet(i)) {
@@ -72,16 +102,21 @@
   // (1) Find the back edges in the graph doing a DFS traversal.
   FindBackEdges(&visited);
 
-  // (2) Remove blocks not visited during the initial DFS.
-  //     Step (3) requires dead blocks to be removed from the
+  // (2) Remove instructions and phis from blocks not visited during
+  //     the initial DFS as users from other instructions, so that
+  //     users can be safely removed before uses later.
+  RemoveInstructionsAsUsersFromDeadBlocks(visited);
+
+  // (3) Remove blocks not visited during the initial DFS.
+  //     Step (4) requires dead blocks to be removed from the
   //     predecessors list of live blocks.
   RemoveDeadBlocks(visited);
 
-  // (3) Simplify the CFG now, so that we don't need to recompute
+  // (4) Simplify the CFG now, so that we don't need to recompute
   //     dominators and the reverse post order.
   SimplifyCFG();
 
-  // (4) Compute the immediate dominator of each block. We visit
+  // (5) Compute the immediate dominator of each block. We visit
   //     the successors of a block only when all its forward branches
   //     have been processed.
   GrowableArray<size_t> visits(arena_, blocks_.Size());
@@ -391,19 +426,7 @@
   instruction->SetBlock(nullptr);
   instruction_list->RemoveInstruction(instruction);
 
-  for (size_t i = 0; i < instruction->InputCount(); i++) {
-    instruction->InputAt(i)->RemoveUser(instruction, i);
-  }
-
-  HEnvironment* environment = instruction->GetEnvironment();
-  if (environment != nullptr) {
-    for (size_t i = 0, e = environment->Size(); i < e; ++i) {
-      HInstruction* vreg = environment->GetInstructionAt(i);
-      if (vreg != nullptr) {
-        vreg->RemoveEnvironmentUser(environment, i);
-      }
-    }
-  }
+  RemoveAsUser(instruction);
 }
 
 void HBasicBlock::RemoveInstruction(HInstruction* instruction) {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 4706b3b..3908a61 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -173,6 +173,7 @@
   void VisitBlockForBackEdges(HBasicBlock* block,
                               ArenaBitVector* visited,
                               ArenaBitVector* visiting);
+  void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
   void RemoveDeadBlocks(const ArenaBitVector& visited) const;
 
   ArenaAllocator* const arena_;
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index c434db3..e7dbe24 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -91,6 +91,9 @@
     // Generate, compile and check long-to-double Dex instructions.
     longToDouble();
 
+    // Generate, compile and check float-to-int Dex instructions.
+    floatToInt();
+
     // Generate, compile and check int-to-byte Dex instructions.
     shortToByte();
     intToByte();
@@ -313,6 +316,32 @@
     assertDoubleEquals(-9223372036854775808D, $opt$LongToDouble(-9223372036854775808L));  // -(2^63)
   }
 
+  private static void floatToInt() {
+    assertIntEquals(1, $opt$FloatToInt(1F));
+    assertIntEquals(0, $opt$FloatToInt(0F));
+    assertIntEquals(0, $opt$FloatToInt(-0F));
+    assertIntEquals(-1, $opt$FloatToInt(-1F));
+    assertIntEquals(51, $opt$FloatToInt(51F));
+    assertIntEquals(-51, $opt$FloatToInt(-51F));
+    assertIntEquals(0, $opt$FloatToInt(0.5F));
+    assertIntEquals(0, $opt$FloatToInt(0.4999999F));
+    assertIntEquals(0, $opt$FloatToInt(-0.4999999F));
+    assertIntEquals(0, $opt$FloatToInt(-0.5F));
+    assertIntEquals(42, $opt$FloatToInt(42.199F));
+    assertIntEquals(-42, $opt$FloatToInt(-42.199F));
+    assertIntEquals(2147483647, $opt$FloatToInt(2147483647F));  // 2^31 - 1
+    assertIntEquals(-2147483648, $opt$FloatToInt(-2147483647F));  // -(2^31 - 1)
+    assertIntEquals(-2147483648, $opt$FloatToInt(-2147483648F));  // -(2^31)
+    assertIntEquals(2147483647, $opt$FloatToInt(2147483648F));  // (2^31)
+    assertIntEquals(-2147483648, $opt$FloatToInt(-2147483649F));  // -(2^31 + 1)
+    assertIntEquals(2147483647, $opt$FloatToInt(9223372036854775807F));  // 2^63 - 1
+    assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775807F));  // -(2^63 - 1)
+    assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775808F));  // -(2^63)
+    assertIntEquals(0, $opt$FloatToInt(Float.NaN));
+    assertIntEquals(2147483647, $opt$FloatToInt(Float.POSITIVE_INFINITY));
+    assertIntEquals(-2147483648, $opt$FloatToInt(Float.NEGATIVE_INFINITY));
+  }
+
   private static void shortToByte() {
     assertByteEquals((byte)1, $opt$ShortToByte((short)1));
     assertByteEquals((byte)0, $opt$ShortToByte((short)0));
@@ -468,6 +497,9 @@
   // This method produces a long-to-double Dex instruction.
   static double $opt$LongToDouble(long a){ return (double)a; }
 
+  // This method produces a float-to-int Dex instruction.
+  static int $opt$FloatToInt(float a){ return (int)a; }
+
   // These methods produce int-to-byte Dex instructions.
   static byte $opt$ShortToByte(short a){ return (byte)a; }
   static byte $opt$IntToByte(int a){ return (byte)a; }
diff --git a/test/435-try-finally-without-catch/expected.txt b/test/435-try-finally-without-catch/expected.txt
new file mode 100644
index 0000000..8a67802
--- /dev/null
+++ b/test/435-try-finally-without-catch/expected.txt
@@ -0,0 +1,3 @@
+In finally
+In finally
+In finally
diff --git a/test/435-try-finally-without-catch/info.txt b/test/435-try-finally-without-catch/info.txt
new file mode 100644
index 0000000..46217c5
--- /dev/null
+++ b/test/435-try-finally-without-catch/info.txt
@@ -0,0 +1,26 @@
+Exercise a method containing a `try' statement with several
+instructions with a `finally' clause but without any `catch' block,
+enclosed in a loop.
+
+When dx processes an integer division (or modulo) enclosing a `try'
+block and whose result is assigned to a local value, it is smart
+enough not to emit a `div-int' (or `rem-int') instruction when the
+divisor is non-null, as it wouldn't be used.  However, dx is not
+that clever regarding exception handling: if the divisor is known to
+be non-null at compile-time (as is the case in this test), it will
+still emit a block with the exception catching and rethrowing
+mechanism, even if it is not used.
+
+This used to be a problem for a `try' block followed by a `finally'
+clause but with no `catch' block: in that case, the generated Dex code
+item would list zero catch block for this method (see
+art::CodeItem::tries_size_) and the optimizing compiler would have no
+clue that it contains a `try' statement, which it cannot optimize
+(yet).  With no hint that this method might contain one (or several)
+special block(s) related to `catch'-less `try' statement(s), the
+optimizing compiler considered this (these) as dead block(s) and
+improperly tried to remove its (their) instructions, sometimes
+removing instructions used by others instructions, thus triggering
+assertions.  The optimizing compiler was thus adjusted to remove these
+instructions in a proper fashion, by removing them as users first, and
+then by suppressing them for good.
diff --git a/test/435-try-finally-without-catch/src/Main.java b/test/435-try-finally-without-catch/src/Main.java
new file mode 100644
index 0000000..3c29ce8
--- /dev/null
+++ b/test/435-try-finally-without-catch/src/Main.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 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 main(String[] args){
+    foo();
+  }
+
+  // Reduced test case inspired by constantPropagationTest() from
+  // test/083-compiler-regressions.
+  static void foo() {
+    int a = 0;
+    int b = 1;
+
+    for (int i = 0; i < 3; i++) {
+      try {
+        a = 1;
+        // Would throw an ArithmeticException if b were null (hence
+        // the enclosing `try' statement).
+        int c = a % b;
+      }
+      finally {
+        System.out.println("In finally");
+      }
+    }
+  }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 3c959fb..b85685b 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -472,6 +472,7 @@
     else
       ifeq ($(4),default)
         test_groups += ART_RUN_TEST_$$(uc_host_or_target)_DEFAULT_RULES
+        run_test_options += --quick
       else
         $$(error found $(4) expected $(COMPILER_TYPES))
       endif
diff --git a/test/run-test b/test/run-test
index 6b8f007..2abc1fa 100755
--- a/test/run-test
+++ b/test/run-test
@@ -194,6 +194,9 @@
         run_args="${run_args} -Xcompiler-option --compiler-backend=Optimizing"
         image_suffix="-optimizing"
         shift
+    elif [ "x$1" = "x--quick" ]; then
+        run_args="${run_args} -Xcompiler-option --compiler-backend=Quick"
+        shift
     elif [ "x$1" = "x--no-verify" ]; then
         run_args="${run_args} --no-verify"
         shift
@@ -421,6 +424,7 @@
         echo "    --build-only          Build test files only (off by default)."
         echo "    --interpreter         Enable interpreter only mode (off by default)."
         echo "    --optimizing          Enable optimizing compiler (off by default)."
+        echo "    --quick               Use Quick compiler (default)."
         echo "    --no-verify           Turn off verification (on by default)."
         echo "    --no-optimize         Turn off optimization (on by default)."
         echo "    --no-precise          Turn off precise GC (on by default)."