8281453: New optimization: convert ~x into -1-x when ~x is used in an arithmetic expression
Reviewed-by: kvn
This commit is contained in:
parent
85569e966c
commit
5dd851d872
@ -364,15 +364,6 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert (~x+c) into (c-1)-x. Note there isn't a bitwise not
|
|
||||||
// bytecode, "~x" would typically represented as "x^(-1)", so (~x+c)
|
|
||||||
// will be (x^(-1))+c.
|
|
||||||
if (op1 == Op_Xor(bt) &&
|
|
||||||
(in2->Opcode() == Op_ConI || in2->Opcode() == Op_ConL) &&
|
|
||||||
phase->type(in1->in(2)) == TypeInteger::minus_1(bt)) {
|
|
||||||
Node* c_minus_one = phase->makecon(add_ring(phase->type(in(2)), TypeInteger::minus_1(bt)));
|
|
||||||
return SubNode::make(c_minus_one, in1->in(1), bt);
|
|
||||||
}
|
|
||||||
return AddNode::Ideal(phase, can_reshape);
|
return AddNode::Ideal(phase, can_reshape);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,20 +853,38 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
|
|||||||
return TypeLong::make( r0->get_con() | r1->get_con() );
|
return TypeLong::make( r0->get_con() | r1->get_con() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------Helper -------------------------------------------
|
||||||
|
/* Decide if the given node is used only in arithmetic expressions(add or sub).
|
||||||
|
*/
|
||||||
|
static bool is_used_in_only_arithmetic(Node* n, BasicType bt) {
|
||||||
|
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
|
||||||
|
Node* u = n->fast_out(i);
|
||||||
|
if (u->Opcode() != Op_Add(bt) && u->Opcode() != Op_Sub(bt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//------------------------------Idealize---------------------------------------
|
//------------------------------Idealize---------------------------------------
|
||||||
Node* XorINode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
Node* XorINode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||||
Node* in1 = in(1);
|
Node* in1 = in(1);
|
||||||
Node* in2 = in(2);
|
Node* in2 = in(2);
|
||||||
int op1 = in1->Opcode();
|
|
||||||
// Convert ~(x+c) into (-c-1)-x. Note there isn't a bitwise not
|
// Convert ~x into -1-x when ~x is used in an arithmetic expression
|
||||||
// bytecode, "~x" would typically represented as "x^(-1)", so ~(x+c)
|
// or x itself is an expression.
|
||||||
// will eventually be (x+c)^-1.
|
if (phase->type(in2) == TypeInt::MINUS_1) { // follows LHS^(-1), i.e., ~LHS
|
||||||
if (op1 == Op_AddI && phase->type(in2) == TypeInt::MINUS_1 &&
|
if (phase->is_IterGVN()) {
|
||||||
in1->in(2)->Opcode() == Op_ConI) {
|
if (is_used_in_only_arithmetic(this, T_INT)
|
||||||
jint c = phase->type(in1->in(2))->isa_int()->get_con();
|
// LHS is arithmetic
|
||||||
Node* neg_c_minus_one = phase->intcon(java_add(-c, -1));
|
|| (in1->Opcode() == Op_AddI || in1->Opcode() == Op_SubI)) {
|
||||||
return new SubINode(neg_c_minus_one, in1->in(1));
|
return new SubINode(in2, in1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// graph could be incomplete in GVN so we postpone to IGVN
|
||||||
|
phase->record_for_igvn(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AddNode::Ideal(phase, can_reshape);
|
return AddNode::Ideal(phase, can_reshape);
|
||||||
}
|
}
|
||||||
@ -947,15 +956,20 @@ const Type *XorLNode::add_ring( const Type *t0, const Type *t1 ) const {
|
|||||||
Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||||
Node* in1 = in(1);
|
Node* in1 = in(1);
|
||||||
Node* in2 = in(2);
|
Node* in2 = in(2);
|
||||||
int op1 = in1->Opcode();
|
|
||||||
// Convert ~(x+c) into (-c-1)-x. Note there isn't a bitwise not
|
// Convert ~x into -1-x when ~x is used in an arithmetic expression
|
||||||
// bytecode, "~x" would typically represented as "x^(-1)", so ~(x+c)
|
// or x itself is an arithmetic expression.
|
||||||
// will eventually be (x+c)^-1.
|
if (phase->type(in2) == TypeLong::MINUS_1) { // follows LHS^(-1), i.e., ~LHS
|
||||||
if (op1 == Op_AddL && phase->type(in2) == TypeLong::MINUS_1 &&
|
if (phase->is_IterGVN()) {
|
||||||
in1->in(2)->Opcode() == Op_ConL) {
|
if (is_used_in_only_arithmetic(this, T_LONG)
|
||||||
jlong c = phase->type(in1->in(2))->isa_long()->get_con();
|
// LHS is arithmetic
|
||||||
Node* neg_c_minus_one = phase->longcon(java_add(-c, (jlong)-1));
|
|| (in1->Opcode() == Op_AddL || in1->Opcode() == Op_SubL)) {
|
||||||
return new SubLNode(neg_c_minus_one, in1->in(1));
|
return new SubLNode(in2, in1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// graph could be incomplete in GVN so we postpone to IGVN
|
||||||
|
phase->record_for_igvn(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return AddNode::Ideal(phase, can_reshape);
|
return AddNode::Ideal(phase, can_reshape);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class AddLNodeIdealizationTests {
|
|||||||
"test11", "test12", "test13",
|
"test11", "test12", "test13",
|
||||||
"test14", "test15", "test16",
|
"test14", "test15", "test16",
|
||||||
"test17", "test18", "test19",
|
"test17", "test18", "test19",
|
||||||
"test20","test21", "test22"})
|
"test20", "test21", "test22"})
|
||||||
public void runMethod() {
|
public void runMethod() {
|
||||||
long a = RunInfo.getRandom().nextLong();
|
long a = RunInfo.getRandom().nextLong();
|
||||||
long b = RunInfo.getRandom().nextLong();
|
long b = RunInfo.getRandom().nextLong();
|
||||||
|
@ -1,367 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022, 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
|
|
||||||
* 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.irTests;
|
|
||||||
|
|
||||||
import jdk.test.lib.Asserts;
|
|
||||||
import compiler.lib.ir_framework.*;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @test
|
|
||||||
* @bug 8279607
|
|
||||||
* @summary Test that transformation from ~x + c to (c - 1) - x and
|
|
||||||
* from ~(x + c) to (-c - 1) - x works as intended.
|
|
||||||
* @library /test/lib /
|
|
||||||
* @requires vm.compiler2.enabled
|
|
||||||
* @run driver compiler.c2.irTests.TestIRAddIdealNotXPlusC
|
|
||||||
*/
|
|
||||||
public class TestIRAddIdealNotXPlusC {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
TestFramework.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConIsNormal1(int x) {
|
|
||||||
return ~x + 1234; // transformed to 1233 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsNormal1")
|
|
||||||
public void checkTestIntConIsNormal1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(1223, testIntConIsNormal1(10));
|
|
||||||
Asserts.assertEquals(1233, testIntConIsNormal1(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConIsNormal2(int x) {
|
|
||||||
return ~(x + -1234); // transformed to 1233 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsNormal2")
|
|
||||||
public void checkTestIntConIsNormal2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(1223, testIntConIsNormal2(10));
|
|
||||||
Asserts.assertEquals(1233, testIntConIsNormal2(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConIsNormal1(long x) {
|
|
||||||
return ~x + 123_456_789_123L; // transformed to 123_456_789_122L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsNormal1")
|
|
||||||
public void checkTestLongConIsNormal1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(113_456_789_122L, testLongConIsNormal1(10_000_000_000L));
|
|
||||||
Asserts.assertEquals(123_456_789_122L, testLongConIsNormal1(0L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConIsNormal2(long x) {
|
|
||||||
return ~(x + -123_456_789_123L); // transformed to 123_456_789_122L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsNormal2")
|
|
||||||
public void checkTestLongConIsNormal2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(113_456_789_122L, testLongConIsNormal2(10_000_000_000L));
|
|
||||||
Asserts.assertEquals(123_456_789_122L, testLongConIsNormal2(0L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConIsZero1(int x) {
|
|
||||||
return ~x + 0; // transformed to -1 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsZero1")
|
|
||||||
public void checkTestIntConIsZero1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-11, testIntConIsZero1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.SUB_I})
|
|
||||||
@IR(counts = {IRNode.XOR_I, "1"})
|
|
||||||
public int testIntConIsZero2(int x) {
|
|
||||||
return ~(x + 0); // should not happen, transformed to ~x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsZero2")
|
|
||||||
public void checkTestIntConIsZero2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-11, testIntConIsZero2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConIsZero1(long x) {
|
|
||||||
return ~x + 0L; // transformed to -1 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsZero1")
|
|
||||||
public void checkTestLongConIsZero1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10_000_000_001L, testLongConIsZero1(10_000_000_000L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.SUB_L})
|
|
||||||
@IR(counts = {IRNode.XOR_L, "1"})
|
|
||||||
public long testLongConIsZero2(long x) {
|
|
||||||
return ~(x + 0L); // should not happen, transformed to ~x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsZero2")
|
|
||||||
public void checkTestLongConIsZero2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10_000_000_001L, testLongConIsZero2(10_000_000_000L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConIsOne1(int x) {
|
|
||||||
return ~x + 1; // transformed to 0 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsOne1")
|
|
||||||
public void checkTestIntConIsOne1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10, testIntConIsOne1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConIsNegOne2(int x) {
|
|
||||||
return ~(x + -1); // transformed to 0 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConIsNegOne2")
|
|
||||||
public void checkTestIntConIsNegOne2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10, testIntConIsNegOne2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConIsOne1(long x) {
|
|
||||||
return ~x + 1L; // transformed to 0 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsOne1")
|
|
||||||
public void checkTestLongConIsOne1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10_000_000_000L, testLongConIsOne1(10_000_000_000L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConIsNegOne2(long x) {
|
|
||||||
return ~(x + -1L); // transformed to 0 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConIsNegOne2")
|
|
||||||
public void checkTestLongConIsNegOne2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(-10_000_000_000L, testLongConIsNegOne2(10_000_000_000L));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntConMinusOneIsUnderflow1(int x) {
|
|
||||||
return ~x + Integer.MIN_VALUE; // transformed to Integer.MAX_VALUE - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntConMinusOneIsUnderflow1")
|
|
||||||
public void checkTestIntConMinusOneIsUnderflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(2147483637, testIntConMinusOneIsUnderflow1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntNegConMinusOneIsUnderflow2(int x) {
|
|
||||||
return ~(x + Integer.MIN_VALUE); // transformed to Integer.MAX_VALUE - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntNegConMinusOneIsUnderflow2")
|
|
||||||
public void checkTestIntNegConMinusOneIsUnderflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(2147483637, testIntNegConMinusOneIsUnderflow2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongConMinusOneIsUnderflow1(long x) {
|
|
||||||
return ~x + Long.MIN_VALUE; // transformed to Long.MAX_VALUE - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongConMinusOneIsUnderflow1")
|
|
||||||
public void checkTestLongConMinusOneIsUnderflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(9223372036854775797L, testLongConMinusOneIsUnderflow1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongNegConMinusOneIsUnderflow2(long x) {
|
|
||||||
return ~(x + Long.MIN_VALUE); // transformed to Long.MAX_VALUE - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongNegConMinusOneIsUnderflow2")
|
|
||||||
public void checkTestLongNegConMinusOneIsUnderflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(9223372036854775797L, testLongNegConMinusOneIsUnderflow2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntResultIsUnderflow1(int x) {
|
|
||||||
return ~x + -2147483638; // transformed to -2147483639 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntResultIsUnderflow1")
|
|
||||||
public void checkTestIntResultIsUnderflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Integer.MAX_VALUE, testIntResultIsUnderflow1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntResultIsUnderflow2(int x) {
|
|
||||||
return ~(x + 2147483638); // transformed to -2147483639 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntResultIsUnderflow2")
|
|
||||||
public void checkTestIntResultIsUnderflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Integer.MAX_VALUE, testIntResultIsUnderflow2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongResultIsUnderflow1(long x) {
|
|
||||||
return ~x + -9223372036854775798L; // transformed to -9223372036854775799L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongResultIsUnderflow1")
|
|
||||||
public void checkTestLongResultIsUnderflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Long.MAX_VALUE, testLongResultIsUnderflow1(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongResultIsUnderflow2(long x) {
|
|
||||||
return ~(x + 9223372036854775798L); // transformed to -9223372036854775799L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongResultIsUnderflow2")
|
|
||||||
public void checkTestLongResultIsUnderflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Long.MAX_VALUE, testLongResultIsUnderflow2(10));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntResultIsOverflow1(int x) {
|
|
||||||
return ~x + 2147483637; // transformed to 2147483646 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntResultIsOverflow1")
|
|
||||||
public void checkTestIntResultIsOverflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Integer.MIN_VALUE, testIntResultIsOverflow1(-12));
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_I, IRNode.XOR_I})
|
|
||||||
@IR(counts = {IRNode.SUB_I, "1"})
|
|
||||||
public int testIntResultIsOverflow2(int x) {
|
|
||||||
return ~(x + -2147483637); // transformed to 2147483646 - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testIntResultIsOverflow2")
|
|
||||||
public void checkTestIntResultIsOverflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Integer.MIN_VALUE, testIntResultIsOverflow2(-12));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongResultIsOverflow1(long x) {
|
|
||||||
return ~x + 9223372036854775797L; // transformed to 9223372036854775798L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongResultIsOverflow1")
|
|
||||||
public void checkTestLongResultIsOverflow1(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Long.MIN_VALUE, testLongResultIsOverflow1(-12));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@IR(failOn = {IRNode.ADD_L, IRNode.XOR_L})
|
|
||||||
@IR(counts = {IRNode.SUB_L, "1"})
|
|
||||||
public long testLongResultIsOverflow2(long x) {
|
|
||||||
return ~(x + -9223372036854775797L); // transformed to 9223372036854775798L - x
|
|
||||||
}
|
|
||||||
|
|
||||||
@Run(test = "testLongResultIsOverflow2")
|
|
||||||
public void checkTestLongResultIsOverflow2(RunInfo info) {
|
|
||||||
assertC2Compiled(info);
|
|
||||||
Asserts.assertEquals(Long.MIN_VALUE, testLongResultIsOverflow2(-12));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertC2Compiled(RunInfo info) {
|
|
||||||
// Test VM allows C2 to work
|
|
||||||
Asserts.assertTrue(info.isC2CompilationEnabled());
|
|
||||||
if (!info.isWarmUp()) {
|
|
||||||
// C2 compilation happens
|
|
||||||
Asserts.assertTrue(info.isTestC2Compiled());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* 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.irTests;
|
||||||
|
|
||||||
|
import jdk.test.lib.Asserts;
|
||||||
|
import compiler.lib.ir_framework.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8281453
|
||||||
|
* @summary Convert ~x into -1-x when ~x is used in an arithmetic expression
|
||||||
|
* @library /test/lib /
|
||||||
|
* @run driver compiler.c2.irTests.XorINodeIdealizationTests
|
||||||
|
*/
|
||||||
|
public class XorINodeIdealizationTests {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestFramework.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Run(test = {"test1", "test2", "test3",
|
||||||
|
"test4", "test5", "test6",
|
||||||
|
"test7", "test8", "test9",
|
||||||
|
"test10", "test11", "test12",
|
||||||
|
"test13", "test14", "test15",
|
||||||
|
"test16", "test17"})
|
||||||
|
public void runMethod() {
|
||||||
|
int a = RunInfo.getRandom().nextInt();
|
||||||
|
int b = RunInfo.getRandom().nextInt();
|
||||||
|
int c = RunInfo.getRandom().nextInt();
|
||||||
|
int d = RunInfo.getRandom().nextInt();
|
||||||
|
|
||||||
|
int min = Integer.MIN_VALUE;
|
||||||
|
int max = Integer.MAX_VALUE;
|
||||||
|
|
||||||
|
assertResult(0, 0, 0, 0);
|
||||||
|
assertResult(a, b, c, d);
|
||||||
|
assertResult(min, min, min, min);
|
||||||
|
assertResult(max, max, max, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DontCompile
|
||||||
|
public void assertResult(int a, int b, int c, int d) {
|
||||||
|
Asserts.assertEQ(b - a , test1(a, b));
|
||||||
|
Asserts.assertEQ(a - b , test2(a, b));
|
||||||
|
Asserts.assertEQ(b - a , test3(a, b));
|
||||||
|
Asserts.assertEQ(a - b , test4(a, b));
|
||||||
|
Asserts.assertEQ(b - a , test5(a, b));
|
||||||
|
Asserts.assertEQ(a + 1 , test6(a));
|
||||||
|
Asserts.assertEQ(a , test7(a));
|
||||||
|
Asserts.assertEQ((b + a) + 1 , test8(a, b));
|
||||||
|
Asserts.assertEQ((-1 - a) - b , test9(a, b));
|
||||||
|
Asserts.assertEQ((b - a) + (-1) , test10(a, b));
|
||||||
|
Asserts.assertEQ((b - a) + (-1) , test11(a, b));
|
||||||
|
Asserts.assertEQ(~a , test12(a));
|
||||||
|
Asserts.assertEQ(~a , test13(a));
|
||||||
|
Asserts.assertEQ(~a , test14(a));
|
||||||
|
Asserts.assertEQ(~a , test15(a));
|
||||||
|
Asserts.assertEQ((~a + b) + (~a | c), test16(a, b, c));
|
||||||
|
Asserts.assertEQ(-2023 - a , test17(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (~x + y) + 1 => y - x
|
||||||
|
public int test1(int x, int y) {
|
||||||
|
return (~x + y) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (x + ~y) + 1 => x - y
|
||||||
|
public int test2(int x, int y) {
|
||||||
|
return (x + ~y) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~x + (y + 1) => y - x
|
||||||
|
public int test3(int x, int y) {
|
||||||
|
return ~x + (y + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (x + 1) + ~y => x - y
|
||||||
|
public int test4(int x, int y) {
|
||||||
|
return (x + 1) + ~y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~x - ~y => y - x
|
||||||
|
public int test5(int x, int y) {
|
||||||
|
return ~x - ~y; // transformed to y - x
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.ADD, "1"})
|
||||||
|
// Checks 0 - ~x => x + 1
|
||||||
|
public int test6(int x) {
|
||||||
|
return 0 - ~x; // transformed to x + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR, IRNode.ADD})
|
||||||
|
// Checks -1 - ~x => x
|
||||||
|
public int test7(int x) {
|
||||||
|
return -1 - ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.ADD, "2"})
|
||||||
|
// Checks y - ~x => (y + x) + 1
|
||||||
|
public int test8(int x, int y) {
|
||||||
|
return y - ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.ADD, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "2"})
|
||||||
|
// Checks ~x - y => (-1 - x) -y
|
||||||
|
public int test9(int x, int y) {
|
||||||
|
return ~x - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1",
|
||||||
|
IRNode.ADD, "1"})
|
||||||
|
// Checks ~x + y => (y - x) + (-1)
|
||||||
|
public int test10(int x, int y) {
|
||||||
|
return ~x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1",
|
||||||
|
IRNode.ADD, "1"})
|
||||||
|
// Checks y + ~x => (y - x) + (-1)
|
||||||
|
public int test11(int x, int y) {
|
||||||
|
return y + ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~(x + 0) => ~x, should not be transformed into -1-x
|
||||||
|
public int test12(int x) {
|
||||||
|
return ~(x + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~(x - 0) => ~x, should not be transformed into -1-x
|
||||||
|
public int test13(int x) {
|
||||||
|
return ~(x - 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x + 0 => ~x, should not be transformed into -1-x
|
||||||
|
public int test14(int x) {
|
||||||
|
return ~x + 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x - 0 => ~x, should not be transformed into -1-x
|
||||||
|
public int test15(int x) {
|
||||||
|
return ~x - 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x + y should NOT be transformed into (y - x) + (-1)
|
||||||
|
// because ~x has one non-arithmetic user.
|
||||||
|
public int test16(int x, int y, int z) {
|
||||||
|
int u = ~x + y;
|
||||||
|
int v = ~x | z;
|
||||||
|
return u + v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~(x + c) => (-c-1) - x
|
||||||
|
public int test17(int x) {
|
||||||
|
return ~(x + 2022);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* 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.irTests;
|
||||||
|
|
||||||
|
import jdk.test.lib.Asserts;
|
||||||
|
import compiler.lib.ir_framework.*;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8281453
|
||||||
|
* @summary Convert ~x into -1-x when ~x is used in an arithmetic expression
|
||||||
|
* @library /test/lib /
|
||||||
|
* @run driver compiler.c2.irTests.XorLNodeIdealizationTests
|
||||||
|
*/
|
||||||
|
public class XorLNodeIdealizationTests {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
TestFramework.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Run(test = {"test1", "test2", "test3",
|
||||||
|
"test4", "test5", "test6",
|
||||||
|
"test7", "test8", "test9",
|
||||||
|
"test10", "test11", "test12",
|
||||||
|
"test13", "test14", "test15",
|
||||||
|
"test16", "test17"})
|
||||||
|
public void runMethod() {
|
||||||
|
long a = RunInfo.getRandom().nextLong();
|
||||||
|
long b = RunInfo.getRandom().nextLong();
|
||||||
|
long c = RunInfo.getRandom().nextLong();
|
||||||
|
long d = RunInfo.getRandom().nextLong();
|
||||||
|
|
||||||
|
long min = Long.MIN_VALUE;
|
||||||
|
long max = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
assertResult(0, 0, 0, 0);
|
||||||
|
assertResult(a, b, c, d);
|
||||||
|
assertResult(min, min, min, min);
|
||||||
|
assertResult(max, max, max, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DontCompile
|
||||||
|
public void assertResult(long a, long b, long c, long d) {
|
||||||
|
Asserts.assertEQ(b - a , test1(a, b));
|
||||||
|
Asserts.assertEQ(a - b , test2(a, b));
|
||||||
|
Asserts.assertEQ(b - a , test3(a, b));
|
||||||
|
Asserts.assertEQ(a - b , test4(a, b));
|
||||||
|
Asserts.assertEQ(b - a , test5(a, b));
|
||||||
|
Asserts.assertEQ(a + 1 , test6(a));
|
||||||
|
Asserts.assertEQ(a , test7(a));
|
||||||
|
Asserts.assertEQ((b + a) + 1 , test8(a, b));
|
||||||
|
Asserts.assertEQ((-1 - a) - b , test9(a, b));
|
||||||
|
Asserts.assertEQ((b - a) + (-1) , test10(a, b));
|
||||||
|
Asserts.assertEQ((b - a) + (-1) , test11(a, b));
|
||||||
|
Asserts.assertEQ(~a , test12(a));
|
||||||
|
Asserts.assertEQ(~a , test13(a));
|
||||||
|
Asserts.assertEQ(~a , test14(a));
|
||||||
|
Asserts.assertEQ(~a , test15(a));
|
||||||
|
Asserts.assertEQ((~a + b) + (~a | c), test16(a, b, c));
|
||||||
|
Asserts.assertEQ(-2023 - a , test17(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (~x + y) + 1 => y - x
|
||||||
|
public long test1(long x, long y) {
|
||||||
|
return (~x + y) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (x + ~y) + 1 => x - y
|
||||||
|
public long test2(long x, long y) {
|
||||||
|
return (x + ~y) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~x + (y + 1) => y - x
|
||||||
|
public long test3(long x, long y) {
|
||||||
|
return ~x + (y + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks (x + 1) + ~y => x - y
|
||||||
|
public long test4(long x, long y) {
|
||||||
|
return (x + 1) + ~y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~x - ~y => y - x
|
||||||
|
public long test5(long x, long y) {
|
||||||
|
return ~x - ~y; // transformed to y - x
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.ADD, "1"})
|
||||||
|
// Checks 0 - ~x => x + 1
|
||||||
|
public long test6(long x) {
|
||||||
|
return 0 - ~x; // transformed to x + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR, IRNode.ADD})
|
||||||
|
// Checks -1 - ~x => x
|
||||||
|
public long test7(long x) {
|
||||||
|
return -1 - ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.ADD, "2"})
|
||||||
|
// Checks y - ~x => (y + x) + 1
|
||||||
|
public long test8(long x, long y) {
|
||||||
|
return y - ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.ADD, IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "2"})
|
||||||
|
// Checks ~x - y => (-1 - x) -y
|
||||||
|
public long test9(long x, long y) {
|
||||||
|
return ~x - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1",
|
||||||
|
IRNode.ADD, "1"})
|
||||||
|
// Checks ~x + y => (y - x) + (-1)
|
||||||
|
public long test10(long x, long y) {
|
||||||
|
return ~x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR})
|
||||||
|
@IR(counts = {IRNode.SUB, "1",
|
||||||
|
IRNode.ADD, "1"})
|
||||||
|
// Checks y + ~x => (y - x) + (-1)
|
||||||
|
public long test11(long x, long y) {
|
||||||
|
return y + ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~(x + 0) => ~x, should not be transformed into -1-x
|
||||||
|
public long test12(long x) {
|
||||||
|
return ~(x + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~(x - 0) => ~x, should not be transformed into -1-x
|
||||||
|
public long test13(long x) {
|
||||||
|
return ~(x - 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x + 0 => ~x, should not be transformed into -1-x
|
||||||
|
public long test14(long x) {
|
||||||
|
return ~x + 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.SUB, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x - 0 => ~x, should not be transformed into -1-x
|
||||||
|
public long test15(long x) {
|
||||||
|
return ~x - 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(counts = {IRNode.XOR, "1"})
|
||||||
|
// Checks ~x + y should NOT be transformed into (y - x) + (-1)
|
||||||
|
// because ~x has one non-arithmetic user.
|
||||||
|
public long test16(long x, long y, long z) {
|
||||||
|
long u = ~x + y;
|
||||||
|
long v = ~x | z;
|
||||||
|
return u + v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@IR(failOn = {IRNode.XOR, IRNode.ADD})
|
||||||
|
@IR(counts = {IRNode.SUB, "1"})
|
||||||
|
// Checks ~(x + c) => (-c-1) - x
|
||||||
|
public long test17(long x) {
|
||||||
|
return ~(x + 2022);
|
||||||
|
}
|
||||||
|
}
|
@ -151,6 +151,7 @@ public class IRNode {
|
|||||||
public static final String AND = START + "And(I|L)" + MID + END;
|
public static final String AND = START + "And(I|L)" + MID + END;
|
||||||
public static final String AND_I = START + "AndI" + MID + END;
|
public static final String AND_I = START + "AndI" + MID + END;
|
||||||
public static final String AND_L = START + "AndL" + MID + END;
|
public static final String AND_L = START + "AndL" + MID + END;
|
||||||
|
public static final String XOR = START + "Xor(I|L)" + MID + END;
|
||||||
public static final String XOR_I = START + "XorI" + MID + END;
|
public static final String XOR_I = START + "XorI" + MID + END;
|
||||||
public static final String XOR_L = START + "XorL" + MID + END;
|
public static final String XOR_L = START + "XorL" + MID + END;
|
||||||
public static final String LSHIFT = START + "LShift(I|L)" + MID + END;
|
public static final String LSHIFT = START + "LShift(I|L)" + MID + END;
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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
|
||||||
|
* 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 org.openjdk.bench.vm.compiler;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.CompilerControl;
|
||||||
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests transformation that converts `~x` into `-1-x` when `~x` is
|
||||||
|
* used in an arithmetic expression.
|
||||||
|
*/
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@Warmup(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@Measurement(iterations = 20, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@Fork(value = 3)
|
||||||
|
public class NotOpTransformation {
|
||||||
|
|
||||||
|
private static final int I_C = 1234567;
|
||||||
|
|
||||||
|
private static final long L_C = 123_456_789_123_456L;
|
||||||
|
|
||||||
|
private int iFld = 4711;
|
||||||
|
|
||||||
|
private long lFld = 4711 * 4711 * 4711;
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void baselineInt(Blackhole bh) {
|
||||||
|
bh.consume(iFld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public void baselineLong(Blackhole bh) {
|
||||||
|
bh.consume(lFld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert c-(~x)-x into c-(-1-x)-x, which is finally converted
|
||||||
|
// into c+1.
|
||||||
|
@Benchmark
|
||||||
|
public void testInt1(Blackhole bh) {
|
||||||
|
bh.consume(I_C - (~iFld) - iFld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert ~(c-x)-x into -1-(c-x)-x, which is finally converted
|
||||||
|
// into -1-c.
|
||||||
|
@Benchmark
|
||||||
|
public void testInt2(Blackhole bh) {
|
||||||
|
bh.consume(~(I_C - iFld) - iFld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert c-(~x)-x into c-(-1-x)-x, which is finally converted
|
||||||
|
// into c+1.
|
||||||
|
@Benchmark
|
||||||
|
public void testLong1(Blackhole bh) {
|
||||||
|
bh.consume(L_C - (~lFld) - lFld);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert ~(c-x)-x into -1-(c-x)-x, which is finally converted
|
||||||
|
// into -1-c.
|
||||||
|
@Benchmark
|
||||||
|
public void testLong2(Blackhole bh) {
|
||||||
|
bh.consume(~(L_C - lFld) - lFld);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user