Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8263006: Add optimization for Max(*)Node and Min(*)Node #3513

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
@@ -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;
@@ -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

@@ -549,9 +574,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;
}


@@ -586,9 +609,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;
}


@@ -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;
@@ -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 {
@@ -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 {
@@ -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; }
};
@@ -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; }
};
@@ -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);
@@ -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);
@@ -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; }
};
@@ -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; }
};
@@ -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);
@@ -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---------------------------------------
@@ -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);
};

@@ -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---------------------------------------
@@ -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---------------------------------------
@@ -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---------------------------------------
@@ -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---------------------------------------
@@ -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---------------------------------------
@@ -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
@@ -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
@@ -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() ||
@@ -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
@@ -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---------------------------------------
@@ -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; }
};
@@ -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; }
};
@@ -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; }
};
@@ -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; }
};
@@ -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; }
};

@@ -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; }
};

Loading