/** Build a new trace starting at {@code block}. */
  @SuppressWarnings("try")
  private Collection<T> startTrace(T block, int traceNumber) {
    ArrayDeque<T> trace = new ArrayDeque<>();
    try (Indent i = Debug.logAndIndent("StartTrace: " + block)) {
      try (Indent indentFront = Debug.logAndIndent("Head:")) {
        for (T currentBlock = block;
            currentBlock != null;
            currentBlock = selectPredecessor(currentBlock)) {
          addBlockToTrace(currentBlock, traceNumber);
          trace.addFirst(currentBlock);
        }
      }
      /* Number head blocks. Can not do this in the loop as we go backwards. */
      int blockNr = 0;
      for (T b : trace) {
        b.setLinearScanNumber(blockNr++);
      }

      try (Indent indentBack = Debug.logAndIndent("Tail:")) {
        for (T currentBlock = selectSuccessor(block);
            currentBlock != null;
            currentBlock = selectSuccessor(currentBlock)) {
          addBlockToTrace(currentBlock, traceNumber);
          trace.addLast(currentBlock);
          /* This time we can number the blocks immediately as we go forwards. */
          currentBlock.setLinearScanNumber(blockNr++);
        }
      }
    }
    Debug.log("Trace: %s", trace);
    return trace;
  }
  @SuppressWarnings("try")
  private int addLiveValueToBlock(Value operand, AbstractBlockBase<?> block) {
    try (Indent indent = Debug.logAndIndent("add incoming value!")) {
      int index = -1;
      for (AbstractBlockBase<?> pred : block.getPredecessors()) {
        try (Indent indent1 = Debug.logAndIndent("Add outgoing operand to %s", pred)) {
          BlockData predData = getOrInit(pred);
          int predIndex = predData.addOutgoing(operand);

          if (index == -1) {
            index = predIndex;
          } else {
            assert predIndex == index;
          }

          for (AbstractBlockBase<?> succ : pred.getSuccessors()) {
            Debug.log("Add incoming operand to %s", succ);
            BlockData succData = getOrInit(succ);
            if (!succData.contains(operand)) {
              int succIndex = succData.addIncoming(operand);
              assert succIndex == predIndex;
            }
          }
        }
      }
      Debug.log("new index: %d", index);
      return index;
    }
  }
  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;
  }
 @SuppressWarnings("try")
 private TraceBuilderResult<T> build(T startBlock) {
   try (Indent indent = Debug.logAndIndent("start trace building: " + startBlock)) {
     ArrayList<Trace<T>> traces = buildTraces(startBlock);
     return new TraceBuilderResult<>(traces, blockToTrace);
   }
 }
  @SuppressWarnings("try")
  private void accessRecursive(
      Value operand,
      AbstractBlockBase<?> defBlock,
      AbstractBlockBase<?> block,
      Deque<AbstractBlockBase<?>> worklist) {
    try (Indent indent = Debug.logAndIndent("get operand %s in block %s", operand, block)) {
      if (block.equals(defBlock)) {
        Debug.log("found definition!");
        return;
      }
      BlockData data = getOrInit(block);
      Integer index = data.getIndex(operand);
      if (index != null) {
        // value is live at block begin but might not be initialized
        Value in = data.getIncoming(index);
        if (Value.ILLEGAL.equals(in)) {
          data.setIncoming(index, operand);
          Debug.log("uninitialized incoming value -> initialize!");
        } else {
          Debug.log("incoming value already initialized!");
        }
        return;
      }

      // the value is not yet live a current block
      int idx = addLiveValueToBlock(operand, block);
      data.setIncoming(idx, operand);

      for (AbstractBlockBase<?> pred : block.getPredecessors()) {
        worklist.addLast(pred);
      }
    }
  }
Esempio n. 6
0
 @SuppressWarnings("try")
 private void doBlock(AbstractBlockBase<?> b) {
   if (visited.get(b.getId())) {
     return;
   }
   for (AbstractBlockBase<?> pred : b.getPredecessors()) {
     if (!b.isLoopHeader() || !pred.isLoopEnd()) {
       doBlock(pred);
     }
   }
   try (Indent indent = Debug.logAndIndent(Debug.INFO_LOG_LEVEL, "handle block %s", b)) {
     assert verifyBlock(b);
   }
 }
  private void optimizeBlock(AbstractBlock<?> block) {
    if (block.getPredecessorCount() == 1) {
      int nextBlock = allocator.getFirstLirInstructionId(block);
      try (Scope s1 = Debug.scope("LSRAOptimization")) {
        Debug.log("next block: %s (%d)", block, nextBlock);
      }
      try (Indent indent0 = Debug.indent()) {
        walkTo(nextBlock);

        try (Scope s1 = Debug.scope("LSRAOptimization")) {
          boolean changed = true;
          // we need to do this because the active lists might change
          loop:
          while (changed) {
            changed = false;
            try (Indent indent1 =
                Debug.logAndIndent("Active intervals: (block %s [%d])", block, nextBlock)) {
              for (Interval active = activeLists.get(RegisterBinding.Any);
                  active != Interval.EndMarker;
                  active = active.next) {
                Debug.log("active   (any): %s", active);
                if (optimize(nextBlock, block, active, RegisterBinding.Any)) {
                  changed = true;
                  break loop;
                }
              }
              for (Interval active = activeLists.get(RegisterBinding.Stack);
                  active != Interval.EndMarker;
                  active = active.next) {
                Debug.log("active (stack): %s", active);
                if (optimize(nextBlock, block, active, RegisterBinding.Stack)) {
                  changed = true;
                  break loop;
                }
              }
            }
          }
        }
      }
    }
  }
  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;
  }