1 /*
  2  * Copyright (c) 2024, 2025, 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  * @summary Smoke test for code reflection with binary operations.
 27  * @modules jdk.incubator.code
 28  * @build BinopTest
 29  * @build CodeReflectionTester
 30  * @run main CodeReflectionTester BinopTest
 31  */
 32 
 33 import jdk.incubator.code.Reflect;
 34 
 35 public class BinopTest {
 36 
 37     @Reflect
 38     @IR("""
 39             func @"test" (%0 : java.type:"BinopTest")java.type:"int" -> {
 40                 %1 : java.type:"int" = constant @5;
 41                 %2 : java.type:"int" = constant @2;
 42                 %3 : java.type:"int" = constant @4;
 43                 %4 : java.type:"int" = mul %2 %3;
 44                 %5 : java.type:"int" = add %1 %4;
 45                 %6 : java.type:"int" = constant @3;
 46                 %7 : java.type:"int" = sub %5 %6;
 47                 return %7;
 48             };
 49             """)
 50     int test() {
 51         return 5 + 2 * 4 - 3;
 52     }
 53 
 54     @Reflect
 55     @IR("""
 56             func @"test2" (%0 : java.type:"BinopTest")java.type:"int" -> {
 57                 %1 : java.type:"int" = constant @1;
 58                 %2 : java.type:"int" = constant @2;
 59                 %3 : java.type:"int" = constant @3;
 60                 %4 : java.type:"int" = constant @4;
 61                 %5 : java.type:"int" = add %3 %4;
 62                 %6 : java.type:"int" = add %2 %5;
 63                 %7 : java.type:"int" = add %1 %6;
 64                 return %7;
 65             };
 66             """)
 67     int test2() {
 68         return 1 + (2 + (3 + 4));
 69     }
 70 
 71     @Reflect
 72     @IR("""
 73             func @"test3" (%0 : java.type:"BinopTest")java.type:"int" -> {
 74                 %1 : java.type:"int" = constant @1;
 75                 %2 : java.type:"int" = constant @2;
 76                 %3 : java.type:"int" = add %1 %2;
 77                 %4 : java.type:"int" = constant @3;
 78                 %5 : java.type:"int" = add %3 %4;
 79                 %6 : java.type:"int" = constant @4;
 80                 %7 : java.type:"int" = add %5 %6;
 81                 return %7;
 82             };
 83             """)
 84     int test3() {
 85         return ((1 + 2) + 3) + 4;
 86     }
 87 
 88     @Reflect
 89     @IR("""
 90             func @"test4" (%0 : java.type:"BinopTest", %1 : java.type:"int")java.type:"int" -> {
 91                 %2 : Var<java.type:"int"> = var %1 @"i";
 92                 %3 : java.type:"int" = var.load %2;
 93                 %4 : java.type:"int" = constant @1;
 94                 %5 : java.type:"int" = add %3 %4;
 95                 var.store %2 %5;
 96                 %6 : java.type:"int" = var.load %2;
 97                 %7 : java.type:"int" = constant @1;
 98                 %8 : java.type:"int" = mul %6 %7;
 99                 var.store %2 %8;
100                 %9 : java.type:"int" = add %5 %8;
101                 %10 : java.type:"int" = var.load %2;
102                 %11 : java.type:"int" = constant @1;
103                 %12 : java.type:"int" = div %10 %11;
104                 var.store %2 %12;
105                 %13 : java.type:"int" = add %9 %12;
106                 %14 : java.type:"int" = var.load %2;
107                 %15 : java.type:"int" = constant @1;
108                 %16 : java.type:"int" = sub %14 %15;
109                 var.store %2 %16;
110                 %17 : java.type:"int" = add %13 %16;
111                 %18 : java.type:"int" = var.load %2;
112                 %19 : java.type:"int" = constant @1;
113                 %20 : java.type:"int" = mod %18 %19;
114                 var.store %2 %20;
115                 %21 : java.type:"int" = add %17 %20;
116                 return %21;
117             };
118             """)
119     int test4(int i) {
120         return (i += 1) + (i *= 1) + (i /= 1) + (i -= 1) + (i %= 1);
121     }
122 
123     @Reflect
124     @IR("""
125             func @"test5" (%0 : java.type:"BinopTest", %1 : java.type:"int")java.type:"boolean" -> {
126                 %2 : Var<java.type:"int"> = var %1 @"i";
127                 %3 : java.type:"int" = var.load %2;
128                 %4 : java.type:"int" = constant @0;
129                 %5 : java.type:"boolean" = eq %3 %4;
130                 %6 : java.type:"boolean" = not %5;
131                 return %6;
132             };
133             """)
134     boolean test5(int i) {
135         return !(i == 0);
136     }
137 
138     @Reflect
139     @IR("""
140             func @"test6" (%0 : java.type:"BinopTest")java.type:"int" -> {
141                 %1 : java.type:"int" = constant @5;
142                 %2 : java.type:"int" = constant @2;
143                 %3 : java.type:"int" = mod %1 %2;
144                 return %3;
145             };
146             """)
147     int test6() {
148         return 5 % 2;
149     }
150 
151     @Reflect
152     @IR("""
153             func @"test7" (%0 : java.type:"BinopTest", %1 : java.type:"double")java.type:"void" -> {
154                 %2 : Var<java.type:"double"> = var %1 @"d";
155                 %3 : java.type:"double" = var.load %2;
156                 %4 : java.type:"int" = constant @1;
157                 %5 : java.type:"double" = conv %4;
158                 %6 : java.type:"double" = add %3 %5;
159                 var.store %2 %6;
160                 %7 : java.type:"long" = constant @1;
161                 %8 : java.type:"double" = conv %7;
162                 %9 : java.type:"double" = var.load %2;
163                 %10 : java.type:"double" = add %8 %9;
164                 var.store %2 %10;
165                 %11 : java.type:"double" = var.load %2;
166                 %12 : java.type:"long" = constant @1;
167                 %13 : java.type:"double" = conv %12;
168                 %14 : java.type:"double" = sub %11 %13;
169                 var.store %2 %14;
170                 %15 : java.type:"int" = constant @1;
171                 %16 : java.type:"double" = conv %15;
172                 %17 : java.type:"double" = var.load %2;
173                 %18 : java.type:"double" = sub %16 %17;
174                 var.store %2 %18;
175                 %19 : java.type:"double" = var.load %2;
176                 %20 : java.type:"int" = constant @1;
177                 %21 : java.type:"double" = conv %20;
178                 %22 : java.type:"double" = mul %19 %21;
179                 var.store %2 %22;
180                 %23 : java.type:"long" = constant @1;
181                 %24 : java.type:"double" = conv %23;
182                 %25 : java.type:"double" = var.load %2;
183                 %26 : java.type:"double" = mul %24 %25;
184                 var.store %2 %26;
185                 %27 : java.type:"double" = var.load %2;
186                 %28 : java.type:"long" = constant @1;
187                 %29 : java.type:"double" = conv %28;
188                 %30 : java.type:"double" = div %27 %29;
189                 var.store %2 %30;
190                 %31 : java.type:"int" = constant @1;
191                 %32 : java.type:"double" = conv %31;
192                 %33 : java.type:"double" = var.load %2;
193                 %34 : java.type:"double" = div %32 %33;
194                 var.store %2 %34;
195                 %35 : java.type:"double" = var.load %2;
196                 %36 : java.type:"int" = constant @1;
197                 %37 : java.type:"double" = conv %36;
198                 %38 : java.type:"double" = mod %35 %37;
199                 var.store %2 %38;
200                 %39 : java.type:"long" = constant @1;
201                 %40 : java.type:"double" = conv %39;
202                 %41 : java.type:"double" = var.load %2;
203                 %42 : java.type:"double" = mod %40 %41;
204                 var.store %2 %42;
205                 %43 : java.type:"int" = constant @-1;
206                 %44 : java.type:"double" = conv %43;
207                 var.store %2 %44;
208                 return;
209             };
210             """)
211     void test7(double d) {
212         d = d + 1;
213         d = 1L + d;
214 
215         d = d - 1L;
216         d = 1 - d;
217 
218         d = d * 1;
219         d = 1L * d;
220 
221         d = d / 1L;
222         d = 1 / d;
223 
224         d = d % 1;
225         d = 1L % d;
226 
227         d = -1;
228     }
229 
230     @Reflect
231     @IR("""
232             func @"test8" (%0 : java.type:"BinopTest", %1 : java.type:"double")java.type:"void" -> {
233                 %2 : Var<java.type:"double"> = var %1 @"d";
234                 %3 : java.type:"double" = var.load %2;
235                 %4 : java.type:"int" = constant @1;
236                 %5 : java.type:"double" = conv %4;
237                 %6 : java.type:"double" = add %3 %5;
238                 var.store %2 %6;
239                 %7 : java.type:"double" = var.load %2;
240                 %8 : java.type:"long" = constant @1;
241                 %9 : java.type:"double" = conv %8;
242                 %10 : java.type:"double" = sub %7 %9;
243                 var.store %2 %10;
244                 %11 : java.type:"double" = var.load %2;
245                 %12 : java.type:"int" = constant @1;
246                 %13 : java.type:"double" = conv %12;
247                 %14 : java.type:"double" = mul %11 %13;
248                 var.store %2 %14;
249                 %15 : java.type:"double" = var.load %2;
250                 %16 : java.type:"long" = constant @1;
251                 %17 : java.type:"double" = conv %16;
252                 %18 : java.type:"double" = div %15 %17;
253                 var.store %2 %18;
254                 %19 : java.type:"double" = var.load %2;
255                 %20 : java.type:"int" = constant @1;
256                 %21 : java.type:"double" = conv %20;
257                 %22 : java.type:"double" = mod %19 %21;
258                 var.store %2 %22;
259                 return;
260             };
261             """)
262     void test8(double d) {
263         d += 1;
264 
265         d -= 1L;
266 
267         d *= 1;
268 
269         d /= 1L;
270 
271         d %= 1;
272     }
273 
274     @Reflect
275     @IR("""
276             func @"test9" (%0 : java.type:"BinopTest", %1 : java.type:"byte", %2 : java.type:"byte", %3 : java.type:"short")java.type:"void" -> {
277                 %4 : Var<java.type:"byte"> = var %1 @"a";
278                 %5 : Var<java.type:"byte"> = var %2 @"b";
279                 %6 : Var<java.type:"short"> = var %3 @"s";
280                 %7 : java.type:"byte" = var.load %4;
281                 %8 : java.type:"byte" = var.load %5;
282                 %9 : java.type:"int" = conv %8;
283                 %10 : java.type:"int" = conv %7;
284                 %11 : java.type:"int" = add %10 %9;
285                 %12 : java.type:"byte" = conv %11;
286                 var.store %4 %12;
287                 %13 : java.type:"byte" = var.load %4;
288                 %14 : java.type:"short" = var.load %6;
289                 %15 : java.type:"int" = conv %14;
290                 %16 : java.type:"int" = conv %13;
291                 %17 : java.type:"int" = div %16 %15;
292                 %18 : java.type:"byte" = conv %17;
293                 var.store %4 %18;
294                 %19 : java.type:"byte" = var.load %4;
295                 %20 : java.type:"double" = constant @3.5d;
296                 %21 : java.type:"double" = conv %19;
297                 %22 : java.type:"double" = mul %21 %20;
298                 %23 : java.type:"byte" = conv %22;
299                 var.store %4 %23;
300                 %24 : java.type:"byte" = var.load %4;
301                 %25 : java.type:"byte" = var.load %5;
302                 %26 : java.type:"int" = conv %25;
303                 %27 : java.type:"int" = conv %24;
304                 %28 : java.type:"int" = lshl %27 %26;
305                 %29 : java.type:"byte" = conv %28;
306                 var.store %4 %29;
307                 %30 : java.type:"byte" = var.load %4;
308                 %31 : java.type:"int" = constant @1;
309                 %32 : java.type:"int" = conv %30;
310                 %33 : java.type:"int" = ashr %32 %31;
311                 %34 : java.type:"byte" = conv %33;
312                 var.store %4 %34;
313                 %35 : java.type:"byte" = var.load %4;
314                 %36 : java.type:"long" = constant @1L;
315                 %37 : java.type:"int" = conv %35;
316                 %38 : java.type:"int" = ashr %37 %36;
317                 %39 : java.type:"byte" = conv %38;
318                 var.store %4 %39;
319                 return;
320             };
321             """)
322     void test9(byte a, byte b, short s) {
323         a += b;
324 
325         a /= s;
326 
327         a *= 3.5d;
328 
329         a <<= b;
330 
331         a >>= 1;
332 
333         a >>= 1L;
334     }
335 
336     @Reflect
337     @IR("""
338             func @"test10" (%0 : java.type:"BinopTest", %1 : java.type:"boolean", %2 : java.type:"java.lang.Boolean")java.type:"void" -> {
339                 %3 : Var<java.type:"boolean"> = var %1 @"b";
340                 %4 : Var<java.type:"java.lang.Boolean"> = var %2 @"B";
341                 %5 : java.type:"boolean" = java.cor
342                     ()java.type:"boolean" -> {
343                         %6 : java.type:"boolean" = var.load %3;
344                         yield %6;
345                     }
346                     ()java.type:"boolean" -> {
347                         %7 : java.type:"java.lang.Boolean" = var.load %4;
348                         %8 : java.type:"boolean" = invoke %7 @java.ref:"java.lang.Boolean::booleanValue():boolean";
349                         yield %8;
350                     };
351                 %9 : Var<java.type:"boolean"> = var %5 @"or1";
352                 %10 : java.type:"boolean" = java.cor
353                     ()java.type:"boolean" -> {
354                         %11 : java.type:"java.lang.Boolean" = var.load %4;
355                         %12 : java.type:"boolean" = invoke %11 @java.ref:"java.lang.Boolean::booleanValue():boolean";
356                         yield %12;
357                     }
358                     ()java.type:"boolean" -> {
359                         %13 : java.type:"boolean" = var.load %3;
360                         yield %13;
361                     };
362                 %14 : Var<java.type:"boolean"> = var %10 @"or2";
363                 %15 : java.type:"boolean" = java.cor
364                     ()java.type:"boolean" -> {
365                         %16 : java.type:"boolean" = var.load %3;
366                         yield %16;
367                     }
368                     ()java.type:"boolean" -> {
369                         %17 : java.type:"boolean" = var.load %3;
370                         yield %17;
371                     };
372                 %18 : Var<java.type:"boolean"> = var %15 @"or3";
373                 %19 : java.type:"boolean" = java.cor
374                     ()java.type:"boolean" -> {
375                         %20 : java.type:"java.lang.Boolean" = var.load %4;
376                         %21 : java.type:"boolean" = invoke %20 @java.ref:"java.lang.Boolean::booleanValue():boolean";
377                         yield %21;
378                     }
379                     ()java.type:"boolean" -> {
380                         %22 : java.type:"java.lang.Boolean" = var.load %4;
381                         %23 : java.type:"boolean" = invoke %22 @java.ref:"java.lang.Boolean::booleanValue():boolean";
382                         yield %23;
383                     };
384                 %24 : Var<java.type:"boolean"> = var %19 @"or4";
385                 %25 : java.type:"boolean" = java.cand
386                     ()java.type:"boolean" -> {
387                         %26 : java.type:"boolean" = var.load %3;
388                         yield %26;
389                     }
390                     ()java.type:"boolean" -> {
391                         %27 : java.type:"java.lang.Boolean" = var.load %4;
392                         %28 : java.type:"boolean" = invoke %27 @java.ref:"java.lang.Boolean::booleanValue():boolean";
393                         yield %28;
394                     };
395                 %29 : Var<java.type:"boolean"> = var %25 @"and1";
396                 %30 : java.type:"boolean" = java.cand
397                     ()java.type:"boolean" -> {
398                         %31 : java.type:"java.lang.Boolean" = var.load %4;
399                         %32 : java.type:"boolean" = invoke %31 @java.ref:"java.lang.Boolean::booleanValue():boolean";
400                         yield %32;
401                     }
402                     ()java.type:"boolean" -> {
403                         %33 : java.type:"boolean" = var.load %3;
404                         yield %33;
405                     };
406                 %34 : Var<java.type:"boolean"> = var %30 @"and2";
407                 %35 : java.type:"boolean" = java.cand
408                     ()java.type:"boolean" -> {
409                         %36 : java.type:"boolean" = var.load %3;
410                         yield %36;
411                     }
412                     ()java.type:"boolean" -> {
413                         %37 : java.type:"boolean" = var.load %3;
414                         yield %37;
415                     };
416                 %38 : Var<java.type:"boolean"> = var %35 @"and3";
417                 %39 : java.type:"boolean" = java.cand
418                     ()java.type:"boolean" -> {
419                         %40 : java.type:"java.lang.Boolean" = var.load %4;
420                         %41 : java.type:"boolean" = invoke %40 @java.ref:"java.lang.Boolean::booleanValue():boolean";
421                         yield %41;
422                     }
423                     ()java.type:"boolean" -> {
424                         %42 : java.type:"java.lang.Boolean" = var.load %4;
425                         %43 : java.type:"boolean" = invoke %42 @java.ref:"java.lang.Boolean::booleanValue():boolean";
426                         yield %43;
427                     };
428                 %44 : Var<java.type:"boolean"> = var %39 @"and4";
429                 %45 : java.type:"boolean" = var.load %3;
430                 %46 : java.type:"boolean" = not %45;
431                 %47 : Var<java.type:"boolean"> = var %46 @"not1";
432                 %48 : java.type:"java.lang.Boolean" = var.load %4;
433                 %49 : java.type:"boolean" = invoke %48 @java.ref:"java.lang.Boolean::booleanValue():boolean";
434                 %50 : java.type:"boolean" = not %49;
435                 %51 : Var<java.type:"boolean"> = var %50 @"not2";
436                 return;
437             };
438             """)
439     void test10(boolean b, Boolean B) {
440         var or1 = b || B;
441         var or2 = B || b;
442         var or3 = b || b;
443         var or4 = B || B;
444 
445         var and1 = b && B;
446         var and2 = B && b;
447         var and3 = b && b;
448         var and4 = B && B;
449 
450         var not1 = !b;
451         var not2 = !B;
452     }
453 }