8291336: Add ideal rule to convert floating point multiply by 2 into addition
Reviewed-by: qamai, thartmann, chagedorn
This commit is contained in:
parent
4b89fce083
commit
cf5546b3ac
@ -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 {
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user