Skip to content

Commit 6dbc155

Browse files
committed
merge_irept: insert once and then const_cast to edit in place
This avoids multiple lookups in the hash set, each of which requires a number of operator== and hash() calls. The use of const_cast is acceptable, because we do not actually change the object in a way that would affect ordering (objects will continue to have the same hash value and still compare equal).
1 parent e78dc6f commit 6dbc155

File tree

1 file changed

+26
-29
lines changed

1 file changed

+26
-29
lines changed

src/util/merge_irep.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -145,49 +145,46 @@ void merge_irept::operator()(irept &irep)
145145

146146
const irept &merge_irept::merged(const irept &irep)
147147
{
148-
if(irep.get_sub().empty() && irep.get_named_sub().empty())
149-
return *irep_store.insert(irep).first;
150-
151-
irep_storet::const_iterator entry=irep_store.find(irep);
152-
if(entry!=irep_store.end())
153-
return *entry;
154-
155-
bool same_irep = true;
156-
irept new_irep(irep.id());
148+
auto entry = irep_store.insert(irep);
149+
if(!entry.second)
150+
return *entry.first;
157151

158152
const irept::subt &src_sub=irep.get_sub();
159-
irept::subt &dest_sub=new_irep.get_sub();
160-
dest_sub.reserve(src_sub.size());
153+
irept::subt *dest_sub_ptr = nullptr;
161154

155+
std::size_t index = 0;
162156
forall_irep(it, src_sub)
163157
{
164158
const irept &op = merged(*it); // recursive call
165-
same_irep &= &op.read() == &(it->read());
166-
dest_sub.push_back(op);
159+
if(&op.read() != &(it->read()))
160+
{
161+
if(!dest_sub_ptr)
162+
dest_sub_ptr = &(const_cast<irept &>(*entry.first)).get_sub();
163+
(*dest_sub_ptr)[index] = op;
164+
}
165+
++index;
167166
}
168167

169168
const irept::named_subt &src_named_sub=irep.get_named_sub();
170-
irept::named_subt &dest_named_sub=new_irep.get_named_sub();
169+
irept::named_subt *dest_named_sub_ptr = nullptr;
171170

172-
#ifdef NAMED_SUB_IS_FORWARD_LIST
173-
irept::named_subt::iterator before = dest_named_sub.before_begin();
174-
#endif
171+
std::ptrdiff_t advance_by = 0;
175172
forall_named_irep(it, src_named_sub)
176173
{
177-
const irept &op = merged(it->second); // recursive call
178-
same_irep &= &op.read() == &(it->second.read());
179-
#ifdef NAMED_SUB_IS_FORWARD_LIST
180-
dest_named_sub.emplace_after(before, it->first, op);
181-
++before;
182-
#else
183-
dest_named_sub.emplace(it->first, op);
184-
#endif
174+
if(!irept::is_comment(it->first))
175+
{
176+
const irept &op = merged(it->second); // recursive call
177+
if(&op.read() != &(it->second.read()))
178+
{
179+
if(!dest_named_sub_ptr)
180+
dest_named_sub_ptr = &(const_cast<irept &>(*entry.first)).get_named_sub();
181+
std::next(dest_named_sub_ptr->begin(), advance_by)->second = op;
182+
}
183+
}
184+
++advance_by;
185185
}
186186

187-
if(same_irep)
188-
return *irep_store.insert(irep).first;
189-
else
190-
return *irep_store.insert(std::move(new_irep)).first;
187+
return *entry.first;
191188
}
192189

193190
void merge_full_irept::operator()(irept &irep)

0 commit comments

Comments
 (0)