Mercurial > hg > graal-compiler
comparison src/share/vm/opto/mathexactnode.cpp @ 12972:59e8ad757e19
8026844: Various Math functions needs intrinsification
Reviewed-by: kvn, twisti
author | rbackman |
---|---|
date | Fri, 18 Oct 2013 10:41:56 +0200 |
parents | 4a2acfb16e97 |
children | cd5d10655495 |
comparison
equal
deleted
inserted
replaced
12971:3a04e444da6d | 12972:59e8ad757e19 |
---|---|
29 #include "opto/machnode.hpp" | 29 #include "opto/machnode.hpp" |
30 #include "opto/matcher.hpp" | 30 #include "opto/matcher.hpp" |
31 #include "opto/mathexactnode.hpp" | 31 #include "opto/mathexactnode.hpp" |
32 #include "opto/subnode.hpp" | 32 #include "opto/subnode.hpp" |
33 | 33 |
34 MathExactNode::MathExactNode(Node* ctrl, Node* n1, Node* n2) : MultiNode(3) { | 34 MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) { |
35 init_class_id(Class_MathExact); | |
35 init_req(0, ctrl); | 36 init_req(0, ctrl); |
36 init_req(1, n1); | 37 init_req(1, in1); |
37 init_req(2, n2); | 38 } |
39 | |
40 MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) { | |
41 init_class_id(Class_MathExact); | |
42 init_req(0, ctrl); | |
43 init_req(1, in1); | |
44 init_req(2, in2); | |
38 } | 45 } |
39 | 46 |
40 BoolNode* MathExactNode::bool_node() const { | 47 BoolNode* MathExactNode::bool_node() const { |
41 Node* flags = flags_node(); | 48 Node* flags = flags_node(); |
42 BoolNode* boolnode = flags->unique_out()->as_Bool(); | 49 BoolNode* boolnode = flags->unique_out()->as_Bool(); |
62 return ifnode->proj_out(0); | 69 return ifnode->proj_out(0); |
63 } | 70 } |
64 return ifnode->proj_out(1); | 71 return ifnode->proj_out(1); |
65 } | 72 } |
66 | 73 |
67 Node* AddExactINode::match(const ProjNode* proj, const Matcher* m) { | |
68 uint ideal_reg = proj->ideal_reg(); | |
69 RegMask rm; | |
70 if (proj->_con == result_proj_node) { | |
71 rm = m->mathExactI_result_proj_mask(); | |
72 } else { | |
73 assert(proj->_con == flags_proj_node, "must be result or flags"); | |
74 assert(ideal_reg == Op_RegFlags, "sanity"); | |
75 rm = m->mathExactI_flags_proj_mask(); | |
76 } | |
77 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); | |
78 } | |
79 | |
80 // If the MathExactNode won't overflow we have to replace the | 74 // If the MathExactNode won't overflow we have to replace the |
81 // FlagsProjNode and ProjNode that is generated by the MathExactNode | 75 // FlagsProjNode and ProjNode that is generated by the MathExactNode |
82 Node* MathExactNode::no_overflow(PhaseGVN *phase, Node* new_result) { | 76 Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) { |
83 PhaseIterGVN *igvn = phase->is_IterGVN(); | 77 PhaseIterGVN* igvn = phase->is_IterGVN(); |
84 if (igvn) { | 78 if (igvn) { |
85 ProjNode* result = result_node(); | 79 ProjNode* result = result_node(); |
86 ProjNode* flags = flags_node(); | 80 ProjNode* flags = flags_node(); |
87 | 81 |
88 if (result != NULL) { | 82 if (result != NULL) { |
108 } | 102 } |
109 } | 103 } |
110 return new_result; | 104 return new_result; |
111 } | 105 } |
112 | 106 |
113 Node *AddExactINode::Ideal(PhaseGVN *phase, bool can_reshape) { | 107 Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) { |
114 Node *arg1 = in(1); | 108 uint ideal_reg = proj->ideal_reg(); |
115 Node *arg2 = in(2); | 109 RegMask rm; |
110 if (proj->_con == result_proj_node) { | |
111 rm = m->mathExactI_result_proj_mask(); | |
112 } else { | |
113 assert(proj->_con == flags_proj_node, "must be result or flags"); | |
114 assert(ideal_reg == Op_RegFlags, "sanity"); | |
115 rm = m->mathExactI_flags_proj_mask(); | |
116 } | |
117 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); | |
118 } | |
119 | |
120 Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) { | |
121 uint ideal_reg = proj->ideal_reg(); | |
122 RegMask rm; | |
123 if (proj->_con == result_proj_node) { | |
124 rm = m->mathExactL_result_proj_mask(); | |
125 } else { | |
126 assert(proj->_con == flags_proj_node, "must be result or flags"); | |
127 assert(ideal_reg == Op_RegFlags, "sanity"); | |
128 rm = m->mathExactI_flags_proj_mask(); | |
129 } | |
130 return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); | |
131 } | |
132 | |
133 Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
134 Node* arg1 = in(1); | |
135 Node* arg2 = in(2); | |
116 | 136 |
117 const Type* type1 = phase->type(arg1); | 137 const Type* type1 = phase->type(arg1); |
118 const Type* type2 = phase->type(arg2); | 138 const Type* type2 = phase->type(arg2); |
119 | 139 |
120 if (type1 != Type::TOP && type1->singleton() && | 140 if (type1 != Type::TOP && type1->singleton() && |
128 return no_overflow(phase, con_result); | 148 return no_overflow(phase, con_result); |
129 } | 149 } |
130 return NULL; | 150 return NULL; |
131 } | 151 } |
132 | 152 |
133 if (type1 == TypeInt::ZERO) { // (Add 0 x) == x | 153 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x |
134 Node* add_result = new (phase->C) AddINode(arg1, arg2); | 154 Node* add_result = new (phase->C) AddINode(arg1, arg2); |
135 return no_overflow(phase, add_result); | 155 return no_overflow(phase, add_result); |
136 } | 156 } |
137 | 157 |
138 if (type2 == TypeInt::ZERO) { // (Add x 0) == x | 158 if (type2->singleton()) { |
159 return NULL; // no change - keep constant on the right | |
160 } | |
161 | |
162 if (type1->singleton()) { | |
163 // Make it x + Constant - move constant to the right | |
164 swap_edges(1, 2); | |
165 return this; | |
166 } | |
167 | |
168 if (arg2->is_Load()) { | |
169 return NULL; // no change - keep load on the right | |
170 } | |
171 | |
172 if (arg1->is_Load()) { | |
173 // Make it x + Load - move load to the right | |
174 swap_edges(1, 2); | |
175 return this; | |
176 } | |
177 | |
178 if (arg1->_idx > arg2->_idx) { | |
179 // Sort the edges | |
180 swap_edges(1, 2); | |
181 return this; | |
182 } | |
183 | |
184 return NULL; | |
185 } | |
186 | |
187 Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
188 Node* arg1 = in(1); | |
189 Node* arg2 = in(2); | |
190 | |
191 const Type* type1 = phase->type(arg1); | |
192 const Type* type2 = phase->type(arg2); | |
193 | |
194 if (type1 != Type::TOP && type1->singleton() && | |
195 type2 != Type::TOP && type2->singleton()) { | |
196 jlong val1 = arg1->get_long(); | |
197 jlong val2 = arg2->get_long(); | |
198 jlong result = val1 + val2; | |
199 // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result | |
200 if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { | |
201 Node* con_result = ConLNode::make(phase->C, result); | |
202 return no_overflow(phase, con_result); | |
203 } | |
204 return NULL; | |
205 } | |
206 | |
207 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x | |
208 Node* add_result = new (phase->C) AddLNode(arg1, arg2); | |
209 return no_overflow(phase, add_result); | |
210 } | |
211 | |
212 if (type2->singleton()) { | |
213 return NULL; // no change - keep constant on the right | |
214 } | |
215 | |
216 if (type1->singleton()) { | |
217 // Make it x + Constant - move constant to the right | |
218 swap_edges(1, 2); | |
219 return this; | |
220 } | |
221 | |
222 if (arg2->is_Load()) { | |
223 return NULL; // no change - keep load on the right | |
224 } | |
225 | |
226 if (arg1->is_Load()) { | |
227 // Make it x + Load - move load to the right | |
228 swap_edges(1, 2); | |
229 return this; | |
230 } | |
231 | |
232 if (arg1->_idx > arg2->_idx) { | |
233 // Sort the edges | |
234 swap_edges(1, 2); | |
235 return this; | |
236 } | |
237 | |
238 return NULL; | |
239 } | |
240 | |
241 Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
242 Node* arg1 = in(1); | |
243 Node* arg2 = in(2); | |
244 | |
245 const Type* type1 = phase->type(arg1); | |
246 const Type* type2 = phase->type(arg2); | |
247 | |
248 if (type1 != Type::TOP && type1->singleton() && | |
249 type2 != Type::TOP && type2->singleton()) { | |
250 jint val1 = arg1->get_int(); | |
251 jint val2 = arg2->get_int(); | |
252 jint result = val1 - val2; | |
253 | |
254 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and | |
255 // the sign of the result is different than the sign of arg1 | |
256 if (((val1 ^ val2) & (val1 ^ result)) >= 0) { | |
257 Node* con_result = ConINode::make(phase->C, result); | |
258 return no_overflow(phase, con_result); | |
259 } | |
260 return NULL; | |
261 } | |
262 | |
263 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { | |
264 // Sub with zero is the same as add with zero | |
139 Node* add_result = new (phase->C) AddINode(arg1, arg2); | 265 Node* add_result = new (phase->C) AddINode(arg1, arg2); |
140 return no_overflow(phase, add_result); | 266 return no_overflow(phase, add_result); |
141 } | 267 } |
142 | 268 |
143 if (type2->singleton()) { | 269 return NULL; |
144 return NULL; // no change - keep constant on the right | 270 } |
145 } | 271 |
146 | 272 Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { |
147 if (type1->singleton()) { | 273 Node* arg1 = in(1); |
148 // Make it x + Constant - move constant to the right | 274 Node* arg2 = in(2); |
149 swap_edges(1, 2); | 275 |
150 return this; | 276 const Type* type1 = phase->type(arg1); |
151 } | 277 const Type* type2 = phase->type(arg2); |
152 | 278 |
153 if (arg2->is_Load()) { | 279 if (type1 != Type::TOP && type1->singleton() && |
154 return NULL; // no change - keep load on the right | 280 type2 != Type::TOP && type2->singleton()) { |
155 } | 281 jlong val1 = arg1->get_long(); |
156 | 282 jlong val2 = arg2->get_long(); |
157 if (arg1->is_Load()) { | 283 jlong result = val1 - val2; |
158 // Make it x + Load - move load to the right | 284 |
159 swap_edges(1, 2); | 285 // Hacker's Delight 2-12 Overflow iff the arguments have different signs and |
160 return this; | 286 // the sign of the result is different than the sign of arg1 |
161 } | 287 if (((val1 ^ val2) & (val1 ^ result)) >= 0) { |
162 | 288 Node* con_result = ConLNode::make(phase->C, result); |
163 if (arg1->_idx > arg2->_idx) { | 289 return no_overflow(phase, con_result); |
164 // Sort the edges | 290 } |
165 swap_edges(1, 2); | 291 return NULL; |
166 return this; | 292 } |
167 } | 293 |
168 | 294 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { |
169 return NULL; | 295 // Sub with zero is the same as add with zero |
170 } | 296 Node* add_result = new (phase->C) AddLNode(arg1, arg2); |
171 | 297 return no_overflow(phase, add_result); |
298 } | |
299 | |
300 return NULL; | |
301 } | |
302 | |
303 Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
304 Node *arg = in(1); | |
305 | |
306 const Type* type = phase->type(arg); | |
307 if (type != Type::TOP && type->singleton()) { | |
308 jint value = arg->get_int(); | |
309 if (value != min_jint) { | |
310 Node* neg_result = ConINode::make(phase->C, -value); | |
311 return no_overflow(phase, neg_result); | |
312 } | |
313 } | |
314 return NULL; | |
315 } | |
316 | |
317 Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
318 Node *arg = in(1); | |
319 | |
320 const Type* type = phase->type(arg); | |
321 if (type != Type::TOP && type->singleton()) { | |
322 jlong value = arg->get_long(); | |
323 if (value != min_jlong) { | |
324 Node* neg_result = ConLNode::make(phase->C, -value); | |
325 return no_overflow(phase, neg_result); | |
326 } | |
327 } | |
328 return NULL; | |
329 } | |
330 | |
331 Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
332 Node* arg1 = in(1); | |
333 Node* arg2 = in(2); | |
334 | |
335 const Type* type1 = phase->type(arg1); | |
336 const Type* type2 = phase->type(arg2); | |
337 | |
338 if (type1 != Type::TOP && type1->singleton() && | |
339 type2 != Type::TOP && type2->singleton()) { | |
340 jint val1 = arg1->get_int(); | |
341 jint val2 = arg2->get_int(); | |
342 jlong result = (jlong) val1 * (jlong) val2; | |
343 if ((jint) result == result) { | |
344 // no overflow | |
345 Node* mul_result = ConINode::make(phase->C, result); | |
346 return no_overflow(phase, mul_result); | |
347 } | |
348 } | |
349 | |
350 if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { | |
351 return no_overflow(phase, ConINode::make(phase->C, 0)); | |
352 } | |
353 | |
354 if (type1 == TypeInt::ONE) { | |
355 Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0)); | |
356 return no_overflow(phase, mul_result); | |
357 } | |
358 if (type2 == TypeInt::ONE) { | |
359 Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0)); | |
360 return no_overflow(phase, mul_result); | |
361 } | |
362 | |
363 if (type1 == TypeInt::MINUS_1) { | |
364 return new (phase->C) NegExactINode(NULL, arg2); | |
365 } | |
366 | |
367 if (type2 == TypeInt::MINUS_1) { | |
368 return new (phase->C) NegExactINode(NULL, arg1); | |
369 } | |
370 | |
371 return NULL; | |
372 } | |
373 | |
374 Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) { | |
375 Node* arg1 = in(1); | |
376 Node* arg2 = in(2); | |
377 | |
378 const Type* type1 = phase->type(arg1); | |
379 const Type* type2 = phase->type(arg2); | |
380 | |
381 if (type1 != Type::TOP && type1->singleton() && | |
382 type2 != Type::TOP && type2->singleton()) { | |
383 jlong val1 = arg1->get_long(); | |
384 jlong val2 = arg2->get_long(); | |
385 | |
386 jlong result = val1 * val2; | |
387 jlong ax = (val1 < 0 ? -val1 : val1); | |
388 jlong ay = (val2 < 0 ? -val2 : val2); | |
389 | |
390 bool overflow = false; | |
391 if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) { | |
392 // potential overflow if any bit in upper 32 bits are set | |
393 if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) { | |
394 // -1 * Long.MIN_VALUE will overflow | |
395 overflow = true; | |
396 } else if (val2 != 0 && (result / val2 != val1)) { | |
397 overflow = true; | |
398 } | |
399 } | |
400 | |
401 if (!overflow) { | |
402 Node* mul_result = ConLNode::make(phase->C, result); | |
403 return no_overflow(phase, mul_result); | |
404 } | |
405 } | |
406 | |
407 if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { | |
408 return no_overflow(phase, ConLNode::make(phase->C, 0)); | |
409 } | |
410 | |
411 if (type1 == TypeLong::ONE) { | |
412 Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0)); | |
413 return no_overflow(phase, mul_result); | |
414 } | |
415 if (type2 == TypeLong::ONE) { | |
416 Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0)); | |
417 return no_overflow(phase, mul_result); | |
418 } | |
419 | |
420 if (type1 == TypeLong::MINUS_1) { | |
421 return new (phase->C) NegExactLNode(NULL, arg2); | |
422 } | |
423 | |
424 if (type2 == TypeLong::MINUS_1) { | |
425 return new (phase->C) NegExactLNode(NULL, arg1); | |
426 } | |
427 | |
428 return NULL; | |
429 } | |
430 |