reviews
This commit is contained in:
parent
c04cefbc06
commit
2d1b109605
@ -3007,50 +3007,50 @@ void OuterStripMinedLoopNode::handle_sunk_stores_at_expansion(PhaseIterGVN* igvn
|
|||||||
// Sunk stores are reachable from the memory state of the outer loop safepoint
|
// Sunk stores are reachable from the memory state of the outer loop safepoint
|
||||||
Node* safepoint = outer_safepoint();
|
Node* safepoint = outer_safepoint();
|
||||||
Node* safepoint_mem = safepoint->in(TypeFunc::Memory);
|
Node* safepoint_mem = safepoint->in(TypeFunc::Memory);
|
||||||
if (safepoint_mem->is_MergeMem()) {
|
if (!safepoint_mem->is_MergeMem()) {
|
||||||
MergeMemNode* mm = safepoint_mem->as_MergeMem();
|
assert(stores_in_outer_loop_cnt == 0, "inconsistent");
|
||||||
DEBUG_ONLY(int stores_in_outer_loop_cnt2 = 0);
|
return;
|
||||||
for (MergeMemStream mms(mm); mms.next_non_empty(); ) {
|
}
|
||||||
Node* mem = mms.memory();
|
MergeMemNode* mm = safepoint_mem->as_MergeMem();
|
||||||
// Traverse up the chain of stores to find the first store pinned
|
DEBUG_ONLY(int stores_in_outer_loop_cnt2 = 0);
|
||||||
// at the loop exit projection.
|
for (MergeMemStream mms(mm); mms.next_non_empty();) {
|
||||||
Node* last = mem;
|
Node* mem = mms.memory();
|
||||||
Node* first = nullptr;
|
// Traverse up the chain of stores to find the first store pinned
|
||||||
while (mem->is_Store() && mem->in(0) == cle_exit_proj) {
|
// at the loop exit projection.
|
||||||
DEBUG_ONLY(stores_in_outer_loop_cnt2++);
|
Node* last = mem;
|
||||||
first = mem;
|
Node* first = nullptr;
|
||||||
mem = mem->in(MemNode::Memory);
|
while (mem->is_Store() && mem->in(0) == cle_exit_proj) {
|
||||||
|
DEBUG_ONLY(stores_in_outer_loop_cnt2++);
|
||||||
|
first = mem;
|
||||||
|
mem = mem->in(MemNode::Memory);
|
||||||
|
}
|
||||||
|
if (first != nullptr) {
|
||||||
|
// Found a chain of Stores that were sunk
|
||||||
|
// Do we already have a memory Phi for that slice on the outer loop? If that is the case, that Phi was created
|
||||||
|
// by cloning an inner loop Phi. The inner loop Phi should have mem, the memory state of the first Store out of
|
||||||
|
// the inner loop, as input on the backedge. So does the outer loop Phi given it's a clone.
|
||||||
|
Node* phi = nullptr;
|
||||||
|
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
|
||||||
|
Node* u = mem->fast_out(i);
|
||||||
|
if (u->is_Phi() && u->in(0) == this && u->in(LoopBackControl) == mem) {
|
||||||
|
assert(phi == nullptr, "there should be only one");
|
||||||
|
phi = u;
|
||||||
|
PRODUCT_ONLY(break);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (first != nullptr) {
|
if (phi == nullptr) {
|
||||||
// Found a chain of Stores that were sunk
|
// No outer loop Phi? create one
|
||||||
// Do we already have a memory Phi for that slice on the outer loop? If that is the case, that Phi was created
|
phi = PhiNode::make(this, last);
|
||||||
// by cloning an inner loop Phi. The inner loop Phi should have mem, the memory state of the first Store out of
|
phi->set_req(EntryControl, mem);
|
||||||
// the inner loop, as input on the backedge. So does the outer loop Phi given it's a clone.
|
phi = igvn->transform(phi);
|
||||||
Node* phi = nullptr;
|
igvn->replace_input_of(first, MemNode::Memory, phi);
|
||||||
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
|
} else {
|
||||||
Node* u = mem->fast_out(i);
|
// Fix memory state along the backedge: it should be the last sunk Store of the chain
|
||||||
if (u->is_Phi() && u->in(0) == this && u->in(LoopBackControl) == mem) {
|
igvn->replace_input_of(phi, LoopBackControl, last);
|
||||||
assert(phi == nullptr, "there should be only one");
|
|
||||||
phi = u;
|
|
||||||
PRODUCT_ONLY(break);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (phi == nullptr) {
|
|
||||||
// No outer loop Phi? create one
|
|
||||||
phi = PhiNode::make(this, last);
|
|
||||||
phi->set_req(EntryControl, mem);
|
|
||||||
phi = igvn->transform(phi);
|
|
||||||
igvn->replace_input_of(first, MemNode::Memory, phi);
|
|
||||||
} else {
|
|
||||||
// Fix memory state along the backedge: it should be the last sunk Store of the chain
|
|
||||||
igvn->replace_input_of(phi, LoopBackControl, last);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(stores_in_outer_loop_cnt == stores_in_outer_loop_cnt2, "inconsistent");
|
|
||||||
} else {
|
|
||||||
assert(stores_in_outer_loop_cnt == 0, "inconsistent");
|
|
||||||
}
|
}
|
||||||
|
assert(stores_in_outer_loop_cnt == stores_in_outer_loop_cnt2, "inconsistent");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) {
|
||||||
|
@ -41,6 +41,7 @@ public class TestStoresSunkInOuterStripMinedLoop {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
A a1 = new A();
|
A a1 = new A();
|
||||||
A a2 = new A();
|
A a2 = new A();
|
||||||
|
A a3 = new A();
|
||||||
for (int i = 0; i < 20_000; i++) {
|
for (int i = 0; i < 20_000; i++) {
|
||||||
field = 0;
|
field = 0;
|
||||||
test1();
|
test1();
|
||||||
@ -57,6 +58,11 @@ public class TestStoresSunkInOuterStripMinedLoop {
|
|||||||
if (a1.field != 1500) {
|
if (a1.field != 1500) {
|
||||||
throw new RuntimeException(a1.field + " != 1500");
|
throw new RuntimeException(a1.field + " != 1500");
|
||||||
}
|
}
|
||||||
|
a1.field = 0;
|
||||||
|
test4(a1, a2, a3);
|
||||||
|
if (a1.field != 1500) {
|
||||||
|
throw new RuntimeException(a1.field + " != 1500");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +110,24 @@ public class TestStoresSunkInOuterStripMinedLoop {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Couples stores sunk in outer loop, store in inner loop
|
||||||
|
private static float test4(A a1, A a2, A a3) {
|
||||||
|
field = a1.field + a2.field + a3.field;
|
||||||
|
volatileField = 42;
|
||||||
|
int v = a1.field;
|
||||||
|
float f = 1;
|
||||||
|
A a = a2;
|
||||||
|
for (int i = 0; i < 1500; i++) {
|
||||||
|
f *= 2;
|
||||||
|
v++;
|
||||||
|
a.field = v;
|
||||||
|
a = a1;
|
||||||
|
a2.field = v;
|
||||||
|
a3.field = v;
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
static class A {
|
static class A {
|
||||||
int field;
|
int field;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user