ART: Refactor SsaBuilder for more precise typing info

This reverts commit 68289a531484d26214e09f1eadd9833531a3bc3c.

Now uses Primitive::Is64BitType instead of Primitive::ComponentSize
because it was incorrectly optimized by GCC.

Bug: 26208284
Bug: 24252151
Bug: 24252100
Bug: 22538329
Bug: 25786318

Change-Id: Ib39f3da2b92bc5be5d76f4240a77567d82c6bebe
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index a9a2493..fc12224 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -198,10 +198,38 @@
   }
 }
 
-void HGraph::TransformToSsa() {
-  DCHECK(!reverse_post_order_.empty());
-  SsaBuilder ssa_builder(this);
-  ssa_builder.BuildSsa();
+BuildSsaResult HGraph::TryBuildingSsa(StackHandleScopeCollection* handles) {
+  BuildDominatorTree();
+
+  // The SSA builder requires loops to all be natural. Specifically, the dead phi
+  // elimination phase checks the consistency of the graph when doing a post-order
+  // visit for eliminating dead phis: a dead phi can only have loop header phi
+  // users remaining when being visited.
+  BuildSsaResult result = AnalyzeNaturalLoops();
+  if (result != kBuildSsaSuccess) {
+    return result;
+  }
+
+  // Precompute per-block try membership before entering the SSA builder,
+  // which needs the information to build catch block phis from values of
+  // locals at throwing instructions inside try blocks.
+  ComputeTryBlockInformation();
+
+  // Create the inexact Object reference type and store it in the HGraph.
+  ScopedObjectAccess soa(Thread::Current());
+  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  inexact_object_rti_ = ReferenceTypeInfo::Create(
+      handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
+      /* is_exact */ false);
+
+  // Tranforms graph to SSA form.
+  result = SsaBuilder(this, handles).BuildSsa();
+  if (result != kBuildSsaSuccess) {
+    return result;
+  }
+
+  in_ssa_form_ = true;
+  return kBuildSsaSuccess;
 }
 
 HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
@@ -410,7 +438,7 @@
   }
 }
 
-bool HGraph::AnalyzeNaturalLoops() const {
+BuildSsaResult HGraph::AnalyzeNaturalLoops() const {
   // Order does not matter.
   for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
     HBasicBlock* block = it.Current();
@@ -418,16 +446,16 @@
       if (block->IsCatchBlock()) {
         // TODO: Dealing with exceptional back edges could be tricky because
         //       they only approximate the real control flow. Bail out for now.
-        return false;
+        return kBuildSsaFailThrowCatchLoop;
       }
       HLoopInformation* info = block->GetLoopInformation();
       if (!info->Populate()) {
         // Abort if the loop is non natural. We currently bailout in such cases.
-        return false;
+        return kBuildSsaFailNonNaturalLoop;
       }
     }
   }
-  return true;
+  return kBuildSsaSuccess;
 }
 
 void HGraph::InsertConstant(HConstant* constant) {
@@ -446,8 +474,13 @@
   // id and/or any invariants the graph is assuming when adding new instructions.
   if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
     cached_null_constant_ = new (arena_) HNullConstant(dex_pc);
+    cached_null_constant_->SetReferenceTypeInfo(inexact_object_rti_);
     InsertConstant(cached_null_constant_);
   }
+  if (kIsDebugBuild) {
+    ScopedObjectAccess soa(Thread::Current());
+    DCHECK(cached_null_constant_->GetReferenceTypeInfo().IsValid());
+  }
   return cached_null_constant_;
 }