[optimizing] Add basic PackedSwitch support

Add HPackedSwitch, and generate it from the builder.  Code generators
convert this to a series of compare/branch tests.  Better implementation
in the code generators as a real jump table will follow as separate CLs.

Change-Id: If14736fa4d62809b6ae95280148c55682e856911
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index d431acf..4cf4596 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -4946,6 +4946,33 @@
   // Will be generated at use site.
 }
 
+// Simple implementation of packed switch - generate cascaded compare/jumps.
+void LocationsBuilderARM::VisitPackedSwitch(HPackedSwitch* switch_instr) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(switch_instr, LocationSummary::kNoCall);
+  locations->SetInAt(0, Location::RequiresRegister());
+}
+
+void InstructionCodeGeneratorARM::VisitPackedSwitch(HPackedSwitch* switch_instr) {
+  int32_t lower_bound = switch_instr->GetStartValue();
+  int32_t num_entries = switch_instr->GetNumEntries();
+  LocationSummary* locations = switch_instr->GetLocations();
+  Register value_reg = locations->InAt(0).AsRegister<Register>();
+  HBasicBlock* default_block = switch_instr->GetDefaultBlock();
+
+  // Create a series of compare/jumps.
+  const ArenaVector<HBasicBlock*>& successors = switch_instr->GetBlock()->GetSuccessors();
+  for (int32_t i = 0; i < num_entries; i++) {
+    GenerateCompareWithImmediate(value_reg, lower_bound + i);
+    __ b(codegen_->GetLabelOf(successors.at(i)), EQ);
+  }
+
+  // And the default for any other value.
+  if (!codegen_->GoesToNextBlock(switch_instr->GetBlock(), default_block)) {
+    __ b(codegen_->GetLabelOf(default_block));
+  }
+}
+
 void CodeGeneratorARM::MoveFromReturnRegister(Location trg, Primitive::Type type) {
   if (!trg.IsValid()) {
     DCHECK(type == Primitive::kPrimVoid);