ART: DCHECK still too strong for String NewInstance

Even though the presence of a irreducible loop phi is the reason why
String.<init> may see its first input not being the NewInstance, it
may see a different phi from the same cycle. We have to relax the
corresponding DCHECK.

Bug: 26676472
Change-Id: Iba6fffa74833c57aad8aa07dc382ff6b93838de1
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index c8244aa..165d09d 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -934,7 +934,7 @@
     if (arg_this->IsNewInstance()) {
       uninitialized_strings_.push_back(arg_this->AsNewInstance());
     } else {
-      DCHECK(arg_this->IsIrreducibleLoopHeaderPhi());
+      DCHECK(arg_this->IsPhi());
       // NewInstance is not the direct input of the StringFactory call. It might
       // be redundant but optimizing this case is not worth the effort.
     }
diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali
index 823ed1e..54312a4 100644
--- a/test/563-checker-fakestring/smali/TestCase.smali
+++ b/test/563-checker-fakestring/smali/TestCase.smali
@@ -128,11 +128,14 @@
 # Test that the compiler does not assume that the first argument of String.<init>
 # is a NewInstance by inserting an irreducible loop between them (b/26676472).
 
-## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance(byte[], boolean) register (after)
+# We verify the type of the input instruction (Phi) in debuggable mode, because
+# it is eliminated by later stages of SsaBuilder otherwise.
+
+## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance1(byte[], boolean) register (after)
 ## CHECK-DAG:                   InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}}
 ## CHECK-DAG:     <<Phi>>       Phi
 
-.method public static thisNotNewInstance([BZ)Ljava/lang/String;
+.method public static thisNotNewInstance1([BZ)Ljava/lang/String;
    .registers 5
 
    new-instance v0, Ljava/lang/String;
@@ -152,3 +155,28 @@
    return-object v0
 
 .end method
+
+## CHECK-START-DEBUGGABLE: java.lang.String TestCase.thisNotNewInstance2(byte[], boolean) register (after)
+## CHECK-DAG:                   InvokeStaticOrDirect env:[[<<Phi:l\d+>>,{{.*]]}}
+## CHECK-DAG:     <<Phi>>       Phi
+
+.method public static thisNotNewInstance2([BZ)Ljava/lang/String;
+   .registers 5
+
+   new-instance v0, Ljava/lang/String;
+
+   # Irreducible loop
+   if-eqz p1, :loop_entry
+   :loop_header
+   if-eqz p1, :string_init
+   :loop_entry
+   const v1, 0x1
+   xor-int p1, p1, v1
+   goto :loop_header
+
+   :string_init
+   const-string v1, "UTF8"
+   invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V
+   return-object v0
+
+.end method
diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java
index 5489a0d..1ac8a5b 100644
--- a/test/563-checker-fakestring/src/Main.java
+++ b/test/563-checker-fakestring/src/Main.java
@@ -65,7 +65,14 @@
     }
 
     {
-      Method m = c.getMethod("thisNotNewInstance", byte[].class, boolean.class);
+      Method m = c.getMethod("thisNotNewInstance1", byte[].class, boolean.class);
+      String result = (String) m.invoke(null, new Object[] { testData, true });
+      assertEqual(testString, result);
+      result = (String) m.invoke(null, new Object[] { testData, false });
+      assertEqual(testString, result);
+    }
+    {
+      Method m = c.getMethod("thisNotNewInstance2", byte[].class, boolean.class);
       String result = (String) m.invoke(null, new Object[] { testData, true });
       assertEqual(testString, result);
       result = (String) m.invoke(null, new Object[] { testData, false });