1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /**
 25  * @test
 26  * @key randomness
 27  * @summary Test that deoptimization at unstable ifs in acmp works as expected.
 28  * @library /test/lib
 29  * @enablePreview
 30  * @run main/othervm TestAcmpWithUnstableIf
 31  * @run main/othervm -XX:CompileCommand=compileonly,TestAcmpWithUnstableIf::test* -Xbatch TestAcmpWithUnstableIf
 32  */
 33 
 34 import jdk.test.lib.Asserts;
 35 import jdk.test.lib.Utils;
 36 
 37 public class TestAcmpWithUnstableIf {
 38 
 39     public static final int     EQUAL = Utils.getRandomInstance().nextInt();
 40     public static final int NOT_EQUAL = Utils.getRandomInstance().nextInt();
 41 
 42     static value class MyValue {
 43         int x;
 44 
 45         public MyValue(int x) {
 46             this.x = x;
 47         }
 48     }
 49 
 50     public static int test1(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 51         if (val1 == val2) {
 52             return resEqual;
 53         }
 54         return resNotEqual;
 55     }
 56 
 57     public static int test2(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 58         if (val1 == val2) {
 59             return resEqual;
 60         }
 61         return resNotEqual;
 62     }
 63 
 64     public static int test3(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 65         if (val1 == val2) {
 66             return resEqual;
 67         }
 68         return resNotEqual;
 69     }
 70 
 71     public static int test4(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 72         if (val1 == val2) {
 73             return resEqual;
 74         }
 75         return resNotEqual;
 76     }
 77 
 78     public static int test5(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 79         if (val1 != val2) {
 80             return resNotEqual;
 81         }
 82         return resEqual;
 83     }
 84 
 85     public static int test6(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 86         if (val1 != val2) {
 87             return resNotEqual;
 88         }
 89         return resEqual;
 90     }
 91 
 92     public static int test7(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
 93         if (val1 != val2) {
 94             return resNotEqual;
 95         }
 96         return resEqual;
 97     }
 98 
 99     public static int test8(MyValue val1, MyValue val2, int resEqual, int resNotEqual) {
100         if (val1 != val2) {
101             return resNotEqual;
102         }
103         return resEqual;
104     }
105 
106     public static void main(String[] args) {
107         MyValue val = new MyValue(EQUAL);
108         MyValue val_copy = new MyValue(EQUAL);
109         MyValue val_diff = new MyValue(EQUAL + 1);
110 
111         // Warmup
112         for (int i = 0; i < 50_000; ++i) {
113             // Equal arguments, same oop
114             Asserts.assertEquals(test1(val, val, EQUAL, NOT_EQUAL), EQUAL);
115             Asserts.assertEquals(test5(val, val, EQUAL, NOT_EQUAL), EQUAL);
116 
117             // Equal arguments, different oop
118             Asserts.assertEquals(test2(val, val_copy, EQUAL, NOT_EQUAL), EQUAL);
119             Asserts.assertEquals(test6(val, val_copy, EQUAL, NOT_EQUAL), EQUAL);
120 
121             // Different arguments
122             Asserts.assertEquals(test3(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
123             Asserts.assertEquals(test4(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
124 
125             Asserts.assertEquals(test7(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
126             Asserts.assertEquals(test8(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
127         }
128 
129         // Now trigger deoptimization
130 
131         // Different arguments
132         Asserts.assertEquals(test1(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
133         Asserts.assertEquals(test2(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
134 
135         Asserts.assertEquals(test5(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
136         Asserts.assertEquals(test6(val, val_diff, EQUAL, NOT_EQUAL), NOT_EQUAL);
137 
138         // Equal arguments, same oop
139         Asserts.assertEquals(test3(val, val, EQUAL, NOT_EQUAL), EQUAL);
140         Asserts.assertEquals(test7(val, val, EQUAL, NOT_EQUAL), EQUAL);
141 
142         // Equal arguments, different oop
143         Asserts.assertEquals(test4(val, val_copy, EQUAL, NOT_EQUAL), EQUAL);
144         Asserts.assertEquals(test8(val, val_copy, EQUAL, NOT_EQUAL), EQUAL);
145     }
146 }