Beispiel #1
0
void LoopFinder::compute_loop_exits_and_entries(LoopList* loops) {
  // create loop exits for each loop
  int loop_index = loops->length() - 1;
  for (; loop_index >= 0; loop_index--) {
    Loop* loop = loops->at(loop_index);
    int n = loop->nof_blocks() - 1;
    // mark all nodes belonging to this loop 
    for (; n >= 0; n --) {
      BlockBegin* bb = loop->block_no(n);
      bb->set_loop_index(loop_index);
    }
    find_loop_entries(loop->start(), loop);
    // search for blocks that have successors outside the loop
    n = loop->nof_blocks() - 1;
    for (; n >= 0; n--) {
      BlockBegin* bb = loop->block_no(n);
      find_loop_exits(bb, loop);
    }
  }
}
Beispiel #2
0
// Returns inner loops that have may or may not have calls
LoopList* LoopFinder::find_loops(LoopList* loops, bool call_free_only) {
  LoopList* inner = new LoopList();
  LoopList* outer = new LoopList();
  int lng = loops->length();
  // First step: find loops that have no calls and no backedges
  //             in the loop except its own
  int i;
  for (i = 0; i < lng; i++) {
    Loop* loop = loops->at(i);
    int k = loop->nof_blocks() - 1;
    bool is_outer = false;
    for (; k >= 0; k--) {
      BlockBegin* b = loop->block_no(k);
      // Is this innermost loop:
      // - no block, except end block, may be a back edge start,
      //   otherwise we have an outer loop
      if (!loop->is_end(b)) {
        BlockLoopInfo* bli = get_block_info(b);
        if (bli->is_backedge_start()) {
          if (WantsLargerLoops) {
            is_outer = true;
          } else {
            loop = NULL;
          }
          break;
        }
      }
    }

    if (loop != NULL) {
      ScanBlocks scan(loop->blocks());
      ScanResult scan_result;
      scan.scan(&scan_result);
      if (!call_free_only || (!scan_result.has_calls() && !scan_result.has_slow_cases())) {
        if (is_outer) {
          outer->append(loop);
        } else {
          inner->append(loop);
        }
      } else {
#ifndef PRODUCT
        if (PrintLoops && Verbose) {
          tty->print("Discarding loop with calls: ");
          loop->print();
        }
#endif // PRODUCT
      }
    }
  }
  // find all surviving outer loops and delete any inner loops contained inside them
  if (inner->length() > 0) {
    for (i = 0; i < outer->length() ; i++) {
      Loop* loop = outer->at(i);
      int k = loop->nof_blocks() - 1;
      for (; k >= 0; k--) {
        BlockBegin* b = loop->block_no(k);
        if (!loop->is_end(b)) {
          BlockLoopInfo* bli = get_block_info(b);
          if (bli->is_backedge_start()) {
            // find the loop contained inside this loop
            int j;
            for (j = 0; j < inner->length(); j++) {
              Loop* inner_loop = inner->at(j);
              if (inner_loop->is_end(b)) {
                inner->remove(inner_loop);
                break;
              }
            }
            for (j = 0; j < outer->length(); j++) {
              Loop* outer_loop = outer->at(j);
              if (outer_loop == loop) {
                continue;
              }

              if (outer_loop->is_end(b)) {
                outer->remove(outer_loop);
                break;
              }
            }
          }
        }
      }
    }
    inner->appendAll(outer);
  }


  // Second step: if several loops have the same loop-end, select the one
  //              with fewer blocks.
  //              if several loops have the same loop-start, select the one
  //              with fewer blocks
  // now check for loops that have the same header and eliminate one
  for (i = 0; i < inner->length() ; i++) {
    Loop* current_loop = inner->at(i);
    BlockBegin* header = current_loop->start();
    for (int n = i + 1; n < inner->length(); n++) {
      Loop*  test_loop = inner->at(n);
      BlockBegin* test = test_loop->start();
      Loop* discarded = NULL;
      bool same_end = false;
      for (int e = 0; e < current_loop->ends()->length(); e++) {
        if (test_loop->is_end(current_loop->ends()->at(e))) {
          same_end = true;
        }
      }
      if (header == test_loop->start() || same_end) {
        // discard loop with fewer blocks
        if (test_loop->nof_blocks() > current_loop->nof_blocks()) {
          if (WantsLargerLoops) {
            discarded = current_loop;
          } else {
            discarded = test_loop;
          }
        } else {
          if (WantsLargerLoops) {
            discarded = test_loop;
          } else {
            discarded = current_loop;
          }
        }
        inner->remove(discarded);
#ifndef PRODUCT
        if (PrintLoops && Verbose && discarded) {
          tty->print("Discarding overlapping loop: ");
          discarded->print();
        }
#endif // PRODUCT
        // restart the computation
        i = -1;
        break;
      }
    }
  }

  if (inner->length() == 0) {
    // we removed all the loops
    if (PrintLoops && Verbose) {
      tty->print_cr("*** deleted all loops in %s", __FILE__);
    }
    set_not_ok();
    return NULL;
  } else {
    return inner;
  }
}