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