1 /*
  2  * Copyright (c) 1997, 2023, 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:
 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;
 50   virtual const Type *bottom_type() const { return TypeInt::INT; }
 51   virtual uint ideal_reg() const { return Op_RegI; }
 52 };
 53 
 54 //------------------------------DivLNode---------------------------------------
 55 // Long division
 56 class DivLNode : public Node {
 57 public:
 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;
 63   virtual const Type *bottom_type() const { return TypeLong::LONG; }
 64   virtual uint ideal_reg() const { return Op_RegL; }
 65 };
 66 
 67 //------------------------------DivFNode---------------------------------------
 68 // Float division
 69 class DivFNode : public Node {
 70 public:
 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;
 76   virtual const Type *bottom_type() const { return Type::FLOAT; }
 77   virtual uint ideal_reg() const { return Op_RegF; }
 78 };
 79 
 80 //------------------------------DivDNode---------------------------------------
 81 // Double division
 82 class DivDNode : public Node {
 83 public:
 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;
 89   virtual const Type *bottom_type() const { return Type::DOUBLE; }
 90   virtual uint ideal_reg() const { return Op_RegD; }
 91 };
 92 
 93 //------------------------------UDivINode---------------------------------------
 94 // Unsigned integer division
 95 class UDivINode : public Node {
 96 public:
 97   UDivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
 98   virtual int Opcode() const;
 99   virtual Node* Identity(PhaseGVN* phase);
100   virtual const Type* Value(PhaseGVN* phase) const;
101   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
102   virtual const Type *bottom_type() const { return TypeInt::INT; }
103   virtual uint ideal_reg() const { return Op_RegI; }
104 };
105 
106 //------------------------------UDivLNode---------------------------------------
107 // Unsigned long division
108 class UDivLNode : public Node {
109 public:
110   UDivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
111   virtual int Opcode() const;
112   virtual Node* Identity(PhaseGVN* phase);
113   virtual const Type* Value(PhaseGVN* phase) const;
114   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
115   virtual const Type *bottom_type() const { return TypeLong::LONG; }
116   virtual uint ideal_reg() const { return Op_RegL; }
117 };
118 
119 //------------------------------ModINode---------------------------------------
120 // Integer modulus
121 class ModINode : public Node {
122 public:
123   ModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
124   virtual int Opcode() const;
125   virtual const Type* Value(PhaseGVN* phase) const;
126   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
127   virtual const Type *bottom_type() const { return TypeInt::INT; }
128   virtual uint ideal_reg() const { return Op_RegI; }
129 };
130 
131 //------------------------------ModLNode---------------------------------------
132 // Long modulus
133 class ModLNode : public Node {
134 public:
135   ModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
136   virtual int Opcode() const;
137   virtual const Type* Value(PhaseGVN* phase) const;
138   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
139   virtual const Type *bottom_type() const { return TypeLong::LONG; }
140   virtual uint ideal_reg() const { return Op_RegL; }
141 };
142 
143 //------------------------------ModFNode---------------------------------------
144 // Float Modulus
145 class ModFNode : public Node {
146 public:
147   ModFNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
148   virtual int Opcode() const;
149   virtual const Type* Value(PhaseGVN* phase) const;
150   virtual const Type *bottom_type() const { return Type::FLOAT; }
151   virtual uint ideal_reg() const { return Op_RegF; }
152 };
153 
154 //------------------------------ModDNode---------------------------------------
155 // Double Modulus
156 class ModDNode : public Node {
157 public:
158   ModDNode( Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {}
159   virtual int Opcode() const;
160   virtual const Type* Value(PhaseGVN* phase) const;
161   virtual const Type *bottom_type() const { return Type::DOUBLE; }
162   virtual uint ideal_reg() const { return Op_RegD; }
163 };
164 
165 //------------------------------UModINode---------------------------------------
166 // Unsigned integer modulus
167 class UModINode : public Node {
168 public:
169   UModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
170   virtual int Opcode() const;
171   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
172   virtual const Type *bottom_type() const { return TypeInt::INT; }
173   virtual uint ideal_reg() const { return Op_RegI; }
174 };
175 
176 //------------------------------UModLNode---------------------------------------
177 // Unsigned long modulus
178 class UModLNode : public Node {
179 public:
180   UModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
181   virtual int Opcode() const;
182   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
183   virtual const Type *bottom_type() const { return TypeLong::LONG; }
184   virtual uint ideal_reg() const { return Op_RegL; }
185 };
186 
187 //------------------------------DivModNode---------------------------------------
188 // Division with remainder result.
189 class DivModNode : public MultiNode {
190 protected:
191   DivModNode( Node *c, Node *dividend, Node *divisor );
192 public:
193   enum {
194     div_proj_num =  0,      // quotient
195     mod_proj_num =  1       // remainder
196   };
197   virtual int Opcode() const;
198   virtual Node* Identity(PhaseGVN* phase) { return this; }
199   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return nullptr; }
200   virtual const Type* Value(PhaseGVN* phase)  const { return bottom_type(); }
201   virtual uint hash() const { return Node::hash(); }
202   virtual bool is_CFG() const  { return false; }
203   virtual uint ideal_reg() const { return NotAMachineReg; }
204 
205   static DivModNode* make(Node* div_or_mod, BasicType bt, bool is_unsigned);
206 
207   ProjNode* div_proj() { return proj_out_or_null(div_proj_num); }
208   ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); }
209 };
210 
211 //------------------------------DivModINode---------------------------------------
212 // Integer division with remainder result.
213 class DivModINode : public DivModNode {
214 public:
215   DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
216   virtual int Opcode() const;
217   virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
218   virtual Node *match(const ProjNode *proj, const Matcher *m, const RegMask* mask);
219 
220   // Make a divmod and associated projections from a div or mod.
221   static DivModINode* make(Node* div_or_mod);
222 };
223 
224 //------------------------------DivModLNode---------------------------------------
225 // Long division with remainder result.
226 class DivModLNode : public DivModNode {
227 public:
228   DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
229   virtual int Opcode() const;
230   virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
231   virtual Node *match(const ProjNode *proj, const Matcher *m, const RegMask* mask);
232 
233   // Make a divmod and associated projections from a div or mod.
234   static DivModLNode* make(Node* div_or_mod);
235 };
236 
237 
238 //------------------------------UDivModINode---------------------------------------
239 // Unsigend integer division with remainder result.
240 class UDivModINode : public DivModNode {
241 public:
242   UDivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
243   virtual int Opcode() const;
244   virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
245   virtual Node* match(const ProjNode* proj, const Matcher* m, const RegMask* mask);
246 
247   // Make a divmod and associated projections from a div or mod.
248   static UDivModINode* make(Node* div_or_mod);
249 };
250 
251 //------------------------------UDivModLNode---------------------------------------
252 // Unsigned long division with remainder result.
253 class UDivModLNode : public DivModNode {
254 public:
255   UDivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
256   virtual int Opcode() const;
257   virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
258   virtual Node* match(const ProjNode* proj, const Matcher* m, const RegMask* mask);
259 
260   // Make a divmod and associated projections from a div or mod.
261   static UDivModLNode* make(Node* div_or_mod);
262 };
263 
264 #endif // SHARE_OPTO_DIVNODE_HPP