Print this page
rev 4533 : 8014811: loopTransform.cpp assert(cmp_end->in(2) == limit) failed
Summary: Stop current iteration of loop opts if partial_peel() failed and it created node clones outside processed loop.
Reviewed-by: roland

Split Split Close
Expand all
Collapse all
          --- old/src/share/vm/opto/loopopts.cpp
          +++ new/src/share/vm/opto/loopopts.cpp
↓ open down ↓ 1918 lines elided ↑ open up ↑
1919 1919      if (vset.test(use->_idx) && !(use->is_Phi() && use->in(0) == head)) {
1920 1920        return true;
1921 1921      }
1922 1922    }
1923 1923    return false;
1924 1924  }
1925 1925  
1926 1926  
1927 1927  //------------------------------ clone_for_use_outside_loop -------------------------------------
1928 1928  // clone "n" for uses that are outside of loop
1929      -void PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) {
1930      -
     1929 +int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) {
     1930 +  int cloned = 0;
1931 1931    assert(worklist.size() == 0, "should be empty");
1932 1932    for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {
1933 1933      Node* use = n->fast_out(j);
1934 1934      if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) {
1935 1935        worklist.push(use);
1936 1936      }
1937 1937    }
1938 1938    while( worklist.size() ) {
1939 1939      Node *use = worklist.pop();
1940 1940      if (!has_node(use) || use->in(0) == C->top()) continue;
1941 1941      uint j;
1942 1942      for (j = 0; j < use->req(); j++) {
1943 1943        if (use->in(j) == n) break;
1944 1944      }
1945 1945      assert(j < use->req(), "must be there");
1946 1946  
1947 1947      // clone "n" and insert it between the inputs of "n" and the use outside the loop
1948 1948      Node* n_clone = n->clone();
1949 1949      _igvn.replace_input_of(use, j, n_clone);
     1950 +    cloned++;
1950 1951      Node* use_c;
1951 1952      if (!use->is_Phi()) {
1952 1953        use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0);
1953 1954      } else {
1954 1955        // Use in a phi is considered a use in the associated predecessor block
1955 1956        use_c = use->in(0)->in(j);
1956 1957      }
1957 1958      set_ctrl(n_clone, use_c);
1958 1959      assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
1959 1960      get_loop(use_c)->_body.push(n_clone);
1960 1961      _igvn.register_new_node_with_optimizer(n_clone);
1961 1962  #if !defined(PRODUCT)
1962 1963      if (TracePartialPeeling) {
1963 1964        tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx);
1964 1965      }
1965 1966  #endif
1966 1967    }
     1968 +  return cloned;
1967 1969  }
1968 1970  
1969 1971  
1970 1972  //------------------------------ clone_for_special_use_inside_loop -------------------------------------
1971 1973  // clone "n" for special uses that are in the not_peeled region.
1972 1974  // If these def-uses occur in separate blocks, the code generator
1973 1975  // marks the method as not compilable.  For example, if a "BoolNode"
1974 1976  // is in a different basic block than the "IfNode" that uses it, then
1975 1977  // the compilation is aborted in the code generator.
1976 1978  void PhaseIdealLoop::clone_for_special_use_inside_loop( IdealLoopTree *loop, Node* n,
↓ open down ↓ 498 lines elided ↑ open up ↑
2475 2477    }
2476 2478  
2477 2479  #if !defined(PRODUCT)
2478 2480    if (TracePartialPeeling) {
2479 2481      tty->print_cr("\npeeled list");
2480 2482    }
2481 2483  #endif
2482 2484  
2483 2485    // Evacuate nodes in peel region into the not_peeled region if possible
2484 2486    uint new_phi_cnt = 0;
     2487 +  uint cloned_for_outside_use = 0;
2485 2488    for (i = 0; i < peel_list.size();) {
2486 2489      Node* n = peel_list.at(i);
2487 2490  #if !defined(PRODUCT)
2488 2491    if (TracePartialPeeling) n->dump();
2489 2492  #endif
2490 2493      bool incr = true;
2491 2494      if ( !n->is_CFG() ) {
2492 2495  
2493 2496        if ( has_use_in_set(n, not_peel) ) {
2494 2497  
2495 2498          // If not used internal to the peeled region,
2496 2499          // move "n" from peeled to not_peeled region.
2497 2500  
2498 2501          if ( !has_use_internal_to_set(n, peel, loop) ) {
2499 2502  
2500 2503            // if not pinned and not a load (which maybe anti-dependent on a store)
2501 2504            // and not a CMove (Matcher expects only bool->cmove).
2502 2505            if ( n->in(0) == NULL && !n->is_Load() && !n->is_CMove() ) {
2503      -            clone_for_use_outside_loop( loop, n, worklist );
2504      -
     2506 +            cloned_for_outside_use += clone_for_use_outside_loop( loop, n, worklist );
2505 2507              sink_list.push(n);
2506 2508              peel     >>= n->_idx; // delete n from peel set.
2507 2509              not_peel <<= n->_idx; // add n to not_peel set.
2508 2510              peel_list.remove(i);
2509 2511              incr = false;
2510 2512  #if !defined(PRODUCT)
2511 2513              if (TracePartialPeeling) {
2512 2514                tty->print_cr("sink to not_peeled region: %d newbb: %d",
2513 2515                              n->_idx, get_ctrl(n)->_idx);
2514 2516              }
↓ open down ↓ 16 lines elided ↑ open up ↑
2531 2533        tty->print_cr("\nToo many new phis: %d  old %d new cmpi: %c",
2532 2534                      new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F');
2533 2535      }
2534 2536  #endif
2535 2537      if (new_peel_if != NULL) {
2536 2538        remove_cmpi_loop_exit(new_peel_if, loop);
2537 2539      }
2538 2540      // Inhibit more partial peeling on this loop
2539 2541      assert(!head->is_partial_peel_loop(), "not partial peeled");
2540 2542      head->mark_partial_peel_failed();
     2543 +    if (cloned_for_outside_use > 0) {
     2544 +      // Terminate this round of loop opts because
     2545 +      // the graph outside this loop was changed.
     2546 +      C->set_major_progress();
     2547 +      return true;
     2548 +    }
2541 2549      return false;
2542 2550    }
2543 2551  
2544 2552    // Step 3: clone loop, retarget control, and insert new phis
2545 2553  
2546 2554    // Create new loop head for new phis and to hang
2547 2555    // the nodes being moved (sinked) from the peel region.
2548 2556    LoopNode* new_head = new (C) LoopNode(last_peel, last_peel);
2549 2557    new_head->set_unswitch_count(head->unswitch_count()); // Preserve
2550 2558    _igvn.register_new_node_with_optimizer(new_head);
↓ open down ↓ 214 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX