diff options
| -rw-r--r-- | compiler/optimizing/nodes.cc | 9 | ||||
| -rw-r--r-- | test/563-checker-fakestring/smali/TestCase.smali | 32 | ||||
| -rw-r--r-- | test/563-checker-fakestring/src/Main.java | 8 |
3 files changed, 48 insertions, 1 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 8f822cce5a..79a7e2c858 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -1301,6 +1301,15 @@ void HInstruction::ReplaceUsesDominatedBy(HInstruction* dominator, HInstruction* ++it; if (dominator->StrictlyDominates(user)) { user->ReplaceInput(replacement, index); + } else if (user->IsPhi() && !user->AsPhi()->IsCatchPhi()) { + // If the input flows from a block dominated by `dominator`, we can replace it. + // We do not perform this for catch phis as we don't have control flow support + // for their inputs. + const ArenaVector<HBasicBlock*>& predecessors = user->GetBlock()->GetPredecessors(); + HBasicBlock* predecessor = predecessors[index]; + if (dominator->GetBlock()->Dominates(predecessor)) { + user->ReplaceInput(replacement, index); + } } } } diff --git a/test/563-checker-fakestring/smali/TestCase.smali b/test/563-checker-fakestring/smali/TestCase.smali index 9d10bd77dd..0fe39ee229 100644 --- a/test/563-checker-fakestring/smali/TestCase.smali +++ b/test/563-checker-fakestring/smali/TestCase.smali @@ -305,3 +305,35 @@ return-object v0 .end method + +## CHECK-START: java.lang.String TestCase.loopAndStringInitAndPhi(byte[], boolean) register (after) +## CHECK: NewInstance +## CHECK-NOT: NewInstance +## CHECK-DAG: <<Invoke1:l\d+>> InvokeStaticOrDirect method_name:java.lang.String.<init> +## CHECK-DAG: <<Invoke2:l\d+>> InvokeStaticOrDirect method_name:java.lang.String.<init> +## CHECK-DAG: <<Phi:l\d+>> Phi [<<Invoke2>>,<<Invoke1>>] +## CHECK-DAG: Return [<<Phi>>] +.method public static loopAndStringInitAndPhi([BZ)Ljava/lang/String; + .registers 4 + + if-nez p1, :allocate_other + new-instance v0, Ljava/lang/String; + + # Loop + :loop_header + if-eqz p1, :loop_exit + goto :loop_header + + :loop_exit + const-string v1, "UTF8" + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + goto : exit + + :allocate_other + const-string v1, "UTF8" + new-instance v0, Ljava/lang/String; + invoke-direct {v0, p0, v1}, Ljava/lang/String;-><init>([BLjava/lang/String;)V + :exit + return-object v0 + +.end method diff --git a/test/563-checker-fakestring/src/Main.java b/test/563-checker-fakestring/src/Main.java index 3639d59878..df9e9dc074 100644 --- a/test/563-checker-fakestring/src/Main.java +++ b/test/563-checker-fakestring/src/Main.java @@ -113,7 +113,6 @@ public class Main { result = (String) m.invoke(null, new Object[] { testData, false }); assertEqual(testString, result); } - { Method m = c.getMethod( "deoptimizeNewInstanceAfterLoop", int[].class, byte[].class, int.class); @@ -127,6 +126,13 @@ public class Main { } } } + { + Method m = c.getMethod("loopAndStringInitAndPhi", 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); + } } public static boolean doThrow = false; |