diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 26e0bcf5320..950112f55c6 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2021, Red Hat, Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -9654,6 +9654,90 @@ instruct get_and_addIi_no_resAcq(indirect mem, Universe dummy, immIAddSub incr) ins_pipe(pipe_serial); %} +// Manifest a CmpU result in an integer register. +// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) +instruct cmpU3_reg_reg(iRegINoSp dst, iRegI src1, iRegI src2, rFlagsReg flags) +%{ + match(Set dst (CmpU3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "cmpw $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpU3(reg)" + %} + ins_encode %{ + __ cmpw($src1$$Register, $src2$$Register); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpU3_reg_imm(iRegINoSp dst, iRegI src1, immIAddSub src2, rFlagsReg flags) +%{ + match(Set dst (CmpU3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "subsw zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpU3(imm)" + %} + ins_encode %{ + __ subsw(zr, $src1$$Register, (int32_t)$src2$$constant); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +// Manifest a CmpUL result in an integer register. +// (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) +instruct cmpUL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) +%{ + match(Set dst (CmpUL3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "cmp $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpUL3(reg)" + %} + ins_encode %{ + __ cmp($src1$$Register, $src2$$Register); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + +instruct cmpUL3_reg_imm(iRegINoSp dst, iRegL src1, immLAddSub src2, rFlagsReg flags) +%{ + match(Set dst (CmpUL3 src1 src2)); + effect(KILL flags); + + ins_cost(INSN_COST * 3); + format %{ + "subs zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lo\t# CmpUL3(imm)" + %} + ins_encode %{ + __ subs(zr, $src1$$Register, (int32_t)$src2$$constant); + __ csetw($dst$$Register, Assembler::NE); + __ cnegw($dst$$Register, $dst$$Register, Assembler::LO); + %} + + ins_pipe(pipe_class_default); +%} + // Manifest a CmpL result in an integer register. // (src1 < src2) ? -1 : ((src1 > src2) ? 1 : 0) instruct cmpL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) @@ -9661,13 +9745,12 @@ instruct cmpL3_reg_reg(iRegINoSp dst, iRegL src1, iRegL src2, rFlagsReg flags) match(Set dst (CmpL3 src1 src2)); effect(KILL flags); - ins_cost(INSN_COST * 6); + ins_cost(INSN_COST * 3); format %{ - "cmp $src1, $src2" - "csetw $dst, ne" - "cnegw $dst, lt" + "cmp $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lt\t# CmpL3(reg)" %} - // format %{ "CmpL3 $dst, $src1, $src2" %} ins_encode %{ __ cmp($src1$$Register, $src2$$Register); __ csetw($dst$$Register, Assembler::NE); @@ -9682,19 +9765,14 @@ instruct cmpL3_reg_imm(iRegINoSp dst, iRegL src1, immLAddSub src2, rFlagsReg fla match(Set dst (CmpL3 src1 src2)); effect(KILL flags); - ins_cost(INSN_COST * 6); + ins_cost(INSN_COST * 3); format %{ - "cmp $src1, $src2" - "csetw $dst, ne" - "cnegw $dst, lt" + "subs zr, $src1, $src2\n\t" + "csetw $dst, ne\n\t" + "cnegw $dst, lt\t# CmpL3(imm)" %} ins_encode %{ - int32_t con = (int32_t)$src2$$constant; - if (con < 0) { - __ adds(zr, $src1$$Register, -con); - } else { - __ subs(zr, $src1$$Register, con); - } + __ subs(zr, $src1$$Register, (int32_t)$src2$$constant); __ csetw($dst$$Register, Assembler::NE); __ cnegw($dst$$Register, $dst$$Register, Assembler::LT); %} diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java index ab699358a46..6d1943ca145 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle 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 @@ -29,8 +29,8 @@ import jdk.test.lib.Utils; /* * @test * @key randomness - * @bug 8283726 - * @requires os.arch=="amd64" | os.arch=="x86_64" + * @bug 8283726 8287925 + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" * @summary Test the intrinsics implementation of Integer/Long::compareUnsigned * @library /test/lib / * @run driver compiler.intrinsics.TestCompareUnsigned @@ -73,13 +73,74 @@ public class TestCompareUnsigned { return Integer.compareUnsigned(x, y); } + @Test + @IR(counts = {IRNode.CMP_U3, "1"}) + public int compareIntWithImm1(int x) { + return Integer.compareUnsigned(x, 42); + } + + @Test + @IR(counts = {IRNode.CMP_U3, "1"}) + public int compareIntWithImm2(int x) { + return Integer.compareUnsigned(x, 42 << 12); + } + + @Test + @IR(counts = {IRNode.CMP_U3, "1"}) + public int compareIntWithImm3(int x) { + return Integer.compareUnsigned(x, 42 << 24); + } + + @Test + @IR(counts = {IRNode.CMP_U3, "1"}) + public int compareIntWithImm4(int x) { + return Integer.compareUnsigned(x, Integer.MIN_VALUE); + } + @Test @IR(counts = {IRNode.CMP_UL3, "1"}) public int compareLong(long x, long y) { return Long.compareUnsigned(x, y); } - @Run(test = {"lessThanInt", "lessThanLong", "compareInt", "compareLong"}) + @Test + @IR(counts = {IRNode.CMP_UL3, "1"}) + public int compareLongWithImm1(long x) { + return Long.compareUnsigned(x, 42); + } + + @Test + @IR(counts = {IRNode.CMP_UL3, "1"}) + public int compareLongWithImm2(long x) { + return Long.compareUnsigned(x, 42 << 12); + } + + @Test + @IR(counts = {IRNode.CMP_UL3, "1"}) + public int compareLongWithImm3(long x) { + return Long.compareUnsigned(x, 42 << 24); + } + + @Test + @IR(counts = {IRNode.CMP_UL3, "1"}) + public int compareLongWithImm4(long x) { + return Long.compareUnsigned(x, Integer.MIN_VALUE); + } + + @Test + @IR(counts = {IRNode.CMP_UL3, "1"}) + public int compareLongWithImm5(long x) { + return Long.compareUnsigned(x, Long.MIN_VALUE); + } + + @Run(test = {"lessThanInt", "lessThanLong", + "compareInt", + "compareIntWithImm1", "compareIntWithImm2", + "compareIntWithImm3", "compareIntWithImm4", + "compareLong", + "compareLongWithImm1", "compareLongWithImm2", + "compareLongWithImm3", "compareLongWithImm4", + "compareLongWithImm5"}) public void runTests() { var random = Utils.getRandomInstance(); for (int i = 0; i < 1000; i++) { @@ -89,6 +150,10 @@ public class TestCompareUnsigned { Asserts.assertEquals(compareInt(x, x), 0); Asserts.assertEquals(lessThanInt(x, y), expectedResult(x, y) < 0 ? TRUE_VALUE : FALSE_VALUE); Asserts.assertEquals(compareInt(x, y), expectedResult(x, y)); + Asserts.assertEquals(compareIntWithImm1(x), expectedResult(x, 42)); + Asserts.assertEquals(compareIntWithImm2(x), expectedResult(x, 42 << 12)); + Asserts.assertEquals(compareIntWithImm3(x), expectedResult(x, 42 << 24)); + Asserts.assertEquals(compareIntWithImm4(x), expectedResult(x, Integer.MIN_VALUE)); } for (int i = 0; i < 1000; i++) { long x = random.nextLong(); @@ -97,6 +162,11 @@ public class TestCompareUnsigned { Asserts.assertEquals(compareLong(x, x), 0); Asserts.assertEquals(lessThanLong(x, y), expectedResult(x, y) < 0 ? TRUE_VALUE : FALSE_VALUE); Asserts.assertEquals(compareLong(x, y), expectedResult(x, y)); + Asserts.assertEquals(compareLongWithImm1(x), expectedResult(x, 42)); + Asserts.assertEquals(compareLongWithImm2(x), expectedResult(x, 42 << 12)); + Asserts.assertEquals(compareLongWithImm3(x), expectedResult(x, 42 << 24)); + Asserts.assertEquals(compareLongWithImm4(x), expectedResult(x, Integer.MIN_VALUE)); + Asserts.assertEquals(compareLongWithImm5(x), expectedResult(x, Long.MIN_VALUE)); } } }