예제 #1
0
  private void splitRegisterInterval(Interval interval, Register reg) {
    // collect current usage of registers
    initVarsForAlloc(interval);
    initUseLists(false);
    spillExcludeActiveFixed();
    // spillBlockUnhandledFixed(cur);
    assert unhandledLists.get(RegisterBinding.Fixed) == Interval.EndMarker
        : "must not have unhandled fixed intervals because all fixed intervals have a use at position 0";
    spillBlockInactiveFixed(interval);
    spillCollectActiveAny();
    spillCollectInactiveAny(interval);

    if (Debug.isLogEnabled()) {
      try (Indent indent2 = Debug.logAndIndent("state of registers:")) {
        for (Register register : availableRegs) {
          int i = register.number;
          try (Indent indent3 =
              Debug.logAndIndent(
                  "reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) {
            for (int j = 0; j < spillIntervals[i].size(); j++) {
              Debug.log("%d ", spillIntervals[i].get(j).operandNumber);
            }
          }
        }
      }
    }

    // the register must be free at least until this position
    boolean needSplit = blockPos[reg.number] <= interval.to();

    int splitPos = blockPos[reg.number];

    assert splitPos > 0 : "invalid splitPos";
    assert needSplit || splitPos > interval.from() : "splitting interval at from";

    Debug.log("assigning interval %s to %s", interval, reg);
    interval.assignLocation(reg.asValue(interval.kind()));
    if (needSplit) {
      // register not available for full interval : so split it
      splitWhenPartialRegisterAvailable(interval, splitPos);
    }

    // perform splitting and spilling for all affected intervals
    splitAndSpillIntersectingIntervals(reg);

    // activate interval
    activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Any, interval);
    interval.state = State.Active;
  }
예제 #2
0
  private boolean optimize(
      int currentPos,
      AbstractBlock<?> currentBlock,
      Interval currentInterval,
      RegisterBinding binding) {
    // BEGIN initialize and sanity checks
    assert currentBlock != null : "block must not be null";
    assert currentInterval != null : "interval must not be null";

    assert currentBlock.getPredecessorCount() == 1
        : "more than one predecessors -> optimization not possible";

    if (!currentInterval.isSplitChild()) {
      // interval is not a split child -> no need for optimization
      return false;
    }

    if (currentInterval.from() == currentPos) {
      // the interval starts at the current position so no need for splitting
      return false;
    }

    // get current location
    AllocatableValue currentLocation = currentInterval.location();
    assert currentLocation != null : "active intervals must have a location assigned!";

    // get predecessor stuff
    AbstractBlock<?> predecessorBlock = currentBlock.getPredecessors().get(0);
    int predEndId = allocator.getLastLirInstructionId(predecessorBlock);
    Interval predecessorInterval = currentInterval.getIntervalCoveringOpId(predEndId);
    assert predecessorInterval != null
        : "variable not live at the end of the only predecessor! "
            + predecessorBlock
            + " -> "
            + currentBlock
            + " interval: "
            + currentInterval;
    AllocatableValue predecessorLocation = predecessorInterval.location();
    assert predecessorLocation != null : "handled intervals must have a location assigned!";

    // END initialize and sanity checks

    if (currentLocation.equals(predecessorLocation)) {
      // locations are already equal -> nothing to optimize
      return false;
    }

    if (!isStackSlot(predecessorLocation) && !isRegister(predecessorLocation)) {
      assert predecessorInterval.canMaterialize();
      // value is materialized -> no need for optimization
      return false;
    }

    assert isStackSlot(currentLocation) || isRegister(currentLocation)
        : "current location not a register or stack slot " + currentLocation;

    try (Indent indent =
        Debug.logAndIndent("location differs: %s vs. %s", predecessorLocation, currentLocation)) {
      // split current interval at current position
      Debug.log("splitting at position %d", currentPos);

      assert allocator.isBlockBegin(currentPos) && ((currentPos & 1) == 0)
          : "split pos must be even when on block boundary";

      Interval splitPart = currentInterval.split(currentPos, allocator);
      activeLists.remove(binding, currentInterval);

      assert splitPart.from() >= currentPosition
          : "cannot append new interval before current walk position";

      // the currentSplitChild is needed later when moves are inserted for reloading
      assert splitPart.currentSplitChild() == currentInterval
          : "overwriting wrong currentSplitChild";
      splitPart.makeCurrentSplitChild();

      if (Debug.isLogEnabled()) {
        Debug.log("left interval  : %s", currentInterval.logString(allocator));
        Debug.log("right interval : %s", splitPart.logString(allocator));
      }

      if (Options.LSRAOptSplitOnly.getValue()) {
        // just add the split interval to the unhandled list
        unhandledLists.addToListSortedByStartAndUsePositions(RegisterBinding.Any, splitPart);
      } else {
        if (isRegister(predecessorLocation)) {
          splitRegisterInterval(splitPart, asRegister(predecessorLocation));
        } else {
          assert isStackSlot(predecessorLocation);
          Debug.log("assigning interval %s to %s", splitPart, predecessorLocation);
          splitPart.assignLocation(predecessorLocation);
          // activate interval
          activeLists.addToListSortedByCurrentFromPositions(RegisterBinding.Stack, splitPart);
          splitPart.state = State.Active;

          splitStackInterval(splitPart);
        }
      }
    }
    return true;
  }