source: icGREP/icgrep-devel/icgrep/icgrep.cpp @ 5684

Last change on this file since 5684 was 5620, checked in by nmedfort, 2 years ago

Bug fixes for multigrep mode. Optional PabloKernel? branch hit counter added. Minor optimizations.

File size: 7.7 KB
RevLine 
[3850]1/*
[4947]2 *  Copyright (c) 2016 International Characters.
[3850]3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
[4961]7#include <cstdio>
[5025]8#include <vector>
[4730]9#include <llvm/Support/CommandLine.h>
[5161]10#include <llvm/Support/ErrorHandling.h>
11#include <llvm/Support/Signals.h>
[5267]12#include <llvm/Support/raw_ostream.h>
[4968]13#include <re/re_alt.h>
[5197]14#include <re/re_seq.h>
15#include <re/re_start.h>
16#include <re/re_end.h>
[4734]17#include <re/re_parser.h>
[5197]18#include <re/re_utility.h>
[4946]19#include <grep_engine.h>
[5476]20#include <grep_interface.h>
[4968]21#include <fstream>
22#include <string>
[5425]23#include <toolchain/toolchain.h>
[5030]24#include <re/re_toolchain.h>
[5031]25#include <pablo/pablo_toolchain.h>
[5163]26#include <boost/filesystem.hpp>
[5016]27#include <iostream> // MEEE
[5156]28#ifdef PRINT_TIMING_INFORMATION
29#include <hrtime.h>
30#include <util/papi_helper.hpp>
31#endif
[5418]32#include <sys/stat.h>
33#include <fcntl.h>
[5156]34
[5267]35using namespace llvm;
36
[5480]37static cl::opt<bool> UTF_16("UTF-16", cl::desc("Regular expressions over the UTF-16 representation of Unicode."));
[5167]38
[4544]39static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
40
[4967]41static cl::opt<int> Threads("t", cl::desc("Total number of threads."), cl::init(1));
[4544]42
[5554]43static cl::opt<bool> ByteMode("enable-byte-mode", cl::desc("Process regular expressions in byte mode"));
44
[5480]45static cl::opt<bool> MultiGrepKernels("enable-multigrep-kernels", cl::desc("Construct separated kernels for each regular expression"));
[5344]46static cl::opt<int> REsPerGroup("re-num", cl::desc("Number of regular expressions processed by each kernel."), cl::init(1));
[5550]47
48static cl::opt<std::string> PTXFile("ptx", cl::desc("compiled PTX file."), cl::init(""));
49
[5163]50static std::vector<std::string> allFiles;
[4963]51static re::ModeFlagSet globalFlags = 0;
[4734]52
[5418]53std::vector<re::RE *> readExpressions() {
[4734]54 
[5480]55    if (grep::FileFlag != "") {
56        std::ifstream regexFile(grep::FileFlag.c_str());
[4734]57        std::string r;
58        if (regexFile.is_open()) {
59            while (std::getline(regexFile, r)) {
[5480]60                grep::RegexpVector.push_back(r);
[4734]61            }
62            regexFile.close();
63        }
64    }
65   
66    // if there are no regexes specified through -e or -f, the first positional argument
67    // must be a regex, not an input file.
68   
[5480]69    if (grep::RegexpVector.size() == 0) {
70        grep::RegexpVector.push_back(inputFiles[0]);
[5015]71        inputFiles.erase(inputFiles.begin());
[4734]72    }
[5473]73    if (grep::IgnoreCaseFlag) {
[5418]74        globalFlags |= re::CASE_INSENSITIVE_MODE_FLAG;
75    }
[4734]76
[5344]77    std::vector<re::RE *> REs;
[5480]78    for (unsigned i = 0; i < grep::RegexpVector.size(); i++) {
[5554]79        re::RE * re_ast = re::RE_Parser::parse(grep::RegexpVector[i], globalFlags, grep::RegexpSyntax, ByteMode);
[4734]80        REs.push_back(re_ast);
81    }
[5344]82
[5418]83    if (MultiGrepKernels) {
84        std::vector<re::RE *> groups;
85        auto start = REs.begin();
86        auto end = start + REsPerGroup;
87        while (end < REs.end()) {
88            groups.push_back(re::makeAlt(start, end));
89            start = end;
90            end += REsPerGroup;
91        }
92        if ((REs.end() - start) > 1) {
93            groups.push_back(re::makeAlt(start, REs.end()));
94        } else {
95            groups.push_back(*start);
96        }
97        REs.swap(groups);
98    } else if (REs.size() > 1) {
[5620]99        REs.assign({re::makeAlt(REs.begin(), REs.end())});
[5344]100    }
101
[5418]102    for (re::RE *& re_ast : REs) {
[5620]103        assert (re_ast);
[5473]104        if (grep::WordRegexpFlag) {
[5418]105            re_ast = re::makeSeq({re::makeWordBoundary(), re_ast, re::makeWordBoundary()});
106        }
[5473]107        if (grep::LineRegexpFlag) {
[5418]108            re_ast = re::makeSeq({re::makeStart(), re_ast, re::makeEnd()});
109        }
[4734]110    }
[5418]111
112    return REs;
[4734]113}
114
[4967]115
[5163]116// This is a stub, to be expanded later.
117bool excludeDirectory(boost::filesystem::path dirpath) { return dirpath.filename() == ".svn";}
118
[5480]119// Determine whether to skip a path based on -D skip or -d skip settings.
120bool skip_path(boost::filesystem::path p) {
121    using namespace boost::filesystem;
122    switch (status(p).type()) {
123        case directory_file: return grep::DirectoriesFlag == grep::Skip;
124        case block_file:
125        case character_file:
126        case fifo_file:
127        case socket_file:
128            return grep::DevicesFlag == grep::Skip;
129        default:
130            return false;
131    }
132}
133
[5163]134std::vector<std::string> getFullFileList(cl::list<std::string> & inputFiles) {
135    using namespace boost::filesystem;
[5473]136    symlink_option follow_symlink = grep::DereferenceRecursiveFlag ? symlink_option::recurse : symlink_option::none;
[5163]137    std::vector<std::string> expanded_paths;
138    boost::system::error_code errc;
[5379]139    for (const std::string & f : inputFiles) {
[5480]140        //        if (f == "-") {
141        //            continue;
142        //        }
[5163]143        path p(f);
[5480]144        if (skip_path(p)) {
145            continue;
146        }
147        if (LLVM_UNLIKELY((grep::DirectoriesFlag == grep::Recurse) && is_directory(p))) {
[5163]148            if (!excludeDirectory(p)) {
149                recursive_directory_iterator di(p, follow_symlink, errc), end;
150                if (errc) {
151                    // If we cannot enter the directory, keep it in the list of files.
[5480]152                    expanded_paths.push_back(f);
[5163]153                    continue;
154                }
155                while (di != end) {
156                    auto & e = di->path();
157                    if (is_directory(e)) {
[5379]158                        if (LLVM_UNLIKELY(excludeDirectory(e))) {
159                            di.no_push();
160                        }
161                    } else {
[5480]162                        if (!skip_path(e)) expanded_paths.push_back(e.string());
[5163]163                    }
164                    di.increment(errc);
165                    if (errc) {
[5480]166                        expanded_paths.push_back(e.string());
[5163]167                    }
168                }
169            }
[5379]170        } else {
171            expanded_paths.push_back(p.string());
[5163]172        }
173    }
174    return expanded_paths;
175}
176
[4325]177int main(int argc, char *argv[]) {
[5476]178
179    grep::InitializeCommandLineInterface(argc, argv);
[5473]180   
[5418]181    const auto REs = readExpressions();
182
[5379]183    allFiles = getFullFileList(inputFiles);
184
[5473]185    grep::GrepEngine grepEngine;
[5087]186
[5379]187    if (allFiles.empty()) {
[5377]188
[5473]189        grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::StdIn);
[5379]190        allFiles = { "-" };
[5473]191        grep::initFileResult(allFiles);
[5484]192        grepEngine.doGrep(STDIN_FILENO, 0);
[5377]193
194    } else {
[5486]195               
[5474]196        if (codegen::NVPTX) {
[5550]197            if(PTXFile=="")
198                grepEngine.grepCodeGen_nvptx(REs, grep::Mode, UTF_16);
[5458]199            for (unsigned i = 0; i != allFiles.size(); ++i) {
[5550]200                grepEngine.doGrep(allFiles[i], PTXFile);
[5474]201            }
[5458]202            return 0;
[5474]203        } else {
[5473]204            grepEngine.grepCodeGen(REs, grep::Mode, UTF_16, GrepSource::File);
[5458]205        }
[5377]206
[5473]207        grep::initFileResult(allFiles);
[4967]208
[5377]209        if (Threads <= 1) {
210            for (unsigned i = 0; i != allFiles.size(); ++i) {
[5484]211                grepEngine.doGrep(allFiles[i], i);
[5377]212            }
213        } else if (Threads > 1) {
214            const unsigned numOfThreads = Threads; // <- convert the command line value into an integer to allow stack allocation
215            pthread_t threads[numOfThreads];
[4967]216
[5377]217            for(unsigned long i = 0; i < numOfThreads; ++i){
[5484]218                const int rc = pthread_create(&threads[i], nullptr, grep::DoGrepThreadFunction, (void *)&grepEngine);
[5377]219                if (rc) {
220                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
221                }
[4968]222            }
[5377]223            for(unsigned i = 0; i < numOfThreads; ++i) {
224                void * status = nullptr;
225                const int rc = pthread_join(threads[i], &status);
226                if (rc) {
227                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
228                }
[4967]229            }
230        }
[5377]231
[3850]232    }
[5377]233   
[5484]234    grep::PrintResults();
[4327]235   
[3850]236    return 0;
237}
Note: See TracBrowser for help on using the repository browser.