]> granicus.if.org Git - re2c/commitdiff
Gather some DFA statistics and use it to omit unused code with '--skeleton'.
authorUlya Trofimovich <skvadrik@gmail.com>
Thu, 17 Sep 2015 12:52:09 +0000 (13:52 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Thu, 17 Sep 2015 12:52:09 +0000 (13:52 +0100)
re2c/src/codegen/emit_dfa.cc
re2c/src/codegen/prepare_dfa.cc
re2c/src/codegen/skeleton/generate_code.cc
re2c/src/codegen/skeleton/skeleton.h
re2c/src/ir/bytecode/bytecode.cc
re2c/src/ir/dfa/dfa.cc
re2c/src/ir/dfa/dfa.h

index 603927b0f9b952fbbdb11e68ab7e564a97144374..b3b0f390b4000419f8201556b572776693d737f2 100644 (file)
@@ -131,10 +131,10 @@ void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBra
        if (flag_skeleton)
        {
                skeleton->emit_data (o.file_name);
-               skeleton->emit_start (o, output.max_fill, accepts.size () > 1);
+               skeleton->emit_start (o, max_fill, need_backup, need_backupctx, need_accept);
                uint32_t i = 2;
                emit_body (o, i, used_labels);
-               skeleton->emit_end (o);
+               skeleton->emit_end (o, need_backup, need_backupctx);
        }
        else
        {
index 397ab4bb5381fa2f4d93c92a09af3f799fa671cb..20972251b7c696eedcb3efb9d4477747efc92377 100644 (file)
@@ -154,22 +154,13 @@ void DFA::findBaseState()
        operator delete (span);
 }
 
-void DFA::prepare(OutputFile & o, uint32_t & max_fill)
+void DFA::prepare ()
 {
        bUsedYYBitmap = false;
 
        findSCCs();
        head->link = head;
 
-       for (State * s = head; s; s = s->next)
-       {
-               s->depth = maxDist(s);
-               if (max_fill < s->depth)
-               {
-                       max_fill = s->depth;
-               }
-       }
-
        // create rule states
        std::map<rule_rank_t, State *> rules;
        for (State * s = head; s; s = s->next)
@@ -228,10 +219,6 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
                                }
                        }
                }
-               if (accepts.size () > 1)
-               {
-                       o.set_used_yyaccept ();
-               }
                default_state->action.set_accept (&accepts);
        }
 
@@ -289,4 +276,33 @@ void DFA::prepare(OutputFile & o, uint32_t & max_fill)
        }
 }
 
+void DFA::calc_stats ()
+{
+       // calculate 'YYMAXFILL'
+       max_fill = 0;
+       for (State * s = head; s; s = s->next)
+       {
+               s->depth = maxDist(s);
+               if (max_fill < s->depth)
+               {
+                       max_fill = s->depth;
+               }
+       }
+
+       // determine if 'YYMARKER' or 'YYBACKUP'/'YYRESTORE' pair is used
+       need_backup = accepts.size () > 0;
+
+       // determine if 'YYCTXMARKER' or 'YYBACKUPCTX'/'YYRESTORECTX' pair is used
+       for (State * s = head; s; s = s->next)
+       {
+               if (s->isPreCtxt)
+               {
+                       need_backupctx = true;
+               }
+       }
+
+       // determine if 'yyaccept' variable is used
+       need_accept = accepts.size () > 1;
+}
+
 } // namespace re2c
index 21cfd62110eaf3564d57b6763d435f6e48c9e252..4cf2498a07f884ed6142148d531cdf739130e8fc 100644 (file)
@@ -86,7 +86,13 @@ void Skeleton::emit_prolog (OutputFile & o)
        o << "\n";
 }
 
-void Skeleton::emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) const
+void Skeleton::emit_start
+       ( OutputFile & o
+       , uint32_t maxfill
+       , bool backup
+       , bool backupctx
+       , bool accept
+       ) const
 {
        const uint32_t default_rule = maxkey ();
 
@@ -96,10 +102,16 @@ void Skeleton::emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) cons
        exact_uint (o, sizeof_key);
        o << "\n" << "#define YYPEEK() *cursor";
        o << "\n" << "#define YYSKIP() ++cursor";
-       o << "\n" << "#define YYBACKUP() marker = cursor";
-       o << "\n" << "#define YYBACKUPCTX() ctxmarker = cursor";
-       o << "\n" << "#define YYRESTORE() cursor = marker";
-       o << "\n" << "#define YYRESTORECTX() cursor = ctxmarker";
+       if (backup)
+       {
+               o << "\n" << "#define YYBACKUP() marker = cursor";
+               o << "\n" << "#define YYRESTORE() cursor = marker";
+       }
+       if (backupctx)
+       {
+               o << "\n" << "#define YYBACKUPCTX() ctxmarker = cursor";
+               o << "\n" << "#define YYRESTORECTX() cursor = ctxmarker";
+       }
        o << "\n" << "#define YYLESSTHAN(n) (limit - cursor) < n";
        o << "\n" << "#define YYFILL(n) { break; }";
        o << "\n";
@@ -158,8 +170,6 @@ void Skeleton::emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) cons
        o << "\n" << indString << "YYCTYPE * input = NULL;";
        o << "\n" << indString << "YYKEYTYPE * keys = NULL;";
        o << "\n" << indString << "const YYCTYPE * cursor = NULL;";
-       o << "\n" << indString << "const YYCTYPE * marker = NULL;";
-       o << "\n" << indString << "const YYCTYPE * ctxmarker = NULL;";
        o << "\n" << indString << "const YYCTYPE * limit = NULL;";
        o << "\n" << indString << "const YYCTYPE * eof = NULL;";
        o << "\n" << indString << "unsigned int i = 0;";
@@ -189,16 +199,22 @@ void Skeleton::emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) cons
        o << "\n" << indString << "}";
        o << "\n";
        o << "\n" << indString << "cursor = input;";
-       o << "\n" << indString << "marker = input;";
-       o << "\n" << indString << "ctxmarker = input;";
        o << "\n" << indString << "limit = input + input_len + padding;";
        o << "\n" << indString << "eof = input + input_len;";
        o << "\n";
        o << "\n" << indString << "for (i = 0; status == 0 && cursor < eof && i < keys_count; ++i)";
        o << "\n" << indString << "{";
+       if (backup)
+       {
+               o << "\n" << indString << indString << "const YYCTYPE * marker = NULL;";
+       }
+       if (backupctx)
+       {
+               o << "\n" << indString << indString << "const YYCTYPE * ctxmarker = NULL;";
+       }
        o << "\n" << indString << indString << "const YYCTYPE * token = cursor;";
        o << "\n" << indString << indString << "YYCTYPE yych;";
-       if (yyaccept)
+       if (accept)
        {
                o << "\n" << indString << indString << "unsigned int yyaccept = 0;";
        }
@@ -209,7 +225,11 @@ void Skeleton::emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) cons
        o << "\n";
 }
 
-void Skeleton::emit_end (OutputFile & o) const
+void Skeleton::emit_end
+       ( OutputFile & o
+       , bool backup
+       , bool backupctx
+       ) const
 {
        o << "\n" << indString << "}";
        o << "\n" << indString << "if (status == 0)";
@@ -237,10 +257,16 @@ void Skeleton::emit_end (OutputFile & o) const
        o << "\n" << "#undef YYKEYTYPE";
        o << "\n" << "#undef YYPEEK";
        o << "\n" << "#undef YYSKIP";
-       o << "\n" << "#undef YYBACKUP";
-       o << "\n" << "#undef YYBACKUPCTX";
-       o << "\n" << "#undef YYRESTORE";
-       o << "\n" << "#undef YYRESTORECTX";
+       if (backup)
+       {
+               o << "\n" << "#undef YYBACKUP";
+               o << "\n" << "#undef YYRESTORE";
+       }
+       if (backupctx)
+       {
+               o << "\n" << "#undef YYBACKUPCTX";
+               o << "\n" << "#undef YYRESTORECTX";
+       }
        o << "\n" << "#undef YYLESSTHAN";
        o << "\n" << "#undef YYFILL";
        o << "\n";
index 147505c3f59e5c8224dd74b3886154af8648a814..8583548665896611781480fabf15db5ffb0a8339 100644 (file)
@@ -73,8 +73,18 @@ struct Skeleton
        void warn_undefined_control_flow ();
        void emit_data (const char * fname);
        static void emit_prolog (OutputFile & o);
-       void emit_start (OutputFile & o, uint32_t maxfill, bool yyaccept) const;
-       void emit_end (OutputFile & o) const;
+       void emit_start
+               ( OutputFile & o
+               , uint32_t maxfill
+               , bool backup
+               , bool backupctx
+               , bool accept
+               ) const;
+       void emit_end
+               ( OutputFile & o
+               , bool backup
+               , bool backupctx
+               ) const;
        static void emit_epilog (OutputFile & o, const std::vector<std::string> & names);
        static void emit_action (OutputFile & o, uint32_t ind, rule_rank_t rank, const std::string & name);
 
index 8d2ed241f01f52b31cad360c62c6fc4495141378..bd88ab54fb0d0aa74b4077c50e9475ab99b5161d 100644 (file)
@@ -64,8 +64,13 @@ smart_ptr<DFA> genCode (RegExp *re, Output & output, const std::string & cond)
                , rep
                ));
 
+       // accumulate global statistics from this particular DFA
        output.names.push_back (dfa->name);
-       dfa->prepare (output.source, output.max_fill);
+       output.max_fill = std::max (output.max_fill, dfa->max_fill);
+       if (dfa->need_accept)
+       {
+               output.source.set_used_yyaccept ();
+       }
 
        return dfa;
 }
index a58e42250a1fa1e5fee7bb91a43088b8884d1b89..f0e45f188f5b2e689ef6024ab43a908a9dbfde4b 100644 (file)
@@ -59,6 +59,12 @@ DFA::DFA
        , toDo(NULL)
        , free_ins(ins)
        , free_rep(rep)
+
+       // statistics
+       , max_fill (0)
+       , need_backup (false)
+       , need_backupctx (false)
+       , need_accept (false)
 {
        if (name.empty ())
        {
@@ -149,6 +155,12 @@ DFA::DFA
        // skeleton must be constructed after DFA construction
        // but prior to any other DFA transformations
        skeleton = new Skeleton (*this);
+
+       // skeleton is constructed, do further DFA transformations
+       prepare ();
+
+       // finally gather overall DFA statistics
+       calc_stats ();
 }
 
 DFA::~DFA()
index 9725ac99c495112c8a8ab21b6ca9d8f3f3b7c52d..66eec1c07abb9d73750560a1380e03acf5d79678 100644 (file)
@@ -29,6 +29,12 @@ public:
        const Ins * free_ins;
        const Char * free_rep;
 
+       // statistics
+       uint32_t max_fill;
+       bool need_backup;
+       bool need_backupctx;
+       bool need_accept;
+
 public:
        DFA
                ( const std::string &
@@ -40,18 +46,19 @@ public:
                , const Char *
                );
        ~DFA ();
+       void emit (Output &, uint32_t &, bool, bool &);
+       friend std::ostream & operator << (std::ostream &, const DFA &);
+
+private:
        void addState (State **, State *);
        State * findState (Ins **, Ins **);
        void split (State *);
-
        void findSCCs ();
        void findBaseState ();
-       void prepare (OutputFile & o, uint32_t &);
+       void calc_stats ();
+       void prepare ();
        void count_used_labels (std::set<label_t> & used, label_t prolog, label_t start, bool force_start) const;
        void emit_body (OutputFile &, uint32_t &, const std::set<label_t> & used_labels) const;
-       void emit (Output &, uint32_t &, bool, bool &);
-
-       friend std::ostream & operator << (std::ostream &, const DFA &);
 
        FORBID_COPY (DFA);
 };