Ignore:
Timestamp:
Jul 20, 2015, 3:43:57 PM (4 years ago)
Author:
nmedfort
Message:

Added optional CMake command -DDISABLE_PREGENERATED_UCD_FUNCTIONS.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/generate_predefined_ucd_functions.cpp

    r4685 r4686  
    3535#include "llvm/Support/FileSystem.h"
    3636#include <llvm/Transforms/Scalar.h>
    37 #include <iostream>
     37#include <llvm/Support/raw_ostream.h>
     38#include <llvm/Analysis/DependenceAnalysis.h>
    3839
    3940using namespace pablo;
     
    4849UCDSourcePath("dir", cl::desc("UCD source code directory"), cl::value_desc("directory"), cl::Required);
    4950
     51static cl::opt<bool> PrintDependenceAnalysis("print-da", cl::init(false), cl::desc("print Dependence Analysis."));
     52
     53
    5054#ifdef ENABLE_MULTIPLEXING
    5155static cl::opt<bool> EnableMultiplexing("multiplexing", cl::init(false),
    5256                                        cl::desc("combine Advances whose inputs are mutual exclusive into the fewest number of advances possible (expensive)."));
     57
     58static cl::opt<std::string>
     59MultiplexingDistribution("multiplexing-dist", cl::desc("Generate a CSV containing the # of Advances found in each UCD function before and after applying multiplexing."), cl::value_desc("filename"));
     60
     61static raw_fd_ostream * MultiplexingDistributionFile = nullptr;
    5362#endif
    5463
     
    5665
    5766/** ------------------------------------------------------------------------------------------------------------- *
     67 * @brief getNumOfAdvances
     68 ** ------------------------------------------------------------------------------------------------------------- */
     69unsigned getNumOfAdvances(const PabloBlock & entry) {
     70    unsigned advances = 0;
     71    for (const Statement * stmt : entry ) {
     72        if (isa<Advance>(stmt)) {
     73            ++advances;
     74        }
     75        else if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
     76            advances += getNumOfAdvances(isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody());
     77        }
     78    }
     79    return advances;
     80}
     81
     82/** ------------------------------------------------------------------------------------------------------------- *
    5883 * @brief compileUnicodeSet
    5984 ** ------------------------------------------------------------------------------------------------------------- */
    6085size_t compileUnicodeSet(std::string name, const UnicodeSet & set, PabloCompiler & pc, Module * module) {
     86    #ifdef ENABLE_MULTIPLEXING
     87    if (MultiplexingDistributionFile) {
     88        (*MultiplexingDistributionFile) << name;
     89    }
     90    #endif
    6191    PabloFunction function = PabloFunction::Create(std::move(name), 8, 1);
    6292    Encoding encoding(Encoding::Type::UTF_8, 8);
     
    6595    PabloBuilder builder(function.getEntryBlock());
    6696    // Build the unicode set function
    67     PabloAST * target = ucdCompiler.generateWithDefaultIfHierarchy(set, builder);
    68     function.setResult(0, builder.createAssign("matches", target));
     97    function.setResult(0, builder.createAssign("matches", ucdCompiler.generateWithDefaultIfHierarchy(set, builder)));
    6998    // Optimize it at the pablo level
    7099    Simplifier::optimize(function);
     
    72101    #ifdef ENABLE_MULTIPLEXING
    73102    if (EnableMultiplexing) {
     103        if (MultiplexingDistributionFile) {
     104            (*MultiplexingDistributionFile) << ',' << getNumOfAdvances(function.getEntryBlock());
     105        }
    74106        AutoMultiplexing::optimize(function);
    75107        Simplifier::optimize(function);
     108        if (MultiplexingDistributionFile) {
     109            (*MultiplexingDistributionFile) << ',' << getNumOfAdvances(function.getEntryBlock()) << '\n';
     110        }
    76111    }
    77112    #endif
     
    132167    cpp << "#include <stdexcept>\n";
    133168    cpp << "#include <unordered_map>\n\n";
    134     cpp << "namespace UCD {\n\n";
     169    cpp << "namespace UCD {\nnamespace {\n\n";
    135170    cpp << "struct Input {\n    BitBlock bit[8];\n};\n\n";
    136171    cpp << "struct Output {\n    BitBlock bit[1];\n};\n\n";
     
    139174    }
    140175
    141     cpp << "\nconst static std::unordered_map<std::string, ExternalProperty> ExternalPropertyMap = {\n";
     176    cpp << "\nconst static std::unordered_map<std::string, ExternalProperty> EXTERNAL_UCD_PROPERTY_MAP = {\n";
    142177    for (auto itr = properties.begin(); itr != properties.end(); ) {
    143178        cpp << "    {\"" + itr->first + "\", std::make_tuple(reinterpret_cast<void *>(&" + itr->first + "), 8, 1, " + std::to_string(itr->second) + ")}";
     
    147182        cpp << "\n";
    148183    }
    149     cpp << "};\n\n";
     184    cpp << "};\n\n} // end of anonymous namespace\n\n";
    150185
    151186    cpp << "const ExternalProperty & resolveExternalProperty(const std::string & name) {\n";
    152     cpp << "    auto f = ExternalPropertyMap.find(name);\n";
    153     cpp << "    if (f == ExternalPropertyMap.end())\n";
     187    cpp << "    auto f = EXTERNAL_UCD_PROPERTY_MAP.find(name);\n";
     188    cpp << "    if (f == EXTERNAL_UCD_PROPERTY_MAP.end())\n";
    154189    cpp << "        throw std::runtime_error(\"No external property named \\\"\" + name + \"\\\" found!\");\n";
    155190    cpp << "    return f->second;\n";
    156     cpp << "}\n\n}\n";
     191    cpp << "}\n\n} // end of UCD namespace\n";
    157192
    158193    cpp.close();
     
    206241    Triple TheTriple;
    207242
     243    TheTriple.setTriple(sys::getDefaultTargetTriple());
     244
     245    // Get the target specific parser.
     246    std::string msg;
     247    const Target * TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), msg);
     248    if (TheTarget == nullptr) {
     249        throw std::runtime_error(msg);
     250    }
     251
     252    TargetOptions Options;
     253
     254    std::unique_ptr<TargetMachine> Target(
     255                TheTarget->createTargetMachine(TheTriple.getTriple(), sys::getHostCPUName(), "", Options,
     256                                               Reloc::Default, CodeModel::Small, CodeGenOpt::Aggressive));
     257
     258    if (Target == nullptr) {
     259        throw std::runtime_error("Could not allocate target machine!");
     260    }
     261
     262    #ifdef USE_LLVM_3_5
     263    std::string error;
     264    std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename.c_str(), error, sys::fs::F_None);
     265    if (!error.empty()) {
     266        throw std::runtime_error(error);
     267    }
     268    #else
     269    std::error_code error;
     270    std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename, error, sys::fs::F_None);
     271    if (error) {
     272        throw std::runtime_error(error.message());
     273    }
     274    #endif
     275
     276    // Build up all of the passes that we want to do to the module.
     277    PassManager PM;
     278
     279    // Add an appropriate TargetLibraryInfo pass for the module's triple.
     280    PM.add(new TargetLibraryInfo(TheTriple));
     281
     282    // Add the target data from the target machine, if it exists, or the module.
     283    #ifdef USE_LLVM_3_5
     284    const DataLayout * DL = Target->getDataLayout();
     285    #else
     286    const DataLayout * DL = Target->getSubtargetImpl()->getDataLayout();
     287    #endif
     288    if (DL) {
     289        module->setDataLayout(DL);
     290    }
     291    #ifdef USE_LLVM_3_5
     292    PM.add(new DataLayoutPass(module));
     293    #else
     294    PM.add(new DataLayoutPass());
     295    #endif
     296    // PM.add(createDependenceAnalysisPass());
     297    PM.add(createReassociatePass());
     298    PM.add(createInstructionCombiningPass());
     299    PM.add(createSinkingPass());
     300
     301    formatted_raw_ostream outStream(out->os());
     302    // Ask the target to add backend passes as necessary.
     303    if (Target->addPassesToEmitFile(PM, outStream, TargetMachine::CGFT_ObjectFile)) {
     304        throw std::runtime_error("Target does not support generation of object file type!\n");
     305    }
     306
     307    PM.run(*module);
     308
     309    out->keep();
     310}
     311
     312/** ------------------------------------------------------------------------------------------------------------- *
     313 * @brief main
     314 ** ------------------------------------------------------------------------------------------------------------- */
     315int main(int argc, char *argv[]) {
    208316    // Initialize targets first, so that --version shows registered targets.
    209317    InitializeAllTargets();
     
    211319    InitializeAllAsmPrinters();
    212320    InitializeAllAsmParsers();
    213 
    214     TheTriple.setTriple(sys::getDefaultTargetTriple());
    215 
    216     // Get the target specific parser.
    217     std::string msg;
    218     const Target * TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), msg);
    219     if (TheTarget == nullptr) {
    220         throw std::runtime_error(msg);
    221     }
    222 
    223     TargetOptions Options;
    224 
    225     std::unique_ptr<TargetMachine> Target(
    226                 TheTarget->createTargetMachine(TheTriple.getTriple(), sys::getHostCPUName(), "", Options,
    227                                                Reloc::Default, CodeModel::Small, CodeGenOpt::Aggressive));
    228 
    229     if (Target == nullptr) {
    230         throw std::runtime_error("Could not allocate target machine!");
    231     }
    232 
    233     #ifdef USE_LLVM_3_5
    234     std::string error;
    235     std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename.c_str(), error, sys::fs::F_None);
    236     if (!error.empty()) {
    237         throw std::runtime_error(error);
    238     }
    239     #else
    240     std::error_code error;
    241     std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename, error, sys::fs::F_None);
    242     if (error) {
    243         throw std::runtime_error(error.message());
    244     }
    245     #endif
    246 
    247     // Build up all of the passes that we want to do to the module.
    248     PassManager PM;
    249 
    250     // Add an appropriate TargetLibraryInfo pass for the module's triple.
    251     PM.add(new TargetLibraryInfo(TheTriple));
    252 
    253     // Add the target data from the target machine, if it exists, or the module.
    254     #ifdef USE_LLVM_3_5
    255     const DataLayout * DL = Target->getDataLayout();
    256     #else
    257     const DataLayout * DL = Target->getSubtargetImpl()->getDataLayout();
    258     #endif
    259     if (DL) {
    260         module->setDataLayout(DL);
    261     }
    262     #ifdef USE_LLVM_3_5
    263     PM.add(new DataLayoutPass(module));
    264     #else
    265     PM.add(new DataLayoutPass());
    266     #endif
    267     PM.add(createReassociatePass());
    268     PM.add(createInstructionCombiningPass());
    269     PM.add(createSinkingPass());
    270 
    271     formatted_raw_ostream FOS(out->os());
    272     // Ask the target to add backend passes as necessary.
    273     if (Target->addPassesToEmitFile(PM, FOS, TargetMachine::CGFT_ObjectFile)) {
    274         throw std::runtime_error("Target does not support generation of object file type!\n");
    275     }
    276 
    277     PM.run(*module);
    278 
    279     out->keep();
    280 }
    281 
    282 /** ------------------------------------------------------------------------------------------------------------- *
    283  * @brief main
    284  ** ------------------------------------------------------------------------------------------------------------- */
    285 int main(int argc, char *argv[]) {
    286321    cl::ParseCommandLineOptions(argc, argv, "UCD Compiler\n");
     322    #ifdef ENABLE_MULTIPLEXING
     323    if (MultiplexingDistribution.length() > 0) {
     324        #ifdef USE_LLVM_3_5
     325        std::string error;
     326        MultiplexingDistributionFile = new raw_fd_ostream(MultiplexingDistribution.c_str(), error, sys::fs::F_Text);
     327        if (!error.empty()) {
     328            throw std::runtime_error(error);
     329        }
     330        #else
     331        std::error_code error;
     332        MultiplexingDistributionFile = new raw_fd_ostream(MultiplexingDistribution, error, sys::fs::F_Text);
     333        if (error) {
     334            throw std::runtime_error(error.message());
     335        }
     336        #endif
     337    }
     338    #endif
    287339    Module * module = generateUCDModule();
     340    #ifdef ENABLE_MULTIPLEXING
     341    if (MultiplexingDistributionFile) {
     342        MultiplexingDistributionFile->close();
     343        delete MultiplexingDistributionFile;
     344    }
     345    #endif
    288346    compileUCDModule(module);
    289347    return 0;
Note: See TracChangeset for help on using the changeset viewer.