Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 86eb9c9

Browse files
committed
Improve SSA DF computation memory usage
DF(b) can be stored in a vector instead of a hashtable (set). Nothing needs a O(1) membership test, the duplicates that may be generated during DF construction can be easily avoided by observing that: * each block in the graph is processed exactly once * during processing the block is added to the relevant DF vectors, at the end of each vector. If the same DF vector is encountered multiple times then checking if the block is already a member is trivial.
1 parent 269e35e commit 86eb9c9

File tree

5 files changed

+73
-29
lines changed

5 files changed

+73
-29
lines changed

src/jit/block.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,9 +1202,15 @@ struct JitPtrKeyFuncs<BasicBlock> : public JitKeyFuncsDefEquals<const BasicBlock
12021202
// A set of blocks.
12031203
typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, bool> BlkSet;
12041204

1205+
// A vector of blocks.
1206+
typedef jitstd::vector<BasicBlock*> BlkVector;
1207+
12051208
// A map of block -> set of blocks, can be used as sparse block trees.
12061209
typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, BlkSet*> BlkToBlkSetMap;
12071210

1211+
// A map of block -> vector of blocks, can be used as sparse block trees.
1212+
typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, BlkVector> BlkToBlkVectorMap;
1213+
12081214
// Map from Block to Block. Used for a variety of purposes.
12091215
typedef JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, BasicBlock*> BlockToBlockMap;
12101216

src/jit/compiler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2525
#include "jit.h"
2626
#include "opcode.h"
2727
#include "varset.h"
28+
#include "jitstd.h"
29+
#include "jithashtable.h"
2830
#include "gentree.h"
2931
#include "lir.h"
3032
#include "block.h"
@@ -33,10 +35,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
3335
#include "instr.h"
3436
#include "regalloc.h"
3537
#include "sm.h"
36-
#include "jithashtable.h"
3738
#include "cycletimer.h"
3839
#include "blockset.h"
39-
#include "jitstd.h"
4040
#include "arraystack.h"
4141
#include "hashbv.h"
4242
#include "fp.h"

src/jit/gentree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2424
#include "ssaconfig.h" // For "SsaConfig::RESERVED_SSA_NUM"
2525
#include "reglist.h"
2626
#include "valuenumtype.h"
27+
#include "jitstd.h"
2728
#include "jithashtable.h"
2829
#include "nodeinfo.h"
2930
#include "simd.h"

src/jit/jithashtable.h

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,50 @@ class JitHashTable
264264
}
265265
else
266266
{
267-
Node* pNewNode = new (m_alloc) Node(k, v, m_table[index]);
267+
Node* pNewNode = new (m_alloc) Node(m_table[index], k, v);
268268
m_table[index] = pNewNode;
269269
m_tableCount++;
270270
return false;
271271
}
272272
}
273273

274+
//------------------------------------------------------------------------
275+
// Emplace: Associates the specified key with a value constructed in-place
276+
// using the supplied args if the key is not already present.
277+
//
278+
// Arguments:
279+
// k - the key
280+
// args - the args used to construct the value
281+
//
282+
// Return Value:
283+
// A pointer to the existing or newly constructed value.
284+
//
285+
template <class... Args>
286+
Value* Emplace(Key k, Args&&... args)
287+
{
288+
CheckGrowth();
289+
290+
assert(m_tableSizeInfo.prime != 0);
291+
292+
unsigned index = GetIndexForKey(k);
293+
294+
Node* n = m_table[index];
295+
while ((n != nullptr) && !KeyFuncs::Equals(k, n->m_key))
296+
{
297+
n = n->m_next;
298+
}
299+
300+
if (n == nullptr)
301+
{
302+
n = new (m_alloc) Node(m_table[index], k, jitstd::forward<Args>(args)...);
303+
304+
m_table[index] = n;
305+
m_tableCount++;
306+
}
307+
308+
return &n->m_val;
309+
}
310+
274311
//------------------------------------------------------------------------
275312
// Remove: Remove the specified key and its associated value.
276313
//
@@ -592,7 +629,7 @@ class JitHashTable
592629
// Assumptions:
593630
// This must not be the "end" iterator.
594631
//
595-
const Value& GetValue() const
632+
Value& GetValue() const
596633
{
597634
assert(m_node != nullptr);
598635

@@ -721,7 +758,8 @@ class JitHashTable
721758
Key m_key;
722759
Value m_val;
723760

724-
Node(Key k, Value v, Node* next) : m_next(next), m_key(k), m_val(v)
761+
template <class... Args>
762+
Node(Node* next, Key k, Args&&... args) : m_next(next), m_key(k), m_val(jitstd::forward<Args>(args)...)
725763
{
726764
}
727765

src/jit/ssabuilder.cpp

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ void SsaBuilder::DisplayDominators(BlkToBlkSetMap* domTree)
513513
// dominance frontiers by a closure operation.
514514
BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOrder, int count)
515515
{
516-
BlkToBlkSetMap* frontier = new (&m_allocator) BlkToBlkSetMap(&m_allocator);
516+
BlkToBlkVectorMap mapDF(&m_allocator);
517517

518518
DBG_SSA_JITDUMP("Computing IDF: First computing DF.\n");
519519

@@ -534,8 +534,8 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
534534

535535
flowList* blockPreds = m_pCompiler->BlockPredsWithEH(block);
536536

537-
// If block has more 0/1 predecessor, skip.
538-
if (blockPreds == nullptr || blockPreds->flNext == nullptr)
537+
// If block has 0/1 predecessor, skip.
538+
if ((blockPreds == nullptr) || (blockPreds->flNext == nullptr))
539539
{
540540
DBG_SSA_JITDUMP(" Has %d preds; skipping.\n", blockPreds == nullptr ? 0 : 1);
541541
continue;
@@ -544,7 +544,7 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
544544
// Otherwise, there are > 1 preds. Each is a candidate B2 in the definition --
545545
// *unless* it dominates "block"/B3.
546546

547-
for (flowList* pred = blockPreds; pred; pred = pred->flNext)
547+
for (flowList* pred = blockPreds; pred != nullptr; pred = pred->flNext)
548548
{
549549
DBG_SSA_JITDUMP(" Considering predecessor BB%02u.\n", pred->flBlock->bbNum);
550550

@@ -560,13 +560,13 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
560560
b1 = b1->bbIDom)
561561
{
562562
DBG_SSA_JITDUMP(" Adding BB%02u to dom frontier of pred dom BB%02u.\n", block->bbNum, b1->bbNum);
563-
BlkSet* pBlkSet;
564-
if (!frontier->Lookup(b1, &pBlkSet))
563+
564+
BlkVector& b1DF = *mapDF.Emplace(b1, &m_allocator);
565+
// It's possible to encounter the same DF multiple times, ensure that we don't add duplicates.
566+
if (b1DF.empty() || (b1DF.back() != block))
565567
{
566-
pBlkSet = new (&m_allocator) BlkSet(&m_allocator);
567-
frontier->Set(b1, pBlkSet);
568+
b1DF.push_back(block);
568569
}
569-
pBlkSet->Set(block, true);
570570
}
571571
}
572572
}
@@ -577,20 +577,20 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
577577
printf("\nComputed DF:\n");
578578
for (int i = 0; i < count; ++i)
579579
{
580-
BasicBlock* block = postOrder[i];
581-
printf("Block BB%02u := {", block->bbNum);
580+
BasicBlock* b = postOrder[i];
581+
printf("Block BB%02u := {", b->bbNum);
582582

583-
bool first = true;
584-
BlkSet* blkDf;
585-
if (frontier->Lookup(block, &blkDf))
583+
bool first = true;
584+
BlkVector* bDF = mapDF.LookupPointer(b);
585+
if (bDF != nullptr)
586586
{
587-
for (BlkSet::KeyIterator blkDfIter = blkDf->Begin(); !blkDfIter.Equal(blkDf->End()); blkDfIter++)
587+
for (BasicBlock* f : *bDF)
588588
{
589589
if (!first)
590590
{
591591
printf(",");
592592
}
593-
printf("BB%02u", blkDfIter.Get()->bbNum);
593+
printf("BB%02u", f->bbNum);
594594
first = false;
595595
}
596596
}
@@ -602,8 +602,7 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
602602
// Now do the closure operation to make the dominance frontier into an IDF.
603603
// There's probably a better way to do this...
604604
BlkToBlkSetMap* idf = new (&m_allocator) BlkToBlkSetMap(&m_allocator);
605-
for (BlkToBlkSetMap::KeyIterator kiFrontBlks = frontier->Begin(); !kiFrontBlks.Equal(frontier->End());
606-
kiFrontBlks++)
605+
for (BlkToBlkVectorMap::KeyIterator kiFrontBlks = mapDF.Begin(); !kiFrontBlks.Equal(mapDF.End()); kiFrontBlks++)
607606
{
608607
// Create IDF(b)
609608
BlkSet* blkIdf = new (&m_allocator) BlkSet(&m_allocator);
@@ -623,16 +622,16 @@ BlkToBlkSetMap* SsaBuilder::ComputeIteratedDominanceFrontier(BasicBlock** postOr
623622
delta->Remove(curBlk);
624623

625624
// Get DF(x).
626-
BlkSet* blkDf;
627-
if (frontier->Lookup(curBlk, &blkDf))
625+
BlkVector* blkDf = mapDF.LookupPointer(curBlk);
626+
if (blkDf != nullptr)
628627
{
629628
// Add DF(x) to IDF(b) and update "delta" i.e., new additions to IDF(b).
630-
for (BlkSet::KeyIterator ki = blkDf->Begin(); !ki.Equal(blkDf->End()); ki++)
629+
for (BasicBlock* f : *blkDf)
631630
{
632-
if (!blkIdf->Lookup(ki.Get()))
631+
if (!blkIdf->Lookup(f))
633632
{
634-
delta->Set(ki.Get(), true);
635-
blkIdf->Set(ki.Get(), true);
633+
delta->Set(f, true);
634+
blkIdf->Set(f, true);
636635
}
637636
}
638637
}

0 commit comments

Comments
 (0)