summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-ir-remove-unused-generic-param.cpp30
-rw-r--r--tests/language-feature/interfaces/generic-value-parameter-via-interface.slang44
2 files changed, 70 insertions, 4 deletions
diff --git a/source/slang/slang-ir-remove-unused-generic-param.cpp b/source/slang/slang-ir-remove-unused-generic-param.cpp
index dd4efeddd..c79e236b8 100644
--- a/source/slang/slang-ir-remove-unused-generic-param.cpp
+++ b/source/slang/slang-ir-remove-unused-generic-param.cpp
@@ -72,17 +72,38 @@ struct RemoveUnusedGenericParamContext : InstPassBase
child = next;
}
SLANG_ASSERT(returnVal);
- List<IRUse*> uses;
+
+ // Collect all specialize uses that we might optimize
+ List<IRUse*> specializeUses;
for (auto use = genInst->firstUse; use; use = use->nextUse)
- uses.add(use);
- for (auto use : uses)
{
if (use->getUser()->getOp() == kIROp_Specialize &&
use == use->getUser()->getOperands())
{
- use->getUser()->replaceUsesWith(returnVal);
+ specializeUses.add(use);
+ }
+ }
+
+ // Check if any of these specialize uses are used by witness tables
+ // If so, we cannot apply the optimization because witness tables are immutable
+ for (auto use : specializeUses)
+ {
+ for (auto specializeUse = use->getUser()->firstUse; specializeUse;
+ specializeUse = specializeUse->nextUse)
+ {
+ auto userOp = specializeUse->getUser()->getOp();
+ if (userOp == kIROp_WitnessTable)
+ {
+ goto skipOptimization;
+ }
}
}
+
+ // Apply the optimization: replace all specialize uses with the return value
+ for (auto use : specializeUses)
+ {
+ use->getUser()->replaceUsesWith(returnVal);
+ }
genInst->replaceUsesWith(returnVal);
genInst->removeAndDeallocate();
}
@@ -118,6 +139,7 @@ struct RemoveUnusedGenericParamContext : InstPassBase
for (auto param : paramsToRemove)
param->removeAndDeallocate();
}
+ skipOptimization:;
}
}
return changed;
diff --git a/tests/language-feature/interfaces/generic-value-parameter-via-interface.slang b/tests/language-feature/interfaces/generic-value-parameter-via-interface.slang
new file mode 100644
index 000000000..abc1131e8
--- /dev/null
+++ b/tests/language-feature/interfaces/generic-value-parameter-via-interface.slang
@@ -0,0 +1,44 @@
+//TEST:INTERPRET(filecheck=CHECK):
+
+interface IFoo
+{
+ void test();
+};
+
+struct Foo<let GenericValue : uint> : IFoo
+{
+ void test()
+ {
+ printf("GenericValue=%d, value=%d\n", GenericValue, value);
+ }
+
+ uint value;
+};
+
+void testInterfaceAsParameter(IFoo foo)
+{
+ foo.test();
+}
+
+void testInterfaceAsGeneric<T:IFoo>(T foo)
+{
+ foo.test();
+}
+
+void main()
+{
+ // CHECK-COUNT-2:GenericValue=0, value=0
+ Foo<0> foo0 = {0};
+ testInterfaceAsParameter(foo0);
+ testInterfaceAsGeneric(foo0);
+
+ // CHECK-COUNT-2:GenericValue=1, value=1
+ Foo<1> foo1 = {1};
+ testInterfaceAsParameter(foo1);
+ testInterfaceAsGeneric(foo1);
+
+ // CHECK-COUNT-2:GenericValue=2, value=2
+ Foo<2> foo2 = {2};
+ testInterfaceAsParameter(foo2);
+ testInterfaceAsGeneric(foo2);
+}