1 #ifndef HALIDE_COMPILER_LOGGER_H_ 2 #define HALIDE_COMPILER_LOGGER_H_ 3 4 /** \file 5 * Defines an interface used to gather and log compile-time information, stats, etc 6 * for use in evaluating internal Halide compilation rules and efficiency. 7 * 8 * The 'standard' implementation simply logs all gathered data to 9 * a local file (in JSON form), but the entire implementation can be 10 * replaced by custom definitions if you have unusual logging needs. 11 */ 12 13 #include <iostream> 14 #include <map> 15 #include <memory> 16 #include <set> 17 #include <string> 18 #include <utility> 19 20 #include "Expr.h" 21 #include "Target.h" 22 23 namespace Halide { 24 namespace Internal { 25 26 class CompilerLogger { 27 public: 28 /** The "Phase" of compilation, used for some calls */ 29 enum class Phase { 30 HalideLowering, 31 LLVM, 32 }; 33 34 CompilerLogger() = default; 35 virtual ~CompilerLogger() = default; 36 37 /** Record when a particular simplifier rule matches. 38 */ 39 virtual void record_matched_simplifier_rule(const std::string &rulename, Expr expr) = 0; 40 41 /** Record when an expression is non-monotonic in a loop variable. 42 */ 43 virtual void record_non_monotonic_loop_var(const std::string &loop_var, Expr expr) = 0; 44 45 /** Record when can_prove() fails, but cannot find a counterexample. 46 */ 47 virtual void record_failed_to_prove(Expr failed_to_prove, Expr original_expr) = 0; 48 49 /** Record total size (in bytes) of final generated object code (e.g., file size of .o output). 50 */ 51 virtual void record_object_code_size(uint64_t bytes) = 0; 52 53 /** Record the compilation time (in seconds) for a given phase. 54 */ 55 virtual void record_compilation_time(Phase phase, double duration) = 0; 56 57 /** 58 * Emit all the gathered data to the given stream. This may be called multiple times. 59 */ 60 virtual std::ostream &emit_to_stream(std::ostream &o) = 0; 61 }; 62 63 /** Set the active CompilerLogger object, replacing any existing one. 64 * It is legal to pass in a nullptr (which means "don't do any compiler logging"). 65 * Returns the previous CompilerLogger (if any). */ 66 std::unique_ptr<CompilerLogger> set_compiler_logger(std::unique_ptr<CompilerLogger> compiler_logger); 67 68 /** Return the currently active CompilerLogger object. If set_compiler_logger() 69 * has never been called, a nullptr implementation will be returned. 70 * Do not save the pointer returned! It is intended to be used for immediate 71 * calls only. */ 72 CompilerLogger *get_compiler_logger(); 73 74 /** JSONCompilerLogger is a basic implementation of the CompilerLogger interface 75 * that saves logged data, then logs it all in JSON format in emit_to_stream(). 76 */ 77 class JSONCompilerLogger : public CompilerLogger { 78 public: 79 JSONCompilerLogger() = default; 80 81 JSONCompilerLogger( 82 const std::string &generator_name, 83 const std::string &function_name, 84 const std::string &autoscheduler_name, 85 const Target &target, 86 const std::string &generator_args, 87 bool obfuscate_exprs); 88 89 void record_matched_simplifier_rule(const std::string &rulename, Expr expr) override; 90 void record_non_monotonic_loop_var(const std::string &loop_var, Expr expr) override; 91 void record_failed_to_prove(Expr failed_to_prove, Expr original_expr) override; 92 void record_object_code_size(uint64_t bytes) override; 93 void record_compilation_time(Phase phase, double duration) override; 94 95 std::ostream &emit_to_stream(std::ostream &o) override; 96 97 protected: 98 const std::string generator_name; 99 const std::string function_name; 100 const std::string autoscheduler_name; 101 const Target target; 102 const std::string generator_args; 103 const bool obfuscate_exprs{false}; 104 105 // Maps from string representing rewrite rule -> list of Exprs that matched that rule 106 std::map<std::string, std::vector<Expr>> matched_simplifier_rules; 107 108 // Maps loop_var -> list of Exprs that were nonmonotonic for that loop_var 109 std::map<std::string, std::vector<Expr>> non_monotonic_loop_vars; 110 111 // List of (unprovable simplified Expr, original version of that Expr passed to can_prove()). 112 std::vector<std::pair<Expr, Expr>> failed_to_prove_exprs; 113 114 // Total code size generated, in bytes. 115 uint64_t object_code_size{0}; 116 117 // Map of the time take for each phase of compilation. 118 std::map<Phase, double> compilation_time; 119 120 void obfuscate(); 121 void emit(); 122 }; 123 124 } // namespace Internal 125 } // namespace Halide 126 127 #endif // HALIDE_COMPILER_LOGGER_H_ 128