diff options
| author | 2015-09-28 13:49:59 +0100 | |
|---|---|---|
| committer | 2015-11-04 18:13:45 +0000 | |
| commit | 1749e2cfb5c5ed4d6970a09aecf898ca9cdfcb75 (patch) | |
| tree | 57ab54c48a7404abf0c9f2c919e8a6c805d98587 /test | |
| parent | c8894ab5021aecd0fa5eba94af47f732914af33b (diff) | |
ART: Implement DeadPhiHandling in PrimitiveTypePropagation
DeadPhiHandling revives non-conflicting phis with environment uses
but does not properly merge types. To not duplicate code, this patch
modifies PrimitiveTypePropagation to deal with conflicts and thus
replaces DeadPhiHandling altogether.
Bug: 24252151
Bug: 24252100
Change-Id: I198c71d1b8167fc05783a5a24aa9f1e3804acafe
Diffstat (limited to 'test')
6 files changed, 400 insertions, 0 deletions
diff --git a/test/538-checker-typeprop-debuggable/expected.txt b/test/538-checker-typeprop-debuggable/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/538-checker-typeprop-debuggable/expected.txt diff --git a/test/538-checker-typeprop-debuggable/info.txt b/test/538-checker-typeprop-debuggable/info.txt new file mode 100644 index 0000000000..9d69056915 --- /dev/null +++ b/test/538-checker-typeprop-debuggable/info.txt @@ -0,0 +1,2 @@ +Test that phis with environment uses which can be properly typed are kept +in --debuggable mode.
\ No newline at end of file diff --git a/test/538-checker-typeprop-debuggable/smali/ArrayGet.smali b/test/538-checker-typeprop-debuggable/smali/ArrayGet.smali new file mode 100644 index 0000000000..19583af3c2 --- /dev/null +++ b/test/538-checker-typeprop-debuggable/smali/ArrayGet.smali @@ -0,0 +1,167 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.class public LArrayGet; +.super Ljava/lang/Object; + + +# Test phi with fixed-type ArrayGet as an input and a matching second input. +# The phi should be typed accordingly. + +## CHECK-START: void ArrayGet.matchingFixedType(float[], float) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFixedType(float[], float) ssa_builder (after) +## CHECK-DAG: <<Arg1:f\d+>> ParameterValue +## CHECK-DAG: <<Aget:f\d+>> ArrayGet +## CHECK-DAG: {{f\d+}} Phi [<<Aget>>,<<Arg1>>] reg:0 +.method public static matchingFixedType([FF)V + .registers 8 + + const v0, 0x0 + const v1, 0x1 + + aget v0, p0, v0 # read value + add-float v2, v0, v1 # float use fixes type + + float-to-int v2, p1 + if-eqz v2, :after + move v0, p1 + :after + # v0 = Phi [ArrayGet, Arg1] => float + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + + +# Test phi with fixed-type ArrayGet as an input and a conflicting second input. +# The phi should be eliminated due to the conflict. + +## CHECK-START: void ArrayGet.conflictingFixedType(float[], int) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType(float[], int) ssa_builder (after) +## CHECK-NOT: Phi +.method public static conflictingFixedType([FI)V + .registers 8 + + const v0, 0x0 + const v1, 0x1 + + aget v0, p0, v0 # read value + add-float v2, v0, v1 # float use fixes type + + if-eqz p1, :after + move v0, p1 + :after + # v0 = Phi [ArrayGet, Arg1] => conflict + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + + +# Same test as the one above, only this time tests that type of ArrayGet is not +# changed. + +## CHECK-START: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after) +## CHECK: {{i\d+}} ArrayGet +.method public static conflictingFixedType2([IF)V + .registers 8 + + const v0, 0x0 + const v1, 0x1 + + aget v0, p0, v0 # read value + add-int v2, v0, v1 # int use fixes type + + float-to-int v2, p1 + if-eqz v2, :after + move v0, p1 + :after + # v0 = Phi [ArrayGet, Arg1] => conflict + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + + +# Test phi with free-type ArrayGet as an input and a matching second input. +# The phi should be typed accordingly. + +## CHECK-START: void ArrayGet.matchingFreeType(float[], float) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFreeType(float[], float) ssa_builder (after) +## CHECK-DAG: <<Arg1:f\d+>> ParameterValue +## CHECK-DAG: <<Aget:f\d+>> ArrayGet +## CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Aget>>] +## CHECK-DAG: {{f\d+}} Phi [<<Aget>>,<<Arg1>>] reg:0 +.method public static matchingFreeType([FF)V + .registers 8 + + const v0, 0x0 + const v1, 0x1 + + aget v0, p0, v0 # read value, should be float but has no typed use + aput v0, p0, v1 # aput does not disambiguate the type + + float-to-int v2, p1 + if-eqz v2, :after + move v0, p1 + :after + # v0 = Phi [ArrayGet, Arg1] => float + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + + +# Test phi with free-type ArrayGet as an input and a conflicting second input. +# The phi will be kept and typed according to the second input despite the +# conflict. + +## CHECK-START: void ArrayGet.conflictingFreeType(int[], float) ssa_builder (after) +## CHECK-NOT: Phi + +## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFreeType(int[], float) ssa_builder (after) +## CHECK-DAG: <<Arg1:f\d+>> ParameterValue +## CHECK-DAG: <<Aget:f\d+>> ArrayGet +## CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Aget>>] +## CHECK-DAG: {{f\d+}} Phi [<<Aget>>,<<Arg1>>] reg:0 +.method public static conflictingFreeType([IF)V + .registers 8 + + const v0, 0x0 + const v1, 0x1 + + aget v0, p0, v0 # read value, should be int but has no typed use + aput v0, p0, v1 # aput does not disambiguate the type + + float-to-int v2, p1 + if-eqz v2, :after + move v0, p1 + :after + # v0 = Phi [ArrayGet, Arg1] => float + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method diff --git a/test/538-checker-typeprop-debuggable/smali/SsaBuilder.smali b/test/538-checker-typeprop-debuggable/smali/SsaBuilder.smali new file mode 100644 index 0000000000..395feaaf61 --- /dev/null +++ b/test/538-checker-typeprop-debuggable/smali/SsaBuilder.smali @@ -0,0 +1,52 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.class public LSsaBuilder; +.super Ljava/lang/Object; + +# Check that a dead phi with a live equivalent is replaced in an environment. The +# following test case throws an exception and uses v0 afterwards. However, v0 +# contains a phi that is interpreted as int for the environment, and as float for +# instruction use. SsaBuilder must substitute the int variant before removing it, +# otherwise running the code with an array short enough to throw will crash at +# runtime because v0 is undefined. + +## CHECK-START: int SsaBuilder.environmentPhi(boolean, int[]) ssa_builder (after) +## CHECK-DAG: <<Cst0:f\d+>> FloatConstant 0 +## CHECK-DAG: <<Cst2:f\d+>> FloatConstant 2 +## CHECK-DAG: <<Phi:f\d+>> Phi [<<Cst0>>,<<Cst2>>] +## CHECK-DAG: BoundsCheck env:[[<<Phi>>,{{i\d+}},{{z\d+}},{{l\d+}}]] + +.method public static environmentPhi(Z[I)I + .registers 4 + + const v0, 0x0 + if-eqz p0, :else + const v0, 0x40000000 + :else + # v0 = phi that can be both int and float + + :try_start + const v1, 0x3 + aput v1, p1, v1 + const v0, 0x1 # generate catch phi for v0 + const v1, 0x4 + aput v1, p1, v1 + :try_end + .catchall {:try_start .. :try_end} :use_as_float + + :use_as_float + float-to-int v0, v0 + return v0 +.end method
\ No newline at end of file diff --git a/test/538-checker-typeprop-debuggable/smali/TypePropagation.smali b/test/538-checker-typeprop-debuggable/smali/TypePropagation.smali new file mode 100644 index 0000000000..58682a1923 --- /dev/null +++ b/test/538-checker-typeprop-debuggable/smali/TypePropagation.smali @@ -0,0 +1,136 @@ +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +.class public LTypePropagation; +.super Ljava/lang/Object; + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDeadPhi(boolean, boolean, int, float, float) ssa_builder (after) +## CHECK-NOT: Phi +.method public static mergeDeadPhi(ZZIFF)V + .registers 8 + + if-eqz p0, :after1 + move p2, p3 + :after1 + # p2 = merge(int,float) = conflict + + if-eqz p1, :after2 + move p2, p4 + :after2 + # p2 = merge(conflict,float) = conflict + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeSameType(boolean, int, int) ssa_builder (after) +## CHECK: {{i\d+}} Phi +## CHECK-NOT: Phi +.method public static mergeSameType(ZII)V + .registers 8 + if-eqz p0, :after + move p1, p2 + :after + # p1 = merge(int,int) = int + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeVoidInput(boolean, boolean, int, int) ssa_builder (after) +## CHECK: {{i\d+}} Phi +## CHECK: {{i\d+}} Phi +## CHECK-NOT: Phi +.method public static mergeVoidInput(ZZII)V + .registers 8 + :loop + # p2 = void (loop phi) => p2 = merge(int,int) = int + if-eqz p0, :after + move p2, p3 + :after + # p2 = merge(void,int) = int + if-eqz p1, :loop + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDifferentSize(boolean, int, long) ssa_builder (after) +## CHECK-NOT: Phi +.method public static mergeDifferentSize(ZIJ)V + .registers 8 + if-eqz p0, :after + move-wide p1, p2 + :after + # p1 = merge(int,long) = conflict + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeRefFloat(boolean, float, java.lang.Object) ssa_builder (after) +## CHECK-NOT: Phi +.method public static mergeRefFloat(ZFLjava/lang/Object;)V + .registers 8 + if-eqz p0, :after + move-object p1, p2 + :after + # p1 = merge(float,reference) = conflict + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Success(boolean, float) ssa_builder (after) +## CHECK: {{f\d+}} Phi +## CHECK-NOT: Phi +.method public static mergeIntFloat_Success(ZF)V + .registers 8 + if-eqz p0, :after + const/4 p1, 0x0 + :after + # p1 = merge(float,0x0) = float + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Fail(boolean, int, float) ssa_builder (after) +## CHECK-NOT: Phi +.method public static mergeIntFloat_Fail(ZIF)V + .registers 8 + if-eqz p0, :after + move p1, p2 + :after + # p1 = merge(int,float) = conflict + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method + +## CHECK-START-DEBUGGABLE: void TypePropagation.updateAllUsersOnConflict(boolean, boolean, int, float, int) ssa_builder (after) +## CHECK-NOT: Phi +.method public static updateAllUsersOnConflict(ZZIFI)V + .registers 8 + + :loop1 + # loop phis for all args + # p2 = merge(int,float) = float? => conflict + move p2, p3 + if-eqz p0, :loop1 + + :loop2 + # loop phis for all args + # requests float equivalent of p4 phi in loop1 => conflict + # propagates conflict to loop2's phis + move p2, p4 + if-eqz p1, :loop2 + + invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use + return-void +.end method diff --git a/test/538-checker-typeprop-debuggable/src/Main.java b/test/538-checker-typeprop-debuggable/src/Main.java new file mode 100644 index 0000000000..fe2343e48a --- /dev/null +++ b/test/538-checker-typeprop-debuggable/src/Main.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.lang.reflect.Method; + +public class Main { + + // Workaround for b/18051191. + class InnerClass {} + + private static void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new Error("Wrong result, expected=" + expected + ", actual=" + actual); + } + } + + public static void main(String[] args) throws Exception { + Class<?> c = Class.forName("SsaBuilder"); + Method m = c.getMethod("environmentPhi", new Class[] { boolean.class, int[].class }); + + int[] array = new int[3]; + int result; + + result = (Integer) m.invoke(null, new Object[] { true, array } ); + assertEquals(2, result); + + result = (Integer) m.invoke(null, new Object[] { false, array } ); + assertEquals(0, result); + } +} |