1 | /* |
2 | * Copyright (c) 1997, 2019, 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 | //------------------------------ModINode--------------------------------------- |
94 | // Integer modulus |
95 | class ModINode : public Node { |
96 | public: |
97 | ModINode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} |
98 | virtual int Opcode() const; |
99 | virtual const Type* Value(PhaseGVN* phase) const; |
100 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
101 | virtual const Type *bottom_type() const { return TypeInt::INT; } |
102 | virtual uint ideal_reg() const { return Op_RegI; } |
103 | }; |
104 | |
105 | //------------------------------ModLNode--------------------------------------- |
106 | // Long modulus |
107 | class ModLNode : public Node { |
108 | public: |
109 | ModLNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} |
110 | virtual int Opcode() const; |
111 | virtual const Type* Value(PhaseGVN* phase) const; |
112 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
113 | virtual const Type *bottom_type() const { return TypeLong::LONG; } |
114 | virtual uint ideal_reg() const { return Op_RegL; } |
115 | }; |
116 | |
117 | //------------------------------ModFNode--------------------------------------- |
118 | // Float Modulus |
119 | class ModFNode : public Node { |
120 | public: |
121 | ModFNode( Node *c, Node *in1, Node *in2 ) : Node(c,in1, in2) {} |
122 | virtual int Opcode() const; |
123 | virtual const Type* Value(PhaseGVN* phase) const; |
124 | virtual const Type *bottom_type() const { return Type::FLOAT; } |
125 | virtual uint ideal_reg() const { return Op_RegF; } |
126 | }; |
127 | |
128 | //------------------------------ModDNode--------------------------------------- |
129 | // Double Modulus |
130 | class ModDNode : public Node { |
131 | public: |
132 | ModDNode( Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {} |
133 | virtual int Opcode() const; |
134 | virtual const Type* Value(PhaseGVN* phase) const; |
135 | virtual const Type *bottom_type() const { return Type::DOUBLE; } |
136 | virtual uint ideal_reg() const { return Op_RegD; } |
137 | }; |
138 | |
139 | //------------------------------DivModNode--------------------------------------- |
140 | // Division with remainder result. |
141 | class DivModNode : public MultiNode { |
142 | protected: |
143 | DivModNode( Node *c, Node *dividend, Node *divisor ); |
144 | public: |
145 | enum { |
146 | div_proj_num = 0, // quotient |
147 | mod_proj_num = 1 // remainder |
148 | }; |
149 | virtual int Opcode() const; |
150 | virtual Node* Identity(PhaseGVN* phase) { return this; } |
151 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { return NULL; } |
152 | virtual const Type* Value(PhaseGVN* phase) const { return bottom_type(); } |
153 | virtual uint hash() const { return Node::hash(); } |
154 | virtual bool is_CFG() const { return false; } |
155 | virtual uint ideal_reg() const { return NotAMachineReg; } |
156 | |
157 | ProjNode* div_proj() { return proj_out_or_null(div_proj_num); } |
158 | ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); } |
159 | }; |
160 | |
161 | //------------------------------DivModINode--------------------------------------- |
162 | // Integer division with remainder result. |
163 | class DivModINode : public DivModNode { |
164 | public: |
165 | DivModINode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} |
166 | virtual int Opcode() const; |
167 | virtual const Type *bottom_type() const { return TypeTuple::INT_PAIR; } |
168 | virtual Node *match( const ProjNode *proj, const Matcher *m ); |
169 | |
170 | // Make a divmod and associated projections from a div or mod. |
171 | static DivModINode* make(Node* div_or_mod); |
172 | }; |
173 | |
174 | //------------------------------DivModLNode--------------------------------------- |
175 | // Long division with remainder result. |
176 | class DivModLNode : public DivModNode { |
177 | public: |
178 | DivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModNode(c, dividend, divisor) {} |
179 | virtual int Opcode() const; |
180 | virtual const Type *bottom_type() const { return TypeTuple::LONG_PAIR; } |
181 | virtual Node *match( const ProjNode *proj, const Matcher *m ); |
182 | |
183 | // Make a divmod and associated projections from a div or mod. |
184 | static DivModLNode* make(Node* div_or_mod); |
185 | }; |
186 | |
187 | #endif // SHARE_OPTO_DIVNODE_HPP |
188 | |