+{"files":[{"patch":"@@ -1085,0 +1085,79 @@\n+\/\/ Ideal transformations for MaxINode\n+Node* MaxINode::Ideal(PhaseGVN* phase, bool can_reshape) {\n+ \/\/ Force a right-spline graph\n+ Node* l = in(1);\n+ Node* r = in(2);\n+ \/\/ Transform MaxI1(MaxI2(a, b), c) into MaxI1(a, MaxI2(b, c))\n+ \/\/ to force a right-spline graph for the rest of MaxINode::Ideal().\n+ if (l->Opcode() == Op_MaxI) {\n+ assert(l != l->in(1), \"dead loop in MaxINode::Ideal\");\n+ r = phase->transform(new MaxINode(l->in(2), r));\n+ l = l->in(1);\n+ set_req_X(1, l, phase);\n+ set_req_X(2, r, phase);\n+ return this;\n+ }\n+\n+ \/\/ Get left input & constant\n+ Node* x = l;\n+ jint x_off = 0;\n+ if (x->Opcode() == Op_AddI && \/\/ Check for \"x+c0\" and collect constant\n+ x->in(2)->is_Con()) {\n+ const Type* t = x->in(2)->bottom_type();\n+ if (t == Type::TOP) return NULL; \/\/ No progress\n+ x_off = t->is_int()->get_con();\n+ x = x->in(1);\n+ }\n+\n+ \/\/ Scan a right-spline-tree for MAXs\n+ Node* y = r;\n+ jint y_off = 0;\n+ \/\/ Check final part of MAX tree\n+ if (y->Opcode() == Op_AddI && \/\/ Check for \"y+c1\" and collect constant\n+ y->in(2)->is_Con()) {\n+ const Type* t = y->in(2)->bottom_type();\n+ if (t == Type::TOP) return NULL; \/\/ No progress\n+ y_off = t->is_int()->get_con();\n+ y = y->in(1);\n+ }\n+ if (x->_idx > y->_idx && r->Opcode() != Op_MaxI) {\n+ swap_edges(1, 2);\n+ return this;\n+ }\n+\n+ const TypeInt* tx = phase->type(x)->isa_int();\n+\n+ if (r->Opcode() == Op_MaxI) {\n+ assert(r != r->in(2), \"dead loop in MaxINode::Ideal\");\n+ y = r->in(1);\n+ \/\/ Check final part of MAX tree\n+ if (y->Opcode() == Op_AddI &&\/\/ Check for \"y+c1\" and collect constant\n+ y->in(2)->is_Con()) {\n+ const Type* t = y->in(2)->bottom_type();\n+ if (t == Type::TOP) return NULL; \/\/ No progress\n+ y_off = t->is_int()->get_con();\n+ y = y->in(1);\n+ }\n+\n+ if (x->_idx > y->_idx)\n+ return new MaxINode(r->in(1), phase->transform(new MaxINode(l, r->in(2))));\n+\n+ \/\/ Transform MAX2(x + c0, MAX2(x + c1, z)) into MAX2(x + MAX2(c0, c1), z)\n+ \/\/ if x == y and the additions can't overflow.\n+ if (x == y && tx != NULL &&\n+ !can_overflow(tx, x_off) &&\n+ !can_overflow(tx, y_off)) {\n+ return new MaxINode(phase->transform(new AddINode(x, phase->intcon(MAX2(x_off, y_off)))), r->in(2));\n+ }\n+ } else {\n+ \/\/ Transform MAX2(x + c0, y + c1) into x + MAX2(c0, c1)\n+ \/\/ if x == y and the additions can't overflow.\n+ if (x == y && tx != NULL &&\n+ !can_overflow(tx, x_off) &&\n+ !can_overflow(tx, y_off)) {\n+ return new AddINode(x, phase->intcon(MAX2(x_off, y_off)));\n+ }\n+ }\n+ return NULL;\n+}\n+\n","filename":"src\/hotspot\/share\/opto\/addnode.cpp","additions":79,"deletions":0,"binary":false,"changes":79,"status":"modified"},{"patch":"@@ -2,1 +2,1 @@\n- * Copyright (c) 1997, 2021, Oracle and\/or its affiliates. All rights reserved.\n+ * Copyright (c) 1997, 2022, Oracle and\/or its affiliates. All rights reserved.\n@@ -302,0 +302,1 @@\n+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);\n","filename":"src\/hotspot\/share\/opto\/addnode.hpp","additions":2,"deletions":1,"binary":false,"changes":3,"status":"modified"},{"patch":"@@ -0,0 +1,119 @@\n+\/*\n+ * Copyright (c) 2022, Arm Limited. All rights reserved.\n+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n+ *\n+ * This code is free software; you can redistribute it and\/or modify it\n+ * under the terms of the GNU General Public License version 2 only, as\n+ * published by the Free Software Foundation.\n+ *\n+ * This code is distributed in the hope that it will be useful, but WITHOUT\n+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n+ * version 2 for more details (a copy is included in the LICENSE file that\n+ * accompanied this code).\n+ *\n+ * You should have received a copy of the GNU General Public License version\n+ * 2 along with this work; if not, write to the Free Software Foundation,\n+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n+ *\n+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n+ * or visit www.oracle.com if you need additional information or have any\n+ * questions.\n+ *\/\n+package compiler.c2.irTests;\n+\n+import jdk.test.lib.Asserts;\n+import compiler.lib.ir_framework.*;\n+\n+\/*\n+ * @test\n+ * @bug 8290248\n+ * @summary Test that Ideal transformations of MaxINode and MinINode are\n+ * being performed as expected.\n+ * @library \/test\/lib \/\n+ * @run driver compiler.c2.irTests.MaxMinINodeIdealizationTests\n+ *\/\n+\n+public class MaxMinINodeIdealizationTests {\n+ public static void main(String[] args) {\n+ TestFramework.run();\n+ }\n+\n+ @Run(test = {\"testMax1\", \"testMax2\", \"testMax3\", \"testMin1\", \"testMin2\", \"testMin3\"})\n+ public void runMethod() {\n+ int a = RunInfo.getRandom().nextInt();\n+ int min = Integer.MIN_VALUE;\n+ int max = Integer.MAX_VALUE;\n+\n+ assertResult(a);\n+ assertResult(0);\n+ assertResult(min);\n+ assertResult(max);\n+ }\n+\n+ @DontCompile\n+ public void assertResult(int a) {\n+ Asserts.assertEQ(Math.max(((a >> 1) + 100), Math.max(((a >> 1) + 150), 200)), testMax1(a));\n+ Asserts.assertEQ(Math.max(((a >> 1) + 10), ((a >> 1) + 11)) , testMax2(a));\n+ Asserts.assertEQ(Math.max(a, a) , testMax3(a));\n+\n+ Asserts.assertEQ(Math.min(((a >> 1) + 100), Math.min(((a >> 1) + 150), 200)), testMin1(a));\n+ Asserts.assertEQ(Math.min(((a >> 1) + 10), ((a >> 1) + 11)) , testMin2(a));\n+ Asserts.assertEQ(Math.min(a, a) , testMin3(a));\n+ }\n+\n+ \/\/ The transformations in test*1 and test*2 can happen only if the compiler has enough information\n+ \/\/ to determine that the two addition operations can not overflow.\n+\n+ \/\/ Transform max(x + c0, max(y + c1, z)) to max(add(x, c2), z) if x == y, where c2 = MAX2(c0, c1).\n+ \/\/ c0,c1,c2 are constants. x,y,z can be any valid c2 nodes. In this example, x and y are\n+ \/\/ RShiftI nodes and z is a ConI.\n+ @Test\n+ @IR(counts = {IRNode.Max_I, \"1\",\n+ IRNode.ADD , \"1\",\n+ })\n+ public int testMax1(int i) {\n+ return Math.max(((i >> 1) + 100), Math.max(((i >> 1) + 150), 200));\n+ }\n+\n+ \/\/ Similarly, transform min(x + c0, min(y + c1, z)) to min(add(x, c2), z) if x == y, where c2 = MIN2(c0, c1).\n+ @Test\n+ @IR(counts = {IRNode.Min_I, \"1\",\n+ IRNode.ADD , \"1\",\n+ })\n+ public int testMin1(int i) {\n+ return Math.min(((i >> 1) + 100), Math.min(((i >> 1) + 150), 200));\n+ }\n+\n+ \/\/ Transform max(x + c0, y + c1) to add(x, c2) if x == y, where c2 = MAX2(c0, c1).\n+ \/\/ c0,c1,c2 are constants. x and y can be any valid c2 nodes. If they are equal, this\n+ \/\/ transformation would take place. In this example, x and y are same RShiftI nodes.\n+ @Test\n+ @IR(failOn = {IRNode.Max_I})\n+ @IR(counts = {IRNode.ADD, \"1\"})\n+ public int testMax2(int i) {\n+ return Math.max((i >> 1) + 10, (i >> 1) + 11);\n+ }\n+\n+ \/\/ Similarly, transform min(x + c0, y + c1) to add(x, c2) if x == y, where c2 = MIN2(c0, c1).\n+ @Test\n+ @IR(failOn = {IRNode.Min_I})\n+ @IR(counts = {IRNode.ADD, \"1\"})\n+ public int testMin2(int i) {\n+ return Math.min((i >> 1) + 10, (i >> 1) + 11);\n+ }\n+\n+ \/\/ Return the same node without generating a MaxINode\/MinINode when a node is compared with itself.\n+ \/\/ In this test, an integer is being compared with itself but it can be any valid c2 node.\n+ @Test\n+ @IR(failOn = {IRNode.Max_I})\n+ public int testMax3(int i) {\n+ return Math.max(i, i);\n+ }\n+\n+ @Test\n+ @IR(failOn = {IRNode.Min_I})\n+ public int testMin3(int i) {\n+ return Math.min(i, i);\n+ }\n+}\n","filename":"test\/hotspot\/jtreg\/compiler\/c2\/irTests\/MaxMinINodeIdealizationTests.java","additions":119,"deletions":0,"binary":false,"changes":119,"status":"added"},{"patch":"@@ -214,0 +214,2 @@\n+ public static final String Min_I = START + \"MinI\" + MID + END;\n+ public static final String Max_I = START + \"MaxI\" + MID + END;\n","filename":"test\/hotspot\/jtreg\/compiler\/lib\/ir_framework\/IRNode.java","additions":2,"deletions":0,"binary":false,"changes":2,"status":"modified"}]}
0 commit comments