Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
adcb643
8323220: Reassociate loop invariants involved in Cmps and Add/Subs
caojoshua Jan 8, 2024
dda874e
Formatting and comments
caojoshua Jan 17, 2024
cb6d24b
Assert for n2. Variables for n1/n2 opcode. More concise comments.
caojoshua Jan 20, 2024
5ea7a53
Formatting and fix typo
caojoshua Jan 22, 2024
a08df7f
reassociate_add_sub -> reassociate_add_sub_cmp
caojoshua Jan 24, 2024
1603864
Small fixes and add check methods for tests
caojoshua Jan 27, 2024
76c8261
Merge branch 'master' into licm
caojoshua Feb 1, 2024
d1cd230
Remove unused TestInfo parameter. Have some tests exit mid-loop.
caojoshua Feb 1, 2024
f3ff547
Add some correctness tests where we do reassociate
caojoshua Feb 8, 2024
b29c557
Add correctness test for some random tests with random inputs
caojoshua Feb 8, 2024
21a3f49
Merge branch 'master' into licm
caojoshua Feb 14, 2024
ad073ef
Update test to utilize @setup method for arguments
caojoshua Feb 16, 2024
3e573b0
Make inputs deterministic. Make size an arg. Fix comments. Formatting.
caojoshua Feb 16, 2024
ab6c409
Merge branch 'master' into licm
caojoshua Feb 29, 2024
e9a0d09
Merge branch 'master' into licm
caojoshua Mar 4, 2024
aaa32c5
Merge branch 'master' into licm
caojoshua Mar 14, 2024
1568fa3
Merge branch 'master' into licm
caojoshua Mar 19, 2024
b151293
Add tests for add/sub reassociation
caojoshua Mar 21, 2024
33e34b0
@run driver -> @run main
caojoshua Mar 21, 2024
32cb9c0
Merge branch 'master' into licm
caojoshua Mar 22, 2024
abd4ddd
Merge branch 'master' into licm
caojoshua Apr 5, 2024
7ab0b41
Merge remote-tracking branch 'josh/licm' into licm
caojoshua Apr 5, 2024
d5cd233
Formatting, use @run driver, remove legacy header comments
caojoshua Apr 5, 2024
1b27aae
Fix typo
caojoshua Apr 5, 2024
3bcab3b
Update src/hotspot/share/opto/loopTransform.cpp
caojoshua Apr 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 53 additions & 19 deletions src/hotspot/share/opto/loopTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,45 +254,62 @@ void IdealLoopTree::compute_profile_trip_cnt(PhaseIdealLoop *phase) {
head->set_profile_trip_cnt(trip_cnt);
}

//---------------------find_invariant-----------------------------
// Return nonzero index of invariant operand for an associative
// binary operation of (nonconstant) invariant and variant values.
// Helper for reassociate_invariants.
int IdealLoopTree::find_invariant(Node* n, PhaseIdealLoop *phase) {
int IdealLoopTree::find_invariant(Node* n, PhaseIdealLoop* phase) {
bool in1_invar = this->is_invariant(n->in(1));
bool in2_invar = this->is_invariant(n->in(2));
if (in1_invar && !in2_invar) return 1;
if (!in1_invar && in2_invar) return 2;
return 0;
}

//---------------------is_associative-----------------------------
// Return TRUE if "n" is an associative cmp node. A cmp node is
// associative if it is only used for equals or not-equals
// comparisons of integers or longs. We cannot reassociate
// non-equality comparisons due to possibility of overflow.
bool IdealLoopTree::is_associative_cmp(Node* n) {
if (n->Opcode() != Op_CmpI && n->Opcode() != Op_CmpL) {
return false;
}
for (DUIterator i = n->outs(); n->has_out(i); i++) {
BoolNode* bool_out = n->out(i)->isa_Bool();
if (bool_out == nullptr || !(bool_out->_test._test == BoolTest::eq ||
bool_out->_test._test == BoolTest::ne)) {
return false;
}
}
return true;
}

// Return TRUE if "n" is an associative binary node. If "base" is
// not null, "n" must be re-associative with it.
bool IdealLoopTree::is_associative(Node* n, Node* base) {
int op = n->Opcode();
if (base != nullptr) {
assert(is_associative(base), "Base node should be associative");
int base_op = base->Opcode();
if (base_op == Op_AddI || base_op == Op_SubI) {
if (base_op == Op_AddI || base_op == Op_SubI || base_op == Op_CmpI) {
return op == Op_AddI || op == Op_SubI;
}
if (base_op == Op_AddL || base_op == Op_SubL) {
if (base_op == Op_AddL || base_op == Op_SubL || base_op == Op_CmpL) {
return op == Op_AddL || op == Op_SubL;
}
return op == base_op;
} else {
// Integer "add/sub/mul/and/or/xor" operations are associative.
// Integer "add/sub/mul/and/or/xor" operations are associative. Integer
// "cmp" operations are associative if it is an equality comparison.
return op == Op_AddI || op == Op_AddL
|| op == Op_SubI || op == Op_SubL
|| op == Op_MulI || op == Op_MulL
|| op == Op_AndI || op == Op_AndL
|| op == Op_OrI || op == Op_OrL
|| op == Op_XorI || op == Op_XorL;
|| op == Op_XorI || op == Op_XorL
|| is_associative_cmp(n);
}
}

//---------------------reassociate_add_sub------------------------
// Reassociate invariant add and subtract expressions:
//
// inv1 + (x + inv2) => ( inv1 + inv2) + x
Expand All @@ -308,22 +325,32 @@ bool IdealLoopTree::is_associative(Node* n, Node* base) {
// (inv2 - x) - inv1 => (-inv1 + inv2) - x
// inv1 - (x + inv2) => ( inv1 - inv2) - x
//
Node* IdealLoopTree::reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop *phase) {
assert(n1->is_Add() || n1->is_Sub(), "Target node should be add or subtract");
// Apply the same transformations to == and !=
// inv1 == (x + inv2) => ( inv1 - inv2 ) == x
// inv1 == (x - inv2) => ( inv1 + inv2 ) == x
// inv1 == (inv2 - x) => (-inv1 + inv2 ) == x
Node* IdealLoopTree::reassociate_add_sub_cmp(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop* phase) {
Node* n2 = n1->in(3 - inv1_idx);
bool n1_is_sub = n1->is_Sub() && !n1->is_Cmp();
bool n1_is_cmp = n1->is_Cmp();
bool n2_is_sub = n2->is_Sub();
assert(n1->is_Add() || n1_is_sub || n1_is_cmp, "Target node should be add, subtract, or compare");
assert(n2->is_Add() || (n2_is_sub && !n2->is_Cmp()), "Child node should be add or subtract");
Node* inv1 = n1->in(inv1_idx);
Node* inv2 = n2->in(inv2_idx);
Node* x = n2->in(3 - inv2_idx);

bool neg_x = n2->is_Sub() && inv2_idx == 1;
bool neg_inv2 = n2->is_Sub() && inv2_idx == 2;
bool neg_inv1 = n1->is_Sub() && inv1_idx == 2;
if (n1->is_Sub() && inv1_idx == 1) {
// Determine whether x, inv1, or inv2 should be negative in the transformed
// expression
bool neg_x = n2_is_sub && inv2_idx == 1;
bool neg_inv2 = (n2_is_sub && !n1_is_cmp && inv2_idx == 2) || (n1_is_cmp && !n2_is_sub);
bool neg_inv1 = (n1_is_sub && inv1_idx == 2) || (n1_is_cmp && inv2_idx == 1 && n2_is_sub);
if (n1_is_sub && inv1_idx == 1) {
neg_x = !neg_x;
neg_inv2 = !neg_inv2;
}

bool is_int = n1->bottom_type()->isa_int() != nullptr;
bool is_int = n2->bottom_type()->isa_int() != nullptr;
Node* inv1_c = phase->get_ctrl(inv1);
Node* n_inv1;
if (neg_inv1) {
Expand All @@ -349,6 +376,9 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, P
inv = new AddINode(n_inv1, inv2);
}
phase->register_new_node(inv, phase->get_early_ctrl(inv));
if (n1_is_cmp) {
return new CmpINode(x, inv);
}
if (neg_x) {
return new SubINode(inv, x);
} else {
Expand All @@ -361,6 +391,9 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, P
inv = new AddLNode(n_inv1, inv2);
}
phase->register_new_node(inv, phase->get_early_ctrl(inv));
if (n1_is_cmp) {
return new CmpLNode(x, inv);
}
if (neg_x) {
return new SubLNode(inv, x);
} else {
Expand All @@ -369,10 +402,9 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, P
}
}

//---------------------reassociate-----------------------------
// Reassociate invariant binary expressions with add/sub/mul/
// and/or/xor operators.
// For add/sub expressions: see "reassociate_add_sub"
// and/or/xor/cmp operators.
// For add/sub/cmp expressions: see "reassociate_add_sub_cmp"
//
// For mul/and/or/xor expressions:
//
Expand All @@ -399,7 +431,9 @@ Node* IdealLoopTree::reassociate(Node* n1, PhaseIdealLoop *phase) {
case Op_AddL:
case Op_SubI:
case Op_SubL:
result = reassociate_add_sub(n1, inv1_idx, inv2_idx, phase);
case Op_CmpI:
case Op_CmpL:
result = reassociate_add_sub_cmp(n1, inv1_idx, inv2_idx, phase);
break;
case Op_MulI:
case Op_MulL:
Expand Down
6 changes: 4 additions & 2 deletions src/hotspot/share/opto/loopnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -739,13 +739,15 @@ class IdealLoopTree : public ResourceObj {
void reassociate_invariants(PhaseIdealLoop *phase);
// Reassociate invariant binary expressions.
Node* reassociate(Node* n1, PhaseIdealLoop *phase);
// Reassociate invariant add and subtract expressions.
Node* reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop *phase);
// Reassociate invariant add, subtract, and compare expressions.
Node* reassociate_add_sub_cmp(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop* phase);
// Return nonzero index of invariant operand if invariant and variant
// are combined with an associative binary. Helper for reassociate_invariants.
int find_invariant(Node* n, PhaseIdealLoop *phase);
// Return TRUE if "n" is associative.
bool is_associative(Node* n, Node* base=nullptr);
// Return TRUE if "n" is an associative cmp node.
bool is_associative_cmp(Node* n);

// Return true if n is invariant
bool is_invariant(Node* n) const;
Expand Down
Loading