14f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee/*
24f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * Copyright (C) 2015 The Android Open Source Project
34f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee *
44f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * Licensed under the Apache License, Version 2.0 (the "License");
54f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * you may not use this file except in compliance with the License.
64f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * You may obtain a copy of the License at
74f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee *
84f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee *      http://www.apache.org/licenses/LICENSE-2.0
94f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee *
104f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * Unless required by applicable law or agreed to in writing, software
114f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * distributed under the License is distributed on an "AS IS" BASIS,
124f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * See the License for the specific language governing permissions and
144f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee * limitations under the License.
154f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee */
164f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
174f81907c5b409bac9cf1ad13801280bb15968533Jongwon Leepublic class Main {
184f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    public static void main(String[] args) {
194f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        new Main().run();
20239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        testPreserveFloat();
21239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        testPreserveDouble();
224f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        System.out.println("finish");
234f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    }
244f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
254f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    public void run() {
264f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        double a[][] = new double[200][201];
274f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        double b[] = new double[200];
284f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        int n = 100;
294f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
304f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        foo1(a, n, b);
314f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    }
324f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
334f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    void foo1(double a[][], int n, double b[]) {
344f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        double t;
354f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        int i,k;
364f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
374f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        for (i = 0; i < n; i++) {
384f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            k = n - (i + 1);
394f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            b[k] /= a[k][k];
404f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            t = -b[k];
414f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            foo2(k + 1000, t, b);
424f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        }
434f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    }
444f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
454f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    void foo2(int n, double c, double b[]) {
464f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        try {
474f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            foo3(n, c, b);
484f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        } catch (Exception e) {
494f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        }
504f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    }
514f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
524f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    void foo3(int n, double c, double b[]) {
534f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        int i = 0;
544f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        for (i = 0; i < n; i++) {
554f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee            b[i + 1] += c * b[i + 1];
564f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee        }
574f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee    }
58239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
59239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /*
60239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * Test that we correctly preserve floating point registers when we deoptimize.
61239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     *
62239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * Note: These tests rely on the deoptimization happening before the loop,
63239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * so that the loop is interpreted and fills the provided arrays. However,
64239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * the BCE transformation can be modified to execute the loop as many times
65239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * as the compiler can guarantee no AIOOBE and only deoptimize thereafter,
66239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * just before the throwing iteration. Then the floating point registers
67239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * would no longer be used after the deoptimization and another approach
68239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     * would be needed to test this.
69239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko     */
70239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
71239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    static public void testPreserveFloat() {
72239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        float[] array = new float[2];
73239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        try {
74239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            $noinline$FloatFill(1.125f, 2.5f, array, 3);
75239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            throw new Error();
76239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        } catch (ArrayIndexOutOfBoundsException expected) {
77239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            System.out.println("array[0]=" + array[0] + "f");
78239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            System.out.println("array[1]=" + array[1] + "f");
79239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        }
80239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    }
81239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
82239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-START: void Main.$noinline$FloatFill(float, float, float[], int) BCE (after)
83239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
84239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
85239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
86239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-NOT:          Deoptimize
87239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
88239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-START: void Main.$noinline$FloatFill(float, float, float[], int) BCE (after)
89239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-NOT:          BoundsCheck
90239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
91239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    public static void $noinline$FloatFill(float f1, float f2, float[] array, int n) {
92239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        if (doThrow) { throw new Error(); }
93239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        for (int i = 0; i < n; ++i) {
94239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            array[i] = ((i & 1) == 1) ? f1 : f2;
95239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            f1 += 1.5f;
96239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            f2 += 2.25f;
97239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        }
98239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    }
99239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
100239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    static public void testPreserveDouble() {
101239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        double[] array = new double[2];
102239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        try {
103239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            $noinline$DoubleFill(2.125, 3.5, array, 3);
104239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            throw new Error();
105239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        } catch (ArrayIndexOutOfBoundsException expected) {
106239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            System.out.println("array[0]=" + array[0]);
107239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            System.out.println("array[1]=" + array[1]);
108239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        }
109239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    }
110239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
111239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-START: void Main.$noinline$DoubleFill(double, double, double[], int) BCE (after)
112239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
113239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
114239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-DAG:          Deoptimize
115239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-NOT:          Deoptimize
116239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
117239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-START: void Main.$noinline$DoubleFill(double, double, double[], int) BCE (after)
118239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    /// CHECK-NOT:          BoundsCheck
119239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
120239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    public static void $noinline$DoubleFill(double d1, double d2, double[] array, int n) {
121239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        if (doThrow) { throw new Error(); }
122239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        for (int i = 0; i < n; ++i) {
123239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            array[i] = ((i & 1) == 1) ? d1 : d2;
124239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            d1 += 1.5;
125239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko            d2 += 2.25;
126239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko        }
127239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    }
128239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko
129239d6eaff0cbb5c4c0139f7053a012758799f186Vladimir Marko    public static boolean doThrow = false;
1304f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee}
1314f81907c5b409bac9cf1ad13801280bb15968533Jongwon Lee
132