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