Skip to content

Commit 23ed3a9

Browse files
author
Xiaohong Gong
committedAug 11, 2020
8250808: Re-associate loop invariants with other associative operations
Reviewed-by: kvn, thartmann
1 parent 91926e2 commit 23ed3a9

File tree

2 files changed

+138
-45
lines changed

2 files changed

+138
-45
lines changed
 

‎src/hotspot/share/opto/loopTransform.cpp

+130-41
Original file line numberDiff line numberDiff line change
@@ -245,21 +245,45 @@ void IdealLoopTree::compute_profile_trip_cnt(PhaseIdealLoop *phase) {
245245
head->set_profile_trip_cnt(trip_cnt);
246246
}
247247

248-
//---------------------is_invariant_addition-----------------------------
249-
// Return nonzero index of invariant operand for an Add or Sub
250-
// of (nonconstant) invariant and variant values. Helper for reassociate_invariants.
251-
int IdealLoopTree::is_invariant_addition(Node* n, PhaseIdealLoop *phase) {
248+
//---------------------find_invariant-----------------------------
249+
// Return nonzero index of invariant operand for an associative
250+
// binary operation of (nonconstant) invariant and variant values.
251+
// Helper for reassociate_invariants.
252+
int IdealLoopTree::find_invariant(Node* n, PhaseIdealLoop *phase) {
253+
bool in1_invar = this->is_invariant(n->in(1));
254+
bool in2_invar = this->is_invariant(n->in(2));
255+
if (in1_invar && !in2_invar) return 1;
256+
if (!in1_invar && in2_invar) return 2;
257+
return 0;
258+
}
259+
260+
//---------------------is_associative-----------------------------
261+
// Return TRUE if "n" is an associative binary node. If "base" is
262+
// not NULL, "n" must be re-associative with it.
263+
bool IdealLoopTree::is_associative(Node* n, Node* base) {
252264
int op = n->Opcode();
253-
if (op == Op_AddI || op == Op_SubI) {
254-
bool in1_invar = this->is_invariant(n->in(1));
255-
bool in2_invar = this->is_invariant(n->in(2));
256-
if (in1_invar && !in2_invar) return 1;
257-
if (!in1_invar && in2_invar) return 2;
265+
if (base != NULL) {
266+
assert(is_associative(base), "Base node should be associative");
267+
int base_op = base->Opcode();
268+
if (base_op == Op_AddI || base_op == Op_SubI) {
269+
return op == Op_AddI || op == Op_SubI;
270+
}
271+
if (base_op == Op_AddL || base_op == Op_SubL) {
272+
return op == Op_AddL || op == Op_SubL;
273+
}
274+
return op == base_op;
275+
} else {
276+
// Integer "add/sub/mul/and/or/xor" operations are associative.
277+
return op == Op_AddI || op == Op_AddL
278+
|| op == Op_SubI || op == Op_SubL
279+
|| op == Op_MulI || op == Op_MulL
280+
|| op == Op_AndI || op == Op_AndL
281+
|| op == Op_OrI || op == Op_OrL
282+
|| op == Op_XorI || op == Op_XorL;
258283
}
259-
return 0;
260284
}
261285

262-
//---------------------reassociate_add_sub-----------------------------
286+
//---------------------reassociate_add_sub------------------------
263287
// Reassociate invariant add and subtract expressions:
264288
//
265289
// inv1 + (x + inv2) => ( inv1 + inv2) + x
@@ -275,22 +299,12 @@ int IdealLoopTree::is_invariant_addition(Node* n, PhaseIdealLoop *phase) {
275299
// (inv2 - x) - inv1 => (-inv1 + inv2) - x
276300
// inv1 - (x + inv2) => ( inv1 - inv2) - x
277301
//
278-
Node* IdealLoopTree::reassociate_add_sub(Node* n1, PhaseIdealLoop *phase) {
279-
if ((!n1->is_Add() && !n1->is_Sub()) || n1->outcnt() == 0) return NULL;
280-
if (is_invariant(n1)) return NULL;
281-
int inv1_idx = is_invariant_addition(n1, phase);
282-
if (!inv1_idx) return NULL;
283-
// Don't mess with add of constant (igvn moves them to expression tree root.)
284-
if (n1->is_Add() && n1->in(2)->is_Con()) return NULL;
302+
Node* IdealLoopTree::reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop *phase) {
303+
assert(n1->is_Add() || n1->is_Sub(), "Target node should be add or subtract");
304+
Node* n2 = n1->in(3 - inv1_idx);
285305
Node* inv1 = n1->in(inv1_idx);
286-
Node* n2 = n1->in(3 - inv1_idx);
287-
int inv2_idx = is_invariant_addition(n2, phase);
288-
if (!inv2_idx) return NULL;
289-
290-
if (!phase->may_require_nodes(10, 10)) return NULL;
291-
292-
Node* x = n2->in(3 - inv2_idx);
293306
Node* inv2 = n2->in(inv2_idx);
307+
Node* x = n2->in(3 - inv2_idx);
294308

295309
bool neg_x = n2->is_Sub() && inv2_idx == 1;
296310
bool neg_inv2 = n2->is_Sub() && inv2_idx == 2;
@@ -299,36 +313,111 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, PhaseIdealLoop *phase) {
299313
neg_x = !neg_x;
300314
neg_inv2 = !neg_inv2;
301315
}
316+
317+
bool is_int = n1->bottom_type()->isa_int() != NULL;
302318
Node* inv1_c = phase->get_ctrl(inv1);
303-
Node* inv2_c = phase->get_ctrl(inv2);
304319
Node* n_inv1;
305320
if (neg_inv1) {
306-
Node *zero = phase->_igvn.intcon(0);
321+
Node* zero;
322+
if (is_int) {
323+
zero = phase->_igvn.intcon(0);
324+
n_inv1 = new SubINode(zero, inv1);
325+
} else {
326+
zero = phase->_igvn.longcon(0L);
327+
n_inv1 = new SubLNode(zero, inv1);
328+
}
307329
phase->set_ctrl(zero, phase->C->root());
308-
n_inv1 = new SubINode(zero, inv1);
309330
phase->register_new_node(n_inv1, inv1_c);
310331
} else {
311332
n_inv1 = inv1;
312333
}
334+
313335
Node* inv;
314-
if (neg_inv2) {
315-
inv = new SubINode(n_inv1, inv2);
336+
if (is_int) {
337+
if (neg_inv2) {
338+
inv = new SubINode(n_inv1, inv2);
339+
} else {
340+
inv = new AddINode(n_inv1, inv2);
341+
}
342+
phase->register_new_node(inv, phase->get_early_ctrl(inv));
343+
if (neg_x) {
344+
return new SubINode(inv, x);
345+
} else {
346+
return new AddINode(x, inv);
347+
}
316348
} else {
317-
inv = new AddINode(n_inv1, inv2);
349+
if (neg_inv2) {
350+
inv = new SubLNode(n_inv1, inv2);
351+
} else {
352+
inv = new AddLNode(n_inv1, inv2);
353+
}
354+
phase->register_new_node(inv, phase->get_early_ctrl(inv));
355+
if (neg_x) {
356+
return new SubLNode(inv, x);
357+
} else {
358+
return new AddLNode(x, inv);
359+
}
318360
}
319-
phase->register_new_node(inv, phase->get_early_ctrl(inv));
361+
}
320362

321-
Node* addx;
322-
if (neg_x) {
323-
addx = new SubINode(inv, x);
324-
} else {
325-
addx = new AddINode(x, inv);
363+
//---------------------reassociate-----------------------------
364+
// Reassociate invariant binary expressions with add/sub/mul/
365+
// and/or/xor operators.
366+
// For add/sub expressions: see "reassociate_add_sub"
367+
//
368+
// For mul/and/or/xor expressions:
369+
//
370+
// inv1 op (x op inv2) => (inv1 op inv2) op x
371+
//
372+
Node* IdealLoopTree::reassociate(Node* n1, PhaseIdealLoop *phase) {
373+
if (!is_associative(n1) || n1->outcnt() == 0) return NULL;
374+
if (is_invariant(n1)) return NULL;
375+
// Don't mess with add of constant (igvn moves them to expression tree root.)
376+
if (n1->is_Add() && n1->in(2)->is_Con()) return NULL;
377+
378+
int inv1_idx = find_invariant(n1, phase);
379+
if (!inv1_idx) return NULL;
380+
Node* n2 = n1->in(3 - inv1_idx);
381+
if (!is_associative(n2, n1)) return NULL;
382+
int inv2_idx = find_invariant(n2, phase);
383+
if (!inv2_idx) return NULL;
384+
385+
if (!phase->may_require_nodes(10, 10)) return NULL;
386+
387+
Node* result = NULL;
388+
switch (n1->Opcode()) {
389+
case Op_AddI:
390+
case Op_AddL:
391+
case Op_SubI:
392+
case Op_SubL:
393+
result = reassociate_add_sub(n1, inv1_idx, inv2_idx, phase);
394+
break;
395+
case Op_MulI:
396+
case Op_MulL:
397+
case Op_AndI:
398+
case Op_AndL:
399+
case Op_OrI:
400+
case Op_OrL:
401+
case Op_XorI:
402+
case Op_XorL: {
403+
Node* inv1 = n1->in(inv1_idx);
404+
Node* inv2 = n2->in(inv2_idx);
405+
Node* x = n2->in(3 - inv2_idx);
406+
Node* inv = n2->clone_with_data_edge(inv1, inv2);
407+
phase->register_new_node(inv, phase->get_early_ctrl(inv));
408+
result = n1->clone_with_data_edge(x, inv);
409+
break;
410+
}
411+
default:
412+
ShouldNotReachHere();
326413
}
327-
phase->register_new_node(addx, phase->get_ctrl(x));
328-
phase->_igvn.replace_node(n1, addx);
414+
415+
assert(result != NULL, "");
416+
phase->register_new_node(result, phase->get_ctrl(n1));
417+
phase->_igvn.replace_node(n1, result);
329418
assert(phase->get_loop(phase->get_ctrl(n1)) == this, "");
330419
_body.yank(n1);
331-
return addx;
420+
return result;
332421
}
333422

334423
//---------------------reassociate_invariants-----------------------------
@@ -337,7 +426,7 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
337426
for (int i = _body.size() - 1; i >= 0; i--) {
338427
Node *n = _body.at(i);
339428
for (int j = 0; j < 5; j++) {
340-
Node* nn = reassociate_add_sub(n, phase);
429+
Node* nn = reassociate(n, phase);
341430
if (nn == NULL) break;
342431
n = nn; // again
343432
}

‎src/hotspot/share/opto/loopnode.hpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -636,11 +636,15 @@ class IdealLoopTree : public ResourceObj {
636636

637637
// Reassociate invariant expressions.
638638
void reassociate_invariants(PhaseIdealLoop *phase);
639+
// Reassociate invariant binary expressions.
640+
Node* reassociate(Node* n1, PhaseIdealLoop *phase);
639641
// Reassociate invariant add and subtract expressions.
640-
Node* reassociate_add_sub(Node* n1, PhaseIdealLoop *phase);
642+
Node* reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop *phase);
641643
// Return nonzero index of invariant operand if invariant and variant
642-
// are combined with an Add or Sub. Helper for reassociate_invariants.
643-
int is_invariant_addition(Node* n, PhaseIdealLoop *phase);
644+
// are combined with an associative binary. Helper for reassociate_invariants.
645+
int find_invariant(Node* n, PhaseIdealLoop *phase);
646+
// Return TRUE if "n" is associative.
647+
bool is_associative(Node* n, Node* base=NULL);
644648

645649
// Return true if n is invariant
646650
bool is_invariant(Node* n) const;

0 commit comments

Comments
 (0)
Please sign in to comment.