summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-07-12 19:55:41 -0700
committerGitHub <noreply@github.com>2023-07-12 19:55:41 -0700
commitf3aba255f6d69ddbf255b33d0eb0f391908e60a8 (patch)
treef43300b1bbbcc82caa1b547dd3922c608010cb98
parent98ba936ed91328338ba95525dd658d5cde6582de (diff)
Pool inst worklists and hashsets to avoid rehashing. (#2982)
Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--build/visual-studio/slang/slang.vcxproj2
-rw-r--r--build/visual-studio/slang/slang.vcxproj.filters6
-rw-r--r--source/slang/slang-container-pool.cpp0
-rw-r--r--source/slang/slang-container-pool.h93
-rw-r--r--source/slang/slang-emit-c-like.cpp3
-rw-r--r--source/slang/slang-ir-address-analysis.cpp4
-rw-r--r--source/slang/slang-ir-augment-make-existential.cpp13
-rw-r--r--source/slang/slang-ir-check-differentiability.cpp6
-rw-r--r--source/slang/slang-ir-cleanup-void.cpp13
-rw-r--r--source/slang/slang-ir-constexpr.cpp13
-rw-r--r--source/slang/slang-ir-dce.cpp5
-rw-r--r--source/slang/slang-ir-deduplicate.cpp8
-rw-r--r--source/slang/slang-ir-generics-lowering-context.h10
-rw-r--r--source/slang/slang-ir-init-local-var.cpp2
-rw-r--r--source/slang/slang-ir-inst-pass-base.h6
-rw-r--r--source/slang/slang-ir-legalize-types.cpp7
-rw-r--r--source/slang/slang-ir-lower-binding-query.cpp19
-rw-r--r--source/slang/slang-ir-lower-error-handling.cpp13
-rw-r--r--source/slang/slang-ir-lower-generics.cpp3
-rw-r--r--source/slang/slang-ir-lower-optional-type.cpp11
-rw-r--r--source/slang/slang-ir-lower-result-type.cpp11
-rw-r--r--source/slang/slang-ir-lower-tuple-types.cpp11
-rw-r--r--source/slang/slang-ir-lower-witness-lookup.cpp4
-rw-r--r--source/slang/slang-ir-redundancy-removal.cpp2
-rw-r--r--source/slang/slang-ir-simplify-for-emit.cpp6
-rw-r--r--source/slang/slang-ir-specialize.cpp4
-rw-r--r--source/slang/slang-ir-ssa-register-allocate.cpp4
-rw-r--r--source/slang/slang-ir.h97
-rw-r--r--source/slang/slang-lower-to-ir.cpp4
29 files changed, 310 insertions, 70 deletions
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj
index 7eca300db..9dcaf5606 100644
--- a/build/visual-studio/slang/slang.vcxproj
+++ b/build/visual-studio/slang/slang.vcxproj
@@ -330,6 +330,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla
<ClInclude Include="..\..\..\source\slang\slang-check-impl.h" />
<ClInclude Include="..\..\..\source\slang\slang-check.h" />
<ClInclude Include="..\..\..\source\slang\slang-compiler.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-container-pool.h" />
<ClInclude Include="..\..\..\source\slang\slang-content-assist-info.h" />
<ClInclude Include="..\..\..\source\slang\slang-diagnostic-defs.h" />
<ClInclude Include="..\..\..\source\slang\slang-diagnostics.h" />
@@ -537,6 +538,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla
<ClCompile Include="..\..\..\source\slang\slang-check-type.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-check.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-compiler.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-container-pool.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-diagnostics.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-doc-ast.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-doc-markdown-writer.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters
index 5d7f49668..d1e06b907 100644
--- a/build/visual-studio/slang/slang.vcxproj.filters
+++ b/build/visual-studio/slang/slang.vcxproj.filters
@@ -78,6 +78,9 @@
<ClInclude Include="..\..\..\source\slang\slang-compiler.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-container-pool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-content-assist-info.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -695,6 +698,9 @@
<ClCompile Include="..\..\..\source\slang\slang-compiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-container-pool.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-diagnostics.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/slang/slang-container-pool.cpp b/source/slang/slang-container-pool.cpp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/source/slang/slang-container-pool.cpp
diff --git a/source/slang/slang-container-pool.h b/source/slang/slang-container-pool.h
new file mode 100644
index 000000000..addeb1607
--- /dev/null
+++ b/source/slang/slang-container-pool.h
@@ -0,0 +1,93 @@
+#ifndef SLANG_CONTAINER_POOL_H
+#define SLANG_CONTAINER_POOL_H
+
+#include "../core/slang-list.h"
+#include "../core/slang-dictionary.h"
+#include "../core/slang-virtual-object-pool.h"
+
+// A pool to allow reuse of common types of containers to avoid
+// frequent resizing and rehashing.
+
+namespace Slang
+{
+static const int kContainerPoolSize = 1024;
+
+template<typename T>
+struct ObjectPool
+{
+ ObjectPool(int maxElementCount)
+ {
+ m_pool.initPool(maxElementCount);
+ m_objects.setCount(maxElementCount);
+ }
+
+ T* getObject()
+ {
+ auto id = m_pool.alloc(1);
+ if (id == -1)
+ SLANG_ABORT_COMPILATION("container pool allocation failure.");
+ return &m_objects[id];
+ }
+
+ void freeObject(T* object)
+ {
+ auto id = (int)(object - m_objects.getBuffer());
+ m_pool.free(id, 1);
+ }
+
+ VirtualObjectPool m_pool;
+ List<T> m_objects;
+};
+
+struct ContainerPool
+{
+ ObjectPool<List<void*>> m_listPool;
+ ObjectPool<Dictionary<void*, void*>> m_dictionaryPool;
+ ObjectPool<HashSet<void*>> m_hashSetPool;
+
+ ContainerPool()
+ :m_listPool(kContainerPoolSize), m_dictionaryPool(kContainerPoolSize), m_hashSetPool(kContainerPoolSize)
+ {}
+
+ template<typename T>
+ List<T*>* getList()
+ {
+ return (List<T*>*)m_listPool.getObject();
+ }
+
+ template<typename T, typename U>
+ Dictionary<T*, U*>* getDictionary()
+ {
+ return (Dictionary<T*, U*>*)m_dictionaryPool.getObject();
+ }
+
+ template<typename T>
+ HashSet<T*>* getHashSet()
+ {
+ return (HashSet<T*>*)m_hashSetPool.getObject();
+ }
+
+ template<typename T>
+ void free(List<T*>* list)
+ {
+ list->clear();
+ m_listPool.freeObject((List<void*>*)list);
+ }
+
+ template<typename T, typename U>
+ void free(Dictionary<T*, U*>* dict)
+ {
+ dict->clear();
+ m_dictionaryPool.freeObject((Dictionary<void*, void*>*)dict);
+ }
+
+ template<typename T>
+ void free(HashSet<T*>* set)
+ {
+ set->clear();
+ m_hashSetPool.freeObject((HashSet<void*>*)set);
+ }
+};
+}
+
+#endif
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 0b5a91d87..718653545 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -36,7 +36,7 @@ namespace Slang {
struct CLikeSourceEmitter::ComputeEmitActionsContext
{
IRInst* moduleInst;
- HashSet<IRInst*> openInsts;
+ InstHashSet openInsts;
Dictionary<IRInst*, EmitAction::Level> mapInstToLevel;
List<EmitAction>* actions;
};
@@ -3880,6 +3880,7 @@ void CLikeSourceEmitter::computeEmitActions(IRModule* module, List<EmitAction>&
ComputeEmitActionsContext ctx;
ctx.moduleInst = module->getModuleInst();
ctx.actions = &ioActions;
+ ctx.openInsts = InstHashSet(module);
for(auto inst : module->getGlobalInsts())
{
diff --git a/source/slang/slang-ir-address-analysis.cpp b/source/slang/slang-ir-address-analysis.cpp
index feba0898a..b00b713b5 100644
--- a/source/slang/slang-ir-address-analysis.cpp
+++ b/source/slang/slang-ir-address-analysis.cpp
@@ -11,8 +11,8 @@ namespace Slang
if (domTree->isUnreachable(as<IRBlock>(inst->getParent())))
return;
- List<IRBlock*> blocks;
- HashSet<IRInst*> operandInsts;
+ InstWorkList blocks(func->getModule());
+ InstHashSet operandInsts(func->getModule());
for (UInt i = 0; i < inst->getOperandCount(); i++)
{
operandInsts.add(inst->getOperand(i));
diff --git a/source/slang/slang-ir-augment-make-existential.cpp b/source/slang/slang-ir-augment-make-existential.cpp
index a2038ea24..43b4ee51d 100644
--- a/source/slang/slang-ir-augment-make-existential.cpp
+++ b/source/slang/slang-ir-augment-make-existential.cpp
@@ -8,8 +8,14 @@ struct AugmentMakeExistentialContext
{
IRModule* module;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ AugmentMakeExistentialContext(IRModule* inModule)
+ : module(inModule)
+ , workList(inModule)
+ , workListSet(inModule)
+ {}
void addToWorkList(IRInst* inst)
{
@@ -70,8 +76,7 @@ struct AugmentMakeExistentialContext
void augmentMakeExistentialInsts(IRModule* module)
{
- AugmentMakeExistentialContext context;
- context.module = module;
+ AugmentMakeExistentialContext context(module);
context.processModule();
}
} // namespace Slang
diff --git a/source/slang/slang-ir-check-differentiability.cpp b/source/slang/slang-ir-check-differentiability.cpp
index 6c9280fca..d4b93be5e 100644
--- a/source/slang/slang-ir-check-differentiability.cpp
+++ b/source/slang/slang-ir-check-differentiability.cpp
@@ -261,9 +261,9 @@ public:
// `produceDiffSet`.
// `expectDiffSet` is a set of insts that expects their operands to produce a diff. It is an error
// if they don't.
- HashSet<IRInst*> produceDiffSet;
- HashSet<IRInst*> expectDiffSet;
- HashSet<IRInst*> carryNonTrivialDiffSet;
+ InstHashSet produceDiffSet(funcInst->getModule());
+ InstHashSet expectDiffSet(funcInst->getModule());
+ InstHashSet carryNonTrivialDiffSet(funcInst->getModule());
int differentiableOutputs = 0;
bool isDifferentiableReturnType = false;
diff --git a/source/slang/slang-ir-cleanup-void.cpp b/source/slang/slang-ir-cleanup-void.cpp
index 7fc9041ec..95716945b 100644
--- a/source/slang/slang-ir-cleanup-void.cpp
+++ b/source/slang/slang-ir-cleanup-void.cpp
@@ -10,8 +10,14 @@ namespace Slang
{
IRModule* module;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ CleanUpVoidContext(IRModule* inModule)
+ : module(inModule)
+ , workList(inModule)
+ , workListSet(inModule)
+ {}
void addToWorkList(
IRInst* inst)
@@ -174,8 +180,7 @@ namespace Slang
void cleanUpVoidType(IRModule* module)
{
- CleanUpVoidContext context;
- context.module = module;
+ CleanUpVoidContext context(module);
context.processModule();
}
}
diff --git a/source/slang/slang-ir-constexpr.cpp b/source/slang/slang-ir-constexpr.cpp
index 1174a53ae..1d6fd163c 100644
--- a/source/slang/slang-ir-constexpr.cpp
+++ b/source/slang/slang-ir-constexpr.cpp
@@ -15,8 +15,14 @@ struct PropagateConstExprContext
IRBuilder builder;
- List<IRInst*> workList;
- HashSet<IRInst*> onWorkList;
+ InstWorkList workList;
+ InstHashSet onWorkList;
+
+ PropagateConstExprContext(IRModule* module)
+ : module(module)
+ , workList(module)
+ , onWorkList(module)
+ {}
IRBuilder* getBuilder() { return &builder; }
@@ -497,8 +503,7 @@ void propagateConstExpr(
IRModule* module,
DiagnosticSink* sink)
{
- PropagateConstExprContext context;
- context.module = module;
+ PropagateConstExprContext context(module);
context.sink = sink;
context.builder = IRBuilder(module);
diff --git a/source/slang/slang-ir-dce.cpp b/source/slang/slang-ir-dce.cpp
index c00e4ca7b..ec4c749fa 100644
--- a/source/slang/slang-ir-dce.cpp
+++ b/source/slang/slang-ir-dce.cpp
@@ -177,11 +177,6 @@ struct DeadCodeEliminationContext
// should be live when its parent is to a subroutine.
//
- if (auto func = as<IRGlobalValueWithCode>(inst))
- {
- module->findOrCreateDominatorTree(func);
- }
-
for (auto child : inst->getDecorationsAndChildren())
{
if (shouldInstBeLiveIfParentIsLive(child))
diff --git a/source/slang/slang-ir-deduplicate.cpp b/source/slang/slang-ir-deduplicate.cpp
index 8db57b3f3..4579ae42b 100644
--- a/source/slang/slang-ir-deduplicate.cpp
+++ b/source/slang/slang-ir-deduplicate.cpp
@@ -13,8 +13,8 @@ namespace Slang
void IRDeduplicationContext::removeHoistableInstFromGlobalNumberingMap(IRInst* instToRemove)
{
- HashSet<IRInst*> userWorkListSet;
- List<IRInst*> userWorkList;
+ InstHashSet userWorkListSet(instToRemove->getModule());
+ InstWorkList userWorkList(instToRemove->getModule());
auto addToWorkList = [&](IRInst* i)
{
if (userWorkListSet.add(i))
@@ -37,8 +37,8 @@ namespace Slang
void IRDeduplicationContext::tryHoistInst(IRInst* inst)
{
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList(inst->getModule());
+ InstHashSet workListSet(inst->getModule());
workList.add(inst);
workListSet.add(inst);
IRBuilder builder(inst->getModule());
diff --git a/source/slang/slang-ir-generics-lowering-context.h b/source/slang/slang-ir-generics-lowering-context.h
index 8790da901..c8a7be3ee 100644
--- a/source/slang/slang-ir-generics-lowering-context.h
+++ b/source/slang/slang-ir-generics-lowering-context.h
@@ -44,8 +44,14 @@ namespace Slang
// We will use a single work list of instructions that need
// to be considered for lowering.
//
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ SharedGenericsLoweringContext(IRModule* inModule)
+ : module(inModule)
+ , workList(inModule)
+ , workListSet(inModule)
+ {}
void addToWorkList(
IRInst* inst)
diff --git a/source/slang/slang-ir-init-local-var.cpp b/source/slang/slang-ir-init-local-var.cpp
index 145d8d569..34a0e5ff4 100644
--- a/source/slang/slang-ir-init-local-var.cpp
+++ b/source/slang/slang-ir-init-local-var.cpp
@@ -9,7 +9,7 @@ namespace Slang
void initializeLocalVariables(IRModule* module, IRGlobalValueWithCode* func)
{
IRBuilder builder(module);
- HashSet<IRInst*> userSet;
+ InstHashSet userSet(module);
for (auto block : func->getBlocks())
{
for (auto inst : block->getChildren())
diff --git a/source/slang/slang-ir-inst-pass-base.h b/source/slang/slang-ir-inst-pass-base.h
index 14607d722..1ebc4e350 100644
--- a/source/slang/slang-ir-inst-pass-base.h
+++ b/source/slang/slang-ir-inst-pass-base.h
@@ -13,8 +13,8 @@ namespace Slang
{
protected:
IRModule* module;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
void addToWorkList(IRInst* inst)
{
if (workListSet.contains(inst))
@@ -38,7 +38,7 @@ namespace Slang
public:
InstPassBase(IRModule* inModule)
- : module(inModule)
+ : module(inModule), workList(inModule), workListSet(inModule)
{}
template <typename InstType, typename Func>
diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp
index bf5893db7..55ed78a50 100644
--- a/source/slang/slang-ir-legalize-types.cpp
+++ b/source/slang/slang-ir-legalize-types.cpp
@@ -3472,7 +3472,7 @@ static constexpr int kHasBeenAddedScratchBitIndex = 1;
struct IRTypeLegalizationPass
{
- IRTypeLegalizationContext* context;
+ IRTypeLegalizationContext* context = nullptr;
// The goal of this pass is to ensure that legalization has been
// applied to each instruction in a module. We also want to
@@ -3485,6 +3485,11 @@ struct IRTypeLegalizationPass
List<IRInst*> workList;
+ IRTypeLegalizationPass()
+ {
+ workList.reserve(8192);
+ }
+
bool hasBeenAddedOrProcessed(IRInst* inst)
{
if (!inst) return true;
diff --git a/source/slang/slang-ir-lower-binding-query.cpp b/source/slang/slang-ir-lower-binding-query.cpp
index d0128d365..116dcff61 100644
--- a/source/slang/slang-ir-lower-binding-query.cpp
+++ b/source/slang/slang-ir-lower-binding-query.cpp
@@ -76,8 +76,12 @@ namespace Slang
// itself is straightforward, and not anything
// that hasn't been seen in other files.
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ WorkListPass(IRModule* inModule)
+ : module(inModule), workList(inModule), workListSet(inModule), toBeDeleted(inModule), toBeDeletedSet(inModule)
+ {}
void addToWorkList(IRInst* inst)
{
@@ -111,8 +115,8 @@ namespace Slang
// frequent need to buffer up instructions to
// be deleted when a pass is complete.
- List<IRInst*> toBeDeleted;
- HashSet<IRInst*> toBeDeletedSet;
+ InstWorkList toBeDeleted;
+ InstHashSet toBeDeletedSet;
void addToBeDeleted(IRInst* inst)
{
@@ -139,6 +143,10 @@ namespace Slang
//
struct BindingQueryLoweringContext : public WorkListPass
{
+ BindingQueryLoweringContext(IRModule* inModule)
+ : WorkListPass(inModule)
+ {}
+
// All of the intrinsics we will be processing use
// the same result type (`uint`), so it is helpful
// to cache a pointer to the IR type at the start
@@ -602,8 +610,7 @@ namespace Slang
IRModule* module,
DiagnosticSink* sink)
{
- BindingQueryLoweringContext context;
- context.module = module;
+ BindingQueryLoweringContext context(module);
context.sink = sink;
context.processModule();
}
diff --git a/source/slang/slang-ir-lower-error-handling.cpp b/source/slang/slang-ir-lower-error-handling.cpp
index d598df9bb..6cfaf1926 100644
--- a/source/slang/slang-ir-lower-error-handling.cpp
+++ b/source/slang/slang-ir-lower-error-handling.cpp
@@ -13,8 +13,14 @@ struct ErrorHandlingLoweringContext
IRModule* module;
DiagnosticSink* diagnosticSink;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ ErrorHandlingLoweringContext(IRModule* inModule)
+ : module(inModule)
+ , workList(inModule)
+ , workListSet(inModule)
+ {}
void addToWorkList(IRInst* inst)
{
@@ -222,8 +228,7 @@ struct ErrorHandlingLoweringContext
void lowerErrorHandling(IRModule* module, DiagnosticSink* sink)
{
- ErrorHandlingLoweringContext context;
- context.module = module;
+ ErrorHandlingLoweringContext context(module);
context.diagnosticSink = sink;
return context.processModule();
}
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index 6a5abbf8c..19c075bf1 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -183,9 +183,8 @@ namespace Slang
{
SLANG_PROFILE;
- SharedGenericsLoweringContext sharedContext;
+ SharedGenericsLoweringContext sharedContext(module);
sharedContext.targetReq = targetReq;
- sharedContext.module = module;
sharedContext.sink = sink;
checkTypeConformanceExists(&sharedContext);
diff --git a/source/slang/slang-ir-lower-optional-type.cpp b/source/slang/slang-ir-lower-optional-type.cpp
index 9d6b98dc9..91b108ffe 100644
--- a/source/slang/slang-ir-lower-optional-type.cpp
+++ b/source/slang/slang-ir-lower-optional-type.cpp
@@ -12,8 +12,12 @@ namespace Slang
IRModule* module;
DiagnosticSink* sink;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ OptionalTypeLoweringContext(IRModule* inModule)
+ :module(inModule), workList(inModule), workListSet(inModule)
+ {}
struct LoweredOptionalTypeInfo : public RefObject
{
@@ -275,8 +279,7 @@ namespace Slang
void lowerOptionalType(IRModule* module, DiagnosticSink* sink)
{
- OptionalTypeLoweringContext context;
- context.module = module;
+ OptionalTypeLoweringContext context(module);
context.sink = sink;
context.processModule();
}
diff --git a/source/slang/slang-ir-lower-result-type.cpp b/source/slang/slang-ir-lower-result-type.cpp
index c8d156cec..a10a9d343 100644
--- a/source/slang/slang-ir-lower-result-type.cpp
+++ b/source/slang/slang-ir-lower-result-type.cpp
@@ -11,8 +11,12 @@ namespace Slang
IRModule* module;
DiagnosticSink* sink;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ ResultTypeLoweringContext(IRModule* inModule)
+ :module(inModule), workList(inModule), workListSet(inModule)
+ {}
struct LoweredResultTypeInfo : public RefObject
{
@@ -296,8 +300,7 @@ namespace Slang
void lowerResultType(IRModule* module, DiagnosticSink* sink)
{
- ResultTypeLoweringContext context;
- context.module = module;
+ ResultTypeLoweringContext context(module);
context.sink = sink;
context.processModule();
}
diff --git a/source/slang/slang-ir-lower-tuple-types.cpp b/source/slang/slang-ir-lower-tuple-types.cpp
index 717c6a896..1392ab453 100644
--- a/source/slang/slang-ir-lower-tuple-types.cpp
+++ b/source/slang/slang-ir-lower-tuple-types.cpp
@@ -11,8 +11,12 @@ namespace Slang
IRModule* module;
DiagnosticSink* sink;
- List<IRInst*> workList;
- HashSet<IRInst*> workListSet;
+ InstWorkList workList;
+ InstHashSet workListSet;
+
+ TupleLoweringContext(IRModule* inModule)
+ :module(inModule), workList(inModule), workListSet(inModule)
+ {}
struct LoweredTupleInfo : public RefObject
{
@@ -175,8 +179,7 @@ namespace Slang
void lowerTuples(IRModule* module, DiagnosticSink* sink)
{
- TupleLoweringContext context;
- context.module = module;
+ TupleLoweringContext context(module);
context.sink = sink;
context.processModule();
}
diff --git a/source/slang/slang-ir-lower-witness-lookup.cpp b/source/slang/slang-ir-lower-witness-lookup.cpp
index b94059238..aca41fd69 100644
--- a/source/slang/slang-ir-lower-witness-lookup.cpp
+++ b/source/slang/slang-ir-lower-witness-lookup.cpp
@@ -40,8 +40,8 @@ struct WitnessLookupLoweringContext
if (!type)
return false;
- HashSet<IRInst*> processedSet;
- List<IRInst*> workList;
+ InstHashSet processedSet(type->getModule());
+ InstWorkList workList(type->getModule());
workList.add(type);
processedSet.add(type);
for (Index i = 0; i < workList.getCount(); i++)
diff --git a/source/slang/slang-ir-redundancy-removal.cpp b/source/slang/slang-ir-redundancy-removal.cpp
index 227ef1d4d..bac39a53c 100644
--- a/source/slang/slang-ir-redundancy-removal.cpp
+++ b/source/slang/slang-ir-redundancy-removal.cpp
@@ -254,7 +254,7 @@ bool tryRemoveRedundantStore(IRGlobalValueWithCode* func, IRStore* store)
{
bool hasNonStoreUse = false;
// If the entire access chain doesn't non-store use, we can safely remove it.
- HashSet<IRInst*> knownAccessChain;
+ InstHashSet knownAccessChain(func->getModule());
for (auto accessChain = store->getPtr(); accessChain;)
{
knownAccessChain.add(accessChain);
diff --git a/source/slang/slang-ir-simplify-for-emit.cpp b/source/slang/slang-ir-simplify-for-emit.cpp
index f040ef1ec..469368ca4 100644
--- a/source/slang/slang-ir-simplify-for-emit.cpp
+++ b/source/slang/slang-ir-simplify-for-emit.cpp
@@ -11,12 +11,12 @@ bool isCUDATarget(TargetRequest* targetReq);
struct SimplifyForEmitContext : public InstPassBase
{
SimplifyForEmitContext(IRModule* inModule, TargetRequest* inTargetReq)
- : InstPassBase(inModule), targetReq(inTargetReq)
+ : InstPassBase(inModule), targetReq(inTargetReq), followUpWorkList(inModule), followUpWorkListSet(inModule)
{}
TargetRequest* targetReq;
- List<IRInst*> followUpWorkList;
- HashSet<IRInst*> followUpWorkListSet;
+ InstWorkList followUpWorkList;
+ InstHashSet followUpWorkListSet;
void addToFollowUpWorkList(IRInst* inst)
{
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp
index 3fc3b153d..26f54a271 100644
--- a/source/slang/slang-ir-specialize.cpp
+++ b/source/slang/slang-ir-specialize.cpp
@@ -1339,8 +1339,8 @@ struct SpecializationContext
// TODO: We probably need/want a more robust test here.
// For now we are just look into the dependency graph of the inst and
// see if there are any opcodes that are causing problems.
- List<IRInst*> localWorkList;
- HashSet<IRInst*> processedInsts;
+ InstWorkList localWorkList(inst->getModule());
+ InstHashSet processedInsts(inst->getModule());
localWorkList.add(inst);
processedInsts.add(inst);
diff --git a/source/slang/slang-ir-ssa-register-allocate.cpp b/source/slang/slang-ir-ssa-register-allocate.cpp
index b1d375fcf..a93a3a8f4 100644
--- a/source/slang/slang-ir-ssa-register-allocate.cpp
+++ b/source/slang/slang-ir-ssa-register-allocate.cpp
@@ -156,8 +156,8 @@ struct RegisterAllocateContext
// This order allows us to easily track what is dominating the current inst.
// We track the insts dominating the current location in a stack.
- List<IRInst*> dominatingInsts;
- HashSet<IRInst*> dominatingInstSet;
+ InstWorkList dominatingInsts(func->getModule());
+ InstHashSet dominatingInstSet(func->getModule());
struct WorkStackItem
{
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index e7c7f4fb2..e61ed99af 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -19,6 +19,7 @@
#include "../compiler-core/slang-source-map.h"
#include "slang-type-system-shared.h"
+#include "slang-container-pool.h"
namespace Slang {
@@ -2168,6 +2169,10 @@ public:
return (T*) _allocateInst(op, operandCount, sizeof(T));
}
+ ContainerPool& getContainerPool()
+ {
+ return m_containerPool;
+ }
private:
IRModule() = delete;
@@ -2194,6 +2199,10 @@ private:
/// The memory arena from which all IR instructions (and any associated state) in this module are allocated.
MemoryArena m_memoryArena;
+ /// A pool to allow reuse of common types of containers to reduce memory allocations
+ /// and rehashing.
+ ContainerPool m_containerPool;
+
/// Shared contexts for constructing and deduplicating the IR.
mutable IRDeduplicationContext m_deduplicationContext;
@@ -2201,8 +2210,96 @@ private:
ComPtr<IBoxValue<SourceMap>> m_obfuscatedSourceMap;
Dictionary<IRInst*, IRAnalysis> m_mapInstToAnalysis;
+
};
+
+struct InstWorkList
+{
+ List<IRInst*>* workList = nullptr;
+ ContainerPool* pool = nullptr;
+
+ InstWorkList() = default;
+ InstWorkList(IRModule* module)
+ {
+ pool = &module->getContainerPool();
+ workList = module->getContainerPool().getList<IRInst>();
+ }
+ ~InstWorkList()
+ {
+ if (pool)
+ pool->free(workList);
+ }
+ InstWorkList(const InstWorkList&) = delete;
+ InstWorkList(InstWorkList&& other)
+ {
+ workList = other.workList;
+ pool = other.pool;
+ other.workList = nullptr;
+ other.pool = nullptr;
+ }
+ InstWorkList& operator=(InstWorkList&& other)
+ {
+ workList = other.workList;
+ pool = other.pool;
+ other.workList = nullptr;
+ other.pool = nullptr;
+ return *this;
+ }
+ IRInst* operator[](Index i) { return (*workList)[i]; }
+ Index getCount() { return workList->getCount(); }
+ IRInst** begin() { return workList->begin(); }
+ IRInst** end() { return workList->end(); }
+ IRInst* getLast() { return workList->getLast(); }
+ void removeLast() { workList->removeLast(); }
+ void remove(IRInst* val) { workList->remove(val); }
+ void fastRemoveAt(Index index) { workList->fastRemoveAt(index); }
+ void add(IRInst* inst) { workList->add(inst); }
+ void clear() { workList->clear(); }
+ void setCount(Index count) { workList->setCount(count); }
+};
+
+struct InstHashSet
+{
+ HashSet<IRInst*>* set = nullptr;
+ ContainerPool* pool = nullptr;
+
+ InstHashSet() = default;
+ InstHashSet(IRModule* module)
+ {
+ pool = &module->getContainerPool();
+ set = module->getContainerPool().getHashSet<IRInst>();
+ }
+ ~InstHashSet()
+ {
+ if (pool)
+ pool->free(set);
+ }
+ InstHashSet(const InstHashSet&) = delete;
+ InstHashSet(InstHashSet&& other)
+ {
+ set = other.set;
+ pool = other.pool;
+ other.set = nullptr;
+ other.pool = nullptr;
+ }
+ InstHashSet& operator=(InstHashSet&& other)
+ {
+ set = other.set;
+ pool = other.pool;
+ other.set = nullptr;
+ other.pool = nullptr;
+ return *this;
+ }
+
+ Index getCount() { return set->getCount(); }
+ bool add(IRInst* inst) { return set->add(inst); }
+ bool contains(IRInst* inst) { return set->contains(inst); }
+ void remove(IRInst* inst) { set->remove(inst); }
+ void clear() { set->clear(); }
+};
+
+
struct IRSpecializationDictionaryItem : public IRInst
{
IR_LEAF_ISA(SpecializationDictionaryItem)
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index b941212ea..4ff14fba7 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -8204,7 +8204,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
child = child->getParent();
return child != nullptr;
}
- static void markInstsToClone(HashSet<IRInst*>& valuesToClone, IRInst* parentBlock, IRInst* value)
+ static void markInstsToClone(InstHashSet& valuesToClone, IRInst* parentBlock, IRInst* value)
{
if (!isChildOf(value, parentBlock))
return;
@@ -8264,7 +8264,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
IRCloneEnv cloneEnv = {};
if (returnType)
{
- HashSet<IRInst*> valuesToClone;
+ InstHashSet valuesToClone(subBuilder->getModule());
markInstsToClone(valuesToClone, parentGeneric->getFirstBlock(), returnType);
// For Function Types, we always clone all generic parameters regardless of whether
// the generic parameter appears in the function signature or not.