summaryrefslogtreecommitdiffstats
path: root/source/slang/ir-existential.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/ir-existential.cpp')
-rw-r--r--source/slang/ir-existential.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/source/slang/ir-existential.cpp b/source/slang/ir-existential.cpp
new file mode 100644
index 000000000..af15472bf
--- /dev/null
+++ b/source/slang/ir-existential.cpp
@@ -0,0 +1,114 @@
+// ir-existential.cpp
+#include "ir-existential.h"
+
+#include "ir.h"
+#include "ir-insts.h"
+
+namespace Slang {
+
+struct ExistentialTypeSimplificationContext
+{
+ List<IRInst*> instsToRemove;
+
+};
+
+void simplifyExistentialTypesRec(
+ ExistentialTypeSimplificationContext* context,
+ IRInst* inst)
+{
+ switch( inst->op )
+ {
+ default:
+ break;
+
+ case kIROp_ExtractExistentialValue:
+ {
+ auto arg = inst->getOperand(0);
+ if( auto makeExistential = as<IRMakeExistential>(arg) )
+ {
+ auto value = makeExistential->getWrappedValue();
+ inst->replaceUsesWith(value);
+ context->instsToRemove.Add(inst);
+ }
+ }
+ break;
+
+ case kIROp_ExtractExistentialType:
+ {
+ auto arg = inst->getOperand(0);
+ if( auto makeExistential = as<IRMakeExistential>(arg) )
+ {
+ auto value = makeExistential->getWrappedValue();
+ inst->replaceUsesWith(value->getFullType());
+ context->instsToRemove.Add(inst);
+ }
+ }
+ break;
+
+ case kIROp_ExtractExistentialWitnessTable:
+ {
+ auto arg = inst->getOperand(0);
+ if( auto makeExistential = as<IRMakeExistential>(arg) )
+ {
+ auto witnessTable = makeExistential->getWitnessTable();
+ inst->replaceUsesWith(witnessTable);
+ context->instsToRemove.Add(inst);
+ }
+ }
+ break;
+ }
+
+ for( auto childInst : inst->getChildren() )
+ {
+ simplifyExistentialTypesRec(context, childInst);
+ }
+}
+
+void removeUnusedExistentialsRec(
+ ExistentialTypeSimplificationContext* context,
+ IRInst* inst)
+{
+ switch( inst->op )
+ {
+ default:
+ break;
+
+ case kIROp_MakeExistential:
+ {
+ if( !inst->hasUses() )
+ {
+ context->instsToRemove.Add(inst);
+ }
+ }
+ break;
+ }
+
+ for( auto childInst : inst->getChildren() )
+ {
+ removeUnusedExistentialsRec(context, childInst);
+ }
+}
+
+void simplifyExistentialTypes(
+ IRModule* module)
+{
+ {
+ ExistentialTypeSimplificationContext context;
+ simplifyExistentialTypesRec(&context, module->getModuleInst());
+ for( auto inst : context.instsToRemove )
+ {
+ inst->removeAndDeallocate();
+ }
+ }
+
+ {
+ ExistentialTypeSimplificationContext context;
+ removeUnusedExistentialsRec(&context, module->getModuleInst());
+ for( auto inst : context.instsToRemove )
+ {
+ inst->removeAndDeallocate();
+ }
+ }
+}
+
+} // namespace Slang