コード例 #1
0
 /** Transform cb into a GOTO, updating PHI nodes to maintain SSA form. */
 private void takeCondBranch(BasicBlock source, Instruction cb, IR ir) {
   if (DEBUG) VM.sysWrite("Eliminating definitely taken branch " + cb + "\n");
   BasicBlock deadBB = source.nextBasicBlockInCodeOrder();
   Instruction next = cb.nextInstructionInCodeOrder();
   if (Goto.conforms(next)) {
     deadBB = next.getBranchTarget();
     next.remove();
   }
   Goto.mutate(cb, GOTO, cb.getBranchTarget().makeJumpTarget());
   source.recomputeNormalOut(ir);
   if (!source.pointsOut(deadBB)) {
     // there is no longer an edge from source to target;
     // update any PHIs in target to reflect this.
     SSA.purgeBlockFromPHIs(source, deadBB);
   }
 }
コード例 #2
0
  /**
   * Perform optimizations for an inline guard.
   *
   * <p>Precondition: InlineGuard.conforms(cb)
   *
   * @param ir the governing IR
   * @param cb the instruction to optimize
   * @param bb the basic block holding if
   * @return {@code true} iff made a transformation
   */
  private boolean processInlineGuard(IR ir, Instruction cb, BasicBlock bb) {
    BasicBlock targetBlock = cb.getBranchTarget();
    Instruction targetLabel = targetBlock.firstInstruction();
    // get the first real instruction at the branch target
    // NOTE: this instruction is not necessarily in targetBlock,
    // iff targetBlock has no real instructions
    Instruction targetInst = firstRealInstructionFollowing(targetLabel);
    if (targetInst == null || targetInst == cb) {
      return false;
    }
    boolean endsBlock = cb.nextInstructionInCodeOrder().operator() == BBEND;
    if (endsBlock) {
      Instruction nextLabel = firstLabelFollowing(cb);
      if (targetLabel == nextLabel) {
        // found a conditional branch to the next instruction.  just remove it.
        cb.remove();
        return true;
      }
      Instruction nextI = firstRealInstructionFollowing(nextLabel);
      if (nextI != null && Goto.conforms(nextI)) {
        // replicate Goto
        cb.insertAfter(nextI.copyWithoutLinks());
        bb.recomputeNormalOut(ir); // fix the CFG
        return true;
      }
    }
    // do we fall through to a block that has only a goto?
    BasicBlock fallThrough = bb.getFallThroughBlock();
    if (fallThrough != null) {
      Instruction fallThroughInstruction = fallThrough.firstRealInstruction();
      if ((fallThroughInstruction != null) && Goto.conforms(fallThroughInstruction)) {
        // copy goto to bb
        bb.appendInstruction(fallThroughInstruction.copyWithoutLinks());
        bb.recomputeNormalOut(ir);
      }
    }

    if (Goto.conforms(targetInst)) {
      // conditional branch to unconditional branch.
      // change conditional branch target to latter's target
      InlineGuard.setTarget(cb, (BranchOperand) Goto.getTarget(targetInst).copy());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    if (targetBlock.isEmpty()) {
      // branch to an empty block.  Change target to the next block.
      BasicBlock nextBlock = targetBlock.getFallThroughBlock();
      InlineGuard.setTarget(cb, nextBlock.makeJumpTarget());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    return false;
  }
コード例 #3
0
 /**
  * Remove cb from source, updating PHI nodes to maintain SSA form.
  *
  * @param source basic block containing cb
  * @param cb conditional branch to remove
  * @param ir containing IR
  * @param di branch that dominates cb
  */
 private void removeCondBranch(BasicBlock source, Instruction cb, IR ir, Instruction di) {
   if (DEBUG) VM.sysWrite("Eliminating definitely not-taken branch " + cb + "\n");
   if (IfCmp.conforms(cb) && IfCmp.hasGuardResult(cb)) {
     cb.insertBefore(
         Move.create(GUARD_MOVE, IfCmp.getGuardResult(cb), IfCmp.getGuardResult(di).copy()));
   }
   BasicBlock deadBB = cb.getBranchTarget();
   cb.remove();
   source.recomputeNormalOut(ir);
   if (!source.pointsOut(deadBB)) {
     // there is no longer an edge from source to target;
     // update any PHIs in target to reflect this.
     SSA.purgeBlockFromPHIs(source, deadBB);
   }
 }
コード例 #4
0
 /**
  * Transform to eliminate redundant branches passed on GVNs and dominator information.
  *
  * @param ir The IR on which to apply the phase
  */
 public void perform(IR ir) {
   // (1) Remove redundant conditional branches and locally fix the PHIs
   GlobalValueNumberState gvns = ir.HIRInfo.valueNumbers;
   DominatorTree dt = ir.HIRInfo.dominatorTree;
   for (BasicBlockEnumeration bbs = ir.getBasicBlocks(); bbs.hasMoreElements(); ) {
     BasicBlock candBB = bbs.next();
     Instruction candTest = candBB.firstBranchInstruction();
     if (candTest == null) continue;
     if (!(IfCmp.conforms(candTest) || InlineGuard.conforms(candTest))) continue;
     GVCongruenceClass cc = gvns.congruenceClass(candTest);
     if (cc.size() > 1) {
       for (ValueGraphVertex vertex : cc) {
         Instruction poss = (Instruction) vertex.getName();
         if (poss != candTest) {
           BasicBlock notTaken = getNotTakenBlock(poss);
           BasicBlock taken = poss.getBranchTarget();
           if (taken == notTaken) continue; // both go to same block, so we don't know anything!
           if (notTaken.hasOneIn() && dt.dominates(notTaken, candBB)) {
             if (DEBUG)
               VM.sysWrite(candTest + " is dominated by not-taken branch of " + poss + "\n");
             removeCondBranch(candBB, candTest, ir, poss);
             cc.removeVertex(gvns.valueGraph.getVertex(candTest));
             break;
           }
           if (taken.hasOneIn() && dt.dominates(taken, candBB)) {
             if (DEBUG)
               VM.sysWrite(candTest + " is dominated by taken branch of " + poss + "\n");
             takeCondBranch(candBB, candTest, ir);
             cc.removeVertex(gvns.valueGraph.getVertex(candTest));
             break;
           }
         }
       }
     }
   }
   // (2) perform a Depth-first search of the control flow graph,
   //     and remove any nodes we have made unreachable
   removeUnreachableCode(ir);
 }
コード例 #5
0
  /**
   * Perform optimizations for a conditional branch.
   *
   * <pre>
   * 1)   IF .. GOTO A          replaced by  IF .. GOTO B
   *      ...
   *   A: GOTO B
   * 2)   conditional branch to next instruction eliminated
   * 3)   IF (condition) GOTO A  replaced by  IF (!condition) GOTO B
   *      GOTO B                           A: ...
   *   A: ...
   * 4) special case to generate Boolean compare opcode
   * 5) special case to generate conditional move sequence
   * 6)   IF .. GOTO A       replaced by  IF .. GOTO B
   *   A: LABEL
   *      BBEND
   *   B:
   * 7)  fallthrough to a goto: replicate goto to enable other optimizations.
   * </pre>
   *
   * <p>Precondition: IfCmp.conforms(cb)
   *
   * @param ir the governing IR
   * @param cb the instruction to optimize
   * @param bb the basic block holding if
   * @return {@code true} iff made a transformation
   */
  private boolean processConditionalBranch(IR ir, Instruction cb, BasicBlock bb) {
    BasicBlock targetBlock = cb.getBranchTarget();

    // don't optimize jumps to a code motion landing pad
    if (targetBlock.getLandingPad()) return false;

    Instruction targetLabel = targetBlock.firstInstruction();
    // get the first real instruction at the branch target
    // NOTE: this instruction is not necessarily in targetBlock,
    // iff targetBlock has no real instructions
    Instruction targetInst = firstRealInstructionFollowing(targetLabel);
    if (targetInst == null || targetInst == cb) {
      return false;
    }
    boolean endsBlock = cb.nextInstructionInCodeOrder().operator() == BBEND;
    if (endsBlock) {
      Instruction nextLabel = firstLabelFollowing(cb);

      if (targetLabel == nextLabel) {
        // found a conditional branch to the next instruction.  just remove it.
        cb.remove();
        return true;
      }
      Instruction nextI = firstRealInstructionFollowing(nextLabel);
      if (nextI != null && Goto.conforms(nextI)) {
        // Check that the target is not the fall through (the goto itself).
        // If we add a goto to the next block, it will be removed by
        // processGoto and we will loop indefinitely.
        // This can be tripped by (strange) code such as:
        // if (condition) while (true);
        BasicBlock gotoTarget = nextI.getBranchTarget();
        Instruction gotoLabel = gotoTarget.firstInstruction();
        Instruction gotoInst = firstRealInstructionFollowing(gotoLabel);

        if (gotoInst != nextI) {
          // replicate Goto
          cb.insertAfter(nextI.copyWithoutLinks());
          bb.recomputeNormalOut(ir); // fix the CFG
          return true;
        }
      }
    }
    // attempt to generate boolean compare.
    if (generateBooleanCompare(ir, bb, cb, targetBlock)) {
      // generateBooleanCompare does all necessary CFG fixup.
      return true;
    }
    // attempt to generate a sequence using conditional moves
    if (generateCondMove(ir, bb, cb)) {
      // generateCondMove does all necessary CFG fixup.
      return true;
    }

    // do we fall through to a block that has only a goto?
    BasicBlock fallThrough = bb.getFallThroughBlock();
    if (fallThrough != null) {
      Instruction fallThroughInstruction = fallThrough.firstRealInstruction();
      if ((fallThroughInstruction != null) && Goto.conforms(fallThroughInstruction)) {
        // copy goto to bb
        bb.appendInstruction(fallThroughInstruction.copyWithoutLinks());
        bb.recomputeNormalOut(ir);
      }
    }

    if (Goto.conforms(targetInst)) {
      // conditional branch to unconditional branch.
      // change conditional branch target to latter's target
      Instruction target2 =
          firstRealInstructionFollowing(targetInst.getBranchTarget().firstInstruction());
      if (target2 == targetInst) {
        // Avoid an infinite recursion in the following scenario:
        // g: if (...) goto L
        // ...
        // L: goto L
        // This happens in GCUtil in some systems due to a while(true) {}
        return false;
      }
      IfCmp.setTarget(cb, (BranchOperand) Goto.getTarget(targetInst).copy());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    if (targetBlock.isEmpty()) {
      // branch to an empty block.  Change target to the next block.
      BasicBlock nextBlock = targetBlock.getFallThroughBlock();
      IfCmp.setTarget(cb, nextBlock.makeJumpTarget());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    if (isFlipCandidate(cb, targetInst)) {
      flipConditionalBranch(cb);
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    return false;
  }
コード例 #6
0
  /**
   * Perform optimizations for a Goto.
   *
   * <p> Patterns:
   * <pre>
   *    1)      GOTO A       replaced by  GOTO B
   *         A: GOTO B
   *
   *    2)      GOTO A       replaced by  IF .. GOTO B
   *         A: IF .. GOTO B              GOTO C
   *         C: ...
   *    3)   GOTO next instruction eliminated
   *    4)      GOTO A       replaced by  GOTO B
   *         A: LABEL
   *            BBEND
   *         B:
   *    5)   GOTO BBn where BBn has exactly one in edge
   *         - move BBn immediately after the GOTO in the code order,
   *           so that pattern 3) will create a fallthrough
   * <pre>
   *
   * <p> Precondition: Goto.conforms(g)
   *
   * @param ir governing IR
   * @param g the instruction to optimize
   * @param bb the basic block holding g
   * @return {@code true} if made a transformation
   */
  private boolean processGoto(IR ir, Instruction g, BasicBlock bb) {
    BasicBlock targetBlock = g.getBranchTarget();

    // don't optimize jumps to a code motion landing pad
    if (targetBlock.getLandingPad()) return false;

    Instruction targetLabel = targetBlock.firstInstruction();
    // get the first real instruction at the g target
    // NOTE: this instruction is not necessarily in targetBlock,
    // iff targetBlock has no real instructions
    Instruction targetInst = firstRealInstructionFollowing(targetLabel);
    if (targetInst == null || targetInst == g) {
      return false;
    }
    Instruction nextLabel = firstLabelFollowing(g);
    if (targetLabel == nextLabel) {
      // found a GOTO to the next instruction.  just remove it.
      g.remove();
      return true;
    }
    if (Goto.conforms(targetInst)) {
      // unconditional branch to unconditional branch.
      // replace g with goto to targetInst's target
      Instruction target2 =
          firstRealInstructionFollowing(targetInst.getBranchTarget().firstInstruction());
      if (target2 == targetInst) {
        // Avoid an infinite recursion in the following bizarre scenario:
        // g: goto L
        // ...
        // L: goto L
        // This happens in jByteMark.EmFloatPnt.denormalize() due to a while(true) {}
        return false;
      }
      Goto.setTarget(g, (BranchOperand) Goto.getTarget(targetInst).copy());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    if (targetBlock.isEmpty()) {
      // GOTO an empty basic block.  Change target to the
      // next block.
      BasicBlock nextBlock = targetBlock.getFallThroughBlock();
      Goto.setTarget(g, nextBlock.makeJumpTarget());
      bb.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    if (mayDuplicateCondBranches && IfCmp.conforms(targetInst)) {
      // unconditional branch to a conditional branch.
      // If the Goto is the only branch instruction in its basic block
      // and the IfCmp is the only non-GOTO branch instruction
      // in its basic block then replace the goto with a copy of
      // targetInst and append another GOTO to the not-taken
      // target of targetInst's block.
      // We impose these additional restrictions to avoid getting
      // multiple conditional branches in a single basic block.
      if (!g.prevInstructionInCodeOrder().isBranch()
          && (targetInst.nextInstructionInCodeOrder().operator == BBEND
              || targetInst.nextInstructionInCodeOrder().operator == GOTO)) {
        Instruction copy = targetInst.copyWithoutLinks();
        g.replace(copy);
        Instruction newGoto = targetInst.getBasicBlock().getNotTakenNextBlock().makeGOTO();
        copy.insertAfter(newGoto);
        bb.recomputeNormalOut(ir); // fix the CFG
        return true;
      }
    }

    // try to create a fallthrough
    if (mayReorderCode && targetBlock.getNumberOfIn() == 1) {
      BasicBlock ftBlock = targetBlock.getFallThroughBlock();
      if (ftBlock != null) {
        BranchOperand ftTarget = ftBlock.makeJumpTarget();
        targetBlock.appendInstruction(CPOS(g, Goto.create(GOTO, ftTarget)));
      }

      ir.cfg.removeFromCodeOrder(targetBlock);
      ir.cfg.insertAfterInCodeOrder(bb, targetBlock);
      targetBlock.recomputeNormalOut(ir); // fix the CFG
      return true;
    }
    return false;
  }
コード例 #7
0
 /** Return the basic block that s's block will goto if s is not taken. */
 private BasicBlock getNotTakenBlock(Instruction s) {
   s = s.nextInstructionInCodeOrder();
   if (Goto.conforms(s)) return s.getBranchTarget();
   if (VM.VerifyAssertions) VM._assert(s.operator() == BBEND);
   return s.getBasicBlock().nextBasicBlockInCodeOrder();
 }