Skip to content

Commit 68ef907

Browse files
committed
irept: Use singly-linked lists with SUB_IS_LIST
This reduces the memory footprint by two pointers for both named_sub and comments. The cost is that computing the size of lists and add/remove require additional iterator increments.
1 parent d2e2802 commit 68ef907

File tree

6 files changed

+165
-41
lines changed

6 files changed

+165
-41
lines changed

src/util/irep.cpp

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,21 @@ void irept::nonrecursive_destructor(dt *old_data)
151151
INVARIANT(d->ref_count!=0, "All contents of the stack must be in use");
152152
d->ref_count--;
153153

154+
#ifdef SUB_IS_LIST
155+
const std::size_t named_sub_size =
156+
std::distance(d->named_sub.begin(), d->named_sub.end());
157+
const std::size_t comments_size =
158+
std::distance(d->comments.begin(), d->comments.end());
159+
#else
160+
const std::size_t named_sub_size = d->named_sub.size();
161+
const std::size_t comments_size = d->comments.size();
162+
#endif
163+
154164
if(d->ref_count==0)
155165
{
156166
stack.reserve(stack.size()+
157-
d->named_sub.size()+
158-
d->comments.size()+
167+
named_sub_size +
168+
comments_size +
159169
d->sub.size());
160170

161171
for(named_subt::iterator
@@ -276,7 +286,11 @@ void irept::remove(const irep_namet &name)
276286
named_subt::iterator it=named_subt_lower_bound(s, name);
277287

278288
if(it!=s.end() && it->first==name)
279-
s.erase(it);
289+
{
290+
named_subt::iterator before = s.before_begin();
291+
while(std::next(before) != it) ++before;
292+
s.erase_after(before);
293+
}
280294
#else
281295
s.erase(name);
282296
#endif
@@ -313,7 +327,11 @@ irept &irept::add(const irep_namet &name)
313327

314328
if(it==s.end() ||
315329
it->first!=name)
316-
it=s.insert(it, std::make_pair(name, irept()));
330+
{
331+
named_subt::iterator before = s.before_begin();
332+
while(std::next(before) != it) ++before;
333+
it = s.emplace_after(before, name, irept());
334+
}
317335

318336
return it->second;
319337
#else
@@ -331,7 +349,11 @@ irept &irept::add(const irep_namet &name, const irept &irep)
331349

332350
if(it==s.end() ||
333351
it->first!=name)
334-
it=s.insert(it, std::make_pair(name, irep));
352+
{
353+
named_subt::iterator before = s.before_begin();
354+
while(std::next(before) != it) ++before;
355+
it = s.emplace_after(before, name, irep);
356+
}
335357
else
336358
it->second=irep;
337359

@@ -394,10 +416,20 @@ bool irept::full_eq(const irept &other) const
394416
const irept::named_subt &i1_comments=get_comments();
395417
const irept::named_subt &i2_comments=other.get_comments();
396418

419+
#ifdef SUB_IS_LIST
420+
if(
421+
i1_sub.size() != i2_sub.size() ||
422+
std::distance(i1_named_sub.begin(), i1_named_sub.end()) !=
423+
std::distance(i2_named_sub.begin(), i2_named_sub.end()) ||
424+
std::distance(i1_comments.begin(), i1_comments.end()) !=
425+
std::distance(i2_comments.begin(), i2_comments.end()))
426+
return false;
427+
#else
397428
if(i1_sub.size()!=i2_sub.size() ||
398429
i1_named_sub.size()!=i2_named_sub.size() ||
399430
i1_comments.size()!=i2_comments.size())
400431
return false;
432+
#endif
401433

402434
for(std::size_t i=0; i<i1_sub.size(); i++)
403435
if(!i1_sub[i].full_eq(i2_sub[i]))
@@ -528,8 +560,15 @@ int irept::compare(const irept &i) const
528560
"Unequal lengths will return before this");
529561
}
530562

563+
#ifdef SUB_IS_LIST
564+
const named_subt::size_type n_size =
565+
std::distance(get_named_sub().begin(), get_named_sub().end());
566+
const named_subt::size_type i_n_size =
567+
std::distance(i.get_named_sub().begin(), i.get_named_sub().end());
568+
#else
531569
const named_subt::size_type n_size=get_named_sub().size(),
532570
i_n_size=i.get_named_sub().size();
571+
#endif
533572
if(n_size<i_n_size)
534573
return -1;
535574
if(n_size>i_n_size)
@@ -592,7 +631,13 @@ std::size_t irept::hash() const
592631
result=hash_combine(result, it->second.hash());
593632
}
594633

595-
result=hash_finalize(result, named_sub.size()+sub.size());
634+
#ifdef SUB_IS_LIST
635+
const std::size_t named_sub_size =
636+
std::distance(named_sub.begin(), named_sub.end());
637+
#else
638+
const std::size_t named_sub_size = named_sub.size();
639+
#endif
640+
result = hash_finalize(result, named_sub_size + sub.size());
596641

597642
#ifdef HASH_CODE
598643
read().hash_code=result;
@@ -625,9 +670,16 @@ std::size_t irept::full_hash() const
625670
result=hash_combine(result, it->second.full_hash());
626671
}
627672

628-
result=hash_finalize(
629-
result,
630-
named_sub.size()+sub.size()+comments.size());
673+
#ifdef SUB_IS_LIST
674+
const std::size_t named_sub_size =
675+
std::distance(named_sub.begin(), named_sub.end());
676+
const std::size_t comments_size =
677+
std::distance(comments.begin(), comments.end());
678+
#else
679+
const std::size_t named_sub_size = named_sub.size();
680+
const std::size_t comments_size = comments.size();
681+
#endif
682+
result = hash_finalize(result, named_sub_size + sub.size() + comments_size);
631683

632684
return result;
633685
}

src/util/irep.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Author: Daniel Kroening, [email protected]
2323
// #define SUB_IS_LIST
2424

2525
#ifdef SUB_IS_LIST
26-
#include <list>
26+
#include <forward_list>
2727
#else
2828
#include <map>
2929
#endif
@@ -95,7 +95,7 @@ class irept
9595
// memory and increase efficiency.
9696

9797
#ifdef SUB_IS_LIST
98-
typedef std::list<std::pair<irep_namet, irept> > named_subt;
98+
typedef std::forward_list<std::pair<irep_namet, irept> > named_subt;
9999
#else
100100
typedef std::map<irep_namet, irept> named_subt;
101101
#endif

src/util/irep_hash_container.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,24 @@ void irep_hash_container_baset::pack(
4949
const irept::named_subt &named_sub=irep.get_named_sub();
5050
const irept::named_subt &comments=irep.get_comments();
5151

52-
packed.reserve(
53-
1+1+sub.size()+named_sub.size()*2+
54-
(full?comments.size()*2:0));
52+
#ifdef SUB_IS_LIST
53+
const std::size_t named_sub_size =
54+
std::distance(named_sub.begin(), named_sub.end());
55+
const std::size_t comments_size = full ?
56+
std::distance(comments.begin(), comments.end()) : 0;
57+
#else
58+
const std::size_t named_sub_size = named_sub.size();
59+
const std::size_t comments_size = full ? comments.size() : 0;
60+
#endif
61+
packed.reserve(1 + 1 + sub.size() + named_sub_size * 2 + comments_size * 2);
5562

5663
packed.push_back(irep_id_hash()(irep.id()));
5764

5865
packed.push_back(sub.size());
5966
forall_irep(it, sub)
6067
packed.push_back(number(*it));
6168

62-
packed.push_back(named_sub.size());
69+
packed.push_back(named_sub_size);
6370
forall_named_irep(it, named_sub)
6471
{
6572
packed.push_back(irep_id_hash()(it->first)); // id
@@ -68,7 +75,7 @@ void irep_hash_container_baset::pack(
6875

6976
if(full)
7077
{
71-
packed.push_back(comments.size());
78+
packed.push_back(comments_size);
7279
forall_named_irep(it, comments)
7380
{
7481
packed.push_back(irep_id_hash()(it->first)); // id

src/util/lispirep.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,17 @@ void irep2lisp(const irept &src, lispexprt &dest)
4646
dest.value="";
4747
dest.type=lispexprt::List;
4848

49-
dest.reserve(2+2*src.get_sub().size()
50-
+2*src.get_named_sub().size()
51-
+2*src.get_comments().size());
49+
#ifdef SUB_IS_LIST
50+
const std::size_t named_sub_size =
51+
std::distance(src.get_named_sub().begin(), src.get_named_sub().end());
52+
const std::size_t comments_size =
53+
std::distance(src.get_comments().begin(), src.get_comments().end());
54+
#else
55+
const std::size_t named_sub_size = src.get_named_sub().size();
56+
const std::size_t comments_size = src.get_comments().size();
57+
#endif
58+
dest.reserve(
59+
2 + 2 * src.get_sub().size() + 2 * named_sub_size + 2 * comments_size);
5260

5361
lispexprt id;
5462
id.type=lispexprt::String;

src/util/merge_irep.cpp

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,13 @@ std::size_t to_be_merged_irept::hash() const
2828
result, static_cast<const merged_irept &>(it->second).hash());
2929
}
3030

31-
result=hash_finalize(result, named_sub.size()+sub.size());
31+
#ifdef SUB_IS_LIST
32+
const std::size_t named_sub_size =
33+
std::distance(named_sub.begin(), named_sub.end());
34+
#else
35+
const std::size_t named_sub_size = named_sub.size();
36+
#endif
37+
result = hash_finalize(result, named_sub_size + sub.size());
3238

3339
return result;
3440
}
@@ -44,9 +50,16 @@ bool to_be_merged_irept::operator == (const to_be_merged_irept &other) const
4450
const irept::named_subt &o_named_sub=other.get_named_sub();
4551

4652
if(sub.size()!=o_sub.size())
47-
return true;
53+
return false;
54+
#ifdef SUB_IS_LIST
55+
if(
56+
std::distance(named_sub.begin(), named_sub.end()) !=
57+
std::distance(o_named_sub.begin(), o_named_sub.end()))
58+
return false;
59+
#else
4860
if(named_sub.size()!=o_named_sub.size())
49-
return true;
61+
return false;
62+
#endif
5063

5164
{
5265
irept::subt::const_iterator s_it=sub.begin();
@@ -95,13 +108,19 @@ const merged_irept &merged_irepst::merged(const irept &irep)
95108
const irept::named_subt &src_named_sub=irep.get_named_sub();
96109
irept::named_subt &dest_named_sub=new_irep.get_named_sub();
97110

111+
#ifdef SUB_IS_LIST
112+
irept::named_subt::iterator before = dest_named_sub.before_begin();
113+
#endif
98114
forall_named_irep(it, src_named_sub)
115+
{
99116
#ifdef SUB_IS_LIST
100-
dest_named_sub.push_back(
101-
std::make_pair(it->first, merged(it->second))); // recursive call
117+
dest_named_sub.emplace_after(
118+
before, it->first, merged(it->second)); // recursive call
119+
++before;
102120
#else
103121
dest_named_sub[it->first]=merged(it->second); // recursive call
104122
#endif
123+
}
105124

106125
std::pair<to_be_merged_irep_storet::const_iterator, bool> result=
107126
to_be_merged_irep_store.insert(to_be_merged_irept(new_irep));
@@ -140,24 +159,36 @@ const irept &merge_irept::merged(const irept &irep)
140159
const irept::named_subt &src_named_sub=irep.get_named_sub();
141160
irept::named_subt &dest_named_sub=new_irep.get_named_sub();
142161

162+
#ifdef SUB_IS_LIST
163+
irept::named_subt::iterator before = dest_named_sub.before_begin();
164+
#endif
143165
forall_named_irep(it, src_named_sub)
166+
{
144167
#ifdef SUB_IS_LIST
145-
dest_named_sub.push_back(
146-
std::make_pair(it->first, merged(it->second))); // recursive call
168+
dest_named_sub.emplace_after(
169+
before, it->first, merged(it->second)); // recursive call
170+
++before;
147171
#else
148172
dest_named_sub[it->first]=merged(it->second); // recursive call
149173
#endif
174+
}
150175

151176
const irept::named_subt &src_comments=irep.get_comments();
152177
irept::named_subt &dest_comments=new_irep.get_comments();
153178

179+
#ifdef SUB_IS_LIST
180+
before = dest_comments.before_begin();
181+
#endif
154182
forall_named_irep(it, src_comments)
183+
{
155184
#ifdef SUB_IS_LIST
156-
dest_comments.push_back(
157-
std::make_pair(it->first, merged(it->second))); // recursive call
185+
dest_comments.emplace_after(
186+
before, it->first, merged(it->second)); // recursive call
187+
++before;
158188
#else
159189
dest_comments[it->first]=merged(it->second); // recursive call
160190
#endif
191+
}
161192

162193
return *irep_store.insert(new_irep).first;
163194
}
@@ -188,24 +219,36 @@ const irept &merge_full_irept::merged(const irept &irep)
188219
const irept::named_subt &src_named_sub=irep.get_named_sub();
189220
irept::named_subt &dest_named_sub=new_irep.get_named_sub();
190221

222+
#ifdef SUB_IS_LIST
223+
irept::named_subt::iterator before = dest_named_sub.before_begin();
224+
#endif
191225
forall_named_irep(it, src_named_sub)
226+
{
192227
#ifdef SUB_IS_LIST
193-
dest_named_sub.push_back(
194-
std::make_pair(it->first, merged(it->second))); // recursive call
228+
dest_named_sub.emplace_after(
229+
before, it->first, merged(it->second)); // recursive call
230+
++before;
195231
#else
196232
dest_named_sub[it->first]=merged(it->second); // recursive call
197233
#endif
234+
}
198235

199236
const irept::named_subt &src_comments=irep.get_comments();
200237
irept::named_subt &dest_comments=new_irep.get_comments();
201238

239+
#ifdef SUB_IS_LIST
240+
before = dest_comments.before_begin();
241+
#endif
202242
forall_named_irep(it, src_comments)
243+
{
203244
#ifdef SUB_IS_LIST
204-
dest_comments.push_back(
205-
std::make_pair(it->first, merged(it->second))); // recursive call
245+
dest_comments.emplace_after(
246+
before, it->first, merged(it->second)); // recursive call
247+
++before;
206248
#else
207249
dest_comments[it->first]=merged(it->second); // recursive call
208250
#endif
251+
}
209252

210253
return *irep_store.insert(new_irep).first;
211254
}

0 commit comments

Comments
 (0)