diff options
| -rw-r--r-- | source/slang/slang-ir-remove-unused-generic-param.cpp | 30 | ||||
| -rw-r--r-- | tests/language-feature/interfaces/generic-value-parameter-via-interface.slang | 44 |
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); +} |
