/* * Copyright (c) 2024 Red Hat and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package compiler.c2; import compiler.lib.ir_framework.*; import compiler.lib.ir_framework.Test; import java.util.Random; /* * @test * @bug 8332442 * @summary Test that DIV and MOD nodes are converted into DIVMOD where possible * @library /test/lib / * @run driver compiler.c2.TestDivModNodes */ public class TestDivModNodes { private static final Random RANDOM = AbstractInfo.getRandom(); private static int intQuotient; private static int intRemainder; private static long longQuotient; private static long longRemainder; public static void main(String[] args) { TestFramework.runWithFlags("-XX:-UseDivMod"); TestFramework.runWithFlags("-XX:+UseDivMod"); } private static int nextNonZeroInt() { int i; do { i = RANDOM.nextInt(); } while (i == 0); return i; } private static long nextNonZeroLong() { long i; do { i = RANDOM.nextLong(); } while (i == 0); return i; } @Test @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"}, counts = {IRNode.DIV_MOD_I, "1"}, failOn = {IRNode.DIV_I, IRNode.MOD_I}) @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"}, counts = {IRNode.DIV_I, "1", IRNode.MUL_I, "1", IRNode.SUB_I, "1"}, failOn = {IRNode.MOD_I}) @IR(applyIf = {"UseDivMod", "false"}, counts = {IRNode.DIV_I, "1", IRNode.MOD_I, "1"}) private static void testSignedIntDivMod(int dividend, int divisor) { intQuotient = dividend / divisor; intRemainder = dividend % divisor; } @Run(test = "testSignedIntDivMod") private static void runSignedIntDivMod() { int dividend = RANDOM.nextInt(); int divisor = nextNonZeroInt(); testSignedIntDivMod(dividend, divisor); verifyResult(dividend, divisor, intQuotient, intRemainder, dividend / divisor, dividend % divisor); } @Test @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"}, counts = {IRNode.DIV_MOD_L, "1"}, failOn = {IRNode.DIV_L, IRNode.MOD_L}) @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"}, counts = {IRNode.DIV_L, "1", IRNode.MUL_L, "1", IRNode.SUB_L, "1"}, failOn = {IRNode.MOD_L}) @IR(applyIf = {"UseDivMod", "false"}, counts = {IRNode.DIV_L, "1", IRNode.MOD_L, "1"}) private static void testSignedLongDivMod(long dividend, long divisor) { longQuotient = dividend / divisor; longRemainder = dividend % divisor; } @Run(test = "testSignedLongDivMod") private static void runSignedLongDivMod() { long dividend = RANDOM.nextLong(); long divisor = nextNonZeroLong(); testSignedLongDivMod(dividend, divisor); verifyResult(dividend, divisor, longQuotient, longRemainder, dividend / divisor, dividend % divisor); } @Test @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"}, counts = {IRNode.UDIV_MOD_I, "1"}, failOn = {IRNode.UDIV_I, IRNode.UMOD_I}) @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"}, counts = {IRNode.UDIV_I, "1", IRNode.MUL_I, "1", IRNode.SUB_I, "1"}, failOn = {IRNode.UMOD_I}) @IR(applyIf = {"UseDivMod", "false"}, counts = {IRNode.UDIV_I, "1", IRNode.UMOD_I, "1"}) private static void testUnsignedIntDivMod(int dividend, int divisor) { intQuotient = Integer.divideUnsigned(dividend, divisor); // intrinsified on x86 intRemainder = Integer.remainderUnsigned(dividend, divisor); // intrinsified on x86 } @Run(test = "testUnsignedIntDivMod") private static void runUnsignedIntDivMod() { int dividend = RANDOM.nextInt(); int divisor = nextNonZeroInt(); testUnsignedIntDivMod(dividend, divisor); verifyResult(dividend, divisor, intQuotient, intRemainder, Integer.divideUnsigned(dividend, divisor), Integer.remainderUnsigned(dividend, divisor)); } @Test @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"}, counts = {IRNode.UDIV_MOD_L, "1"}, failOn = {IRNode.UDIV_L, IRNode.UMOD_L}) @IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"}, counts = {IRNode.UDIV_L, "1", IRNode.MUL_L, "1", IRNode.SUB_L, "1"}, failOn = {IRNode.MOD_L}) @IR(applyIf = {"UseDivMod", "false"}, counts = {IRNode.UDIV_L, "1", IRNode.UMOD_L, "1"}) private static void testUnsignedLongDivMod(long dividend, long divisor) { longQuotient = Long.divideUnsigned(dividend, divisor); // intrinsified on x86 longRemainder = Long.remainderUnsigned(dividend, divisor); // intrinsified on x86 } @Run(test = "testUnsignedLongDivMod") private static void runUnsignedLongDivMod() { long dividend = RANDOM.nextLong(); long divisor = nextNonZeroLong(); testUnsignedLongDivMod(dividend, divisor); verifyResult(dividend, divisor, longQuotient, longRemainder, Long.divideUnsigned(dividend, divisor), Long.remainderUnsigned(dividend, divisor)); } private static void verifyResult(T dividend, T divisor, T quotient, T remainder, T expectedQ, T expectedR) { if (!expectedQ.equals(quotient) || !expectedR.equals(remainder)) { throw new AssertionError(String.format("Mismatched result from %d / %d. " + "Expected: quotient = %d remainder = %d, " + "but got: quotient = %d remainder = %d", dividend, divisor, expectedQ, expectedR, quotient, remainder)); } } }