From c7755b815d149425534aa4344c753591aa41b725 Mon Sep 17 00:00:00 2001 From: Zhiqiang Zang Date: Wed, 13 Apr 2022 16:01:10 +0000 Subject: [PATCH] 8283094: Add Ideal transformation: x + (con - y) -> (x - y) + con Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/addnode.cpp | 14 +-- src/hotspot/share/opto/node.hpp | 8 ++ .../c2/irTests/AddINodeIdealizationTests.java | 48 +++++++++- .../c2/irTests/AddLNodeIdealizationTests.java | 91 ++++++++++++++----- .../compiler/lib/ir_framework/IRNode.java | 2 + 5 files changed, 135 insertions(+), 28 deletions(-) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 9edb868b7bf..deed562a762 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -304,14 +304,16 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { } } - // Convert "x+(0-y)" into "(x-y)" - if (op2 == Op_Sub(bt) && phase->type(in2->in(1)) == TypeInteger::zero(bt)) { - return SubNode::make(in1, in2->in(2), bt); + // Convert (con - y) + x into "(x - y) + con" + if (op1 == Op_Sub(bt) && in1->in(1)->Opcode() == Op_ConIL(bt) + && in1 != in1->in(2) && !(in1->in(2)->is_Phi() && in1->in(2)->as_Phi()->is_tripcount(bt))) { + return AddNode::make(phase->transform(SubNode::make(in2, in1->in(2), bt)), in1->in(1), bt); } - // Convert "(0-y)+x" into "(x-y)" - if (op1 == Op_Sub(bt) && phase->type(in1->in(1)) == TypeInteger::zero(bt)) { - return SubNode::make(in2, in1->in(2), bt); + // Convert x + (con - y) into "(x - y) + con" + if (op2 == Op_Sub(bt) && in2->in(1)->Opcode() == Op_ConIL(bt) + && in2 != in2->in(2) && !(in2->in(2)->is_Phi() && in2->in(2)->as_Phi()->is_tripcount(bt))) { + return AddNode::make(phase->transform(SubNode::make(in1, in2->in(2), bt)), in2->in(1), bt); } // Associative diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 9d5e948fd8b..5a99734a84c 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1853,6 +1853,14 @@ Op_IL(LShift) Op_IL(Xor) Op_IL(Cmp) +inline int Op_ConIL(BasicType bt) { + assert(bt == T_INT || bt == T_LONG, "only for int or longs"); + if (bt == T_INT) { + return Op_ConI; + } + return Op_ConL; +} + inline int Op_Cmp_unsigned(BasicType bt) { assert(bt == T_INT || bt == T_LONG, "only for int or longs"); if (bt == T_INT) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java index ede1f4e89c0..afd28850df3 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java @@ -43,7 +43,9 @@ public class AddINodeIdealizationTests { "test8", "test9", "test10", "test11", "test12", "test13", "test14", "test15", "test16", - "test17", "test18", "test19"}) + "test17", "test18", "test19", + "test20", "test21", "test22", + "test23"}) public void runMethod() { int a = RunInfo.getRandom().nextInt(); int b = RunInfo.getRandom().nextInt(); @@ -82,6 +84,10 @@ public class AddINodeIdealizationTests { Asserts.assertEQ(a*b + b*c , test17(a, b, c)); Asserts.assertEQ(a*c + b*c , test18(a, b, c)); Asserts.assertEQ(a*b + c*a , test19(a, b, c)); + Asserts.assertEQ((a - b) + 210 , test20(a, b)); + Asserts.assertEQ((a - b) + 190 , test21(a, b)); + Asserts.assertEQ((a - b) + 210 , test22(a, b)); + Asserts.assertEQ((a - b) + 190 , test23(a, b)); } @Test @@ -247,4 +253,44 @@ public class AddINodeIdealizationTests { public int test19(int a, int b, int c) { return a*b + c*a; } + + @Test + @IR(counts = {IRNode.SUB_I, "1", + IRNode.ADD_I, "1", + IRNode.CON_I, "1"}) + // Checks x + (con - y) => (x - y) + con + // where con > 0 + public int test20(int x, int y) { + return x + (10 - y) + 200; // transformed to (x - y) + 210; + } + + @Test + @IR(counts = {IRNode.SUB_I, "1", + IRNode.ADD_I, "1", + IRNode.CON_I, "1"}) + // Checks x + (con - y) => (x - y) + con + // where con < 0 + public int test21(int x, int y) { + return x + (-10 - y) + 200; // transformed to (x - y) + 190; + } + + @Test + @IR(counts = {IRNode.SUB_I, "1", + IRNode.ADD_I, "1", + IRNode.CON_I, "1"}) + // Checks (con - y) + x => (x - y) + con + // where con > 0 + public int test22(int x, int y) { + return (10 - y) + x + 200; // transformed to (x - y) + 210; + } + + @Test + @IR(counts = {IRNode.SUB_I, "1", + IRNode.ADD_I, "1", + IRNode.CON_I, "1"}) + // Checks (con - y) + x => (x - y) + con + // where con < 0 + public int test23(int x, int y) { + return x + (-10 - y) + 200; // transformed to (x - y) + 190; + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/AddLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/AddLNodeIdealizationTests.java index 6ea1cf6a262..ca318382cfc 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/AddLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/AddLNodeIdealizationTests.java @@ -43,7 +43,8 @@ public class AddLNodeIdealizationTests { "test8", "test9", "test10", "test11", "test12", "test13", "test14", "test15", "test16", - "test17", "test18"}) + "test17", "test18", "test19", + "test20","test21", "test22"}) public void runMethod() { long a = RunInfo.getRandom().nextLong(); long b = RunInfo.getRandom().nextLong(); @@ -61,26 +62,30 @@ public class AddLNodeIdealizationTests { @DontCompile public void assertResult(long a, long b, long c, long d) { - Asserts.assertEQ(((a+a) + (a+a)) , additions(a)); - Asserts.assertEQ(0L , xMinusX(a)); - Asserts.assertEQ(a + 1 + 2 , test1(a)); - Asserts.assertEQ((a + 2021) + b , test2(a, b)); - Asserts.assertEQ(a + (b + 2021) , test3(a, b)); - Asserts.assertEQ((1 - a) + 2 , test4(a)); - Asserts.assertEQ((a - b) + (c - d), test5(a, b, c, d)); - Asserts.assertEQ((a - b) + (b + c), test6(a, b, c)); - Asserts.assertEQ((a - b) + (c + b), test7(a, b, c)); - Asserts.assertEQ((a - b) + (c - a), test8(a, b, c)); - Asserts.assertEQ(a + (0 - b) , test9(a, b)); - Asserts.assertEQ((0 - b) + a , test10(a, b)); - Asserts.assertEQ((a - b) + b , test11(a, b)); - Asserts.assertEQ(b + (a - b) , test12(a, b)); - Asserts.assertEQ(a + 0 , test13(a)); - Asserts.assertEQ(0 + a , test14(a)); - Asserts.assertEQ(a*b + a*c , test15(a, b, c)); - Asserts.assertEQ(a*b + b*c , test16(a, b, c)); - Asserts.assertEQ(a*c + b*c , test17(a, b, c)); - Asserts.assertEQ(a*b + c*a , test18(a, b, c)); + Asserts.assertEQ(((a+a) + (a+a)) , additions(a)); + Asserts.assertEQ(0L , xMinusX(a)); + Asserts.assertEQ(a + 1 + 2 , test1(a)); + Asserts.assertEQ((a + 2021) + b , test2(a, b)); + Asserts.assertEQ(a + (b + 2021) , test3(a, b)); + Asserts.assertEQ((1 - a) + 2 , test4(a)); + Asserts.assertEQ((a - b) + (c - d) , test5(a, b, c, d)); + Asserts.assertEQ((a - b) + (b + c) , test6(a, b, c)); + Asserts.assertEQ((a - b) + (c + b) , test7(a, b, c)); + Asserts.assertEQ((a - b) + (c - a) , test8(a, b, c)); + Asserts.assertEQ(a + (0 - b) , test9(a, b)); + Asserts.assertEQ((0 - b) + a , test10(a, b)); + Asserts.assertEQ((a - b) + b , test11(a, b)); + Asserts.assertEQ(b + (a - b) , test12(a, b)); + Asserts.assertEQ(a + 0 , test13(a)); + Asserts.assertEQ(0 + a , test14(a)); + Asserts.assertEQ(a*b + a*c , test15(a, b, c)); + Asserts.assertEQ(a*b + b*c , test16(a, b, c)); + Asserts.assertEQ(a*c + b*c , test17(a, b, c)); + Asserts.assertEQ(a*b + c*a , test18(a, b, c)); + Asserts.assertEQ((a - b) + 123_456_789_123L , test19(a, b)); + Asserts.assertEQ((a - b) + -123_456_788_877L , test20(a, b)); + Asserts.assertEQ((a - b) + 123_456_789_123L , test21(a, b)); + Asserts.assertEQ((a - b) + -123_456_788_877L , test22(a, b)); } @Test @@ -238,4 +243,48 @@ public class AddLNodeIdealizationTests { public long test18(long a, long b, long c) { return a*b + c*a; } + + @Test + @IR(counts = {IRNode.SUB_L, "1", + IRNode.ADD_L, "1", + IRNode.CON_L, "1"}) + // Checks x + (con - y) => (x - y) + con + // where con > 0 + public long test19(long x, long y) { + return x + (123_456_789_000L - y) + 123; + // transformed to (x - y) + 123_456_789_123L; + } + + @Test + @IR(counts = {IRNode.SUB_L, "1", + IRNode.ADD_L, "1", + IRNode.CON_L, "1"}) + // Checks x + (con - y) => (x - y) + con + // where con < 0 + public long test20(long x, long y) { + return x + (-123_456_789_000L - y) + 123; + // transformed to (x - y) + -123_456_788_877L; + } + + @Test + @IR(counts = {IRNode.SUB_L, "1", + IRNode.ADD_L, "1", + IRNode.CON_L, "1"}) + // Checks (con - y) + x => (x - y) + con + // where con > 0 + public long test21(long x, long y) { + return x + (123_456_789_000L - y) + 123; + // transformed to (x - y) + 123_456_789_123L; + } + + @Test + @IR(counts = {IRNode.SUB_L, "1", + IRNode.ADD_L, "1", + IRNode.CON_L, "1"}) + // Checks (con - y) + x => (x - y) + con + // where con < 0 + public long test22(long x, long y) { + return x + (-123_456_789_000L - y) + 123; + // transformed to (x - y) + -123_456_788_877L; + } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index de91a0054b2..27c358abe69 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -171,6 +171,8 @@ public class IRNode { public static final String MUL_L = START + "MulL" + MID + END; public static final String DIV = START + "Div(I|L|F|D)" + MID + END; public static final String DIV_L = START + "DivL" + MID + END; + public static final String CON_I = START + "ConI" + MID + END; + public static final String CON_L = START + "ConL" + MID + END; public static final String CONV_I2L = START + "ConvI2L" + MID + END; public static final String CONV_L2I = START + "ConvL2I" + MID + END; public static final String POPCOUNT_L = START + "PopCountL" + MID + END;