1 /*
  2  * Copyright (c) 1997, 2025, 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/callnode.hpp"
 29 #include "opto/multnode.hpp"
 30 #include "opto/node.hpp"
 31 #include "opto/opcodes.hpp"
 32 #include "opto/type.hpp"
 33 
 34 // Portions of code courtesy of Clifford Click
 35 
 36 // Optimization - Graph Style
 37 
 38 
 39 //------------------------------DivINode---------------------------------------
 40 // Integer division
 41 // Note: this is division as defined by JVMS, i.e., MinInt/-1 == MinInt.
 42 // On processors which don't naturally support this special case (e.g., x86),
 43 // the matcher or runtime system must take care of this.
 44 class DivINode : public Node {
 45 public:
 46   DivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
 47   virtual int Opcode() const;
 48   virtual Node* Identity(PhaseGVN* phase);
 49   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 50   virtual const Type* Value(PhaseGVN* phase) const;
 51   virtual const Type *bottom_type() const { return TypeInt::INT; }
 52   virtual uint ideal_reg() const { return Op_RegI; }
 53 };
 54 
 55 //------------------------------DivLNode---------------------------------------
 56 // Long division
 57 class DivLNode : public Node {
 58 public:
 59   DivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
 60   virtual int Opcode() const;
 61   virtual Node* Identity(PhaseGVN* phase);
 62   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 63   virtual const Type* Value(PhaseGVN* phase) const;
 64   virtual const Type *bottom_type() const { return TypeLong::LONG; }
 65   virtual uint ideal_reg() const { return Op_RegL; }
 66 };
 67 
 68 //------------------------------DivFNode---------------------------------------
 69 // Float division
 70 class DivFNode : public Node {
 71 public:
 72   DivFNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor) {}
 73   virtual int Opcode() const;
 74   virtual Node* Identity(PhaseGVN* phase);
 75   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
 76   virtual const Type* Value(PhaseGVN* phase) const;
 77   virtual const Type *bottom_type() const { return Type::FLOAT; }
 78   virtual uint ideal_reg() const { return Op_RegF; }
 79 };
 80 
 81 
 82 //------------------------------DivHFNode--------------------------------------
 83 // Half float division
 84 class DivHFNode : public Node {
 85 public:
 86   DivHFNode(Node* c, Node* dividend, Node* divisor) : Node(c, dividend, divisor) {}
 87   virtual int Opcode() const;
 88   virtual Node* Identity(PhaseGVN* phase);
 89   virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
 90   virtual const Type* Value(PhaseGVN* phase) const;
 91   virtual const Type* bottom_type() const { return Type::HALF_FLOAT; }
 92   virtual uint ideal_reg() const { return Op_RegF; }
 93 };
 94 
 95 //------------------------------DivDNode---------------------------------------
 96 // Double division
 97 class DivDNode : public Node {
 98 public:
 99   DivDNode( Node *c, Node *dividend, Node *divisor ) : Node(c,dividend, divisor) {}
100   virtual int Opcode() const;
101   virtual Node* Identity(PhaseGVN* phase);
102   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
103   virtual const Type* Value(PhaseGVN* phase) const;
104   virtual const Type *bottom_type() const { return Type::DOUBLE; }
105   virtual uint ideal_reg() const { return Op_RegD; }
106 };
107 
108 //------------------------------UDivINode---------------------------------------
109 // Unsigned integer division
110 class UDivINode : public Node {
111 public:
112   UDivINode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
113   virtual int Opcode() const;
114   virtual Node* Identity(PhaseGVN* phase);
115   virtual const Type* Value(PhaseGVN* phase) const;
116   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
117   virtual const Type *bottom_type() const { return TypeInt::INT; }
118   virtual uint ideal_reg() const { return Op_RegI; }
119 };
120 
121 //------------------------------UDivLNode---------------------------------------
122 // Unsigned long division
123 class UDivLNode : public Node {
124 public:
125   UDivLNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor ) {}
126   virtual int Opcode() const;
127   virtual Node* Identity(PhaseGVN* phase);
128   virtual const Type* Value(PhaseGVN* phase) const;
129   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
130   virtual const Type *bottom_type() const { return TypeLong::LONG; }
131   virtual uint ideal_reg() const { return Op_RegL; }
132 };
133 
134 //------------------------------ModINode---------------------------------------
135 // Integer modulus
136 class ModINode : public Node {
137 public:
138   ModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
139   virtual int Opcode() const;
140   virtual const Type* Value(PhaseGVN* phase) const;
141   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
142   virtual const Type *bottom_type() const { return TypeInt::INT; }
143   virtual uint ideal_reg() const { return Op_RegI; }
144 };
145 
146 //------------------------------ModLNode---------------------------------------
147 // Long modulus
148 class ModLNode : public Node {
149 public:
150   ModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
151   virtual int Opcode() const;
152   virtual const Type* Value(PhaseGVN* phase) const;
153   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
154   virtual const Type *bottom_type() const { return TypeLong::LONG; }
155   virtual uint ideal_reg() const { return Op_RegL; }
156 };
157 
158 // Base class for float and double modulus
159 class ModFloatingNode : public CallLeafNode {
160 protected:
161   Node* replace_with_con(PhaseIterGVN* phase, const Type* con);
162 
163 public:
164   ModFloatingNode(Compile* C, const TypeFunc* tf, const char *name);
165 };
166 
167 // Float Modulus
168 class ModFNode : public ModFloatingNode {
169 private:
170   Node* dividend() const { return in(TypeFunc::Parms + 0); }
171   Node* divisor() const { return in(TypeFunc::Parms + 1); }
172 
173 public:
174   ModFNode(Compile* C, Node* a, Node* b);
175   virtual int Opcode() const;
176   virtual uint ideal_reg() const { return Op_RegF; }
177   virtual uint size_of() const { return sizeof(*this); }
178   virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
179 };
180 
181 // Double Modulus
182 class ModDNode : public ModFloatingNode {
183 private:
184   Node* dividend() const { return in(TypeFunc::Parms + 0); }
185   Node* divisor() const { return in(TypeFunc::Parms + 2); }
186 
187 public:
188   ModDNode(Compile* C, Node* a, Node* b);
189   virtual int Opcode() const;
190   virtual uint ideal_reg() const { return Op_RegD; }
191   virtual uint size_of() const { return sizeof(*this); }
192   virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
193 };
194 
195 //------------------------------UModINode---------------------------------------
196 // Unsigned integer modulus
197 class UModINode : public Node {
198 public:
199   UModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
200   virtual int Opcode() const;
201   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
202   virtual const Type *bottom_type() const { return TypeInt::INT; }
203   virtual uint ideal_reg() const { return Op_RegI; }
204   virtual const Type* Value(PhaseGVN* phase) const;
205 };
206 
207 //------------------------------UModLNode---------------------------------------
208 // Unsigned long modulus
209 class UModLNode : public Node {
210 public:
211   UModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
212   virtual int Opcode() const;
213   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
214   virtual const Type *bottom_type() const { return TypeLong::LONG; }
215   virtual uint ideal_reg() const { return Op_RegL; }
216   virtual const Type* Value(PhaseGVN* phase) const;
217 };
218 
219 //------------------------------DivModNode---------------------------------------
220 // Division with remainder result.
221 class DivModNode : public MultiNode {
222 protected:
223   DivModNode( Node *c, Node *dividend, Node *divisor );
224 public:
225   enum {
226     div_proj_num =  0,      // quotient
227     mod_proj_num =  1       // remainder
228   };
229   virtual int Opcode() const;
230   virtual Node* Identity(PhaseGVN* phase) { return this; }
231   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return nullptr; }
232   virtual const Type* Value(PhaseGVN* phase)  const { return bottom_type(); }
233   virtual uint hash() const { return Node::hash(); }
234   virtual bool is_CFG() const  { return false; }
235   virtual uint ideal_reg() const { return NotAMachineReg; }
236 
237   static DivModNode* make(Node* div_or_mod, BasicType bt, bool is_unsigned);
238 
239   ProjNode* div_proj() { return proj_out_or_null(div_proj_num); }
240   ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); }
241 };
242 
243 //------------------------------DivModINode---------------------------------------
244 // Integer division with remainder result.
245 class DivModINode : public DivModNode {
246 public:
247   DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
248   virtual int Opcode() const;
249   virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
250   virtual Node *match( const ProjNode *proj, const Matcher *m );
251 
252   // Make a divmod and associated projections from a div or mod.
253   static DivModINode* make(Node* div_or_mod);
254 };
255 
256 //------------------------------DivModLNode---------------------------------------
257 // Long division with remainder result.
258 class DivModLNode : public DivModNode {
259 public:
260   DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
261   virtual int Opcode() const;
262   virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
263   virtual Node *match( const ProjNode *proj, const Matcher *m );
264 
265   // Make a divmod and associated projections from a div or mod.
266   static DivModLNode* make(Node* div_or_mod);
267 };
268 
269 
270 //------------------------------UDivModINode---------------------------------------
271 // Unsigend integer division with remainder result.
272 class UDivModINode : public DivModNode {
273 public:
274   UDivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
275   virtual int Opcode() const;
276   virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
277   virtual Node *match( const ProjNode *proj, const Matcher *m );
278 
279   // Make a divmod and associated projections from a div or mod.
280   static UDivModINode* make(Node* div_or_mod);
281 };
282 
283 //------------------------------UDivModLNode---------------------------------------
284 // Unsigned long division with remainder result.
285 class UDivModLNode : public DivModNode {
286 public:
287   UDivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
288   virtual int Opcode() const;
289   virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
290   virtual Node *match( const ProjNode *proj, const Matcher *m );
291 
292   // Make a divmod and associated projections from a div or mod.
293   static UDivModLNode* make(Node* div_or_mod);
294 };
295 
296 #endif // SHARE_OPTO_DIVNODE_HPP