< prev index next >

src/share/vm/opto/block.cpp

Print this page

        

@@ -772,14 +772,23 @@
 void PhaseCFG::fixup_flow() {
   // Fixup final control flow for the blocks.  Remove jump-to-next
   // block. If neither arm of an IF follows the conditional branch, we
   // have to add a second jump after the conditional.  We place the
   // TRUE branch target in succs[0] for both GOTOs and IFs.
+  bool found_fixup_loops = false;
   for (uint i = 0; i < number_of_blocks(); i++) {
     Block* block = get_block(i);
     block->_pre_order = i;          // turn pre-order into block-index
 
+    Node *bh = block->head();
+    if (bh->is_Loop()) {
+      LoopNode *loop = bh->as_Loop();
+      if (loop->is_inner_loop() && loop->is_multiversioned() && loop->is_vectorized_loop() && !loop->range_checks_present()) {
+        found_fixup_loops = true;
+      }
+    }
+
     // Connector blocks need no further processing.
     if (block->is_connector()) {
       assert((i+1) == number_of_blocks() || get_block(i + 1)->is_connector(), "All connector blocks should sink to the end");
       continue;
     }

@@ -925,10 +934,54 @@
     } else {
       // Multi-exit block, e.g. a switch statement
       // But we don't need to do anything here
     }
   } // End of for all blocks
+
+  if (found_fixup_loops) {
+    // find all fixup-loops and process them
+    for (uint i = 0; i < number_of_blocks(); i++) {
+      Block* block = get_block(i);
+      Node *bh = block->head();
+      if (bh->is_Loop()) {
+        LoopNode *loop = bh->as_Loop();
+        // fixup loops are only marked for processing when they are predicated and
+        // vectorized else they are just post loops.
+        if (Matcher::has_predicated_vectors()) {
+          if (loop->is_inner_loop() && loop->is_multiversioned() && loop->is_vectorized_loop() && !loop->range_checks_present()) {
+            CFGLoop *cur_loop = block->_loop;
+            // fixup loops can have multiple exits, so we need to find the backedge
+            Block *back_edge = cur_loop->backedge_block();
+            if (back_edge) {
+              // fetch the region of the back edge
+              Node *backedge_region = back_edge->get_node(0);
+              Block *idom = back_edge->_idom;
+              if (backedge_region->is_Region()) {
+                Node *if_true = backedge_region->in(1);
+                if (if_true->Opcode() == Op_IfTrue) {
+                  Node *backedge_iff = if_true->in(0);
+                  if (backedge_iff->is_MachIf() && idom) {
+                    for (uint j = 0; j < idom->number_of_nodes(); j++) {
+                      Node *n = idom->get_node(j);
+                      if (n == backedge_iff) {
+                        MachMskNode *mask = new MachMskNode(true);
+                        if (mask) {
+                          idom->insert_node(mask, j);
+                          map_node_to_block(mask, idom);
+                          break;
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }
 
 
 // postalloc_expand: Expand nodes after register allocation.
 //
< prev index next >