1 /*
2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_OPTO_DIVNODE_HPP
26 #define SHARE_OPTO_DIVNODE_HPP
27 
28 #include "opto/multnode.hpp"
29 #include "opto/node.hpp"
30 #include "opto/opcodes.hpp"
31 #include "opto/type.hpp"
32 
33 // Portions of code courtesy of Clifford Click
34 
35 // Optimization - Graph Style
36 
37 
38 //------------------------------DivINode---------------------------------------
39 // Integer division
40 // Note: this is division as defined by JVMS, i.e., MinInt/-1 == MinInt.
41 // On processors which don't naturally support this special case (e.g., x86),
42 // the matcher or runtime system must take care of this.
43 class DivINode : public Node {
44 public:
DivINode(Node * c,Node * dividend,Node * divisor)45   DivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
46   virtual int Opcode() const;
47   virtual Node* Identity(PhaseGVN* phase);
48   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
49   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const50   virtual const Type *bottom_type() const { return TypeInt::INT; }
ideal_reg() const51   virtual uint ideal_reg() const { return Op_RegI; }
52 };
53 
54 //------------------------------DivLNode---------------------------------------
55 // Long division
56 class DivLNode : public Node {
57 public:
DivLNode(Node * c,Node * dividend,Node * divisor)58   DivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
59   virtual int Opcode() const;
60   virtual Node* Identity(PhaseGVN* phase);
61   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
62   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const63   virtual const Type *bottom_type() const { return TypeLong::LONG; }
ideal_reg() const64   virtual uint ideal_reg() const { return Op_RegL; }
65 };
66 
67 //------------------------------DivFNode---------------------------------------
68 // Float division
69 class DivFNode : public Node {
70 public:
DivFNode(Node * c,Node * dividend,Node * divisor)71   DivFNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor) {}
72   virtual int Opcode() const;
73   virtual Node* Identity(PhaseGVN* phase);
74   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
75   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const76   virtual const Type *bottom_type() const { return Type::FLOAT; }
ideal_reg() const77   virtual uint ideal_reg() const { return Op_RegF; }
78 };
79 
80 //------------------------------DivDNode---------------------------------------
81 // Double division
82 class DivDNode : public Node {
83 public:
DivDNode(Node * c,Node * dividend,Node * divisor)84   DivDNode( Node *c, Node *dividend, Node *divisor ) : Node(c,dividend, divisor) {}
85   virtual int Opcode() const;
86   virtual Node* Identity(PhaseGVN* phase);
87   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
88   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const89   virtual const Type *bottom_type() const { return Type::DOUBLE; }
ideal_reg() const90   virtual uint ideal_reg() const { return Op_RegD; }
91 };
92 
93 //------------------------------ModINode---------------------------------------
94 // Integer modulus
95 class ModINode : public Node {
96 public:
ModINode(Node * c,Node * in1,Node * in2)97   ModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
98   virtual int Opcode() const;
99   virtual const Type* Value(PhaseGVN* phase) const;
100   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
bottom_type() const101   virtual const Type *bottom_type() const { return TypeInt::INT; }
ideal_reg() const102   virtual uint ideal_reg() const { return Op_RegI; }
103 };
104 
105 //------------------------------ModLNode---------------------------------------
106 // Long modulus
107 class ModLNode : public Node {
108 public:
ModLNode(Node * c,Node * in1,Node * in2)109   ModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
110   virtual int Opcode() const;
111   virtual const Type* Value(PhaseGVN* phase) const;
112   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
bottom_type() const113   virtual const Type *bottom_type() const { return TypeLong::LONG; }
ideal_reg() const114   virtual uint ideal_reg() const { return Op_RegL; }
115 };
116 
117 //------------------------------ModFNode---------------------------------------
118 // Float Modulus
119 class ModFNode : public Node {
120 public:
ModFNode(Node * c,Node * in1,Node * in2)121   ModFNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
122   virtual int Opcode() const;
123   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const124   virtual const Type *bottom_type() const { return Type::FLOAT; }
ideal_reg() const125   virtual uint ideal_reg() const { return Op_RegF; }
126 };
127 
128 //------------------------------ModDNode---------------------------------------
129 // Double Modulus
130 class ModDNode : public Node {
131 public:
ModDNode(Node * c,Node * in1,Node * in2)132   ModDNode( Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {}
133   virtual int Opcode() const;
134   virtual const Type* Value(PhaseGVN* phase) const;
bottom_type() const135   virtual const Type *bottom_type() const { return Type::DOUBLE; }
ideal_reg() const136   virtual uint ideal_reg() const { return Op_RegD; }
137 };
138 
139 //------------------------------DivModNode---------------------------------------
140 // Division with remainder result.
141 class DivModNode : public MultiNode {
142 protected:
143   DivModNode( Node *c, Node *dividend, Node *divisor );
144 public:
145   enum {
146     div_proj_num =  0,      // quotient
147     mod_proj_num =  1       // remainder
148   };
149   virtual int Opcode() const;
Identity(PhaseGVN * phase)150   virtual Node* Identity(PhaseGVN* phase) { return this; }
Ideal(PhaseGVN * phase,bool can_reshape)151   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return NULL; }
Value(PhaseGVN * phase) const152   virtual const Type* Value(PhaseGVN* phase)  const { return bottom_type(); }
hash() const153   virtual uint hash() const { return Node::hash(); }
is_CFG() const154   virtual bool is_CFG() const  { return false; }
ideal_reg() const155   virtual uint ideal_reg() const { return NotAMachineReg; }
156 
div_proj()157   ProjNode* div_proj() { return proj_out_or_null(div_proj_num); }
mod_proj()158   ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); }
159 };
160 
161 //------------------------------DivModINode---------------------------------------
162 // Integer division with remainder result.
163 class DivModINode : public DivModNode {
164 public:
DivModINode(Node * c,Node * dividend,Node * divisor)165   DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
166   virtual int Opcode() const;
bottom_type() const167   virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
168   virtual Node *match( const ProjNode *proj, const Matcher *m );
169 
170   // Make a divmod and associated projections from a div or mod.
171   static DivModINode* make(Node* div_or_mod);
172 };
173 
174 //------------------------------DivModLNode---------------------------------------
175 // Long division with remainder result.
176 class DivModLNode : public DivModNode {
177 public:
DivModLNode(Node * c,Node * dividend,Node * divisor)178   DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
179   virtual int Opcode() const;
bottom_type() const180   virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
181   virtual Node *match( const ProjNode *proj, const Matcher *m );
182 
183   // Make a divmod and associated projections from a div or mod.
184   static DivModLNode* make(Node* div_or_mod);
185 };
186 
187 #endif // SHARE_OPTO_DIVNODE_HPP
188