private static void splitExpressions(ExprNodeDesc exprNode,
      List<ExprNodeDesc> allExprNodesExceptSemijoin, List<ExprNodeDesc> semijoinExprNodes) {
    if (FunctionRegistry.isOpAnd(exprNode)) {
      for (ExprNodeDesc expr : exprNode.getChildren()) {
        if (isSemijoinExpr(expr)) {
          semijoinExprNodes.add(expr);
        } else {
          allExprNodesExceptSemijoin.add(expr);
        }
      }
    } else if (isSemijoinExpr(exprNode)) {
      semijoinExprNodes.add(exprNode);
    } else {
      allExprNodesExceptSemijoin.add(exprNode);
    }
  }
When we call this method, we have already verified that the SJ expressions targeting
two TS operators are the same.
Since we already had a method to push the filter expressions on top of the discardable
TS (pushFilterToTopOfTableScan), here we remove the old SJ expressions from the
discardable TS (and follow-up Filters if present) and we add the SJ expressions
from the retainable TS. That way the SJ expressions will be pushed on top of the
discardable TS by pushFilterToTopOfTableScan.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SharedWorkOptimizer.java