Avoid double traversal of maps

The typical find/if-not-exists-insert pattern can be achieved with 1
lookup instead of 2 using emplace with a sentinel value. Also maps value
initialize their values when inserted with the [] operator, this is
defined and so there is no need to explicitly insert zeroes for integer
values.
This commit is contained in:
Geza Lore 2023-10-28 13:38:02 +01:00
parent 30318a6654
commit d60f180f43
25 changed files with 240 additions and 311 deletions

View File

@ -1178,13 +1178,10 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd,
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) { AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(), const VBasicTypeKey key{nodep->width(), nodep->widthMin(), nodep->numeric(), nodep->keyword(),
nodep->nrange()}; nodep->nrange()};
DetailedMap& mapr = m_detailedMap; auto pair = m_detailedMap.emplace(key, nodep);
const auto it = mapr.find(key); if (pair.second) nodep->generic(true);
if (it != mapr.end()) return it->second;
mapr.emplace(key, nodep);
nodep->generic(true);
// No addTypesp; the upper function that called new() is responsible for adding // No addTypesp; the upper function that called new() is responsible for adding
return nodep; return pair.first->second;
} }
AstConstPool::AstConstPool(FileLine* fl) AstConstPool::AstConstPool(FileLine* fl)
@ -1641,13 +1638,13 @@ void AstInitArray::cloneRelink() {
} }
} }
void AstInitArray::addIndexValuep(uint64_t index, AstNodeExpr* newp) { void AstInitArray::addIndexValuep(uint64_t index, AstNodeExpr* newp) {
const auto it = m_map.find(index); const auto pair = m_map.emplace(index, nullptr);
if (it != m_map.end()) { if (pair.second) {
it->second->valuep(newp);
} else {
AstInitItem* const itemp = new AstInitItem{fileline(), newp}; AstInitItem* const itemp = new AstInitItem{fileline(), newp};
m_map.emplace(index, itemp); pair.first->second = itemp;
addInitsp(itemp); addInitsp(itemp);
} else {
pair.first->second->valuep(newp);
} }
} }
AstNodeExpr* AstInitArray::getIndexValuep(uint64_t index) const { AstNodeExpr* AstInitArray::getIndexValuep(uint64_t index) const {

View File

@ -400,12 +400,10 @@ public:
bool getEntryMatch(const V3ConfigScopeTraceEntry* entp, const string& scopepart) { bool getEntryMatch(const V3ConfigScopeTraceEntry* entp, const string& scopepart) {
// Return if a entry matches the scopepart, with memoization // Return if a entry matches the scopepart, with memoization
const auto& key = V3ConfigScopeTraceEntryMatch{entp, scopepart}; const V3ConfigScopeTraceEntryMatch key{entp, scopepart};
const auto& it = m_matchCache.find(key); const auto pair = m_matchCache.emplace(key, false);
if (it != m_matchCache.end()) return it->second; // Cached if (pair.second) pair.first->second = VString::wildmatch(scopepart, entp->m_scope);
const bool matched = VString::wildmatch(scopepart, entp->m_scope); return pair.first->second;
m_matchCache.emplace(key, matched);
return matched;
} }
bool getScopeTraceOn(const string& scope) { bool getScopeTraceOn(const string& scope) {

View File

@ -77,7 +77,8 @@ private:
CheckState m_state; // State save-restored on each new coverage scope/block CheckState m_state; // State save-restored on each new coverage scope/block
AstNodeModule* m_modp = nullptr; // Current module to add statement to AstNodeModule* m_modp = nullptr; // Current module to add statement to
bool m_inToggleOff = false; // In function/task etc bool m_inToggleOff = false; // In function/task etc
std::unordered_map<std::string, int> m_varnames; // Uniquification of inserted variable names // Uniquification of inserted variable names
std::unordered_map<std::string, uint32_t> m_varnames;
string m_beginHier; // AstBegin hier name for user coverage points string m_beginHier; // AstBegin hier name for user coverage points
std::unordered_map<int, LinenoSet> std::unordered_map<int, LinenoSet>
m_handleLines; // All line numbers for a given m_stateHandle m_handleLines; // All line numbers for a given m_stateHandle
@ -141,13 +142,7 @@ private:
string traceNameForLine(AstNode* nodep, const string& type) { string traceNameForLine(AstNode* nodep, const string& type) {
string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__" string name = "vlCoverageLineTrace_" + nodep->fileline()->filebasenameNoExt() + "__"
+ cvtToStr(nodep->fileline()->lineno()) + "_" + type; + cvtToStr(nodep->fileline()->lineno()) + "_" + type;
const auto it = m_varnames.find(name); if (const uint32_t suffix = m_varnames[name]++) name += "_" + cvtToStr(suffix);
if (it == m_varnames.end()) {
m_varnames.emplace(name, 1);
} else {
const int suffix = (it->second)++;
name += "_" + cvtToStr(suffix);
}
return name; return name;
} }

View File

@ -145,30 +145,26 @@ private:
int width /*0==fromoldvar*/, AstNodeDType* newdtypep) { int width /*0==fromoldvar*/, AstNodeDType* newdtypep) {
// Because we've already scoped it, we may need to add both the AstVar and the AstVarScope // Because we've already scoped it, we may need to add both the AstVar and the AstVarScope
UASSERT_OBJ(oldvarscp->scopep(), oldvarscp, "Var unscoped"); UASSERT_OBJ(oldvarscp->scopep(), oldvarscp, "Var unscoped");
AstVar* varp; FileLine* const flp = oldvarscp->fileline();
AstNodeModule* const addmodp = oldvarscp->scopep()->modp(); AstNodeModule* const addmodp = oldvarscp->scopep()->modp();
// We need a new AstVar, but only one for all scopes, to match the new AstVarScope // We need a new AstVar, but only one for all scopes, to match the new AstVarScope
const auto it = m_modVarMap.find(std::make_pair(addmodp, name)); const auto pair = m_modVarMap.emplace(std::make_pair(addmodp, name), nullptr);
if (it != m_modVarMap.end()) { if (pair.second) {
// Created module's AstVar earlier under some other scope AstVar* varp = nullptr;
varp = it->second;
} else {
if (newdtypep) { if (newdtypep) {
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name, newdtypep}; varp = new AstVar{flp, VVarType::BLOCKTEMP, name, newdtypep};
} else if (width == 0) { } else if (width == 0) {
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name, varp = new AstVar{flp, VVarType::BLOCKTEMP, name, oldvarscp->varp()};
oldvarscp->varp()};
varp->dtypeFrom(oldvarscp); varp->dtypeFrom(oldvarscp);
} else { // Used for vset and dimensions, so can zero init } else { // Used for vset and dimensions, so can zero init
varp = new AstVar{oldvarscp->fileline(), VVarType::BLOCKTEMP, name, varp = new AstVar{flp, VVarType::BLOCKTEMP, name, VFlagBitPacked{}, width};
VFlagBitPacked{}, width};
} }
addmodp->addStmtsp(varp); addmodp->addStmtsp(varp);
m_modVarMap.emplace(std::make_pair(addmodp, name), varp); pair.first->second = varp;
} }
AstVar* const varp = pair.first->second;
AstVarScope* const varscp AstVarScope* const varscp = new AstVarScope{flp, oldvarscp->scopep(), varp};
= new AstVarScope{oldvarscp->fileline(), oldvarscp->scopep(), varp};
oldvarscp->scopep()->addVarsp(varscp); oldvarscp->scopep()->addVarsp(varscp);
return varscp; return varscp;
} }

View File

@ -63,13 +63,7 @@ void V3DupFinder::dumpFile(const string& filename, bool tree) {
for (auto it = cbegin(); true; ++it) { for (auto it = cbegin(); true; ++it) {
if (it == cend() || lasthash != it->first) { if (it == cend() || lasthash != it->first) {
if (it != cend()) lasthash = it->first; if (it != cend()) lasthash = it->first;
if (num_in_bucket) { if (num_in_bucket) ++dist[num_in_bucket];
if (dist.find(num_in_bucket) == dist.end()) {
dist.emplace(num_in_bucket, 1);
} else {
++dist[num_in_bucket];
}
}
num_in_bucket = 0; num_in_bucket = 0;
} }
if (it == cend()) break; if (it == cend()) break;

View File

@ -187,12 +187,9 @@ class EmitCSyms final : EmitCBaseVisitorConst {
const auto scpit = m_vpiScopeCandidates.find(scopeSymString(scp)); const auto scpit = m_vpiScopeCandidates.find(scopeSymString(scp));
if ((scpit != m_vpiScopeCandidates.end()) if ((scpit != m_vpiScopeCandidates.end())
&& (m_scopeNames.find(scp) == m_scopeNames.end())) { && (m_scopeNames.find(scp) == m_scopeNames.end())) {
const auto scopeNameit = m_scopeNames.find(scpit->second.m_symName); // If not in m_scopeNames, add it, otherwise just update m_type
if (scopeNameit == m_scopeNames.end()) { const auto pair = m_scopeNames.emplace(scpit->second.m_symName, scpit->second);
m_scopeNames.emplace(scpit->second.m_symName, scpit->second); if (!pair.second) pair.first->second.m_type = scpit->second.m_type;
} else {
scopeNameit->second.m_type = scpit->second.m_type;
}
} }
string::size_type pos = scp.rfind("__DOT__"); string::size_type pos = scp.rfind("__DOT__");
if (pos == string::npos) { if (pos == string::npos) {

View File

@ -991,10 +991,8 @@ public:
string protectIf(const string& old, bool doIt) VL_MT_SAFE_EXCLUDES(m_mutex) { string protectIf(const string& old, bool doIt) VL_MT_SAFE_EXCLUDES(m_mutex) {
if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old; if (!v3Global.opt.protectIds() || old.empty() || !doIt) return old;
const V3LockGuard lock{m_mutex}; const V3LockGuard lock{m_mutex};
const auto it = m_nameMap.find(old); const auto pair = m_nameMap.emplace(old, "");
if (it != m_nameMap.end()) { if (pair.second) {
return it->second;
} else {
string out; string out;
if (v3Global.opt.debugProtect()) { if (v3Global.opt.debugProtect()) {
// This lets us see the symbol being protected to debug cases // This lets us see the symbol being protected to debug cases
@ -1009,16 +1007,15 @@ public:
// See if we can shrink the digest symbol to something smaller // See if we can shrink the digest symbol to something smaller
for (size_t len = 6; len < out.size() - 3; len += 3) { for (size_t len = 6; len < out.size() - 3; len += 3) {
const string tryout = out.substr(0, len); const string tryout = out.substr(0, len);
if (m_newIdSet.find(tryout) == m_newIdSet.end()) { if (m_newIdSet.insert(tryout).second) {
out = tryout; out = tryout;
break; break;
} }
} }
} }
m_nameMap.emplace(old, out); pair.first->second = out;
m_newIdSet.insert(out);
return out;
} }
return pair.first->second;
} }
string protectWordsIf(const string& old, bool doIt) VL_MT_SAFE { string protectWordsIf(const string& old, bool doIt) VL_MT_SAFE {
// Split at " " (for traces), "." (for scopes), "->", "(", "&", ")" (for self pointers) // Split at " " (for traces), "." (for scopes), "->", "(", "&", ")" (for self pointers)

View File

@ -114,8 +114,8 @@ void V3Global::dumpCheckGlobalTree(const string& stagename, int newNumber, bool
} }
const std::string& V3Global::ptrToId(const void* p) { const std::string& V3Global::ptrToId(const void* p) {
auto it = m_ptrToId.find(p); const auto pair = m_ptrToId.emplace(p, "");
if (it == m_ptrToId.end()) { if (pair.second) {
std::ostringstream os; std::ostringstream os;
if (p) { if (p) {
os << "("; os << "(";
@ -125,7 +125,7 @@ const std::string& V3Global::ptrToId(const void* p) {
} else { } else {
os << "0"; os << "0";
} }
it = m_ptrToId.emplace(p, os.str()).first; pair.first->second = os.str();
} }
return it->second; return pair.first->second;
} }

View File

@ -306,12 +306,12 @@ public:
//###################################################################### //######################################################################
void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector<AstVar*>& gparams) { void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector<AstVar*>& gparams) {
const iterator it = m_blocks.find(modp); const auto pair = m_blocks.emplace(modp, nullptr);
if (it == m_blocks.end()) { if (pair.second) {
V3HierBlock* hblockp = new V3HierBlock{modp, gparams}; V3HierBlock* hblockp = new V3HierBlock{modp, gparams};
UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters" UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters"
<< std::endl); << std::endl);
m_blocks.emplace(modp, hblockp); pair.first->second = hblockp;
} }
} }

View File

@ -157,31 +157,27 @@ public:
// Do we have a old assignment we can nuke? // Do we have a old assignment we can nuke?
UINFO(4, " ASSIGNof: " << nodep << endl); UINFO(4, " ASSIGNof: " << nodep << endl);
UINFO(7, " new: " << assp << endl); UINFO(7, " new: " << assp << endl);
const auto it = m_map.find(nodep); const auto pair = m_map.emplace(std::piecewise_construct, //
if (it != m_map.end()) { std::forward_as_tuple(nodep),
checkRemoveAssign(it); std::forward_as_tuple(LifeVarEntry::SIMPLEASSIGN{}, assp));
it->second.simpleAssign(assp); if (!pair.second) {
} else { checkRemoveAssign(pair.first);
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::SIMPLEASSIGN{}, assp}); pair.first->second.simpleAssign(assp);
} }
// lifeDump(); // lifeDump();
} }
void complexAssign(AstVarScope* nodep) { void complexAssign(AstVarScope* nodep) {
UINFO(4, " clearof: " << nodep << endl); UINFO(4, " clearof: " << nodep << endl);
const auto it = m_map.find(nodep); const auto pair = m_map.emplace(nodep, LifeVarEntry::COMPLEXASSIGN{});
if (it != m_map.end()) { if (!pair.second) pair.first->second.complexAssign();
it->second.complexAssign();
} else {
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}});
}
} }
void clearReplaced() { m_replacedVref = false; } void clearReplaced() { m_replacedVref = false; }
bool replaced() const { return m_replacedVref; } bool replaced() const { return m_replacedVref; }
void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) { void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) {
// Variable rvalue. If it references a constant, we can replace it // Variable rvalue. If it references a constant, we can replace it
const auto it = m_map.find(nodep); const auto pair = m_map.emplace(nodep, LifeVarEntry::CONSUMED{});
if (it != m_map.end()) { if (!pair.second) {
if (AstConst* const constp = it->second.constNodep()) { if (AstConst* const constp = pair.first->second.constNodep()) {
if (!varrefp->varp()->isSigPublic() && !varrefp->varp()->isUsedVirtIface()) { if (!varrefp->varp()->isSigPublic() && !varrefp->varp()->isUsedVirtIface()) {
// Aha, variable is constant; substitute in. // Aha, variable is constant; substitute in.
// We'll later constant propagate // We'll later constant propagate
@ -194,27 +190,19 @@ public:
} }
} }
UINFO(4, " usage: " << nodep << endl); UINFO(4, " usage: " << nodep << endl);
it->second.consumed(); pair.first->second.consumed();
} else {
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}});
} }
} }
void complexAssignFind(AstVarScope* nodep) { void complexAssignFind(AstVarScope* nodep) {
const auto it = m_map.find(nodep); const auto pair = m_map.emplace(nodep, LifeVarEntry::COMPLEXASSIGN{});
if (it != m_map.end()) { if (!pair.second) {
UINFO(4, " casfind: " << it->first << endl); UINFO(4, " casfind: " << pair.first->first << endl);
it->second.complexAssign(); pair.first->second.complexAssign();
} else {
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::COMPLEXASSIGN{}});
} }
} }
void consumedFind(AstVarScope* nodep) { void consumedFind(AstVarScope* nodep) {
const auto it = m_map.find(nodep); const auto pair = m_map.emplace(nodep, LifeVarEntry::CONSUMED{});
if (it != m_map.end()) { if (!pair.second) pair.first->second.consumed();
it->second.consumed();
} else {
m_map.emplace(nodep, LifeVarEntry{LifeVarEntry::CONSUMED{}});
}
} }
void lifeToAbove() { void lifeToAbove() {
// Any varrefs under a if/else branch affect statements outside and after the if/else // Any varrefs under a if/else branch affect statements outside and after the if/else

View File

@ -195,22 +195,18 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) { for (AstNode* subnodep = oldmodp->stmtsp(); subnodep; subnodep = subnodep->nextp()) {
if (AstVar* const oldvarp = VN_CAST(subnodep, Var)) { if (AstVar* const oldvarp = VN_CAST(subnodep, Var)) {
if (oldvarp->isIO()) { if (oldvarp->isIO()) {
if (ioNames.find(oldvarp->name()) != ioNames.end()) { if (!ioNames.insert(oldvarp->name()).second) {
// UINFO(8, "Multitop dup I/O found: " << oldvarp << endl); // UINFO(8, "Multitop dup I/O found: " << oldvarp << endl);
dupNames.insert(oldvarp->name()); dupNames.insert(oldvarp->name());
} else {
ioNames.insert(oldvarp->name());
} }
} else if (v3Global.opt.topIfacesSupported() && oldvarp->isIfaceRef()) { } else if (v3Global.opt.topIfacesSupported() && oldvarp->isIfaceRef()) {
const AstNodeDType* const subtypep = oldvarp->subDTypep(); const AstNodeDType* const subtypep = oldvarp->subDTypep();
if (VN_IS(subtypep, IfaceRefDType)) { if (VN_IS(subtypep, IfaceRefDType)) {
const AstIfaceRefDType* const ifacerefp = VN_AS(subtypep, IfaceRefDType); const AstIfaceRefDType* const ifacerefp = VN_AS(subtypep, IfaceRefDType);
if (!ifacerefp->cellp()) { if (!ifacerefp->cellp()) {
if (ioNames.find(oldvarp->name()) != ioNames.end()) { if (!ioNames.insert(oldvarp->name()).second) {
// UINFO(8, "Multitop dup interface found: " << oldvarp << endl); // UINFO(8, "Multitop dup interface found: " << oldvarp << endl);
dupNames.insert(oldvarp->name()); dupNames.insert(oldvarp->name());
} else {
ioNames.insert(oldvarp->name());
} }
} }
} }
@ -221,12 +217,10 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) {
const AstIfaceRefDType* const ifacerefp const AstIfaceRefDType* const ifacerefp
= VN_AS(arrsubtypep, IfaceRefDType); = VN_AS(arrsubtypep, IfaceRefDType);
if (!ifacerefp->cellp()) { if (!ifacerefp->cellp()) {
if (ioNames.find(oldvarp->name()) != ioNames.end()) { if (!ioNames.insert(oldvarp->name()).second) {
// UINFO(8, "Multitop dup interface array found: " << oldvarp // UINFO(8, "Multitop dup interface array found: " << oldvarp
// << endl); // << endl);
dupNames.insert(oldvarp->name()); dupNames.insert(oldvarp->name());
} else {
ioNames.insert(oldvarp->name());
} }
} }
} }

View File

@ -495,14 +495,9 @@ public:
V3List<OrderMoveVertex*>& readyVertices() { return m_readyVertices; } V3List<OrderMoveVertex*>& readyVertices() { return m_readyVertices; }
static OrderMoveDomScope* findCreate(const AstSenTree* domainp, const AstScope* scopep) { static OrderMoveDomScope* findCreate(const AstSenTree* domainp, const AstScope* scopep) {
const DomScopeKey key = std::make_pair(domainp, scopep); const DomScopeKey key = std::make_pair(domainp, scopep);
const auto iter = s_dsMap.find(key); const auto pair = s_dsMap.emplace(key, nullptr);
if (iter != s_dsMap.end()) { if (pair.second) pair.first->second = new OrderMoveDomScope{domainp, scopep};
return iter->second; return pair.first->second;
} else {
OrderMoveDomScope* domScopep = new OrderMoveDomScope{domainp, scopep};
s_dsMap.emplace(key, domScopep);
return domScopep;
}
} }
string name() const { string name() const {
return string{"MDS:"} + " d=" + cvtToHex(domainp()) + " s=" + cvtToHex(scopep()); return string{"MDS:"} + " d=" + cvtToHex(domainp()) + " s=" + cvtToHex(scopep());

View File

@ -356,27 +356,22 @@ class ParamProcessor final {
// cppcheck-has-bug-suppress unreadVariable // cppcheck-has-bug-suppress unreadVariable
if (VL_UNLIKELY(v3Global.opt.debugCollision())) hash = V3Hash{paramStr}; if (VL_UNLIKELY(v3Global.opt.debugCollision())) hash = V3Hash{paramStr};
int num; int num;
const auto it = m_valueMap.find(hash); const auto pair = m_valueMap.emplace(hash, 0);
if (it != m_valueMap.end()) { if (pair.second) pair.first->second = m_nextValue++;
num = it->second; num = pair.first->second;
} else {
num = m_nextValue++;
m_valueMap[hash] = num;
}
return std::string{"z"} + cvtToStr(num); return std::string{"z"} + cvtToStr(num);
} }
string moduleCalcName(const AstNodeModule* srcModp, const string& longname) { string moduleCalcName(const AstNodeModule* srcModp, const string& longname) {
string newname = longname; string newname = longname;
if (longname.length() > 30) { if (longname.length() > 30) {
const auto iter = m_longMap.find(longname); const auto pair = m_longMap.emplace(longname, "");
if (iter != m_longMap.end()) { if (pair.second) {
newname = iter->second;
} else {
newname = srcModp->name(); newname = srcModp->name();
// We use all upper case above, so lower here can't conflict // We use all upper case above, so lower here can't conflict
newname += "__pi" + cvtToStr(++m_longId); newname += "__pi" + cvtToStr(++m_longId);
m_longMap.emplace(longname, newname); pair.first->second = newname;
} }
newname = pair.first->second;
} }
UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl); UINFO(4, "Name: " << srcModp->name() << "->" << longname << "->" << newname << endl);
return newname; return newname;
@ -496,8 +491,9 @@ class ParamProcessor final {
} }
} }
auto paramsIt = m_defaultParameterValues.find(modp); const auto pair = m_defaultParameterValues.emplace(
if (paramsIt == m_defaultParameterValues.end()) { // Not cached yet, so check parameters std::piecewise_construct, std::forward_as_tuple(modp), std::forward_as_tuple());
if (pair.second) { // Not cached yet, so check parameters
// Using map with key=string so that we can scan it in deterministic order // Using map with key=string so that we can scan it in deterministic order
DefaultValueMap params; DefaultValueMap params;
for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
@ -511,8 +507,9 @@ class ParamProcessor final {
} }
} }
} }
paramsIt = m_defaultParameterValues.emplace(modp, std::move(params)).first; pair.first->second = std::move(params);
} }
const auto paramsIt = pair.first;
if (paramsIt->second.empty()) return modp->name(); // modp has no parameter if (paramsIt->second.empty()) return modp->name(); // modp has no parameter
string longname = modp->name(); string longname = modp->name();

View File

@ -93,10 +93,9 @@ public:
PartPtrIdMap() = default; PartPtrIdMap() = default;
// METHODS // METHODS
uint64_t findId(const void* ptrp) const { uint64_t findId(const void* ptrp) const {
const auto it = m_id.find(ptrp); const auto pair = m_id.emplace(ptrp, m_nextId);
if (it != m_id.end()) return it->second; if (pair.second) ++m_nextId;
m_id[ptrp] = m_nextId; return pair.first->second;
return m_nextId++;
} }
}; };

View File

@ -178,12 +178,13 @@ private:
const std::string type = AstCDType::typeToHold(items); const std::string type = AstCDType::typeToHold(items);
const std::string name = "VlRandC<" + type + ", " + cvtToStr(items) + "ULL>"; const std::string name = "VlRandC<" + type + ", " + cvtToStr(items) + "ULL>";
// Create or reuse (to avoid duplicates) randomization object dtype // Create or reuse (to avoid duplicates) randomization object dtype
auto it = m_randcDtypes.find(name); const auto pair = m_randcDtypes.emplace(name, nullptr);
if (it != m_randcDtypes.end()) return it->second; if (pair.second) {
AstCDType* newp = new AstCDType{fl, name}; AstCDType* newp = new AstCDType{fl, name};
v3Global.rootp()->typeTablep()->addTypesp(newp); v3Global.rootp()->typeTablep()->addTypesp(newp);
m_randcDtypes.emplace(name, newp); pair.first->second = newp;
return newp; }
return pair.first->second;
} }
AstVar* newRandcVarsp(AstVar* varp) { AstVar* newRandcVarsp(AstVar* varp) {

View File

@ -155,10 +155,9 @@ class SchedGraphBuilder final : public VNVisitor {
// rst), so we use a hash map to get the unique SchedSenVertex. (Note: This creates // rst), so we use a hash map to get the unique SchedSenVertex. (Note: This creates
// separate vertices for ET_CHANGED and ET_HYBRID over the same expression, but that is // separate vertices for ET_CHANGED and ET_HYBRID over the same expression, but that is
// OK for now). // OK for now).
auto it = m_senVertices.find(*senItemp); const auto pair = m_senVertices.emplace(*senItemp, nullptr);
// If it does not exist, create it // If it does not exist, create it
if (it == m_senVertices.end()) { if (pair.second) {
// Create the vertex // Create the vertex
SchedSenVertex* const vtxp = new SchedSenVertex{m_graphp, senItemp}; SchedSenVertex* const vtxp = new SchedSenVertex{m_graphp, senItemp};
@ -168,11 +167,11 @@ class SchedGraphBuilder final : public VNVisitor {
}); });
// Store back to hash map so we can find it next time // Store back to hash map so we can find it next time
it = m_senVertices.emplace(*senItemp, vtxp).first; pair.first->second = vtxp;
} }
// Cache sensitivity vertex // Cache sensitivity vertex
senItemp->user1p(it->second); senItemp->user1p(pair.first->second);
} }
return senItemp->user1u().to<SchedSenVertex*>(); return senItemp->user1u().to<SchedSenVertex*>();
} }

View File

@ -96,8 +96,8 @@ class SenExprBuilder final {
AstNode* scopeExprp = exprp; AstNode* scopeExprp = exprp;
if (AstVarRef* const refp = VN_CAST(exprp, VarRef)) scopeExprp = refp->varScopep(); if (AstVarRef* const refp = VN_CAST(exprp, VarRef)) scopeExprp = refp->varScopep();
// Create the 'previous value' variable // Create the 'previous value' variable
auto it = m_prev.find(*scopeExprp); const auto pair = m_prev.emplace(*scopeExprp, nullptr);
if (it == m_prev.end()) { if (pair.second) {
AstVarScope* prevp; AstVarScope* prevp;
if (m_scopep->isTop()) { if (m_scopep->isTop()) {
// For readability, use the scoped signal name if the trigger is a simple AstVarRef // For readability, use the scoped signal name if the trigger is a simple AstVarRef
@ -118,7 +118,7 @@ class SenExprBuilder final {
prevp = new AstVarScope{flp, m_scopep, varp}; prevp = new AstVarScope{flp, m_scopep, varp};
m_scopep->addVarsp(prevp); m_scopep->addVarsp(prevp);
} }
it = m_prev.emplace(*scopeExprp, prevp).first; pair.first->second = prevp;
// Add the initializer init // Add the initializer init
AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE}, AstAssign* const initp = new AstAssign{flp, new AstVarRef{flp, prevp, VAccess::WRITE},
@ -126,7 +126,7 @@ class SenExprBuilder final {
m_inits.push_back(initp); m_inits.push_back(initp);
} }
AstVarScope* const prevp = it->second; AstVarScope* const prevp = pair.first->second;
const auto wrPrev = [=]() { return new AstVarRef{flp, prevp, VAccess::WRITE}; }; const auto wrPrev = [=]() { return new AstVarRef{flp, prevp, VAccess::WRITE}; };

View File

@ -310,7 +310,7 @@ private:
UASSERT_OBJ(varp->attrSplitVar(), varp, " no split_var metacomment"); UASSERT_OBJ(varp->attrSplitVar(), varp, " no split_var metacomment");
const MapIt it = m_map.find(varp); const MapIt it = m_map.find(varp);
if (it == m_map.end()) return false; // Not registered if (it == m_map.end()) return false; // Not registered
const bool ok = m_map[varp].insert(ref).second; const bool ok = it->second.insert(ref).second;
return ok; return ok;
} }

View File

@ -71,12 +71,10 @@ public:
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix; if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
os << " n=" << nodep(); os << " n=" << nodep();
os << '\n'; os << '\n';
if (VL_UNCOVERABLE(doneSymsr.find(this) != doneSymsr.end())) { if (VL_UNCOVERABLE(!doneSymsr.insert(this).second)) {
os << indent << "| ^ duplicate, so no children printed\n"; // LCOV_EXCL_LINE os << indent << "| ^ duplicate, so no children printed\n"; // LCOV_EXCL_LINE
} else { } else {
doneSymsr.insert(this); for (auto it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end();
++it) {
if (numLevels >= 1) { if (numLevels >= 1) {
it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1, it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
it->first); it->first);

View File

@ -85,10 +85,8 @@ public:
// METHODS // METHODS
void addVertex(const T_Key& key) { void addVertex(const T_Key& key) {
const auto itr = m_vertices.find(key); const bool newEntry = m_vertices.emplace(key, new Vertex{this, key}).second;
UASSERT(itr == m_vertices.end(), "Vertex already exists with same key"); UASSERT(newEntry, "Vertex already exists with same key");
Vertex* v = new Vertex{this, key};
m_vertices[key] = v;
} }
// For purposes of TSP, we are using non-directional graphs. // For purposes of TSP, we are using non-directional graphs.

View File

@ -971,19 +971,21 @@ private:
// Only create one DPI Import prototype or DPI Export entry point for each unique cname as // Only create one DPI Import prototype or DPI Export entry point for each unique cname as
// it is illegal for the user to attach multiple tasks with different signatures to one DPI // it is illegal for the user to attach multiple tasks with different signatures to one DPI
// cname. // cname.
const auto it = m_dpiNames.find(nodep->cname()); const auto pair = m_dpiNames.emplace(std::piecewise_construct, //
if (it == m_dpiNames.end()) { std::forward_as_tuple(nodep->cname()),
std::forward_as_tuple(nodep, signature, nullptr));
if (pair.second) {
// First time encountering this cname. Create Import prototype / Export entry point // First time encountering this cname. Create Import prototype / Export entry point
AstCFunc* const funcp = nodep->dpiExport() ? makeDpiExportDispatcher(nodep, rtnvarp) AstCFunc* const funcp = nodep->dpiExport() ? makeDpiExportDispatcher(nodep, rtnvarp)
: makeDpiImportPrototype(nodep, rtnvarp); : makeDpiImportPrototype(nodep, rtnvarp);
m_dpiNames.emplace(nodep->cname(), std::make_tuple(nodep, signature, funcp)); std::get<2>(pair.first->second) = funcp;
return funcp; return funcp;
} else { } else {
// Seen this cname import before. Check if it's the same prototype. // Seen this cname import before. Check if it's the same prototype.
const AstNodeFTask* firstNodep; const AstNodeFTask* firstNodep;
string firstSignature; string firstSignature;
AstCFunc* firstFuncp; AstCFunc* firstFuncp;
std::tie(firstNodep, firstSignature, firstFuncp) = it->second; std::tie(firstNodep, firstSignature, firstFuncp) = pair.first->second;
if (signature != firstSignature) { if (signature != firstSignature) {
// Different signature, so error. // Different signature, so error.
nodep->v3error("Duplicate declaration of DPI function with different signature: '" nodep->v3error("Duplicate declaration of DPI function with different signature: '"
@ -1779,16 +1781,13 @@ void V3Task::taskConnectWrap(AstNodeFTaskRef* nodep, const V3TaskConnects& tconn
// Make wrapper name such that is same iff same args are defaulted // Make wrapper name such that is same iff same args are defaulted
std::string newname = nodep->name() + "__Vtcwrap"; std::string newname = nodep->name() + "__Vtcwrap";
for (const AstVar* varp : argWrap) newname += "_" + cvtToStr(varp->pinNum()); for (const AstVar* varp : argWrap) newname += "_" + cvtToStr(varp->pinNum());
const auto namekey = std::make_pair(nodep->taskp(), newname); const auto pair = statep->wrapMap().emplace(std::piecewise_construct,
auto& wrapMapr = statep->wrapMap(); std::forward_as_tuple(nodep->taskp(), newname),
const auto it = wrapMapr.find(namekey); std::forward_as_tuple(nullptr));
AstNodeFTask* newTaskp; if (pair.second) {
if (it != wrapMapr.end()) { pair.first->second = taskConnectWrapNew(nodep->taskp(), newname, tconnects, argWrap);
newTaskp = it->second;
} else {
newTaskp = taskConnectWrapNew(nodep->taskp(), newname, tconnects, argWrap);
wrapMapr.emplace(namekey, newTaskp);
} }
AstNodeFTask* const newTaskp = pair.first->second;
// Remove the defaulted arguments from original outside call // Remove the defaulted arguments from original outside call
for (const auto& tconnect : tconnects) { for (const auto& tconnect : tconnects) {

View File

@ -549,16 +549,11 @@ class TristateVisitor final : public TristateBaseVisitor {
} }
void mapInsertLhsVarRef(AstVarRef* nodep) { void mapInsertLhsVarRef(AstVarRef* nodep) {
AstVar* const key = nodep->varp();
const auto it = m_lhsmap.find(key);
UINFO(9, " mapInsertLhsVarRef " << nodep << endl); UINFO(9, " mapInsertLhsVarRef " << nodep << endl);
if (it == m_lhsmap.end()) { // Not found AstVar* const key = nodep->varp();
RefStrengthVec* const refsp = new RefStrengthVec; const auto pair = m_lhsmap.emplace(key, nullptr);
refsp->push_back(RefStrength{nodep, m_currentStrength}); if (pair.second) pair.first->second = new RefStrengthVec;
m_lhsmap.emplace(key, refsp); pair.first->second->push_back(RefStrength{nodep, m_currentStrength});
} else {
it->second->push_back(RefStrength{nodep, m_currentStrength});
}
} }
AstNodeExpr* newEnableDeposit(AstSel* selp, AstNodeExpr* enp) { AstNodeExpr* newEnableDeposit(AstSel* selp, AstNodeExpr* enp) {

View File

@ -2296,15 +2296,14 @@ private:
} }
num.opAssign(constp->num()); num.opAssign(constp->num());
// Look for duplicates // Look for duplicates
if (inits.find(num) != inits.end()) { // IEEE says illegal const auto pair = inits.emplace(num, itemp);
const AstNode* const otherp = inits.find(num)->second; if (!pair.second) { // IEEE says illegal
const AstNode* const otherp = pair.first->second;
itemp->v3error("Overlapping enumeration value: " itemp->v3error("Overlapping enumeration value: "
<< itemp->prettyNameQ() << '\n' << itemp->prettyNameQ() << '\n'
<< itemp->warnContextPrimary() << '\n' << itemp->warnContextPrimary() << '\n'
<< otherp->warnOther() << "... Location of original declaration\n" << otherp->warnOther() << "... Location of original declaration\n"
<< otherp->warnContextSecondary()); << otherp->warnContextSecondary());
} else {
inits.emplace(num, itemp);
} }
num.opAdd(one, constp->num()); num.opAdd(one, constp->num());
} }
@ -3985,12 +3984,10 @@ private:
= VN_CAST(patp->keyp(), NodeDType)) { = VN_CAST(patp->keyp(), NodeDType)) {
// data_type: default_value // data_type: default_value
const string dtype = nodedtypep->dtypep()->prettyDTypeName(); const string dtype = nodedtypep->dtypep()->prettyDTypeName();
auto it = dtypemap.find(dtype); const auto pair = dtypemap.emplace(dtype, patp);
if (it == dtypemap.end()) { if (!pair.second) {
dtypemap.emplace(dtype, patp);
} else {
// Override stored default_value // Override stored default_value
it->second = patp->cloneTree(false); pair.first->second = patp->cloneTree(false);
} }
} else { } else {
// Undefined pattern // Undefined pattern
@ -7192,30 +7189,33 @@ private:
} }
AstVar* dimensionVarp(AstNodeDType* nodep, VAttrType attrType, uint32_t msbdim) { AstVar* dimensionVarp(AstNodeDType* nodep, VAttrType attrType, uint32_t msbdim) {
// Return a variable table which has specified dimension properties for this variable // Return a variable table which has specified dimension properties for this variable
const auto pos = m_tableMap.find(std::make_pair(nodep, attrType)); const auto pair = m_tableMap.emplace(std::piecewise_construct, //
if (pos != m_tableMap.end()) return pos->second; std::forward_as_tuple(nodep, attrType),
AstNodeArrayDType* const vardtypep std::forward_as_tuple(nullptr));
= new AstUnpackArrayDType{nodep->fileline(), nodep->findSigned32DType(), if (pair.second) {
new AstRange(nodep->fileline(), msbdim, 0)}; AstNodeArrayDType* const vardtypep
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr}; = new AstUnpackArrayDType{nodep->fileline(), nodep->findSigned32DType(),
v3Global.rootp()->typeTablep()->addTypesp(vardtypep); new AstRange(nodep->fileline(), msbdim, 0)};
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
"__Vdimtab_" + VString::downcase(attrType.ascii()) v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
+ cvtToStr(m_dtTables++), AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
vardtypep}; "__Vdimtab_" + VString::downcase(attrType.ascii())
varp->isConst(true); + cvtToStr(m_dtTables++),
varp->isStatic(true); vardtypep};
varp->valuep(initp); varp->isConst(true);
// Add to root, as don't know module we are in, and aids later structure sharing varp->isStatic(true);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp); varp->valuep(initp);
// Element 0 is a non-index and has speced values // Add to root, as don't know module we are in, and aids later structure sharing
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0)); v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
for (unsigned i = 1; i < msbdim + 1; ++i) { // Element 0 is a non-index and has speced values
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i)); initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, 0));
for (unsigned i = 1; i < msbdim + 1; ++i) {
initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i));
}
userIterate(varp, nullptr); // May have already done $unit so must do this var
pair.first->second = varp;
} }
userIterate(varp, nullptr); // May have already done $unit so must do this var return pair.first->second;
m_tableMap.emplace(std::make_pair(nodep, attrType), varp);
return varp;
} }
uint64_t enumMaxValue(const AstNode* errNodep, const AstEnumDType* adtypep) { uint64_t enumMaxValue(const AstNode* errNodep, const AstEnumDType* adtypep) {
// Most enums unless overridden are 32 bits, so we size array // Most enums unless overridden are 32 bits, so we size array
@ -7237,94 +7237,97 @@ private:
} }
return maxval; return maxval;
} }
AstVar* enumVarp(AstEnumDType* nodep, VAttrType attrType, bool assoc, uint32_t msbdim) { AstVar* enumVarp(AstEnumDType* const nodep, VAttrType attrType, bool assoc, uint32_t msbdim) {
// Return a variable table which has specified dimension properties for this variable // Return a variable table which has specified dimension properties for this variable
const auto& tableMapr = nodep->tableMap(); const auto pair = nodep->tableMap().emplace(attrType, nullptr);
const auto pos = tableMapr.find(attrType); if (pair.second) {
if (pos != tableMapr.end()) return pos->second; UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " assoc=" << assoc
UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " assoc=" << assoc << " max=" << msbdim << " for " << nodep << endl);
<< " max=" << msbdim << " for " << nodep << endl); AstNodeDType* basep;
AstNodeDType* basep; if (attrType == VAttrType::ENUM_NAME) {
if (attrType == VAttrType::ENUM_NAME) { basep = nodep->findStringDType();
basep = nodep->findStringDType(); } else if (attrType == VAttrType::ENUM_VALID) {
} else if (attrType == VAttrType::ENUM_VALID) { // TODO in theory we could bit-pack the bits in the table, but
// TODO in theory we could bit-pack the bits in the table, but // would require additional operations to extract, so only
// would require additional operations to extract, so only // would be worth it for larger tables which perhaps could be
// would be worth it for larger tables which perhaps could be // better handled with equation generation?
// better handled with equation generation? basep = nodep->findBitDType();
basep = nodep->findBitDType(); } else {
} else { basep = nodep->dtypep();
basep = nodep->dtypep(); }
} AstNodeDType* vardtypep;
AstNodeDType* vardtypep; if (assoc) {
if (assoc) { vardtypep = new AstAssocArrayDType{nodep->fileline(), basep, nodep};
vardtypep = new AstAssocArrayDType{nodep->fileline(), basep, nodep}; } else {
} else { vardtypep = new AstUnpackArrayDType{nodep->fileline(), basep,
vardtypep = new AstUnpackArrayDType{nodep->fileline(), basep, new AstRange(nodep->fileline(), msbdim, 0)};
new AstRange(nodep->fileline(), msbdim, 0)}; }
} AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr};
AstInitArray* const initp = new AstInitArray{nodep->fileline(), vardtypep, nullptr}; v3Global.rootp()->typeTablep()->addTypesp(vardtypep);
v3Global.rootp()->typeTablep()->addTypesp(vardtypep); AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__Venumtab_" + VString::downcase(attrType.ascii())
"__Venumtab_" + VString::downcase(attrType.ascii()) + cvtToStr(m_dtTables++),
+ cvtToStr(m_dtTables++), vardtypep};
vardtypep}; varp->lifetime(VLifetime::STATIC);
varp->lifetime(VLifetime::STATIC); varp->isConst(true);
varp->isConst(true); varp->isStatic(true);
varp->isStatic(true); varp->valuep(initp);
varp->valuep(initp); // Add to root, as don't know module we are in, and aids later structure sharing
// Add to root, as don't know module we are in, and aids later structure sharing v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(varp);
// Default for all unspecified values // Default for all unspecified values
if (attrType == VAttrType::ENUM_NAME) { if (attrType == VAttrType::ENUM_NAME) {
initp->defaultp(new AstConst{nodep->fileline(), AstConst::String{}, ""}); initp->defaultp(new AstConst{nodep->fileline(), AstConst::String{}, ""});
} else if (attrType == VAttrType::ENUM_NEXT || attrType == VAttrType::ENUM_PREV) { } else if (attrType == VAttrType::ENUM_NEXT || attrType == VAttrType::ENUM_PREV) {
initp->defaultp(new AstConst{nodep->fileline(), V3Number{nodep, nodep->width(), 0}}); initp->defaultp(
} else if (attrType == VAttrType::ENUM_VALID) { new AstConst{nodep->fileline(), V3Number{nodep, nodep->width(), 0}});
initp->defaultp(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); } else if (attrType == VAttrType::ENUM_VALID) {
} else { initp->defaultp(new AstConst{nodep->fileline(), AstConst::BitFalse{}});
nodep->v3fatalSrc("Bad case"); } else {
} nodep->v3fatalSrc("Bad case");
}
// Find valid values and populate // Find valid values and populate
UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items"); UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items");
std::map<uint64_t, AstNodeExpr*> values; std::map<uint64_t, AstNodeExpr*> values;
{ {
AstEnumItem* const firstp = nodep->itemsp(); AstEnumItem* const firstp = nodep->itemsp();
const AstEnumItem* prevp = firstp; // Prev must start with last item const AstEnumItem* prevp = firstp; // Prev must start with last item
while (prevp->nextp()) prevp = VN_AS(prevp->nextp(), EnumItem); while (prevp->nextp()) prevp = VN_AS(prevp->nextp(), EnumItem);
for (AstEnumItem* itemp = firstp; itemp;) { for (AstEnumItem* itemp = firstp; itemp;) {
AstEnumItem* const nextp = VN_AS(itemp->nextp(), EnumItem); AstEnumItem* const nextp = VN_AS(itemp->nextp(), EnumItem);
const AstConst* const vconstp = VN_AS(itemp->valuep(), Const); const AstConst* const vconstp = VN_AS(itemp->valuep(), Const);
UASSERT_OBJ(vconstp, nodep, "Enum item without constified value"); UASSERT_OBJ(vconstp, nodep, "Enum item without constified value");
const uint64_t i = vconstp->toUQuad(); const uint64_t i = vconstp->toUQuad();
if (attrType == VAttrType::ENUM_NAME) { if (attrType == VAttrType::ENUM_NAME) {
values[i] = new AstConst{nodep->fileline(), AstConst::String{}, itemp->name()}; values[i]
} else if (attrType == VAttrType::ENUM_NEXT) { = new AstConst{nodep->fileline(), AstConst::String{}, itemp->name()};
values[i] = (nextp ? nextp : firstp)->valuep()->cloneTree(false); // A const } else if (attrType == VAttrType::ENUM_NEXT) {
} else if (attrType == VAttrType::ENUM_PREV) { values[i]
values[i] = prevp->valuep()->cloneTree(false); // A const = (nextp ? nextp : firstp)->valuep()->cloneTree(false); // A const
} else if (attrType == VAttrType::ENUM_VALID) { } else if (attrType == VAttrType::ENUM_PREV) {
values[i] = new AstConst{nodep->fileline(), AstConst::BitTrue{}}; values[i] = prevp->valuep()->cloneTree(false); // A const
} else { } else if (attrType == VAttrType::ENUM_VALID) {
nodep->v3fatalSrc("Bad case"); values[i] = new AstConst{nodep->fileline(), AstConst::BitTrue{}};
} else {
nodep->v3fatalSrc("Bad case");
}
prevp = itemp;
itemp = nextp;
} }
prevp = itemp;
itemp = nextp;
} }
} // Add all specified values to table
// Add all specified values to table if (assoc) {
if (assoc) { for (const auto& itr : values) initp->addIndexValuep(itr.first, itr.second);
for (const auto& itr : values) initp->addIndexValuep(itr.first, itr.second); } else {
} else { for (uint64_t i = 0; i < (msbdim + 1); ++i) {
for (uint64_t i = 0; i < (msbdim + 1); ++i) { if (values[i]) initp->addIndexValuep(i, values[i]);
if (values[i]) initp->addIndexValuep(i, values[i]); }
} }
userIterate(varp, nullptr); // May have already done $unit so must do this var
pair.first->second = varp;
} }
userIterate(varp, nullptr); // May have already done $unit so must do this var return pair.first->second;
nodep->tableMap().emplace(attrType, varp);
return varp;
} }
PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) { PatVecMap patVectorMap(AstPattern* nodep, const VNumRange& range) {
@ -7340,10 +7343,9 @@ private:
<< patp->keyp()->prettyTypeName()); << patp->keyp()->prettyTypeName());
} }
} }
if (patmap.find(element) != patmap.end()) { const bool newEntry = patmap.emplace(element, patp).second;
if (!newEntry) {
patp->v3error("Assignment pattern key used multiple times: " << element); patp->v3error("Assignment pattern key used multiple times: " << element);
} else {
patmap.emplace(element, patp);
} }
element += range.leftToRightInc(); element += range.leftToRightInc();
} }

View File

@ -139,18 +139,10 @@ public:
} }
VlcPoint& pointNumber(uint64_t num) { return m_points[num]; } VlcPoint& pointNumber(uint64_t num) { return m_points[num]; }
uint64_t findAddPoint(const string& name, uint64_t count) { uint64_t findAddPoint(const string& name, uint64_t count) {
uint64_t pointnum; const auto pair = m_nameMap.emplace(name, m_numPoints);
const auto iter = m_nameMap.find(name); if (pair.second) m_points.emplace_back(name, m_numPoints++);
if (iter != m_nameMap.end()) { const uint64_t pointnum = pair.first->second;
pointnum = iter->second; m_points[pointnum].countInc(count);
m_points[pointnum].countInc(count);
} else {
pointnum = m_numPoints++;
VlcPoint point{name, pointnum};
point.countInc(count);
m_points.push_back(point);
m_nameMap.emplace(point.name(), point.pointNum());
}
return pointnum; return pointnum;
} }
}; };

View File

@ -36,7 +36,7 @@ private:
using PointsSet = std::set<const VlcPoint*>; using PointsSet = std::set<const VlcPoint*>;
// MEMBERS // MEMBERS
int m_lineno; ///< Line number const int m_lineno; ///< Line number
uint64_t m_count = 0; ///< Count uint64_t m_count = 0; ///< Count
bool m_ok = false; ///< Coverage is above threshold bool m_ok = false; ///< Coverage is above threshold
PointsSet m_points; // Points on this line PointsSet m_points; // Points on this line
@ -94,9 +94,7 @@ public:
// METHODS // METHODS
void lineIncCount(int lineno, uint64_t count, bool ok, const VlcPoint* pointp) { void lineIncCount(int lineno, uint64_t count, bool ok, const VlcPoint* pointp) {
auto lit = m_lines.find(lineno); VlcSourceCount& sc = m_lines.emplace(lineno, lineno).first->second;
if (lit == m_lines.end()) lit = m_lines.emplace(lineno, VlcSourceCount{lineno}).first;
VlcSourceCount& sc = lit->second;
sc.incCount(count, ok); sc.incCount(count, ok);
sc.insertPoint(pointp); sc.insertPoint(pointp);
} }