proc_clean: remove any empty cases if all cases use all-def compare.
authorwhitequark <whitequark@whitequark.org>
Sun, 23 Dec 2018 09:04:23 +0000 (09:04 +0000)
committerwhitequark <whitequark@whitequark.org>
Sun, 23 Dec 2018 09:04:30 +0000 (09:04 +0000)
kernel/rtlil.cc
kernel/rtlil.h
passes/proc/proc_clean.cc

index 14259f8ed3c97c6f329a37815b3eba6997e6e53d..8404db5e94ec1e9fef2ce66c059d31ea555fb46b 100644 (file)
@@ -3793,6 +3793,11 @@ RTLIL::CaseRule::~CaseRule()
                delete *it;
 }
 
+bool RTLIL::CaseRule::empty() const
+{
+       return actions.empty() && switches.empty();
+}
+
 RTLIL::CaseRule *RTLIL::CaseRule::clone() const
 {
        RTLIL::CaseRule *new_caserule = new RTLIL::CaseRule;
@@ -3809,6 +3814,11 @@ RTLIL::SwitchRule::~SwitchRule()
                delete *it;
 }
 
+bool RTLIL::SwitchRule::empty() const
+{
+       return cases.empty();
+}
+
 RTLIL::SwitchRule *RTLIL::SwitchRule::clone() const
 {
        RTLIL::SwitchRule *new_switchrule = new RTLIL::SwitchRule;
index 276540aa174731fb7cb75251dff6371db5626586..f877622aa4f781e20cc21a6ef4ce36adb3a36f31 100644 (file)
@@ -1227,6 +1227,8 @@ struct RTLIL::CaseRule
        ~CaseRule();
        void optimize();
 
+       bool empty() const;
+
        template<typename T> void rewrite_sigspecs(T &functor);
        RTLIL::CaseRule *clone() const;
 };
@@ -1238,6 +1240,8 @@ struct RTLIL::SwitchRule : public RTLIL::AttrObject
 
        ~SwitchRule();
 
+       bool empty() const;
+
        template<typename T> void rewrite_sigspecs(T &functor);
        RTLIL::SwitchRule *clone() const;
 };
index 477d1ac60c1398fdfd18ef7b7f5cfa0730a3497b..3919e4b9c1a8016119d8ba662739032fe9482ed4 100644 (file)
@@ -77,14 +77,36 @@ void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did
        }
        else
        {
-               for (auto cs : sw->cases) {
+               bool all_fully_def = true;
+               for (auto cs : sw->cases)
+               {
                        if (max_depth != 0)
                                proc_clean_case(cs, did_something, count, max_depth-1);
+                       for (auto cmp : cs->compare)
+                               if (!cmp.is_fully_def())
+                                       all_fully_def = false;
                }
-               while (!sw->cases.empty() && (sw->cases.back()->actions.empty() && sw->cases.back()->switches.empty())) {
-                       did_something = true;
-                       delete sw->cases.back();
-                       sw->cases.pop_back();
+               if (all_fully_def)
+               {
+                       for (auto cs = sw->cases.begin(); cs != sw->cases.end();)
+                       {
+                               if ((*cs)->empty())
+                               {
+                                       did_something = true;
+                                       delete *cs;
+                                       cs = sw->cases.erase(cs);
+                               }
+                               else ++cs;
+                       }
+               }
+               else
+               {
+                       while (!sw->cases.empty() && sw->cases.back()->empty())
+                       {
+                               did_something = true;
+                               delete sw->cases.back();
+                               sw->cases.pop_back();
+                       }
                }
        }
 }
@@ -102,7 +124,7 @@ void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int m
        }
        for (size_t i = 0; i < cs->switches.size(); i++) {
                RTLIL::SwitchRule *sw = cs->switches[i];
-               if (sw->cases.size() == 0) {
+               if (sw->empty()) {
                        cs->switches.erase(cs->switches.begin() + (i--));
                        did_something = true;
                        delete sw;