1# Copyright (C) 2015 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15.class public LArrayGet;
16.super Ljava/lang/Object;
17
18
19# Test phi with fixed-type ArrayGet as an input and a matching second input.
20# The phi should be typed accordingly.
21
22## CHECK-START: void ArrayGet.matchingFixedType(float[], float) builder (after)
23## CHECK-NOT: Phi
24
25## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFixedType(float[], float) builder (after)
26## CHECK-DAG:  <<Arg1:f\d+>> ParameterValue
27## CHECK-DAG:  <<Aget:f\d+>> ArrayGet
28## CHECK-DAG:  {{f\d+}}      Phi [<<Aget>>,<<Arg1>>] reg:0
29.method public static matchingFixedType([FF)V
30  .registers 8
31
32  const v0, 0x0
33  const v1, 0x1
34
35  aget v0, p0, v0       # read value
36  add-float v2, v0, v1  # float use fixes type
37
38  float-to-int v2, p1
39  if-eqz v2, :after
40  move v0, p1
41  :after
42  # v0 = Phi [ArrayGet, Arg1] => float
43
44  invoke-static {}, Ljava/lang/System;->nanoTime()J  # create an env use
45  return-void
46.end method
47
48
49# Test phi with fixed-type ArrayGet as an input and a conflicting second input.
50# The phi should be eliminated due to the conflict.
51
52## CHECK-START: void ArrayGet.conflictingFixedType(float[], int) builder (after)
53## CHECK-NOT: Phi
54
55## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType(float[], int) builder (after)
56## CHECK-NOT: Phi
57.method public static conflictingFixedType([FI)V
58  .registers 8
59
60  const v0, 0x0
61  const v1, 0x1
62
63  aget v0, p0, v0       # read value
64  add-float v2, v0, v1  # float use fixes type
65
66  if-eqz p1, :after
67  move v0, p1
68  :after
69  # v0 = Phi [ArrayGet, Arg1] => conflict
70
71  invoke-static {}, Ljava/lang/System;->nanoTime()J  # create an env use
72  return-void
73.end method
74
75
76# Same test as the one above, only this time tests that type of ArrayGet is not
77# changed.
78
79## CHECK-START: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
80## CHECK-NOT: Phi
81
82## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
83## CHECK-NOT: Phi
84
85## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
86## CHECK:     {{i\d+}} ArrayGet
87.method public static conflictingFixedType2([IF)V
88  .registers 8
89
90  const v0, 0x0
91  const v1, 0x1
92
93  aget v0, p0, v0       # read value
94  add-int v2, v0, v1    # int use fixes type
95
96  float-to-int v2, p1
97  if-eqz v2, :after
98  move v0, p1
99  :after
100  # v0 = Phi [ArrayGet, Arg1] => conflict
101
102  invoke-static {}, Ljava/lang/System;->nanoTime()J  # create an env use
103  return-void
104.end method
105
106
107# Test phi with free-type ArrayGet as an input and a matching second input.
108# The phi should be typed accordingly.
109
110## CHECK-START: void ArrayGet.matchingFreeType(float[], float) builder (after)
111## CHECK-NOT: Phi
112
113## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFreeType(float[], float) builder (after)
114## CHECK-DAG:  <<Arg1:f\d+>> ParameterValue
115## CHECK-DAG:  <<Aget:f\d+>> ArrayGet
116## CHECK-DAG:                ArraySet [{{l\d+}},{{i\d+}},<<Aget>>]
117## CHECK-DAG:  {{f\d+}}      Phi [<<Aget>>,<<Arg1>>] reg:0
118.method public static matchingFreeType([FF)V
119  .registers 8
120
121  const v0, 0x0
122  const v1, 0x1
123
124  aget v0, p0, v0       # read value, should be float but has no typed use
125  aput v0, p0, v1       # aput does not disambiguate the type
126
127  float-to-int v2, p1
128  if-eqz v2, :after
129  move v0, p1
130  :after
131  # v0 = Phi [ArrayGet, Arg1] => float
132
133  invoke-static {}, Ljava/lang/System;->nanoTime()J  # create an env use
134  return-void
135.end method
136
137
138# Test phi with free-type ArrayGet as an input and a conflicting second input.
139# The phi will be kept and typed according to the second input despite the
140# conflict.
141
142## CHECK-START: void ArrayGet.conflictingFreeType(int[], float) builder (after)
143## CHECK-NOT: Phi
144
145## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFreeType(int[], float) builder (after)
146## CHECK-NOT: Phi
147
148.method public static conflictingFreeType([IF)V
149  .registers 8
150
151  const v0, 0x0
152  const v1, 0x1
153
154  aget v0, p0, v0       # read value, should be int but has no typed use
155  aput v0, p0, v1
156
157  float-to-int v2, p1
158  if-eqz v2, :after
159  move v0, p1
160  :after
161  # v0 = Phi [ArrayGet, Arg1] => float
162
163  invoke-static {}, Ljava/lang/System;->nanoTime()J  # create an env use
164  return-void
165.end method
166
167
168# Test that real use of ArrayGet is propagated through phis. The following test
169# case uses ArrayGet indirectly through two phis. It also creates an unused
170# conflicting phi which should not be preserved.
171
172## CHECK-START: void ArrayGet.conflictingPhiUses(int[], float, boolean, boolean, boolean) builder (after)
173## CHECK:         InvokeStaticOrDirect env:[[{{i\d+}},{{i\d+}},_,{{i\d+}},{{.*}}
174
175.method public static conflictingPhiUses([IFZZZ)V
176  .registers 10
177
178  const v0, 0x0
179
180  # Create v1 = Phi [0x0, int ArrayGet]
181  move v1, v0
182  if-eqz p2, :else1
183  aget v1, p0, v0
184  :else1
185
186  # Create v2 = Phi [v1, float]
187  move v2, v1
188  if-eqz p3, :else2
189  move v2, p1
190  :else2
191
192  # Create v3 = Phi [v1, int]
193  move v3, v1
194  if-eqz p4, :else3
195  move v3, v0
196  :else3
197
198  # Use v3 as int.
199  add-int/lit8 v4, v3, 0x2a
200
201  # Create env uses.
202  invoke-static {}, Ljava/lang/System;->nanoTime()J
203
204  return-void
205.end method
206
207# Test that the right ArrayGet equivalent is always selected. The following test
208# case uses ArrayGet as float through one phi and as an indeterminate type through
209# another. The situation needs to be resolved so that only one instruction
210# remains.
211
212## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) builder (after)
213## CHECK:         {{f\d+}} ArrayGet
214
215## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) builder (after)
216## CHECK-NOT:     {{i\d+}} ArrayGet
217
218.method public static typedVsUntypedPhiUse([FFZZ)V
219  .registers 10
220
221  const v0, 0x0
222
223  # v1 = float ArrayGet
224  aget v1, p0, v0
225
226  # Create v2 = Phi [v1, 0.0f]
227  move v2, v1
228  if-eqz p2, :else1
229  move v2, v0
230  :else1
231
232  # Use v2 as float
233  cmpl-float v2, v2, p1
234
235  # Create v3 = Phi [v1, 0.0f]
236  move v3, v1
237  if-eqz p3, :else2
238  move v3, v0
239  :else2
240
241  # Use v3 without a determinate type.
242  aput v3, p0, v0
243
244  return-void
245.end method
246