source: icGREP/icgrep-devel/icgrep/generate_predefined_ucd_functions.cpp @ 4777

Last change on this file since 4777 was 4777, checked in by nmedfort, 4 years ago

CMake fix

File size: 22.7 KB
RevLine 
[4657]1/*
2 *  Copyright (c) 2015 International Characters.
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
[4661]7#include <cc/cc_compiler.h>
[4657]8#include <UCD/unicode_set.h>
[4661]9#include <UCD/PropertyObjectTable.h>
[4657]10#include <UCD/ucd_compiler.hpp>
11#include <pablo/pablo_compiler.h>
[4661]12#include <pablo/builder.hpp>
[4657]13#include <pablo/function.h>
14#include <llvm/Support/CommandLine.h>
[4661]15#include <utf_encoding.h>
[4775]16#include <pablo/analysis/pabloverifier.hpp>
[4661]17#include <pablo/optimizers/pablo_simplifier.hpp>
18#include <pablo/optimizers/pablo_codesinking.hpp>
[4665]19#ifdef ENABLE_MULTIPLEXING
[4775]20#include <pablo/optimizers/pablo_bddminimization.h>
[4661]21#include <pablo/optimizers/pablo_automultiplexing.hpp>
[4665]22#endif
[4775]23#include <pablo/optimizers/booleanreassociationpass.h>
[4665]24#include <llvm/IR/Verifier.h>
25#include <llvm/Support/Debug.h>
26#include <llvm/Support/TargetRegistry.h>
27#include <llvm/Support/TargetSelect.h>
28#include <llvm/Target/TargetLibraryInfo.h>
29#include <llvm/Target/TargetMachine.h>
30#include <llvm/Support/Host.h>
31#include <llvm/ADT/Triple.h>
32#include <llvm/Support/ToolOutputFile.h>
33#include <llvm/Pass.h>
34#include <llvm/PassManager.h>
35#include <llvm/ADT/STLExtras.h>
36#include <llvm/Target/TargetSubtargetInfo.h>
37#include <llvm/Support/FormattedStream.h>
38#include "llvm/Support/FileSystem.h"
[4666]39#include <llvm/Transforms/Scalar.h>
[4686]40#include <llvm/Support/raw_ostream.h>
41#include <llvm/Analysis/DependenceAnalysis.h>
[4723]42#include <boost/container/flat_map.hpp>
[4722]43#include <queue>
44#include <unordered_map>
[4724]45#include <pablo/printer_pablos.h>
46#include <llvm/Analysis/PostDominators.h>
[4722]47
[4657]48using namespace pablo;
[4661]49using namespace UCD;
50using namespace cc;
[4665]51using namespace llvm;
[4723]52using namespace boost::container;
[4657]53
[4736]54enum IfHierarchy {DefaultIfHierarchy, NoIfHierarchy};
55
[4684]56static cl::opt<std::string>
57ObjectFilename("o", cl::desc("Output object filename"), cl::value_desc("filename"), cl::Required);
[4657]58
[4665]59static cl::opt<std::string>
[4684]60UCDSourcePath("dir", cl::desc("UCD source code directory"), cl::value_desc("directory"), cl::Required);
[4657]61
[4723]62static cl::opt<std::string>
63PrintLongestDependenceChain("ldc", cl::desc("print longest dependency chain metrics."), cl::value_desc("filename"));
[4686]64
[4736]65static cl::opt<IfHierarchy> IfHierarchyStrategy(cl::desc("If Hierarchy strategy:"),
66                                                cl::values(clEnumVal(DefaultIfHierarchy, "Default"),
67                                                           clEnumVal(NoIfHierarchy, "None"),
68                                                           clEnumValEnd));
69
[4775]70static cl::opt<bool> EnableReassociation("reassoc", cl::init(false),
71                                      cl::desc("Enable reassociation and distribution optimization of Boolean functions."), cl::Optional);
[4736]72
73
[4723]74static raw_fd_ostream * LongestDependenceChainFile = nullptr;
[4686]75
[4667]76#ifdef ENABLE_MULTIPLEXING
77static cl::opt<bool> EnableMultiplexing("multiplexing", cl::init(false),
[4722]78    cl::desc("combine Advances whose inputs are mutual exclusive into the fewest number of advances possible (expensive)."));
[4686]79
80static cl::opt<std::string>
[4722]81MultiplexingDistribution("multiplexing-dist",
[4723]82    cl::desc("Generate a CSV containing the # of Advances found in each UCD function before and after applying multiplexing."),
83    cl::value_desc("filename"));
[4686]84
85static raw_fd_ostream * MultiplexingDistributionFile = nullptr;
[4723]86#else
87const bool EnableMultiplexing = false;
[4667]88#endif
89
[4726]90using property_list = std::vector<std::string>;
[4671]91
[4665]92/** ------------------------------------------------------------------------------------------------------------- *
[4686]93 * @brief getNumOfAdvances
94 ** ------------------------------------------------------------------------------------------------------------- */
95unsigned getNumOfAdvances(const PabloBlock & entry) {
96    unsigned advances = 0;
97    for (const Statement * stmt : entry ) {
98        if (isa<Advance>(stmt)) {
99            ++advances;
100        }
101        else if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
102            advances += getNumOfAdvances(isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody());
103        }
104    }
105    return advances;
106}
107
108/** ------------------------------------------------------------------------------------------------------------- *
[4722]109 * @brief computePabloDependencyMetrics
110 ** ------------------------------------------------------------------------------------------------------------- */
[4724]111unsigned computePabloDependencyChainMetrics(const PabloBlock & b, std::unordered_map<const PabloAST *, unsigned> & G) {
[4723]112    unsigned lpl = 0;
113    flat_map<const PabloAST *, unsigned> L;
114    for (const Statement * stmt : b) {
115        unsigned local_lpl = 0;
116        unsigned global_lpl = 0;
117        for (unsigned i = 0; i != stmt->getNumOperands(); ++i) {
[4724]118            const PabloAST * const op = stmt->getOperand(i);
119            if (isa<String>(op) || isa<Integer>(op)) {
120                continue;
121            }
122            const auto l = L.find(op);
[4723]123            if (l != L.end()) {
124                local_lpl = std::max<unsigned>(local_lpl, l->second);
[4722]125            }
[4724]126            const auto g = G.find(op);
[4723]127            if (LLVM_UNLIKELY(g == G.end())) {
128                throw std::runtime_error("Could not find dependency chain length for all operands!");
129            }
130            global_lpl = std::max<unsigned>(global_lpl, g->second);
[4722]131        }
[4723]132        L.emplace(stmt, local_lpl + 1);
133        G.insert(std::make_pair(stmt, global_lpl + 1));
134        if (LLVM_UNLIKELY(isa<If>(stmt) || isa<While>(stmt))) {
135            for (const auto & l : L) {
136                lpl = std::max(lpl, l.second);
[4722]137            }
[4723]138            L.clear();
139            lpl = std::max(lpl, computePabloDependencyChainMetrics(isa<If>(stmt) ? cast<If>(stmt)->getBody() : cast<While>(stmt)->getBody(), G));
[4722]140        }
141    }
[4723]142    return lpl;
143}
[4722]144
[4723]145/** ------------------------------------------------------------------------------------------------------------- *
146 * @brief computePabloDependencyMetrics
147 ** ------------------------------------------------------------------------------------------------------------- */
[4736]148std::pair<unsigned, unsigned> computePabloDependencyChainMetrics(const PabloFunction * f) {
[4723]149    std::unordered_map<const PabloAST *, unsigned> G;
[4736]150    G.insert(std::make_pair(f->getEntryBlock().createZeroes(), 0));
151    G.insert(std::make_pair(f->getEntryBlock().createOnes(), 0));
152    for (unsigned i = 0; i != f->getNumOfParameters(); ++i) {
153        G.insert(std::make_pair(f->getParameter(i), 0));
[4723]154    }
[4736]155    const unsigned local_lpl = computePabloDependencyChainMetrics(f->getEntryBlock(), G);
[4723]156    unsigned global_lpl = 0;
[4736]157    for (unsigned i = 0; i != f->getNumOfResults(); ++i) {
158        const auto e = G.find(f->getResult(i));
[4724]159        if (e == G.end()) {
160            throw std::runtime_error("No result computed!");
161        }
162        global_lpl = std::max<unsigned>(global_lpl, e->second);
[4722]163    }
[4723]164    return std::make_pair(global_lpl, local_lpl);
165}
[4722]166
[4723]167/** ------------------------------------------------------------------------------------------------------------- *
168 * @brief computeLLVMDependencyMetrics
169 ** ------------------------------------------------------------------------------------------------------------- */
[4724]170unsigned computeLLVMDependencyChainMetrics(const DomTreeNode * t, std::unordered_map<const Value *, unsigned> & G) {
[4723]171    unsigned lpl = 0;
172    if (true) {
[4724]173        flat_map<const Value *, unsigned> L;
174        const BasicBlock * b = t->getBlock();
175        for (auto itr = b->rbegin(); itr != b->rend(); ++itr) {
[4723]176            unsigned local_lpl = 0;
177            unsigned global_lpl = 0;
[4724]178            const Instruction & inst = *itr;
179            for (const Value * user : inst.users()) {
180                if (LLVM_LIKELY(isa<Instruction>(user))) {
181                    const auto l = L.find(user);
182                    if (l != L.end()) {
183                        local_lpl = std::max<unsigned>(local_lpl, l->second);
184                    }
185                    const auto g = G.find(user);
186                    if (LLVM_UNLIKELY(g == G.end())) {
187                        throw std::runtime_error("Could not find chain length for all users!");
188                    }
189                    global_lpl = std::max<unsigned>(global_lpl, g->second);
[4723]190                }
191            }
192            L.emplace(&inst, local_lpl + 1);
193            G.insert(std::make_pair(&inst, global_lpl + 1));
[4724]194            lpl = std::max(lpl, local_lpl + 1);
[4723]195        }
196    }
[4724]197    for (const DomTreeNode * pt : *t) {
198        lpl = std::max(lpl, computeLLVMDependencyChainMetrics(pt, G));
[4723]199    }
200    return lpl;
[4722]201}
202
203/** ------------------------------------------------------------------------------------------------------------- *
204 * @brief computeLLVMDependencyMetrics
205 ** ------------------------------------------------------------------------------------------------------------- */
[4736]206std::pair<unsigned, unsigned> computeLLVMDependencyChainMetrics(llvm::Function * f) {
[4723]207    std::unordered_map<const llvm::Value *, unsigned> G;
[4724]208
[4736]209    auto itr = f->getArgumentList().begin();
[4724]210    const Argument & input = *itr++;
211    const Argument & output = *itr;
212    for (const User * user : output.users()) {
[4723]213        G.insert(std::make_pair(user, 0));
214    }
[4724]215
216    PostDominatorTree dt;
[4736]217    dt.runOnFunction(*f);
[4724]218    const unsigned local_lpl = computeLLVMDependencyChainMetrics(dt.getRootNode(), G);
219    dt.releaseMemory();
220
[4723]221    unsigned global_lpl = 0;
[4724]222    for (const User * user : input.users()) {
223        const auto e = G.find(user);
224        if (e == G.end()) {
225            throw std::runtime_error("No result computed!");
226        }
227        global_lpl = std::max<unsigned>(global_lpl, e->second);
[4723]228    }
229    return std::make_pair(global_lpl, local_lpl);
[4722]230}
231
232/** ------------------------------------------------------------------------------------------------------------- *
[4665]233 * @brief compileUnicodeSet
234 ** ------------------------------------------------------------------------------------------------------------- */
[4726]235void compileUnicodeSet(std::string name, const UnicodeSet & set, PabloCompiler & pc, Module * module) {
[4686]236    #ifdef ENABLE_MULTIPLEXING
237    if (MultiplexingDistributionFile) {
238        (*MultiplexingDistributionFile) << name;
239    }
240    #endif
[4723]241    if (LongestDependenceChainFile) {
242        (*LongestDependenceChainFile) << name;
243    }
[4777]244    // std::cerr << name << std::endl;
[4736]245    PabloFunction * function = PabloFunction::Create(std::move(name), 8, 1);
[4661]246    Encoding encoding(Encoding::Type::UTF_8, 8);
[4736]247    CC_Compiler ccCompiler(*function, encoding);
[4661]248    UCDCompiler ucdCompiler(ccCompiler);
[4736]249    PabloBuilder builder(function->getEntryBlock());
[4661]250    // Build the unicode set function
[4736]251    PabloAST * result = nullptr;
252    if (IfHierarchyStrategy == IfHierarchy::DefaultIfHierarchy) {
253        result = ucdCompiler.generateWithDefaultIfHierarchy(set, builder);
254    } else if (IfHierarchyStrategy == IfHierarchy::NoIfHierarchy) {
255        result = ucdCompiler.generateWithoutIfHierarchy(set, builder);
256    } else {
257        throw std::runtime_error("Unknown if hierarchy strategy!");
258    }
259    function->setResult(0, builder.createAssign("matches", result));
[4661]260    // Optimize it at the pablo level
[4736]261    Simplifier::optimize(*function);
262    CodeSinking::optimize(*function);
[4723]263
[4665]264    #ifdef ENABLE_MULTIPLEXING
[4775]265    BDDMinimizationPass::optimize(*function);
[4667]266    if (EnableMultiplexing) {
[4724]267        if (LongestDependenceChainFile) {
268            const auto pablo_metrix = computePabloDependencyChainMetrics(function);
269            (*LongestDependenceChainFile) << ',' << pablo_metrix.first << ',' << pablo_metrix.second;
270            Module module("tmp", getGlobalContext());
[4736]271            llvm::Function * func = pc.compile(function, &module);
272            const auto llvm_metrix = computeLLVMDependencyChainMetrics(func);
[4724]273            (*LongestDependenceChainFile) << ',' << llvm_metrix.first << ',' << llvm_metrix.second;
274        }
275
[4686]276        if (MultiplexingDistributionFile) {
[4736]277            (*MultiplexingDistributionFile) << ',' << getNumOfAdvances(function->getEntryBlock());
[4686]278        }
[4754]279        AutoMultiplexing::optimize(*function);
[4686]280        if (MultiplexingDistributionFile) {
[4736]281            (*MultiplexingDistributionFile) << ',' << getNumOfAdvances(function->getEntryBlock()) << '\n';
[4686]282        }
[4667]283    }
[4665]284    #endif
[4775]285    if (EnableReassociation) {
286        BooleanReassociationPass::optimize(*function);
287    }
288
[4661]289    // Now compile the function ...
[4736]290    llvm::Function * func = pc.compile(function, module);
[4665]291    releaseSlabAllocatorMemory();
[4736]292
[4723]293    if (LongestDependenceChainFile) {
294        const auto pablo_metrix = computePabloDependencyChainMetrics(function);
295        (*LongestDependenceChainFile) << ',' << pablo_metrix.first << ',' << pablo_metrix.second;
[4736]296        const auto llvm_metrix = computeLLVMDependencyChainMetrics(func);
[4723]297        (*LongestDependenceChainFile) << ',' << llvm_metrix.first << ',' << llvm_metrix.second << '\n';
298    }
[4736]299
[4661]300}
[4657]301
[4665]302/** ------------------------------------------------------------------------------------------------------------- *
[4671]303 * @brief writePropertyInstaller
[4665]304 ** ------------------------------------------------------------------------------------------------------------- */
[4668]305
[4684]306void writePrecompiledProperties(property_list && properties) {
[4671]307
[4684]308    const std::string headerFilename = UCDSourcePath + "/precompiled_properties.h";
[4668]309    #ifdef USE_LLVM_3_5
310    std::string error;
[4684]311    raw_fd_ostream header(headerFilename.c_str(), error, sys::fs::F_None);
[4668]312    if (!error.empty()) {
313        throw std::runtime_error(error);
314    }
315    #else
316    std::error_code error;
[4684]317    raw_fd_ostream header(headerFilename, error, sys::fs::F_None);
[4668]318    if (error) {
319        throw std::runtime_error(error.message());
320    }
321    #endif
322
[4684]323    header << "#ifndef PRECOMPILED_PROPERTIES\n";
324    header << "#define PRECOMPILED_PROPERTIES\n\n";
325    header << "#include <string>\n\n";
326    header << "#include <tuple>\n";
327    header << "namespace UCD {\n\n";
[4726]328    header << "using ExternalProperty = std::tuple<void *, unsigned, unsigned>;\n\n";
[4684]329    header << "const ExternalProperty & resolveExternalProperty(const std::string & name);\n\n";
330    header << "}\n\n";
331    header << "#endif\n";
332    header.close();
333
334    const std::string cppFilename = UCDSourcePath + "/precompiled_properties.cpp";
335    #ifdef USE_LLVM_3_5
336    raw_fd_ostream cpp(cppFilename.c_str(), error, sys::fs::F_None);
337    if (!error.empty()) {
338        throw std::runtime_error(error);
[4671]339    }
[4684]340    #else
341    raw_fd_ostream cpp(cppFilename, error, sys::fs::F_None);
342    if (error) {
343        throw std::runtime_error(error.message());
344    }
345    #endif
346
347    cpp << "#include \"precompiled_properties.h\"\n";
348    cpp << "#include <include/simd-lib/bitblock.hpp>\n";
349    cpp << "#include <stdexcept>\n";
350    cpp << "#include <unordered_map>\n\n";
[4686]351    cpp << "namespace UCD {\nnamespace {\n\n";
[4684]352    cpp << "struct Input {\n    BitBlock bit[8];\n};\n\n";
353    cpp << "struct Output {\n    BitBlock bit[1];\n};\n\n";
[4671]354    for (auto prop : properties) {
[4726]355        cpp << "extern \"C\" void " + prop + "(const Input &, Output &);\n";
[4671]356    }
[4684]357
[4686]358    cpp << "\nconst static std::unordered_map<std::string, ExternalProperty> EXTERNAL_UCD_PROPERTY_MAP = {\n";
[4684]359    for (auto itr = properties.begin(); itr != properties.end(); ) {
[4726]360        cpp << "    {\"" + *itr + "\", std::make_tuple(reinterpret_cast<void *>(&" + *itr + "), 8, 1)}";
[4684]361        if (++itr != properties.end()) {
362            cpp << ",";
363        }
364        cpp << "\n";
365    }
[4686]366    cpp << "};\n\n} // end of anonymous namespace\n\n";
[4684]367
368    cpp << "const ExternalProperty & resolveExternalProperty(const std::string & name) {\n";
[4686]369    cpp << "    auto f = EXTERNAL_UCD_PROPERTY_MAP.find(name);\n";
370    cpp << "    if (f == EXTERNAL_UCD_PROPERTY_MAP.end())\n";
[4684]371    cpp << "        throw std::runtime_error(\"No external property named \\\"\" + name + \"\\\" found!\");\n";
372    cpp << "    return f->second;\n";
[4686]373    cpp << "}\n\n} // end of UCD namespace\n";
[4684]374
375    cpp.close();
376
[4671]377}
[4668]378
[4671]379/** ------------------------------------------------------------------------------------------------------------- *
380 * @brief generateUCDModule
381 ** ------------------------------------------------------------------------------------------------------------- */
382Module * generateUCDModule() {
383
384    property_list properties;
385
[4661]386    PabloCompiler pc;
[4665]387    Module * module = new Module("ucd", getGlobalContext());
[4661]388    for (PropertyObject * obj : property_object_table) {
[4667]389        if (EnumeratedPropertyObject * enumObj = dyn_cast<EnumeratedPropertyObject>(obj)) {
[4661]390            for (const std::string value : *enumObj) {
391                const UnicodeSet & set = enumObj->GetCodepointSet(canonicalize_value_name(value));
[4667]392                std::string name = "__get_" + property_enum_name[enumObj->getPropertyCode()] + "_" + value;
[4726]393                compileUnicodeSet(name, set, pc, module);
394                properties.emplace_back(name);
[4661]395            }
396        }
[4667]397        else if (ExtensionPropertyObject * extObj = dyn_cast<ExtensionPropertyObject>(obj)) {
[4665]398            for (const std::string value : *extObj) {
399                const UnicodeSet & set = extObj->GetCodepointSet(canonicalize_value_name(value));
[4667]400                std::string name = "__get_" + property_enum_name[extObj->getPropertyCode()] + "_" + value;
[4726]401                compileUnicodeSet(name, set, pc, module);
402                properties.emplace_back(name);
[4665]403            }
404        }
[4667]405        else if (BinaryPropertyObject * binObj = dyn_cast<BinaryPropertyObject>(obj)) {
[4665]406            const UnicodeSet & set = binObj->GetCodepointSet(Binary_ns::Y);
[4667]407            std::string name = "__get_" + property_enum_name[binObj->getPropertyCode()] + "_Y";
[4726]408            compileUnicodeSet(name, set, pc, module);
409            properties.emplace_back(name);
[4665]410        }
411    }
[4657]412
[4665]413    // Print an error message if our module is malformed in any way.
414    verifyModule(*module, &dbgs());
[4657]415
[4684]416    writePrecompiledProperties(std::move(properties));
[4671]417
[4665]418    return module;
419}
420
421/** ------------------------------------------------------------------------------------------------------------- *
422 * @brief compileUCDModule
423 ** ------------------------------------------------------------------------------------------------------------- */
424void compileUCDModule(Module * module) {
425    Triple TheTriple;
426
[4666]427    TheTriple.setTriple(sys::getDefaultTargetTriple());
428
[4665]429    // Get the target specific parser.
430    std::string msg;
431    const Target * TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), msg);
432    if (TheTarget == nullptr) {
433        throw std::runtime_error(msg);
434    }
435
436    TargetOptions Options;
437
438    std::unique_ptr<TargetMachine> Target(
[4685]439                TheTarget->createTargetMachine(TheTriple.getTriple(), sys::getHostCPUName(), "", Options,
[4665]440                                               Reloc::Default, CodeModel::Small, CodeGenOpt::Aggressive));
441
442    if (Target == nullptr) {
443        throw std::runtime_error("Could not allocate target machine!");
444    }
445
446    #ifdef USE_LLVM_3_5
447    std::string error;
[4685]448    std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename.c_str(), error, sys::fs::F_None);
[4665]449    if (!error.empty()) {
450        throw std::runtime_error(error);
451    }
452    #else
453    std::error_code error;
[4685]454    std::unique_ptr<tool_output_file> out = make_unique<tool_output_file>(ObjectFilename, error, sys::fs::F_None);
[4665]455    if (error) {
456        throw std::runtime_error(error.message());
457    }
458    #endif
459
460    // Build up all of the passes that we want to do to the module.
461    PassManager PM;
462
463    // Add an appropriate TargetLibraryInfo pass for the module's triple.
[4669]464    PM.add(new TargetLibraryInfo(TheTriple));
[4665]465
466    // Add the target data from the target machine, if it exists, or the module.
467    #ifdef USE_LLVM_3_5
468    const DataLayout * DL = Target->getDataLayout();
469    #else
470    const DataLayout * DL = Target->getSubtargetImpl()->getDataLayout();
471    #endif
472    if (DL) {
473        module->setDataLayout(DL);
474    }
[4669]475    #ifdef USE_LLVM_3_5
476    PM.add(new DataLayoutPass(module));
477    #else
[4665]478    PM.add(new DataLayoutPass());
[4692]479    #endif   
[4666]480    PM.add(createReassociatePass());
481    PM.add(createInstructionCombiningPass());
482    PM.add(createSinkingPass());
[4665]483
[4686]484    formatted_raw_ostream outStream(out->os());
[4665]485    // Ask the target to add backend passes as necessary.
[4686]486    if (Target->addPassesToEmitFile(PM, outStream, TargetMachine::CGFT_ObjectFile)) {
[4671]487        throw std::runtime_error("Target does not support generation of object file type!\n");
[4665]488    }
489
490    PM.run(*module);
491
[4692]492
[4685]493    out->keep();
[4665]494}
495
496/** ------------------------------------------------------------------------------------------------------------- *
497 * @brief main
498 ** ------------------------------------------------------------------------------------------------------------- */
499int main(int argc, char *argv[]) {
[4686]500    // Initialize targets first, so that --version shows registered targets.
501    InitializeAllTargets();
502    InitializeAllTargetMCs();
503    InitializeAllAsmPrinters();
504    InitializeAllAsmParsers();
[4665]505    cl::ParseCommandLineOptions(argc, argv, "UCD Compiler\n");
[4692]506
507
[4686]508    #ifdef ENABLE_MULTIPLEXING
509    if (MultiplexingDistribution.length() > 0) {
510        #ifdef USE_LLVM_3_5
511        std::string error;
512        MultiplexingDistributionFile = new raw_fd_ostream(MultiplexingDistribution.c_str(), error, sys::fs::F_Text);
513        if (!error.empty()) {
514            throw std::runtime_error(error);
515        }
516        #else
517        std::error_code error;
518        MultiplexingDistributionFile = new raw_fd_ostream(MultiplexingDistribution, error, sys::fs::F_Text);
519        if (error) {
520            throw std::runtime_error(error.message());
521        }
522        #endif
523    }
524    #endif
[4723]525
526    if (PrintLongestDependenceChain.length() > 0) {
527        #ifdef USE_LLVM_3_5
528        std::string error;
529        LongestDependenceChainFile = new raw_fd_ostream(PrintLongestDependenceChain.c_str(), error, sys::fs::F_Text);
530        if (!error.empty()) {
531            throw std::runtime_error(error);
532        }
533        #else
534        std::error_code error;
535        LongestDependenceChainFile = new raw_fd_ostream(PrintLongestDependenceChain, error, sys::fs::F_Text);
536        if (error) {
537            throw std::runtime_error(error.message());
538        }
539        #endif
540
541        if (LongestDependenceChainFile) {
542            if (EnableMultiplexing) {
543                (*LongestDependenceChainFile) << ",Pre-Multiplexing,,,,Post-Multiplexing\n";
544            }
545            (*LongestDependenceChainFile) << ",Pablo,,LLVM,";
546            if (EnableMultiplexing) {
547                (*LongestDependenceChainFile) << ",Pablo,,LLVM,";
548            }
549            (*LongestDependenceChainFile) << "\nName,Global,Max Local,Global,Max Local";
550            if (EnableMultiplexing) {
551                (*LongestDependenceChainFile) << ",Global,Max Local,Global,Max Local";
552            }
553            (*LongestDependenceChainFile) << "\n";
554        }
555    }
556
[4665]557    Module * module = generateUCDModule();
[4686]558    #ifdef ENABLE_MULTIPLEXING
559    if (MultiplexingDistributionFile) {
560        MultiplexingDistributionFile->close();
561        delete MultiplexingDistributionFile;
[4723]562    }   
563    #endif
564    if (LongestDependenceChainFile) {
565        LongestDependenceChainFile->close();
566        delete LongestDependenceChainFile;
[4686]567    }
[4665]568    compileUCDModule(module);
[4661]569    return 0;
[4657]570}
Note: See TracBrowser for help on using the repository browser.