Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8263006: Add optimization for Max(*)Node and Min(*)Node
Co-authored-by: Wang Huang <whuang@openjdk.org>
Co-authored-by: Wu Yan <wuyan34@huawei.com>
Reviewed-by: kvn
  • Loading branch information
2 people authored and Vladimir Kozlov committed May 14, 2021
1 parent 16ca370 commit 599d07c
Show file tree
Hide file tree
Showing 6 changed files with 473 additions and 10 deletions.
37 changes: 29 additions & 8 deletions src/hotspot/share/opto/addnode.cpp
Expand Up @@ -62,10 +62,35 @@ Node* AddNode::Identity(PhaseGVN* phase) {

//------------------------------commute----------------------------------------
// Commute operands to move loads and constants to the right.
static bool commute(Node *add, bool con_left, bool con_right) {
static bool commute(PhaseGVN* phase, Node* add) {
Node *in1 = add->in(1);
Node *in2 = add->in(2);

// convert "max(a,b) + min(a,b)" into "a+b".
if ((in1->Opcode() == add->as_Add()->max_opcode() && in2->Opcode() == add->as_Add()->min_opcode())
|| (in1->Opcode() == add->as_Add()->min_opcode() && in2->Opcode() == add->as_Add()->max_opcode())) {
Node *in11 = in1->in(1);
Node *in12 = in1->in(2);

Node *in21 = in2->in(1);
Node *in22 = in2->in(2);

if ((in11 == in21 && in12 == in22) ||
(in11 == in22 && in12 == in21)) {
add->set_req(1, in11);
add->set_req(2, in12);
PhaseIterGVN* igvn = phase->is_IterGVN();
if (igvn) {
igvn->_worklist.push(in1);
igvn->_worklist.push(in2);
}
return true;
}
}

bool con_left = phase->type(in1)->singleton();
bool con_right = phase->type(in2)->singleton();

// Convert "1+x" into "x+1".
// Right is a constant; leave it
if( con_right ) return false;
Expand Down Expand Up @@ -115,7 +140,7 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
bool con_right = t2->singleton();

// Check for commutative operation desired
if (commute(this, con_left, con_right)) return this;
if (commute(phase, this)) return this;

AddNode *progress = NULL; // Progress flag

Expand Down Expand Up @@ -539,9 +564,7 @@ Node *AddFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}

// Floating point additions are not associative because of boundary conditions (infinity)
return commute(this,
phase->type( in(1) )->singleton(),
phase->type( in(2) )->singleton() ) ? this : NULL;
return commute(phase, this) ? this : NULL;
}


Expand Down Expand Up @@ -576,9 +599,7 @@ Node *AddDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}

// Floating point additions are not associative because of boundary conditions (infinity)
return commute(this,
phase->type( in(1) )->singleton(),
phase->type( in(2) )->singleton() ) ? this : NULL;
return commute(phase, this) ? this : NULL;
}


Expand Down
40 changes: 40 additions & 0 deletions src/hotspot/share/opto/addnode.hpp
Expand Up @@ -68,6 +68,12 @@ class AddNode : public Node {
// Supplied function to return the additive identity type
virtual const Type *add_id() const = 0;

// Supplied function to return the additive opcode
virtual int max_opcode() const = 0;

// Supplied function to return the multiplicative opcode
virtual int min_opcode() const = 0;

virtual bool operates_on(BasicType bt, bool signed_int) const {
assert(bt == T_INT || bt == T_LONG, "unsupported");
return false;
Expand All @@ -84,6 +90,8 @@ class AddINode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeInt::ZERO; }
virtual const Type *bottom_type() const { return TypeInt::INT; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual Node* Identity(PhaseGVN* phase);
virtual bool operates_on(BasicType bt, bool signed_int) const {
Expand All @@ -102,6 +110,8 @@ class AddLNode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeLong::ZERO; }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual Node* Identity(PhaseGVN* phase);
virtual bool operates_on(BasicType bt, bool signed_int) const {
Expand All @@ -122,6 +132,8 @@ class AddFNode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeF::ZERO; }
virtual const Type *bottom_type() const { return Type::FLOAT; }
int max_opcode() const { return Op_MaxF; }
int min_opcode() const { return Op_MinF; }
virtual Node* Identity(PhaseGVN* phase) { return this; }
virtual uint ideal_reg() const { return Op_RegF; }
};
Expand All @@ -137,6 +149,8 @@ class AddDNode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeD::ZERO; }
virtual const Type *bottom_type() const { return Type::DOUBLE; }
int max_opcode() const { return Op_MaxD; }
int min_opcode() const { return Op_MinD; }
virtual Node* Identity(PhaseGVN* phase) { return this; }
virtual uint ideal_reg() const { return Op_RegD; }
};
Expand Down Expand Up @@ -183,6 +197,8 @@ class OrINode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeInt::ZERO; }
virtual const Type *bottom_type() const { return TypeInt::INT; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
virtual Node* Identity(PhaseGVN* phase);
virtual uint ideal_reg() const { return Op_RegI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
Expand All @@ -198,6 +214,8 @@ class OrLNode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeLong::ZERO; }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual Node* Identity(PhaseGVN* phase);
virtual uint ideal_reg() const { return Op_RegL; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
Expand All @@ -212,6 +230,8 @@ class XorINode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeInt::ZERO; }
virtual const Type *bottom_type() const { return TypeInt::INT; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
virtual const Type *Value(PhaseGVN *phase) const;
virtual uint ideal_reg() const { return Op_RegI; }
};
Expand All @@ -225,6 +245,8 @@ class XorLNode : public AddNode {
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeLong::ZERO; }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual const Type *Value(PhaseGVN *phase) const;
virtual uint ideal_reg() const { return Op_RegL; }
};
Expand All @@ -241,6 +263,8 @@ class MaxNode : public AddNode {
public:
MaxNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
virtual int Opcode() const = 0;
virtual int max_opcode() const = 0;
virtual int min_opcode() const = 0;

static Node* unsigned_max(Node* a, Node* b, const Type* t, PhaseGVN& gvn) {
return build_min_max(a, b, true, true, t, gvn);
Expand Down Expand Up @@ -280,6 +304,8 @@ class MaxINode : public MaxNode {
virtual const Type *add_id() const { return TypeInt::make(min_jint); }
virtual const Type *bottom_type() const { return TypeInt::INT; }
virtual uint ideal_reg() const { return Op_RegI; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
};

//------------------------------MinINode---------------------------------------
Expand All @@ -293,6 +319,8 @@ class MinINode : public MaxNode {
virtual const Type *add_id() const { return TypeInt::make(max_jint); }
virtual const Type *bottom_type() const { return TypeInt::INT; }
virtual uint ideal_reg() const { return Op_RegI; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
};

Expand All @@ -306,6 +334,8 @@ class MaxLNode : public MaxNode {
virtual const Type *add_id() const { return TypeLong::make(min_jlong); }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
};

//------------------------------MinLNode---------------------------------------
Expand All @@ -318,6 +348,8 @@ class MinLNode : public MaxNode {
virtual const Type *add_id() const { return TypeLong::make(max_jlong); }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
};

//------------------------------MaxFNode---------------------------------------
Expand All @@ -330,6 +362,8 @@ class MaxFNode : public MaxNode {
virtual const Type *add_id() const { return TypeF::NEG_INF; }
virtual const Type *bottom_type() const { return Type::FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
int max_opcode() const { return Op_MaxF; }
int min_opcode() const { return Op_MinF; }
};

//------------------------------MinFNode---------------------------------------
Expand All @@ -342,6 +376,8 @@ class MinFNode : public MaxNode {
virtual const Type *add_id() const { return TypeF::POS_INF; }
virtual const Type *bottom_type() const { return Type::FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
int max_opcode() const { return Op_MaxF; }
int min_opcode() const { return Op_MinF; }
};

//------------------------------MaxDNode---------------------------------------
Expand All @@ -354,6 +390,8 @@ class MaxDNode : public MaxNode {
virtual const Type *add_id() const { return TypeD::NEG_INF; }
virtual const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
int max_opcode() const { return Op_MaxD; }
int min_opcode() const { return Op_MinD; }
};

//------------------------------MinDNode---------------------------------------
Expand All @@ -366,6 +404,8 @@ class MinDNode : public MaxNode {
virtual const Type *add_id() const { return TypeD::POS_INF; }
virtual const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
int max_opcode() const { return Op_MaxD; }
int min_opcode() const { return Op_MinD; }
};

#endif // SHARE_OPTO_ADDNODE_HPP
27 changes: 26 additions & 1 deletion src/hotspot/share/opto/mulnode.cpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
Expand Down Expand Up @@ -62,6 +62,31 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) {
const Type *t1 = phase->type( in(1) );
const Type *t2 = phase->type( in(2) );
Node *progress = NULL; // Progress flag

// convert "max(a,b) * min(a,b)" into "a*b".
Node *in1 = in(1);
Node *in2 = in(2);
if ((in(1)->Opcode() == max_opcode() && in(2)->Opcode() == min_opcode())
|| (in(1)->Opcode() == min_opcode() && in(2)->Opcode() == max_opcode())) {
Node *in11 = in(1)->in(1);
Node *in12 = in(1)->in(2);

Node *in21 = in(2)->in(1);
Node *in22 = in(2)->in(2);

if ((in11 == in21 && in12 == in22) ||
(in11 == in22 && in12 == in21)) {
set_req(1, in11);
set_req(2, in12);
PhaseIterGVN* igvn = phase->is_IterGVN();
if (igvn) {
igvn->_worklist.push(in1);
igvn->_worklist.push(in2);
}
progress = this;
}
}

// We are OK if right is a constant, or right is a load and
// left is a non-constant.
if( !(t2->singleton() ||
Expand Down
19 changes: 18 additions & 1 deletion src/hotspot/share/opto/mulnode.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
Expand Down Expand Up @@ -75,6 +75,11 @@ class MulNode : public Node {
// Supplied function to return the multiplicative opcode
virtual int mul_opcode() const = 0;

// Supplied function to return the additive opcode
virtual int max_opcode() const = 0;

// Supplied function to return the multiplicative opcode
virtual int min_opcode() const = 0;
};

//------------------------------MulINode---------------------------------------
Expand All @@ -89,6 +94,8 @@ class MulINode : public MulNode {
const Type *add_id() const { return TypeInt::ZERO; }
int add_opcode() const { return Op_AddI; }
int mul_opcode() const { return Op_MulI; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
const Type *bottom_type() const { return TypeInt::INT; }
virtual uint ideal_reg() const { return Op_RegI; }
};
Expand All @@ -105,6 +112,8 @@ class MulLNode : public MulNode {
const Type *add_id() const { return TypeLong::ZERO; }
int add_opcode() const { return Op_AddL; }
int mul_opcode() const { return Op_MulL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
const Type *bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
};
Expand All @@ -121,6 +130,8 @@ class MulFNode : public MulNode {
const Type *add_id() const { return TypeF::ZERO; }
int add_opcode() const { return Op_AddF; }
int mul_opcode() const { return Op_MulF; }
int max_opcode() const { return Op_MaxF; }
int min_opcode() const { return Op_MinF; }
const Type *bottom_type() const { return Type::FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
};
Expand All @@ -136,6 +147,8 @@ class MulDNode : public MulNode {
const Type *add_id() const { return TypeD::ZERO; }
int add_opcode() const { return Op_AddD; }
int mul_opcode() const { return Op_MulD; }
int max_opcode() const { return Op_MaxD; }
int min_opcode() const { return Op_MinD; }
const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
};
Expand Down Expand Up @@ -165,6 +178,8 @@ class AndINode : public MulINode {
const Type *add_id() const { return TypeInt::ZERO; }
int add_opcode() const { return Op_OrI; }
int mul_opcode() const { return Op_AndI; }
int max_opcode() const { return Op_MaxI; }
int min_opcode() const { return Op_MinI; }
virtual uint ideal_reg() const { return Op_RegI; }
};

Expand All @@ -182,6 +197,8 @@ class AndLNode : public MulLNode {
const Type *add_id() const { return TypeLong::ZERO; }
int add_opcode() const { return Op_OrL; }
int mul_opcode() const { return Op_AndL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual uint ideal_reg() const { return Op_RegL; }
};

Expand Down

1 comment on commit 599d07c

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.