/*
 * Copyright (c) 1997, 2010, 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.
 *
 */

#ifndef SHARE_VM_OPTO_ADDNODE_HPP
#define SHARE_VM_OPTO_ADDNODE_HPP

#include "opto/node.hpp"
#include "opto/opcodes.hpp"
#include "opto/type.hpp"

// Portions of code courtesy of Clifford Click

class PhaseTransform;

//------------------------------AddNode----------------------------------------
// Classic Add functionality.  This covers all the usual 'add' behaviors for
// an algebraic ring.  Add-integer, add-float, add-double, and binary-or are
// all inherited from this class.  The various identity values are supplied
// by virtual functions.
class AddNode : public Node {
  virtual uint hash() const;
public:
  AddNode( Node *in1, Node *in2 ) : Node(0,in1,in2) {
    init_class_id(Class_Add);
  }

  // Handle algebraic identities here.  If we have an identity, return the Node
  // we are equivalent to.  We look for "add of zero" as an identity.
  virtual Node *Identity( PhaseTransform *phase );

  // We also canonicalize the Node, moving constants to the right input,
  // and flatten expressions (so that 1+x+2 becomes x+3).
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);

  // Compute a new Type for this node.  Basically we just do the pre-check,
  // then call the virtual add() to set the type.
  virtual const Type *Value( PhaseTransform *phase ) const;

  // Check if this addition involves the additive identity
  virtual const Type *add_of_identity( const Type *t1, const Type *t2 ) const;

  // Supplied function returns the sum of the inputs.
  // This also type-checks the inputs for sanity.  Guaranteed never to
  // be passed a TOP or BOTTOM type, these are filtered out by a pre-check.
  virtual const Type *add_ring( const Type *, const Type * ) const = 0;

  // Supplied function to return the additive identity type
  virtual const Type *add_id() const = 0;

};

//------------------------------AddINode---------------------------------------
// Add 2 integers
class AddINode : public AddNode {
public:
  AddINode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
  virtual Node *Identity( PhaseTransform *phase );
  virtual uint ideal_reg() const { return Op_RegI; }
};

//------------------------------AddLNode---------------------------------------
// Add 2 longs
class AddLNode : public AddNode {
public:
  AddLNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
  virtual Node *Identity( PhaseTransform *phase );
  virtual uint ideal_reg() const { return Op_RegL; }
};

//------------------------------AddFNode---------------------------------------
// Add 2 floats
class AddFNode : public AddNode {
public:
  AddFNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
  virtual const Type *add_of_identity( const Type *t1, const Type *t2 ) const;
  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; }
  virtual Node *Identity( PhaseTransform *phase ) { return this; }
  virtual uint ideal_reg() const { return Op_RegF; }
};

//------------------------------AddDNode---------------------------------------
// Add 2 doubles
class AddDNode : public AddNode {
public:
  AddDNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
  virtual const Type *add_of_identity( const Type *t1, const Type *t2 ) const;
  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; }
  virtual Node *Identity( PhaseTransform *phase ) { return this; }
  virtual uint ideal_reg() const { return Op_RegD; }
};

//------------------------------AddPNode---------------------------------------
// Add pointer plus integer to get pointer.  NOT commutative, really.
// So not really an AddNode.  Lives here, because people associate it with
// an add.
class AddPNode : public Node {
public:
  enum { Control,               // When is it safe to do this add?
         Base,                  // Base oop, for GC purposes
         Address,               // Actually address, derived from base
         Offset } ;             // Offset added to address
  AddPNode( Node *base, Node *ptr, Node *off ) : Node(0,base,ptr,off) {
    init_class_id(Class_AddP);
  }
  virtual int Opcode() const;
  virtual Node *Identity( PhaseTransform *phase );
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
  virtual const Type *Value( PhaseTransform *phase ) const;
  virtual const Type *bottom_type() const;
  virtual uint  ideal_reg() const { return Op_RegP; }
  Node         *base_node() { assert( req() > Base, "Missing base"); return in(Base); }
  static Node* Ideal_base_and_offset(Node* ptr, PhaseTransform* phase,
                                     // second return value:
                                     intptr_t& offset);

  // Collect the AddP offset values into the elements array, giving up
  // if there are more than length.
  int unpack_offsets(Node* elements[], int length);

  // Do not match base-ptr edge
  virtual uint match_edge(uint idx) const;
};

//------------------------------OrINode----------------------------------------
// Logically OR 2 integers.  Included with the ADD nodes because it inherits
// all the behavior of addition on a ring.
class OrINode : public AddNode {
public:
  OrINode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual Node *Identity( PhaseTransform *phase );
  virtual uint ideal_reg() const { return Op_RegI; }
};

//------------------------------OrLNode----------------------------------------
// Logically OR 2 longs.  Included with the ADD nodes because it inherits
// all the behavior of addition on a ring.
class OrLNode : public AddNode {
public:
  OrLNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual Node *Identity( PhaseTransform *phase );
  virtual uint ideal_reg() const { return Op_RegL; }
};

//------------------------------XorINode---------------------------------------
// XOR'ing 2 integers
class XorINode : public AddNode {
public:
  XorINode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual uint ideal_reg() const { return Op_RegI; }
};

//------------------------------XorINode---------------------------------------
// XOR'ing 2 longs
class XorLNode : public AddNode {
public:
  XorLNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const;
  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; }
  virtual uint ideal_reg() const { return Op_RegL; }
};

//------------------------------MaxNode----------------------------------------
// Max (or min) of 2 values.  Included with the ADD nodes because it inherits
// all the behavior of addition on a ring.  Only new thing is that we allow
// 2 equal inputs to be equal.
class MaxNode : public AddNode {
public:
  MaxNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
  virtual int Opcode() const = 0;
};

//------------------------------MaxINode---------------------------------------
// Maximum of 2 integers.  Included with the ADD nodes because it inherits
// all the behavior of addition on a ring.
class MaxINode : public MaxNode {
public:
  MaxINode( Node *in1, Node *in2 ) : MaxNode(in1,in2) {}
  virtual int Opcode() const;
  virtual const Type *add_ring( const Type *, const Type * ) const;
  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; }
};

//------------------------------MinINode---------------------------------------
// MINimum of 2 integers.  Included with the ADD nodes because it inherits
// all the behavior of addition on a ring.
class MinINode : public MaxNode {
public:
  MinINode( Node *in1, Node *in2 ) : MaxNode(in1,in2) {}
  virtual int Opcode() const;
  virtual const Type *add_ring( const Type *, const Type * ) const;
  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; }
  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
};

#endif // SHARE_VM_OPTO_ADDNODE_HPP
