@Override
    public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
        Object... nodeOutputs) throws SemanticException {

      SyntheticContext sCtx = (SyntheticContext) procCtx;

      @SuppressWarnings("unchecked")
      CommonJoinOperator<JoinDesc> join = (CommonJoinOperator<JoinDesc>) nd;

      ReduceSinkOperator source = (ReduceSinkOperator) stack.get(stack.size() - 2);
      int srcPos = join.getParentOperators().indexOf(source);

      List<Operator<? extends OperatorDesc>> parents = join.getParentOperators();

      int[][] targets = getTargets(join);

      Operator<? extends OperatorDesc> parent = source.getParentOperators().get(0);
      RowSchema parentRS = parent.getSchema();

      // don't generate for null-safes.
      if (join.getConf().getNullSafes() != null) {
        for (boolean b : join.getConf().getNullSafes()) {
          if (b) {
            return null;
          }
        }
      }

      for (int targetPos: targets[srcPos]) {
        if (srcPos == targetPos) {
          continue;
        }

        ReduceSinkOperator target = (ReduceSinkOperator) parents.get(targetPos);
        List<ExprNodeDesc> sourceKeys = source.getConf().getKeyCols();
        List<ExprNodeDesc> targetKeys = target.getConf().getKeyCols();

        ExprNodeDesc syntheticExpr = null;

        if (sourceKeys.size() > 0) {
          for (int i = 0; i < sourceKeys.size(); ++i) {
            final ExprNodeDesc sourceKey = sourceKeys.get(i);

            List<ExprNodeDesc> inArgs = new ArrayList<>();
            inArgs.add(sourceKey);

            ExprNodeDynamicListDesc dynamicExpr =
              new ExprNodeDynamicListDesc(targetKeys.get(i).getTypeInfo(), target, i);

            inArgs.add(dynamicExpr);

            ExprNodeDesc syntheticInExpr =
              ExprNodeGenericFuncDesc.newInstance(FunctionRegistry.getFunctionInfo("in")
                .getGenericUDF(), inArgs);
            if (LOG.isDebugEnabled()) {
              LOG.debug("Synthetic predicate in " + join + ": " + srcPos + " --> " + targetPos + " (" + syntheticInExpr + ")");
            }

            List<ExprNodeDesc> andArgs = new ArrayList<>();
            if (syntheticExpr != null) {
              andArgs.add(syntheticExpr);
            }
            andArgs.add(syntheticInExpr);

            if (sCtx.isExtended()) {
              // Backtrack
              List<ExprNodeDesc> newExprs = createDerivatives(target.getParentOperators().get(0), targetKeys.get(i), sourceKey);
              if (!newExprs.isEmpty()) {
                if (LOG.isDebugEnabled()) {
                  for (ExprNodeDesc expr : newExprs) {
                    LOG.debug("Additional synthetic predicate in " + join + ": " + srcPos + " --> " + targetPos + " (" + expr + ")");
                  }
                }
                andArgs.addAll(newExprs);
              }
            }

            if (andArgs.size() < 2) {
              syntheticExpr = syntheticInExpr;
            } else {
              // Create AND expression
              syntheticExpr =
                ExprNodeGenericFuncDesc.newInstance(FunctionRegistry.getFunctionInfo("and")
                  .getGenericUDF(), andArgs);
            }
          }
        }

        // Handle non-equi joins like <, <=, >, and >=
        List<ExprNodeDesc> residualFilters = join.getConf().getResidualFilterExprs();
        if (residualFilters != null && residualFilters.size() != 0 &&
          !(srcPos > 1 || targetPos > 1)) { // Either srcPos or targetPos is larger than 1, making this filter a complex one.

          for (ExprNodeDesc filter : residualFilters) {
            if (!(filter instanceof ExprNodeGenericFuncDesc)) {
              continue;
            }

            ExprNodeGenericFuncDesc funcDesc = (ExprNodeGenericFuncDesc) filter;
            // filter should be of type <, >, <= or >=
            if (getFuncText(funcDesc.getFuncText(), 1) == null) {
              // unsupported
              continue;
            }

            final ExprNodeDesc sourceChild = funcDesc.getChildren().get(srcPos);
            final ExprNodeDesc targetChild = funcDesc.getChildren().get(targetPos);
            if (!(sourceChild instanceof ExprNodeColumnDesc &&
              targetChild instanceof ExprNodeColumnDesc)) {
              continue;
            }
            // Create non-equi function.
            List<ExprNodeDesc> funcArgs = new ArrayList<>();
            ExprNodeDesc sourceKey = getRSColExprFromResidualFilter(sourceChild, join);
            funcArgs.add(sourceKey);
            final ExprNodeDynamicListDesc dynamicExpr =
              new ExprNodeDynamicListDesc(targetChild.getTypeInfo(), target, 0,
                getRSColExprFromResidualFilter(targetChild, join));
            funcArgs.add(dynamicExpr);
            ExprNodeDesc funcExpr =
              ExprNodeGenericFuncDesc.newInstance(FunctionRegistry.getFunctionInfo(getFuncText(funcDesc.getFuncText(), srcPos)).getGenericUDF(), funcArgs);

            // TODO : deduplicate the code below.
            LOG.debug(" Non-Equi Join Predicate {}", funcExpr);

            List<ExprNodeDesc> andArgs = new ArrayList<>();
            if (syntheticExpr != null) {
              andArgs.add(syntheticExpr);
            }
            andArgs.add(funcExpr);

            // TODO : HIVE-21098 : Support for extended predicates
            if (andArgs.size() < 2) {
              syntheticExpr = funcExpr;
            } else {
              syntheticExpr =
                ExprNodeGenericFuncDesc.newInstance(FunctionRegistry.getFunctionInfo("and").getGenericUDF(), andArgs);
            }
          }
        }

        if (syntheticExpr != null) {
          Operator<FilterDesc> newFilter = createFilter(source, parent, parentRS, syntheticExpr);
          parent = newFilter;
        }
      }

      return null;
    }
creates synthetic predicates that represent "IN (keylist other table)"
ql/src/java/org/apache/hadoop/hive/ql/ppd/SyntheticJoinPredicate.java