1.1 --- a/src/share/vm/opto/superword.cpp Mon Aug 31 02:24:21 2009 -0700 1.2 +++ b/src/share/vm/opto/superword.cpp Mon Aug 31 08:31:45 2009 -0700 1.3 @@ -990,8 +990,8 @@ 1.4 // (5) We know there is no dependence cycle, so there in no other case; 1.5 // (6) Finally, all memory ops in another single pack should be moved in the same direction. 1.6 // 1.7 -// To schedule a load pack: the memory edge of every loads in the pack must be 1.8 -// the same as the memory edge of the last executed load in the pack 1.9 +// To schedule a load pack, we use the memory state of either the first or the last load in 1.10 +// the pack, based on the dependence constraint. 1.11 void SuperWord::co_locate_pack(Node_List* pk) { 1.12 if (pk->at(0)->is_Store()) { 1.13 MemNode* first = executed_first(pk)->as_Mem(); 1.14 @@ -1076,15 +1076,32 @@ 1.15 current = my_mem->as_Mem(); 1.16 } // end while 1.17 } else if (pk->at(0)->is_Load()) { //load 1.18 - // all use the memory state that the last executed load uses 1.19 - LoadNode* last_load = executed_last(pk)->as_Load(); 1.20 - Node* last_mem = last_load->in(MemNode::Memory); 1.21 - _igvn.hash_delete(last_mem); 1.22 - // Give each load same memory state as last 1.23 + // all loads in the pack should have the same memory state. By default, 1.24 + // we use the memory state of the last load. However, if any load could 1.25 + // not be moved down due to the dependence constraint, we use the memory 1.26 + // state of the first load. 1.27 + Node* last_mem = executed_last(pk)->in(MemNode::Memory); 1.28 + Node* first_mem = executed_first(pk)->in(MemNode::Memory); 1.29 + bool schedule_last = true; 1.30 + for (uint i = 0; i < pk->size(); i++) { 1.31 + Node* ld = pk->at(i); 1.32 + for (Node* current = last_mem; current != ld->in(MemNode::Memory); 1.33 + current=current->in(MemNode::Memory)) { 1.34 + assert(current != first_mem, "corrupted memory graph"); 1.35 + if(current->is_Mem() && !independent(current, ld)){ 1.36 + schedule_last = false; // a later store depends on this load 1.37 + break; 1.38 + } 1.39 + } 1.40 + } 1.41 + 1.42 + Node* mem_input = schedule_last ? last_mem : first_mem; 1.43 + _igvn.hash_delete(mem_input); 1.44 + // Give each load the same memory state 1.45 for (uint i = 0; i < pk->size(); i++) { 1.46 LoadNode* ld = pk->at(i)->as_Load(); 1.47 _igvn.hash_delete(ld); 1.48 - ld->set_req(MemNode::Memory, last_mem); 1.49 + ld->set_req(MemNode::Memory, mem_input); 1.50 _igvn._worklist.push(ld); 1.51 } 1.52 }