diff options
| author | Yong He <yonghe@outlook.com> | 2023-07-12 19:55:41 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-12 19:55:41 -0700 |
| commit | f3aba255f6d69ddbf255b33d0eb0f391908e60a8 (patch) | |
| tree | f43300b1bbbcc82caa1b547dd3922c608010cb98 | |
| parent | 98ba936ed91328338ba95525dd658d5cde6582de (diff) | |
Pool inst worklists and hashsets to avoid rehashing. (#2982)
Co-authored-by: Yong He <yhe@nvidia.com>
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. |
