class BusyCodeMotion extends BodyTransformer {
  private static final Logger logger = LoggerFactory.getLogger(BusyCodeMotion.class);

  private static final String PREFIX = "$bcm";

  public BusyCodeMotion(Singletons.Global g) {
  }

  public static BusyCodeMotion v() {
    return G.v().soot_jimple_toolkits_scalar_pre_BusyCodeMotion();
  }

  /**
   * performs the busy code motion.
   */
  @Override
  protected void internalTransform(Body b, String phaseName, Map<String, String> opts) {<FILL_FUNCTION_BODY>}

  private Unit getFirstNonIdentityStmt(Body b) {
    for (Unit u : b.getUnits()) {
      if (!(u instanceof IdentityStmt)) {
        return u;
      }
    }
    return null;
  }
}

    final BCMOptions options = new BCMOptions(opts);

    if (Options.v().verbose()) {
      logger.debug("[" + b.getMethod().getName() + "]     performing Busy Code Motion...");
    }

    CriticalEdgeRemover.v().transform(b, phaseName + ".cer");

    UnitGraph graph = new BriefUnitGraph(b);

    /* Map each unit to its RHS. Take only BinopExpr and ConcreteRef */
    Map<Unit, EquivalentValue> unitToEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
      @Override
      protected EquivalentValue mapTo(Unit unit) {
        Value tmp = SootFilter.noInvokeRhs(unit);
        Value tmp2 = SootFilter.binop(tmp);
        if (tmp2 == null) {
          tmp2 = SootFilter.concreteRef(tmp);
        }
        return SootFilter.equiVal(tmp2);
      }
    };

    /* Same as before, but without exception-throwing expressions */
    Map<Unit, EquivalentValue> unitToNoExceptionEquivRhs = new UnitMap<EquivalentValue>(b, graph.size() + 1, 0.7f) {
      @Override
      protected EquivalentValue mapTo(Unit unit) {
        return SootFilter.equiVal(SootFilter.noExceptionThrowing(SootFilter.binopRhs(unit)));
      }
    };

    final Scene sc = Scene.v();
    /* if a more precise sideeffect-tester comes out, please change it here! */
    final SideEffectTester sideEffect;
    if (sc.hasCallGraph() && !options.naive_side_effect()) {
      sideEffect = new PASideEffectTester();
    } else {
      sideEffect = new NaiveSideEffectTester();
    }
    sideEffect.newMethod(b.getMethod());

    final UpSafetyAnalysis upSafe = new UpSafetyAnalysis(graph, unitToEquivRhs, sideEffect);
    final DownSafetyAnalysis downSafe = new DownSafetyAnalysis(graph, unitToNoExceptionEquivRhs, sideEffect);
    final EarliestnessComputation earliest = new EarliestnessComputation(graph, upSafe, downSafe, sideEffect);
    final LocalCreation localCreation = sc.createLocalCreation(b.getLocals(), PREFIX);
    final HashMap<EquivalentValue, Local> expToHelper = new HashMap<EquivalentValue, Local>();

    Chain<Unit> unitChain = b.getUnits();

    /* insert the computations at the earliest positions */
    for (Iterator<Unit> unitIt = unitChain.snapshotIterator(); unitIt.hasNext();) {
      Unit currentUnit = unitIt.next();
      for (EquivalentValue equiVal : earliest.getFlowBefore(currentUnit)) {
        /* get the unic helper-name for this expression */
        Local helper = expToHelper.get(equiVal);
        if (helper == null) {
          helper = localCreation.newLocal(equiVal.getType());
          expToHelper.put(equiVal, helper);
        }

        // Make sure not to place any stuff inside the identity block at
        // the beginning of the method
        if (currentUnit instanceof IdentityStmt) {
          currentUnit = getFirstNonIdentityStmt(b);
        }

        /* insert a new Assignment-stmt before the currentUnit */
        Value insertValue = Jimple.cloneIfNecessary(equiVal.getValue());
        Unit firstComp = Jimple.v().newAssignStmt(helper, insertValue);
        unitChain.insertBefore(firstComp, currentUnit);
      }
    }

    /* replace old computations by the helper-vars */
    for (Unit currentUnit : unitChain) {
      EquivalentValue rhs = unitToEquivRhs.get(currentUnit);
      if (rhs != null) {
        Local helper = expToHelper.get(rhs);
        if (helper != null) {
          ((AssignStmt) currentUnit).setRightOp(helper);
        }
      }
    }

    if (Options.v().verbose()) {
      logger.debug("[" + b.getMethod().getName() + "]     Busy Code Motion done!");
    }
  
<methods>public non-sealed void <init>() ,public final void transform(soot.Body, java.lang.String, Map<java.lang.String,java.lang.String>) ,public final void transform(soot.Body, java.lang.String) ,public final void transform(soot.Body) <variables>private static final Map<java.lang.String,java.lang.String> enabledOnlyMap