8291336: Add ideal rule to convert floating point multiply by 2 into addition

Reviewed-by: qamai, thartmann, chagedorn
This commit is contained in:
SuperCoder79 2022-10-28 10:04:38 +00:00 committed by Christian Hagedorn
parent 4b89fce083
commit cf5546b3ac
4 changed files with 154 additions and 0 deletions

View File

@ -423,6 +423,20 @@ const Type *MulFNode::mul_ring(const Type *t0, const Type *t1) const {
return TypeF::make( t0->getf() * t1->getf() );
}
//------------------------------Ideal---------------------------------------
// Check to see if we are multiplying by a constant 2 and convert to add, then try the regular MulNode::Ideal
Node* MulFNode::Ideal(PhaseGVN* phase, bool can_reshape) {
const TypeF *t2 = phase->type(in(2))->isa_float_constant();
// x * 2 -> x + x
if (t2 != NULL && t2->getf() == 2) {
Node* base = in(1);
return new AddFNode(base, base);
}
return MulNode::Ideal(phase, can_reshape);
}
//=============================================================================
//------------------------------mul_ring---------------------------------------
// Compute the product type of two double ranges into this node.
@ -432,6 +446,20 @@ const Type *MulDNode::mul_ring(const Type *t0, const Type *t1) const {
return TypeD::make( t0->getd() * t1->getd() );
}
//------------------------------Ideal---------------------------------------
// Check to see if we are multiplying by a constant 2 and convert to add, then try the regular MulNode::Ideal
Node* MulDNode::Ideal(PhaseGVN* phase, bool can_reshape) {
const TypeD *t2 = phase->type(in(2))->isa_double_constant();
// x * 2 -> x + x
if (t2 != NULL && t2->getd() == 2) {
Node* base = in(1);
return new AddDNode(base, base);
}
return MulNode::Ideal(phase, can_reshape);
}
//=============================================================================
//------------------------------Value------------------------------------------
const Type* MulHiLNode::Value(PhaseGVN* phase) const {

View File

@ -130,6 +130,7 @@ class MulFNode : public MulNode {
public:
MulFNode( Node *in1, Node *in2 ) : MulNode(in1,in2) {}
virtual int Opcode() const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual const Type *mul_ring( const Type *, const Type * ) const;
const Type *mul_id() const { return TypeF::ONE; }
const Type *add_id() const { return TypeF::ZERO; }
@ -147,6 +148,7 @@ class MulDNode : public MulNode {
public:
MulDNode( Node *in1, Node *in2 ) : MulNode(in1,in2) {}
virtual int Opcode() const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual const Type *mul_ring( const Type *, const Type * ) const;
const Type *mul_id() const { return TypeD::ONE; }
const Type *add_id() const { return TypeD::ZERO; }

View File

@ -0,0 +1,73 @@
/*
* 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.*;
import java.util.Random;
import jdk.test.lib.Utils;
/*
* @test
* @bug 8291336
* @summary Test that transformation of multiply-by-2 is appropriately turned into additions.
* @library /test/lib /
* @requires vm.compiler2.enabled
* @run driver compiler.c2.irTests.TestMulNodeIdealization
*/
public class TestMulNodeIdealization {
private static final Random RANDOM = Utils.getRandomInstance();
public static void main(String[] args) {
TestFramework.run();
}
@Test
@IR(failOn = {IRNode.MUL})
// Checks x * 2 -> x + x
public float testFloat(float x) {
return x * 2;
}
@Test
@IR(failOn = {IRNode.MUL})
// Checks x * 2 -> x + x
public double testDouble(double x) {
return x * 2;
}
@Run(test = "testFloat")
public void runTestFloat() {
float value = RANDOM.nextFloat();
float interpreterResult = value * 2;
Asserts.assertEQ(testFloat(value), interpreterResult);
}
@Run(test = "testDouble")
public void runTestDouble() {
double value = RANDOM.nextDouble();
double interpreterResult = value * 2;
Asserts.assertEQ(testDouble(value), interpreterResult);
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.*;
import org.openjdk.jmh.infra.Blackhole;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
@Fork(3)
public class MulNodeIdealize {
private static final int SIZE = 50;
@Benchmark
public void testMul2Float(Blackhole blackhole) {
for (float i = 0; i < SIZE; i++) {
blackhole.consume(i * 2);
}
}
@Benchmark
public void testMul2Double(Blackhole blackhole) {
for (double i = 0; i < SIZE; i++) {
blackhole.consume(i * 2);
}
}
}