hotspot/src/share/vm/opto/superword.cpp
changeset 2334 742b05aeec42
parent 2154 72a9b7284ccf
child 3799 6eddf8400cbc
equal deleted inserted replaced
2333:79fb1ed554bd 2334:742b05aeec42
   452         if (out->is_MergeMem() && !in_bb(out)) {
   452         if (out->is_MergeMem() && !in_bb(out)) {
   453           // Either unrolling is causing a memory edge not to disappear,
   453           // Either unrolling is causing a memory edge not to disappear,
   454           // or need to run igvn.optimize() again before SLP
   454           // or need to run igvn.optimize() again before SLP
   455         } else if (out->is_Phi() && out->bottom_type() == Type::MEMORY && !in_bb(out)) {
   455         } else if (out->is_Phi() && out->bottom_type() == Type::MEMORY && !in_bb(out)) {
   456           // Ditto.  Not sure what else to check further.
   456           // Ditto.  Not sure what else to check further.
   457         } else if (out->Opcode() == Op_StoreCM && out->in(4) == n) {
   457         } else if (out->Opcode() == Op_StoreCM && out->in(MemNode::OopStore) == n) {
   458           // StoreCM has an input edge used as a precedence edge.
   458           // StoreCM has an input edge used as a precedence edge.
   459           // Maybe an issue when oop stores are vectorized.
   459           // Maybe an issue when oop stores are vectorized.
       
   460         } else if( out->is_MergeMem() && prev &&
       
   461                    prev->Opcode() == Op_StoreCM && out == prev->in(MemNode::OopStore)) {
       
   462           // Oop store is a MergeMem! This should not happen. Temporarily remove the assertion
       
   463           // for this case because it could not be superwordized anyway.
   460         } else {
   464         } else {
   461           assert(out == prev || prev == NULL, "no branches off of store slice");
   465           assert(out == prev || prev == NULL, "no branches off of store slice");
   462         }
   466         }
   463       }
   467       }
   464     }
   468     }
   910   for (int i = 0; i < _packset.length(); i++) {
   914   for (int i = 0; i < _packset.length(); i++) {
   911     co_locate_pack(_packset.at(i));
   915     co_locate_pack(_packset.at(i));
   912   }
   916   }
   913 }
   917 }
   914 
   918 
   915 //------------------------------co_locate_pack---------------------------
   919 //-------------------------------remove_and_insert-------------------
   916 // Within a pack, move stores down to the last executed store,
   920 //remove "current" from its current position in the memory graph and insert
   917 // and move loads up to the first executed load.
   921 //it after the appropriate insertion point (lip or uip)
       
   922 void SuperWord::remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip,
       
   923                                   Node *uip, Unique_Node_List &sched_before) {
       
   924   Node* my_mem = current->in(MemNode::Memory);
       
   925   _igvn.hash_delete(current);
       
   926   _igvn.hash_delete(my_mem);
       
   927 
       
   928   //remove current_store from its current position in the memmory graph
       
   929   for (DUIterator i = current->outs(); current->has_out(i); i++) {
       
   930     Node* use = current->out(i);
       
   931     if (use->is_Mem()) {
       
   932       assert(use->in(MemNode::Memory) == current, "must be");
       
   933       _igvn.hash_delete(use);
       
   934       if (use == prev) { // connect prev to my_mem
       
   935         use->set_req(MemNode::Memory, my_mem);
       
   936       } else if (sched_before.member(use)) {
       
   937         _igvn.hash_delete(uip);
       
   938         use->set_req(MemNode::Memory, uip);
       
   939       } else {
       
   940         _igvn.hash_delete(lip);
       
   941         use->set_req(MemNode::Memory, lip);
       
   942       }
       
   943       _igvn._worklist.push(use);
       
   944       --i; //deleted this edge; rescan position
       
   945     }
       
   946   }
       
   947 
       
   948   bool sched_up = sched_before.member(current);
       
   949   Node *insert_pt =  sched_up ?  uip : lip;
       
   950   _igvn.hash_delete(insert_pt);
       
   951 
       
   952   // all uses of insert_pt's memory state should use current's instead
       
   953   for (DUIterator i = insert_pt->outs(); insert_pt->has_out(i); i++) {
       
   954     Node* use = insert_pt->out(i);
       
   955     if (use->is_Mem()) {
       
   956       assert(use->in(MemNode::Memory) == insert_pt, "must be");
       
   957       _igvn.hash_delete(use);
       
   958       use->set_req(MemNode::Memory, current);
       
   959       _igvn._worklist.push(use);
       
   960       --i; //deleted this edge; rescan position
       
   961     } else if (!sched_up && use->is_Phi() && use->bottom_type() == Type::MEMORY) {
       
   962       uint pos; //lip (lower insert point) must be the last one in the memory slice
       
   963       _igvn.hash_delete(use);
       
   964       for (pos=1; pos < use->req(); pos++) {
       
   965         if (use->in(pos) == insert_pt) break;
       
   966       }
       
   967       use->set_req(pos, current);
       
   968       _igvn._worklist.push(use);
       
   969       --i;
       
   970     }
       
   971   }
       
   972 
       
   973   //connect current to insert_pt
       
   974   current->set_req(MemNode::Memory, insert_pt);
       
   975   _igvn._worklist.push(current);
       
   976 }
       
   977 
       
   978 //------------------------------co_locate_pack----------------------------------
       
   979 // To schedule a store pack, we need to move any sandwiched memory ops either before
       
   980 // or after the pack, based upon dependence information:
       
   981 // (1) If any store in the pack depends on the sandwiched memory op, the
       
   982 //     sandwiched memory op must be scheduled BEFORE the pack;
       
   983 // (2) If a sandwiched memory op depends on any store in the pack, the
       
   984 //     sandwiched memory op must be scheduled AFTER the pack;
       
   985 // (3) If a sandwiched memory op (say, memA) depends on another sandwiched
       
   986 //     memory op (say memB), memB must be scheduled before memA. So, if memA is
       
   987 //     scheduled before the pack, memB must also be scheduled before the pack;
       
   988 // (4) If there is no dependence restriction for a sandwiched memory op, we simply
       
   989 //     schedule this store AFTER the pack
       
   990 // (5) We know there is no dependence cycle, so there in no other case;
       
   991 // (6) Finally, all memory ops in another single pack should be moved in the same direction.
       
   992 //
       
   993 // To schedule a load pack: the memory edge of every loads in the pack must be
       
   994 // the same as the memory edge of the last executed load in the pack
   918 void SuperWord::co_locate_pack(Node_List* pk) {
   995 void SuperWord::co_locate_pack(Node_List* pk) {
   919   if (pk->at(0)->is_Store()) {
   996   if (pk->at(0)->is_Store()) {
   920     // Push Stores down towards last executed pack member
       
   921     MemNode* first     = executed_first(pk)->as_Mem();
   997     MemNode* first     = executed_first(pk)->as_Mem();
   922     MemNode* last      = executed_last(pk)->as_Mem();
   998     MemNode* last      = executed_last(pk)->as_Mem();
   923     MemNode* insert_pt = last;
   999     Unique_Node_List schedule_before_pack;
       
  1000     Unique_Node_List memops;
       
  1001 
   924     MemNode* current   = last->in(MemNode::Memory)->as_Mem();
  1002     MemNode* current   = last->in(MemNode::Memory)->as_Mem();
       
  1003     MemNode* previous  = last;
   925     while (true) {
  1004     while (true) {
   926       assert(in_bb(current), "stay in block");
  1005       assert(in_bb(current), "stay in block");
       
  1006       memops.push(previous);
       
  1007       for (DUIterator i = current->outs(); current->has_out(i); i++) {
       
  1008         Node* use = current->out(i);
       
  1009         if (use->is_Mem() && use != previous)
       
  1010           memops.push(use);
       
  1011       }
       
  1012       if(current == first) break;
       
  1013       previous = current;
       
  1014       current  = current->in(MemNode::Memory)->as_Mem();
       
  1015     }
       
  1016 
       
  1017     // determine which memory operations should be scheduled before the pack
       
  1018     for (uint i = 1; i < memops.size(); i++) {
       
  1019       Node *s1 = memops.at(i);
       
  1020       if (!in_pack(s1, pk) && !schedule_before_pack.member(s1)) {
       
  1021         for (uint j = 0; j< i; j++) {
       
  1022           Node *s2 = memops.at(j);
       
  1023           if (!independent(s1, s2)) {
       
  1024             if (in_pack(s2, pk) || schedule_before_pack.member(s2)) {
       
  1025               schedule_before_pack.push(s1); //s1 must be scheduled before
       
  1026               Node_List* mem_pk = my_pack(s1);
       
  1027               if (mem_pk != NULL) {
       
  1028                 for (uint ii = 0; ii < mem_pk->size(); ii++) {
       
  1029                   Node* s = mem_pk->at(ii); // follow partner
       
  1030                   if (memops.member(s) && !schedule_before_pack.member(s))
       
  1031                     schedule_before_pack.push(s);
       
  1032                 }
       
  1033               }
       
  1034             }
       
  1035           }
       
  1036         }
       
  1037       }
       
  1038     }
       
  1039 
       
  1040     MemNode* lower_insert_pt = last;
       
  1041     Node*    upper_insert_pt = first->in(MemNode::Memory);
       
  1042     previous                 = last; //previous store in pk
       
  1043     current                  = last->in(MemNode::Memory)->as_Mem();
       
  1044 
       
  1045     //start scheduling from "last" to "first"
       
  1046     while (true) {
       
  1047       assert(in_bb(current), "stay in block");
       
  1048       assert(in_pack(previous, pk), "previous stays in pack");
   927       Node* my_mem = current->in(MemNode::Memory);
  1049       Node* my_mem = current->in(MemNode::Memory);
       
  1050 
   928       if (in_pack(current, pk)) {
  1051       if (in_pack(current, pk)) {
   929         // Forward users of my memory state to my input memory state
  1052         // Forward users of my memory state (except "previous) to my input memory state
   930         _igvn.hash_delete(current);
  1053         _igvn.hash_delete(current);
   931         _igvn.hash_delete(my_mem);
       
   932         for (DUIterator i = current->outs(); current->has_out(i); i++) {
  1054         for (DUIterator i = current->outs(); current->has_out(i); i++) {
   933           Node* use = current->out(i);
  1055           Node* use = current->out(i);
   934           if (use->is_Mem()) {
  1056           if (use->is_Mem() && use != previous) {
   935             assert(use->in(MemNode::Memory) == current, "must be");
  1057             assert(use->in(MemNode::Memory) == current, "must be");
   936             _igvn.hash_delete(use);
  1058             _igvn.hash_delete(use);
   937             use->set_req(MemNode::Memory, my_mem);
  1059             if (schedule_before_pack.member(use)) {
       
  1060               _igvn.hash_delete(upper_insert_pt);
       
  1061               use->set_req(MemNode::Memory, upper_insert_pt);
       
  1062             } else {
       
  1063               _igvn.hash_delete(lower_insert_pt);
       
  1064               use->set_req(MemNode::Memory, lower_insert_pt);
       
  1065             }
   938             _igvn._worklist.push(use);
  1066             _igvn._worklist.push(use);
   939             --i; // deleted this edge; rescan position
  1067             --i; // deleted this edge; rescan position
   940           }
  1068           }
   941         }
  1069         }
   942         // put current immediately before insert_pt
  1070         previous = current;
   943         current->set_req(MemNode::Memory, insert_pt->in(MemNode::Memory));
  1071       } else { // !in_pack(current, pk) ==> a sandwiched store
   944         _igvn.hash_delete(insert_pt);
  1072         remove_and_insert(current, previous, lower_insert_pt, upper_insert_pt, schedule_before_pack);
   945         insert_pt->set_req(MemNode::Memory, current);
  1073       }
   946         _igvn._worklist.push(insert_pt);
  1074 
   947         _igvn._worklist.push(current);
       
   948         insert_pt = current;
       
   949       }
       
   950       if (current == first) break;
  1075       if (current == first) break;
   951       current = my_mem->as_Mem();
  1076       current = my_mem->as_Mem();
   952     }
  1077     } // end while
   953   } else if (pk->at(0)->is_Load()) {
  1078   } else if (pk->at(0)->is_Load()) { //load
   954     // Pull Loads up towards first executed pack member
  1079     // all use the memory state that the last executed load uses
   955     LoadNode* first = executed_first(pk)->as_Load();
  1080     LoadNode* last_load  = executed_last(pk)->as_Load();
   956     Node* first_mem = first->in(MemNode::Memory);
  1081     Node* last_mem       = last_load->in(MemNode::Memory);
   957     _igvn.hash_delete(first_mem);
  1082     _igvn.hash_delete(last_mem);
   958     // Give each load same memory state as first
  1083     // Give each load same memory state as last
   959     for (uint i = 0; i < pk->size(); i++) {
  1084     for (uint i = 0; i < pk->size(); i++) {
   960       LoadNode* ld = pk->at(i)->as_Load();
  1085       LoadNode* ld = pk->at(i)->as_Load();
   961       _igvn.hash_delete(ld);
  1086       _igvn.hash_delete(ld);
   962       ld->set_req(MemNode::Memory, first_mem);
  1087       ld->set_req(MemNode::Memory, last_mem);
   963       _igvn._worklist.push(ld);
  1088       _igvn._worklist.push(ld);
   964     }
  1089     }
   965   }
  1090   }
   966 }
  1091 }
   967 
  1092