private void addSplitsForGroup(List<Path> dirs, TableScanOperator tableScan, JobConf conf,
      InputFormat inputFormat, Class<? extends InputFormat> inputFormatClass, int splits,
      TableDesc table, List<InputSplit> result)
          throws IOException {
    String tableName = table.getTableName();
    ValidWriteIdList validWriteIdList = AcidUtils.getTableValidWriteIdList(
        conf, tableName == null ? null : HiveStringUtils.normalizeIdentifier(tableName));
    ValidWriteIdList validMmWriteIdList = getMmValidWriteIds(conf, table, validWriteIdList);

    try {
      Utilities.copyJobSecretToTableProperties(table);
      Utilities.copyTablePropertiesToConf(table, conf);
      if (tableScan != null) {
        AcidUtils.setAcidOperationalProperties(conf, tableScan.getConf().isTranscationalTable(),
            tableScan.getConf().getAcidOperationalProperties());

        if (tableScan.getConf().isTranscationalTable() && (validWriteIdList == null)) {
          throw new IOException("Acid table: " + table.getTableName()
                  + " is missing from the ValidWriteIdList config: "
                  + conf.get(ValidTxnWriteIdList.VALID_TABLES_WRITEIDS_KEY));
        }
        if (validWriteIdList != null) {
          AcidUtils.setValidWriteIdList(conf, validWriteIdList);
        }
      }
    } catch (HiveException e) {
      throw new IOException(e);
    }

    if (tableScan != null) {
      pushFiltersAndAsOf(conf, tableScan, this.mrwork);
    }

    List<Path> dirsWithFileOriginals = Collections.synchronizedList(new ArrayList<>()),
            finalDirs = Collections.synchronizedList(new ArrayList<>());
    processPathsForMmRead(dirs, conf, validMmWriteIdList, finalDirs, dirsWithFileOriginals);
    if (finalDirs.isEmpty() && dirsWithFileOriginals.isEmpty()) {
      // This is for transactional tables.
      if (!conf.getBoolean(Utilities.ENSURE_OPERATORS_EXECUTED, false)) {
        LOG.warn("No valid inputs found in " + dirs);
      } else if (validMmWriteIdList != null) {
        // AcidUtils.getAcidState() is already called to verify there is no input split.
        // Thus for a GroupByOperator summary row, set finalDirs and add a Dummy split here.
        result.add(new HiveInputSplit(new NullRowsInputFormat.DummyInputSplit(
            dirs.get(0).toString()), ZeroRowsInputFormat.class.getName()));
      }
      return; // No valid inputs.
    }

    conf.setInputFormat(inputFormat.getClass());
    if (table != null) {
      int headerCount = Utilities.getHeaderCount(table);
      int footerCount = Utilities.getFooterCount(table, conf);
      if (headerCount != 0 || footerCount != 0) {
        if (TextInputFormat.class.isAssignableFrom(inputFormatClass) && isUncompressedInput(finalDirs, conf)) {
          SkippingTextInputFormat skippingTextInputFormat = new SkippingTextInputFormat();
          skippingTextInputFormat.configure(conf, headerCount, footerCount);
          inputFormat = skippingTextInputFormat;
        } else {
          // if the input is Compressed OR not text we have no way of splitting them!
          // In that case RecordReader should take care of header/footer skipping!
          HiveConf.setLongVar(conf, ConfVars.MAPRED_MIN_SPLIT_SIZE, Long.MAX_VALUE);
        }
      }
    }

    if (!finalDirs.isEmpty()) {
      FileInputFormat.setInputPaths(conf, finalDirs.toArray(new Path[finalDirs.size()]));
      InputSplit[] iss = inputFormat.getSplits(conf, splits);
      for (InputSplit is : iss) {
        result.add(new HiveInputSplit(is, inputFormatClass.getName()));
      }
    }

    if (!dirsWithFileOriginals.isEmpty()) {
      // We are going to add splits for these directories with recursive = false, so we ignore
      // any subdirectories (deltas or original directories) and only read the original files.
      // The fact that there's a loop calling addSplitsForGroup already implies it's ok to
      // the real input format multiple times... however some split concurrency/etc configs
      // that are applied separately in each call will effectively be ignored for such splits.
      JobConf nonRecConf = createConfForMmOriginalsSplit(conf, dirsWithFileOriginals);
      InputSplit[] iss = inputFormat.getSplits(nonRecConf, splits);
      for (InputSplit is : iss) {
        result.add(new HiveInputSplit(is, inputFormatClass.getName()));
      }
    }

    if (result.isEmpty() && conf.getBoolean(Utilities.ENSURE_OPERATORS_EXECUTED, false)) {
      // If there are no inputs; the Execution engine skips the operator tree.
      // To prevent it from happening; an opaque  ZeroRows input is added here - when needed.
      result.add(new HiveInputSplit(new NullRowsInputFormat.DummyInputSplit(
          finalDirs.get(0).toString()), ZeroRowsInputFormat.class.getName()));
    }
  }
NOTE: this no longer wraps the IF for LLAP. Call wrapForLlap manually if needed.
ql/src/java/org/apache/hadoop/hive/ql/io/HiveInputFormat.java