@@ -530,6 +530,13 @@ struct SpecializationContext
530
530
maybeSpecializeFieldAddress (as<IRFieldAddress>(inst));
531
531
break ;
532
532
533
+ case kIROp_getElement :
534
+ maybeSpecializeGetElement (as<IRGetElement>(inst));
535
+ break ;
536
+ case kIROp_getElementPtr :
537
+ maybeSpecializeGetElementAddress (as<IRGetElementPtr>(inst));
538
+ break ;
539
+
533
540
case kIROp_BindExistentialsType :
534
541
maybeSpecializeBindExistentialsType (as<IRBindExistentialsType>(inst));
535
542
break ;
@@ -1506,6 +1513,11 @@ struct SpecializationContext
1506
1513
type = ptrLikeType->getElementType ();
1507
1514
goto top;
1508
1515
}
1516
+ else if (auto arrayType = as<IRArrayTypeBase>(type))
1517
+ {
1518
+ type = arrayType->getElementType ();
1519
+ goto top;
1520
+ }
1509
1521
else if ( auto structType = as<IRStructType>(type) )
1510
1522
{
1511
1523
UInt count = 0 ;
@@ -1695,6 +1707,82 @@ struct SpecializationContext
1695
1707
}
1696
1708
}
1697
1709
1710
+ void maybeSpecializeGetElement (IRGetElement* inst)
1711
+ {
1712
+ auto baseArg = inst->getBase ();
1713
+ if (auto wrapInst = as<IRWrapExistential>(baseArg))
1714
+ {
1715
+ // We have `getElement(wrapExistential(val, ...), index)`
1716
+ // We need to replace this instruction with
1717
+ // `wrapExistential(getElement(val, index), ...)`
1718
+ auto index = inst->getIndex ();
1719
+
1720
+ auto val = wrapInst->getWrappedValue ();
1721
+ auto resultType = inst->getFullType ();
1722
+
1723
+ IRBuilder builder;
1724
+ builder.sharedBuilder = &sharedBuilderStorage;
1725
+ builder.setInsertBefore (inst);
1726
+
1727
+ auto elementType = cast<IRArrayTypeBase>(val->getDataType ())->getElementType ();
1728
+
1729
+ List<IRInst*> slotOperands;
1730
+ UInt slotOperandCount = wrapInst->getSlotOperandCount ();
1731
+
1732
+ for (UInt ii = 0 ; ii < slotOperandCount; ++ii)
1733
+ {
1734
+ slotOperands.add (wrapInst->getSlotOperand (ii));
1735
+ }
1736
+
1737
+ auto newGetElement = builder.emitElementExtract (elementType, val, index );
1738
+
1739
+ auto newWrapExistentialInst = builder.emitWrapExistential (
1740
+ resultType, newGetElement, slotOperandCount, slotOperands.getBuffer ());
1741
+
1742
+ addUsersToWorkList (inst);
1743
+ inst->replaceUsesWith (newWrapExistentialInst);
1744
+ inst->removeAndDeallocate ();
1745
+ }
1746
+ }
1747
+
1748
+ void maybeSpecializeGetElementAddress (IRGetElementPtr* inst)
1749
+ {
1750
+ auto baseArg = inst->getBase ();
1751
+ if (auto wrapInst = as<IRWrapExistential>(baseArg))
1752
+ {
1753
+ // We have `getElementPtr(wrapExistential(val, ...), index)`
1754
+ // We need to replace this instruction with
1755
+ // `wrapExistential(getElementPtr(val, index), ...)`
1756
+ auto index = inst->getIndex ();
1757
+
1758
+ auto val = wrapInst->getWrappedValue ();
1759
+ auto resultType = inst->getFullType ();
1760
+
1761
+ IRBuilder builder;
1762
+ builder.sharedBuilder = &sharedBuilderStorage;
1763
+ builder.setInsertBefore (inst);
1764
+
1765
+ auto elementType = cast<IRArrayTypeBase>(val->getDataType ())->getElementType ();
1766
+
1767
+ List<IRInst*> slotOperands;
1768
+ UInt slotOperandCount = wrapInst->getSlotOperandCount ();
1769
+
1770
+ for (UInt ii = 0 ; ii < slotOperandCount; ++ii)
1771
+ {
1772
+ slotOperands.add (wrapInst->getSlotOperand (ii));
1773
+ }
1774
+
1775
+ auto newElementAddr = builder.emitElementAddress (elementType, val, index );
1776
+
1777
+ auto newWrapExistentialInst = builder.emitWrapExistential (
1778
+ resultType, newElementAddr, slotOperandCount, slotOperands.getBuffer ());
1779
+
1780
+ addUsersToWorkList (inst);
1781
+ inst->replaceUsesWith (newWrapExistentialInst);
1782
+ inst->removeAndDeallocate ();
1783
+ }
1784
+ }
1785
+
1698
1786
UInt calcExistentialTypeParamSlotCount (IRType* type)
1699
1787
{
1700
1788
top:
@@ -1764,7 +1852,9 @@ struct SpecializationContext
1764
1852
type->removeAndDeallocate ();
1765
1853
return ;
1766
1854
}
1767
- else if ( as<IRPointerLikeType>(baseType) || as<IRHLSLStructuredBufferTypeBase>(baseType) )
1855
+ else if ( as<IRPointerLikeType>(baseType) ||
1856
+ as<IRHLSLStructuredBufferTypeBase>(baseType) ||
1857
+ as<IRArrayTypeBase>(baseType))
1768
1858
{
1769
1859
// A `BindExistentials<P<T>, ...>` can be simplified to
1770
1860
// `P<BindExistentials<T, ...>>` when `P` is a pointer-like
@@ -1773,6 +1863,8 @@ struct SpecializationContext
1773
1863
IRType* baseElementType = nullptr ;
1774
1864
if (auto basePtrLikeType = as<IRPointerLikeType>(baseType))
1775
1865
baseElementType = basePtrLikeType->getElementType ();
1866
+ else if (auto arrayType = as<IRArrayTypeBase>(baseType))
1867
+ baseElementType = arrayType->getElementType ();
1776
1868
else if (auto baseSBType = as<IRHLSLStructuredBufferTypeBase>(baseType))
1777
1869
baseElementType = baseSBType->getElementType ();
1778
1870
0 commit comments