private void removeCycleOperator(Set<Operator<?>> component, OptimizeTezProcContext context) throws SemanticException {
    AppMasterEventOperator victimAM = null;
    TableScanOperator victimTS = null;
    ReduceSinkOperator victimRS = null;

    // If there is a hint and no operator is removed then throw error
    boolean hasHint = false;
    boolean removed = false;
    for (Operator<?> o : component) {
      // Look for AppMasterEventOperator or ReduceSinkOperator
      if (o instanceof AppMasterEventOperator) {
        if (victimAM == null
                || o.getStatistics().getDataSize() < victimAM.getStatistics()
                .getDataSize()) {
          victimAM = (AppMasterEventOperator) o;
          removed = true;
        }
      } else if (o instanceof ReduceSinkOperator) {

        SemiJoinBranchInfo sjInfo =
                context.parseContext.getRsToSemiJoinBranchInfo().get(o);
        if (sjInfo == null ) {
          continue;
        }
        if (sjInfo.getIsHint()) {
          // Skipping because of hint. Mark this info,
          hasHint = true;
          continue;
        }

        TableScanOperator ts = sjInfo.getTsOp();
        // Sanity check
        assert component.contains(ts);

        if (victimRS == null ||
                ts.getStatistics().getDataSize() <
                        victimTS.getStatistics().getDataSize()) {
          victimRS = (ReduceSinkOperator) o;
          victimTS = ts;
          removed = true;
        }
      }
    }

    // Always set the semijoin optimization as victim.
    Operator<?> victim = victimRS;

    if (victimRS == null && victimAM != null ) {
        victim = victimAM;
    } else if (victimAM == null) {
      // do nothing
    } else {
      // Cycle consists of atleast one dynamic partition pruning(DPP)
      // optimization and atleast one min/max optimization.
      // DPP is a better optimization unless it ends up scanning the
      // bigger table for keys instead of the smaller table.

      // Get the parent TS of victimRS.
      Operator<?> op = victimRS;
      while(!(op instanceof TableScanOperator)) {
        op = op.getParentOperators().get(0);
      }
      if ((2 * op.getStatistics().getDataSize()) <
              victimAM.getStatistics().getDataSize()) {
        victim = victimAM;
      }
    }

    if (hasHint && !removed) {
      // There is hint but none of the operators removed. Throw error
      throw new SemanticException("The user hint is causing an operator cycle. Please fix it and retry");
    }

    if (victim == null ||
            (!context.pruningOpsRemovedByPriorOpt.isEmpty() &&
                    context.pruningOpsRemovedByPriorOpt.contains(victim))) {
      return;
    }

    GenTezUtils.removeBranch(victim);

    if (victim == victimRS) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Cycle found. Removing semijoin "
            + OperatorUtils.getOpNamePretty(victimRS) + " - " + OperatorUtils.getOpNamePretty(victimTS));
      }
      GenTezUtils.removeSemiJoinOperator(context.parseContext, victimRS, victimTS);
    } else {
      // at this point we've found the fork in the op pipeline that has the pruning as a child plan.
      LOG.info("Disabling dynamic pruning for: "
          + ((DynamicPruningEventDesc) victim.getConf()).getTableScan().toString()
          + ". Needed to break cyclic dependency");
    }
  }
TezCompiler translates the operator plan into TezTasks.
ql/src/java/org/apache/hadoop/hive/ql/parse/TezCompiler.java