comparison src/share/vm/opto/divnode.cpp @ 3410:121e5708ae96

7169782: C2: SIGSEGV in LShiftLNode::Ideal(PhaseGVN*, bool) Summary: keep intermediate node alive till the end of the graph construction using dummy hook node trick Reviewed-by: kvn, twisti Contributed-by: vladimir.x.ivanov@oracle.com
author kvn
date Tue, 12 Jun 2012 09:47:23 -0700
parents f95d63e2154a
children e626685e9f6c
comparison
equal deleted inserted replaced
15:b155e29ec7a1 16:95172d5ee010
282 // Note: The version above is for 32x32 multiplications, while the 282 // Note: The version above is for 32x32 multiplications, while the
283 // following inline comments are adapted to 64x64. 283 // following inline comments are adapted to 64x64.
284 284
285 const int N = 64; 285 const int N = 64;
286 286
287 // Dummy node to keep intermediate nodes alive during construction
288 Node* hook = new (phase->C, 4) Node(4);
289
287 // u0 = u & 0xFFFFFFFF; u1 = u >> 32; 290 // u0 = u & 0xFFFFFFFF; u1 = u >> 32;
288 Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); 291 Node* u0 = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF)));
289 Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); 292 Node* u1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2)));
293 hook->init_req(0, u0);
294 hook->init_req(1, u1);
290 295
291 // v0 = v & 0xFFFFFFFF; v1 = v >> 32; 296 // v0 = v & 0xFFFFFFFF; v1 = v >> 32;
292 Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF); 297 Node* v0 = phase->longcon(magic_const & 0xFFFFFFFF);
293 Node* v1 = phase->longcon(magic_const >> (N / 2)); 298 Node* v1 = phase->longcon(magic_const >> (N / 2));
294 299
297 302
298 // t = u1*v0 + (w0 >> 32); 303 // t = u1*v0 + (w0 >> 32);
299 Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0)); 304 Node* u1v0 = phase->transform(new (phase->C, 3) MulLNode(u1, v0));
300 Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2))); 305 Node* temp = phase->transform(new (phase->C, 3) URShiftLNode(w0, phase->intcon(N / 2)));
301 Node* t = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp)); 306 Node* t = phase->transform(new (phase->C, 3) AddLNode(u1v0, temp));
307 hook->init_req(2, t);
302 308
303 // w1 = t & 0xFFFFFFFF; 309 // w1 = t & 0xFFFFFFFF;
304 Node* w1 = new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF)); 310 Node* w1 = phase->transform(new (phase->C, 3) AndLNode(t, phase->longcon(0xFFFFFFFF)));
311 hook->init_req(3, w1);
305 312
306 // w2 = t >> 32; 313 // w2 = t >> 32;
307 Node* w2 = new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2)); 314 Node* w2 = phase->transform(new (phase->C, 3) RShiftLNode(t, phase->intcon(N / 2)));
308
309 // 6732154: Construct both w1 and w2 before transforming, so t
310 // doesn't go dead prematurely.
311 // 6837011: We need to transform w2 before w1 because the
312 // transformation of w1 could return t.
313 w2 = phase->transform(w2);
314 w1 = phase->transform(w1);
315 315
316 // w1 = u0*v1 + w1; 316 // w1 = u0*v1 + w1;
317 Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1)); 317 Node* u0v1 = phase->transform(new (phase->C, 3) MulLNode(u0, v1));
318 w1 = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1)); 318 w1 = phase->transform(new (phase->C, 3) AddLNode(u0v1, w1));
319 319
320 // return u1*v1 + w2 + (w1 >> 32); 320 // return u1*v1 + w2 + (w1 >> 32);
321 Node* u1v1 = phase->transform(new (phase->C, 3) MulLNode(u1, v1)); 321 Node* u1v1 = phase->transform(new (phase->C, 3) MulLNode(u1, v1));
322 Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2)); 322 Node* temp1 = phase->transform(new (phase->C, 3) AddLNode(u1v1, w2));
323 Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2))); 323 Node* temp2 = phase->transform(new (phase->C, 3) RShiftLNode(w1, phase->intcon(N / 2)));
324
325 // Remove the bogus extra edges used to keep things alive
326 PhaseIterGVN* igvn = phase->is_IterGVN();
327 if (igvn != NULL) {
328 igvn->remove_dead_node(hook);
329 } else {
330 for (int i = 0; i < 4; i++) {
331 hook->set_req(i, NULL);
332 }
333 }
324 334
325 return new (phase->C, 3) AddLNode(temp1, temp2); 335 return new (phase->C, 3) AddLNode(temp1, temp2);
326 } 336 }
327 337
328 338