src/share/vm/opto/superword.cpp

changeset 1387
ace8397c8563
parent 1102
78af5ae8e731
child 1420
685e959d09ea
     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    }

mercurial