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 CallLeafPureNode {
160 TupleNode* make_tuple_of_input_state_and_constant_result(PhaseIterGVN* phase, const Type* con) const;
161
162 protected:
163 virtual Node* dividend() const = 0;
164 virtual Node* divisor() const = 0;
165 virtual const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const = 0;
166
167 public:
168 ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name);
169 Node* Ideal(PhaseGVN* phase, bool can_reshape) override;
170 };
171
172 // Float Modulus
173 class ModFNode : public ModFloatingNode {
174 private:
175 Node* dividend() const override { return in(TypeFunc::Parms + 0); }
176 Node* divisor() const override { return in(TypeFunc::Parms + 1); }
177 const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override;
178
179 public:
180 ModFNode(Compile* C, Node* a, Node* b);
181 int Opcode() const override;
182 uint ideal_reg() const override { return Op_RegF; }
183 uint size_of() const override { return sizeof(*this); }
184 };
185
186 // Double Modulus
187 class ModDNode : public ModFloatingNode {
188 private:
189 Node* dividend() const override { return in(TypeFunc::Parms + 0); }
190 Node* divisor() const override { return in(TypeFunc::Parms + 2); }
191 const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override;
192
193 public:
194 ModDNode(Compile* C, Node* a, Node* b);
195 int Opcode() const override;
196 uint ideal_reg() const override { return Op_RegD; }
197 uint size_of() const override { return sizeof(*this); }
198 };
199
200 //------------------------------UModINode---------------------------------------
201 // Unsigned integer modulus
202 class UModINode : public Node {
203 public:
204 UModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
205 virtual int Opcode() const;
206 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
207 virtual const Type *bottom_type() const { return TypeInt::INT; }
208 virtual uint ideal_reg() const { return Op_RegI; }
209 virtual const Type* Value(PhaseGVN* phase) const;
210 };
211
212 //------------------------------UModLNode---------------------------------------
213 // Unsigned long modulus
214 class UModLNode : public Node {
215 public:
216 UModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {}
217 virtual int Opcode() const;
218 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
219 virtual const Type *bottom_type() const { return TypeLong::LONG; }
220 virtual uint ideal_reg() const { return Op_RegL; }
221 virtual const Type* Value(PhaseGVN* phase) const;
222 };
223
224 //------------------------------DivModNode---------------------------------------
225 // Division with remainder result.
226 class DivModNode : public MultiNode {
227 protected:
228 DivModNode( Node *c, Node *dividend, Node *divisor );
229 public:
230 enum {
231 div_proj_num = 0, // quotient
232 mod_proj_num = 1 // remainder
233 };
234 virtual int Opcode() const;
235 virtual Node* Identity(PhaseGVN* phase) { return this; }
236 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return nullptr; }
237 virtual const Type* Value(PhaseGVN* phase) const { return bottom_type(); }
238 virtual uint hash() const { return Node::hash(); }
239 virtual bool is_CFG() const { return false; }
240 virtual uint ideal_reg() const { return NotAMachineReg; }
241
242 static DivModNode* make(Node* div_or_mod, BasicType bt, bool is_unsigned);
243
244 ProjNode* div_proj() { return proj_out_or_null(div_proj_num); }
245 ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); }
246 };
247
248 //------------------------------DivModINode---------------------------------------
249 // Integer division with remainder result.
250 class DivModINode : public DivModNode {
251 public:
252 DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
253 virtual int Opcode() const;
254 virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
255 virtual Node *match( const ProjNode *proj, const Matcher *m );
256
257 // Make a divmod and associated projections from a div or mod.
258 static DivModINode* make(Node* div_or_mod);
259 };
260
261 //------------------------------DivModLNode---------------------------------------
262 // Long division with remainder result.
263 class DivModLNode : public DivModNode {
264 public:
265 DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
266 virtual int Opcode() const;
267 virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
268 virtual Node *match( const ProjNode *proj, const Matcher *m );
269
270 // Make a divmod and associated projections from a div or mod.
271 static DivModLNode* make(Node* div_or_mod);
272 };
273
274
275 //------------------------------UDivModINode---------------------------------------
276 // Unsigend integer division with remainder result.
277 class UDivModINode : public DivModNode {
278 public:
279 UDivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
280 virtual int Opcode() const;
281 virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; }
282 virtual Node *match( const ProjNode *proj, const Matcher *m );
283
284 // Make a divmod and associated projections from a div or mod.
285 static UDivModINode* make(Node* div_or_mod);
286 };
287
288 //------------------------------UDivModLNode---------------------------------------
289 // Unsigned long division with remainder result.
290 class UDivModLNode : public DivModNode {
291 public:
292 UDivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {}
293 virtual int Opcode() const;
294 virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; }
295 virtual Node *match( const ProjNode *proj, const Matcher *m );
296
297 // Make a divmod and associated projections from a div or mod.
298 static UDivModLNode* make(Node* div_or_mod);
299 };
300
301 #endif // SHARE_OPTO_DIVNODE_HPP