Create a typedef for HInstruction::GetInputs() return type.

And some other cleanup after
    https://android-review.googlesource.com/230742

Test: No new tests. ART test suite passed (tested on host).
Change-Id: I4743bf17544d0234c6ccb46dd0c1b9aae5c93e17
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index e9fcfe2..5f27e14 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -912,9 +912,9 @@
 
   static bool HasSameInputAtBackEdges(HPhi* phi) {
     DCHECK(phi->IsLoopHeaderPhi());
-    auto&& inputs = phi->GetInputs();
+    HConstInputsRef inputs = phi->GetInputs();
     // Start with input 1. Input 0 is from the incoming block.
-    HInstruction* input1 = inputs[1];
+    const HInstruction* input1 = inputs[1];
     DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
         *phi->GetBlock()->GetPredecessors()[1]));
     for (size_t i = 2; i < inputs.size(); ++i) {
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 12aa152..4520f9b 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -111,7 +111,7 @@
         << " " << locations->Out();
   }
 
-  auto&& inputs = instruction->GetInputs();
+  HConstInputsRef inputs = instruction->GetInputs();
   for (size_t i = 0; i < inputs.size(); ++i) {
     DCHECK(CheckType(inputs[i]->GetType(), locations->InAt(i)))
       << inputs[i]->GetType() << " " << locations->InAt(i);
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 2bd2403..c8cba20 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -362,7 +362,7 @@
                             instruction->GetId()));
     }
     size_t use_index = use.GetIndex();
-    auto&& user_inputs = user->GetInputs();
+    HConstInputsRef user_inputs = user->GetInputs();
     if ((use_index >= user_inputs.size()) || (user_inputs[use_index] != instruction)) {
       AddError(StringPrintf("User %s:%d of instruction %s:%d has a wrong "
                             "UseListNode index.",
@@ -490,7 +490,7 @@
   VisitInstruction(invoke);
 
   if (invoke->IsStaticWithExplicitClinitCheck()) {
-    HInstruction* last_input = invoke->GetInputs().back();
+    const HInstruction* last_input = invoke->GetInputs().back();
     if (last_input == nullptr) {
       AddError(StringPrintf("Static invoke %s:%d marked as having an explicit clinit check "
                             "has a null pointer as last input.",
@@ -664,17 +664,19 @@
   }
 }
 
-static bool IsSameSizeConstant(HInstruction* insn1, HInstruction* insn2) {
+static bool IsSameSizeConstant(const HInstruction* insn1, const HInstruction* insn2) {
   return insn1->IsConstant()
       && insn2->IsConstant()
       && Primitive::Is64BitType(insn1->GetType()) == Primitive::Is64BitType(insn2->GetType());
 }
 
-static bool IsConstantEquivalent(HInstruction* insn1, HInstruction* insn2, BitVector* visited) {
+static bool IsConstantEquivalent(const HInstruction* insn1,
+                                 const HInstruction* insn2,
+                                 BitVector* visited) {
   if (insn1->IsPhi() &&
       insn1->AsPhi()->IsVRegEquivalentOf(insn2)) {
-    auto&& insn1_inputs = insn1->GetInputs();
-    auto&& insn2_inputs = insn2->GetInputs();
+    HConstInputsRef insn1_inputs = insn1->GetInputs();
+    HConstInputsRef insn2_inputs = insn2->GetInputs();
     if (insn1_inputs.size() != insn2_inputs.size()) {
       return false;
     }
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 4af8d19..9d67373 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -511,7 +511,7 @@
 
   void PrintInstruction(HInstruction* instruction) {
     output_ << instruction->DebugName();
-    auto&& inputs = instruction->GetInputs();
+    HConstInputsRef inputs = instruction->GetInputs();
     if (!inputs.empty()) {
       StringList input_list;
       for (const HInstruction* input : inputs) {
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index 52426d7..129c2a9 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -341,7 +341,7 @@
                                                                          HInstruction* phi,
                                                                          size_t input_index) {
   // Match all phi inputs from input_index onwards exactly.
-  auto&& inputs = phi->GetInputs();
+  HInputsRef inputs = phi->GetInputs();
   DCHECK_LT(input_index, inputs.size());
   InductionInfo* a = LookupInfo(loop, inputs[input_index]);
   for (size_t i = input_index + 1; i < inputs.size(); i++) {
@@ -464,7 +464,7 @@
 HInductionVarAnalysis::InductionInfo* HInductionVarAnalysis::SolvePhi(HInstruction* phi,
                                                                       size_t input_index) {
   // Match all phi inputs from input_index onwards exactly.
-  auto&& inputs = phi->GetInputs();
+  HInputsRef inputs = phi->GetInputs();
   DCHECK_LT(input_index, inputs.size());
   auto ita = cycle_.find(inputs[input_index]);
   if (ita != cycle_.end()) {
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index c2c212b..d557f42 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -754,7 +754,7 @@
 }
 
 static void UpdateInputsUsers(HInstruction* instruction) {
-  auto&& inputs = instruction->GetInputs();
+  HInputsRef inputs = instruction->GetInputs();
   for (size_t i = 0; i < inputs.size(); ++i) {
     inputs[i]->AddUseAt(instruction, i);
   }
@@ -1312,8 +1312,8 @@
   DCHECK_EQ(GetKind(), other->GetKind());
   if (!InstructionDataEquals(other)) return false;
   if (GetType() != other->GetType()) return false;
-  auto&& inputs = GetInputs();
-  auto&& other_inputs = other->GetInputs();
+  HConstInputsRef inputs = GetInputs();
+  HConstInputsRef other_inputs = other->GetInputs();
   if (inputs.size() != other_inputs.size()) return false;
   for (size_t i = 0; i != inputs.size(); ++i) {
     if (inputs[i] != other_inputs[i]) return false;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 6b2c33e..d98dd06 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1415,6 +1415,21 @@
   typename HUseList<T>::iterator before_use_node_;
 };
 
+// Helper class that extracts the input instruction from HUserRecord<HInstruction*>.
+// This is used for HInstruction::GetInputs() to return a container wrapper providing
+// HInstruction* values even though the underlying container has HUserRecord<>s.
+struct HInputExtractor {
+  HInstruction* operator()(HUserRecord<HInstruction*>& record) const {
+    return record.GetInstruction();
+  }
+  const HInstruction* operator()(const HUserRecord<HInstruction*>& record) const {
+    return record.GetInstruction();
+  }
+};
+
+using HInputsRef = TransformArrayRef<HUserRecord<HInstruction*>, HInputExtractor>;
+using HConstInputsRef = TransformArrayRef<const HUserRecord<HInstruction*>, HInputExtractor>;
+
 /**
  * Side-effects representation.
  *
@@ -1804,20 +1819,12 @@
         const_cast<HInstruction*>(this)->GetInputRecords());
   }
 
-  auto GetInputs() {
-    return MakeTransformArrayRef(
-        GetInputRecords(),
-        [](HUserRecord<HInstruction*>& record) -> HInstruction* {
-            return record.GetInstruction();
-        });
+  HInputsRef GetInputs() {
+    return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
   }
 
-  auto GetInputs() const {
-    return MakeTransformArrayRef(
-        GetInputRecords(),
-        [](const HUserRecord<HInstruction*>& record) -> const HInstruction* {
-            return record.GetInstruction();
-        });
+  HConstInputsRef GetInputs() const {
+    return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
   }
 
   size_t InputCount() const { return GetInputRecords().size(); }
@@ -2408,7 +2415,7 @@
   bool IsDead() const { return !IsLive(); }
   bool IsLive() const { return GetPackedFlag<kFlagIsLive>(); }
 
-  bool IsVRegEquivalentOf(HInstruction* other) const {
+  bool IsVRegEquivalentOf(const HInstruction* other) const {
     return other != nullptr
         && other->IsPhi()
         && other->AsPhi()->GetBlock() == GetBlock()
diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc
index 93116f8..921f3df 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -211,7 +211,7 @@
     }
 
     // Ensure that we can load FP arguments from the constant area.
-    auto&& inputs = invoke->GetInputs();
+    HInputsRef inputs = invoke->GetInputs();
     for (size_t i = 0; i < inputs.size(); i++) {
       HConstant* input = inputs[i]->AsConstant();
       if (input != nullptr && Primitive::IsFloatingPointType(input->GetType())) {
diff --git a/compiler/optimizing/pretty_printer.h b/compiler/optimizing/pretty_printer.h
index f9bef68..5891350 100644
--- a/compiler/optimizing/pretty_printer.h
+++ b/compiler/optimizing/pretty_printer.h
@@ -39,7 +39,7 @@
   }
 
   void PrintPostInstruction(HInstruction* instruction) {
-    auto&& inputs = instruction->GetInputs();
+    HConstInputsRef inputs = instruction->GetInputs();
     if (!inputs.empty()) {
       PrintString("(");
       bool first = true;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 3dfd728..965d5ee 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -816,10 +816,10 @@
 void ReferenceTypePropagation::UpdatePhi(HPhi* instr) {
   DCHECK(instr->IsLive());
 
-  auto&& inputs = instr->GetInputs();
+  HInputsRef inputs = instr->GetInputs();
   size_t first_input_index_not_null = 0;
   while (first_input_index_not_null < inputs.size() &&
-      inputs[first_input_index_not_null]->IsNullConstant()) {
+         inputs[first_input_index_not_null]->IsNullConstant()) {
     first_input_index_not_null++;
   }
   if (first_input_index_not_null == inputs.size()) {
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index 4a6b835..9d99668 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -753,7 +753,7 @@
   if (defined_by != nullptr && !current->IsSplit()) {
     LocationSummary* locations = defined_by->GetLocations();
     if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
-      auto&& inputs = defined_by->GetInputs();
+      HInputsRef inputs = defined_by->GetInputs();
       for (size_t i = 0; i < inputs.size(); ++i) {
         // Take the last interval of the input. It is the location of that interval
         // that will be used at `defined_by`.
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index ed50c69..5a574d9 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -181,7 +181,7 @@
     return true;
   } else {
     DCHECK(common_type == Primitive::kPrimNot || Primitive::IsFloatingPointType(common_type));
-    auto&& inputs = phi->GetInputs();
+    HInputsRef inputs = phi->GetInputs();
     for (size_t i = 0; i < inputs.size(); ++i) {
       HInstruction* input = inputs[i];
       if (input->GetType() != common_type) {
@@ -617,7 +617,7 @@
       || (next->AsPhi()->GetRegNumber() != phi->GetRegNumber())
       || (next->GetType() != type)) {
     ArenaAllocator* allocator = graph_->GetArena();
-    auto&& inputs = phi->GetInputs();
+    HInputsRef inputs = phi->GetInputs();
     HPhi* new_phi =
         new (allocator) HPhi(allocator, phi->GetRegNumber(), inputs.size(), type);
     // Copy the inputs. Note that the graph may not be correctly typed
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 212d935..7af4302 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -177,7 +177,7 @@
 static void RecursivelyProcessInputs(HInstruction* current,
                                      HInstruction* actual_user,
                                      BitVector* live_in) {
-  auto&& inputs = current->GetInputs();
+  HInputsRef inputs = current->GetInputs();
   for (size_t i = 0; i < inputs.size(); ++i) {
     HInstruction* input = inputs[i];
     bool has_in_location = current->GetLocations()->InAt(i).IsValid();
@@ -431,7 +431,7 @@
         // If the instruction dies at the phi assignment, we can try having the
         // same register.
         if (end == user->GetBlock()->GetPredecessors()[input_index]->GetLifetimeEnd()) {
-          auto&& inputs = user->GetInputs();
+          HInputsRef inputs = user->GetInputs();
           for (size_t i = 0; i < inputs.size(); ++i) {
             if (i == input_index) {
               continue;
@@ -472,7 +472,7 @@
   if (defined_by_->IsPhi()) {
     // Try to use the same register as one of the inputs.
     const ArenaVector<HBasicBlock*>& predecessors = defined_by_->GetBlock()->GetPredecessors();
-    auto&& inputs = defined_by_->GetInputs();
+    HInputsRef inputs = defined_by_->GetInputs();
     for (size_t i = 0; i < inputs.size(); ++i) {
       size_t end = predecessors[i]->GetLifetimeEnd();
       LiveInterval* input_interval = inputs[i]->GetLiveInterval()->GetSiblingAt(end - 1);
diff --git a/compiler/utils/transform_array_ref.h b/compiler/utils/transform_array_ref.h
index 6297b88..a6da34f 100644
--- a/compiler/utils/transform_array_ref.h
+++ b/compiler/utils/transform_array_ref.h
@@ -70,6 +70,11 @@
   TransformArrayRef(const ArrayRef<OtherBT>& base, Function fn)
       : data_(base, fn) { }
 
+  template <typename OtherBT,
+            typename = typename std::enable_if<std::is_same<BaseType, const OtherBT>::value>::type>
+  TransformArrayRef(const TransformArrayRef<OtherBT, Function>& other)
+      : TransformArrayRef(other.base(), other.GetFunction()) { }
+
   // Assignment operators.
 
   TransformArrayRef& operator=(const TransformArrayRef& other) = default;
@@ -149,6 +154,9 @@
   }
 
   Data data_;
+
+  template <typename OtherBT, typename OtherFunction>
+  friend class TransformArrayRef;
 };
 
 template <typename BaseType, typename Function>
diff --git a/compiler/utils/transform_array_ref_test.cc b/compiler/utils/transform_array_ref_test.cc
index 2593fad..8d71fd7 100644
--- a/compiler/utils/transform_array_ref_test.cc
+++ b/compiler/utils/transform_array_ref_test.cc
@@ -160,6 +160,48 @@
     taref[i] = transform_input[i];
   }
   ASSERT_EQ(std::vector<ValueHolder>({ 24, 37, 11, 71 }), transformed);
+
+  const std::vector<ValueHolder>& cinput = input;
+
+  auto ctaref = MakeTransformArrayRef(cinput, ref);
+  static_assert(std::is_same<int, decltype(ctaref)::value_type>::value, "value_type");
+  static_assert(std::is_same<const int*, decltype(ctaref)::pointer>::value, "pointer");
+  static_assert(std::is_same<const int&, decltype(ctaref)::reference>::value, "reference");
+  static_assert(std::is_same<const int*, decltype(ctaref)::const_pointer>::value, "const_pointer");
+  static_assert(std::is_same<const int&, decltype(ctaref)::const_reference>::value,
+                "const_reference");
+
+  std::copy(ctaref.begin(), ctaref.end(), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
+  output.clear();
+
+  std::copy(ctaref.cbegin(), ctaref.cend(), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 0, 1, 0, 3, 1 }), output);
+  output.clear();
+
+  std::copy(ctaref.rbegin(), ctaref.rend(), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
+  output.clear();
+
+  std::copy(ctaref.crbegin(), ctaref.crend(), std::back_inserter(output));
+  ASSERT_EQ(std::vector<int>({ 1, 3, 0, 1, 0, 1 }), output);
+  output.clear();
+
+  ASSERT_EQ(cinput.size(), ctaref.size());
+  ASSERT_EQ(cinput.empty(), ctaref.empty());
+  ASSERT_EQ(cinput.front().value, ctaref.front());
+  ASSERT_EQ(cinput.back().value, ctaref.back());
+
+  for (size_t i = 0; i != cinput.size(); ++i) {
+    ASSERT_EQ(cinput[i].value, ctaref[i]);
+  }
+
+  // Test conversion adding const.
+  decltype(ctaref) ctaref2 = taref;
+  ASSERT_EQ(taref.size(), ctaref2.size());
+  for (size_t i = 0; i != taref.size(); ++i) {
+    ASSERT_EQ(taref[i], ctaref2[i]);
+  }
 }
 
 }  // namespace art
diff --git a/compiler/utils/transform_iterator.h b/compiler/utils/transform_iterator.h
index f0769d4..3bc9046 100644
--- a/compiler/utils/transform_iterator.h
+++ b/compiler/utils/transform_iterator.h
@@ -44,11 +44,7 @@
                     typename std::iterator_traits<BaseIterator>::iterator_category>::value,
                 "Transform iterator base must be an input iterator.");
 
-  using InputType =
-      typename std::conditional<
-          std::is_same<void, typename std::iterator_traits<BaseIterator>::reference>::value,
-          typename std::iterator_traits<BaseIterator>::value_type,
-          typename std::iterator_traits<BaseIterator>::reference>::type;
+  using InputType = typename std::iterator_traits<BaseIterator>::reference;
   using ResultType = typename std::result_of<Function(InputType)>::type;
 
  public:
diff --git a/compiler/utils/transform_iterator_test.cc b/compiler/utils/transform_iterator_test.cc
index dbb4779..57ff0a6 100644
--- a/compiler/utils/transform_iterator_test.cc
+++ b/compiler/utils/transform_iterator_test.cc
@@ -20,8 +20,6 @@
 #include <type_traits>
 #include <vector>
 
-#include <array>
-
 #include "gtest/gtest.h"
 
 #include "utils/transform_iterator.h"