Minor optimisation in Module::wire() and Module::cell()
authorRupert Swarbrick <rswarbrick@gmail.com>
Tue, 26 May 2020 14:19:39 +0000 (15:19 +0100)
committerRupert Swarbrick <rswarbrick@gmail.com>
Tue, 26 May 2020 15:07:36 +0000 (16:07 +0100)
The existing code does a search to figure out whether id is in the
dict (with the call to count()), and then looks it up again to get the
result (with the call to at()). This version calls find() instead,
avoiding the double lookup.

Code size increases slightly (6kb). I think this is because the
contents of find() are getting inlined, and then inlined into lots of
the callsites for cell() and wire().

Looking at the compiled code before this patch, you just get
a (non-inlined) call to count() followed by a call to at(). After the
patch, the contents of find() have been inlined (so you see do_hash,
then do_lookup). The result for each function is about 30 bytes / 40%
bigger, which presumably also enlarges call-sites that inline it.

kernel/rtlil.h

index 11c45bbec77904615e85d669cfd5b2a181fb1bcb..76c5b53047ce5ffe3ebf0288681a69761a58330b 100644 (file)
@@ -1134,8 +1134,14 @@ public:
                return design->selected_member(name, member->name);
        }
 
-       RTLIL::Wire* wire(RTLIL::IdString id) { return wires_.count(id) ? wires_.at(id) : nullptr; }
-       RTLIL::Cell* cell(RTLIL::IdString id) { return cells_.count(id) ? cells_.at(id) : nullptr; }
+       RTLIL::Wire* wire(RTLIL::IdString id) {
+               auto it = wires_.find(id);
+               return it == wires_.end() ? nullptr : it->second;
+       }
+       RTLIL::Cell* cell(RTLIL::IdString id) {
+               auto it = cells_.find(id);
+               return it == cells_.end() ? nullptr : it->second;
+       }
 
        RTLIL::ObjRange<RTLIL::Wire*> wires() { return RTLIL::ObjRange<RTLIL::Wire*>(&wires_, &refcount_wires_); }
        RTLIL::ObjRange<RTLIL::Cell*> cells() { return RTLIL::ObjRange<RTLIL::Cell*>(&cells_, &refcount_cells_); }