diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-ir-specialize.cpp | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff) | |
format
* format
* Minor test fixes
* enable checking cpp format in ci
Diffstat (limited to 'source/slang/slang-ir-specialize.cpp')
| -rw-r--r-- | source/slang/slang-ir-specialize.cpp | 393 |
1 files changed, 205 insertions, 188 deletions
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp index 519c4b260..be7812264 100644 --- a/source/slang/slang-ir-specialize.cpp +++ b/source/slang/slang-ir-specialize.cpp @@ -1,15 +1,16 @@ // slang-ir-specialize.cpp #include "slang-ir-specialize.h" -#include "slang-ir-peephole.h" -#include "slang-ir.h" + +#include "../core/slang-performance-profiler.h" #include "slang-ir-clone.h" +#include "slang-ir-dce.h" #include "slang-ir-insts.h" -#include "slang-ir-ssa-simplification.h" #include "slang-ir-lower-witness-lookup.h" -#include "slang-ir-dce.h" +#include "slang-ir-peephole.h" #include "slang-ir-sccp.h" +#include "slang-ir-ssa-simplification.h" #include "slang-ir-util.h" -#include "../core/slang-performance-profiler.h" +#include "slang-ir.h" namespace Slang { @@ -71,8 +72,7 @@ struct SpecializationContext // An instruction is then fully specialized if and only // if it is in our set. // - bool isInstFullySpecialized( - IRInst* inst) + bool isInstFullySpecialized(IRInst* inst) { // A small wrinkle is that a null instruction pointer // sometimes appears a a type, and so should be treated @@ -80,14 +80,14 @@ struct SpecializationContext // // TODO: It would be nice to remove this wrinkle. // - if (!inst) return true; + if (!inst) + return true; switch (inst->getOp()) { case kIROp_GlobalGenericParam: case kIROp_LookupWitness: - case kIROp_GetTupleElement: - return false; + case kIROp_GetTupleElement: return false; case kIROp_Specialize: // The `specialize` instruction is a bit sepcial, // because it is possible to have a `specialize` @@ -133,7 +133,7 @@ struct SpecializationContext return false; } - // Check if an inst is a dynamic dispatch witness table. + // Check if an inst is a dynamic dispatch witness table. // These insts may not have any uses yet, and do not have side effects, // but should be specialized if necessary. // @@ -146,8 +146,7 @@ struct SpecializationContext // then it is a candidate for specialization itself, so we will have // a query to check for the "all operands fully specialized" case. // - bool areAllOperandsFullySpecialized( - IRInst* inst) + bool areAllOperandsFullySpecialized(IRInst* inst) { if (!isInstFullySpecialized(inst->getFullType())) return false; @@ -171,8 +170,7 @@ struct SpecializationContext HashSet<IRInst*>& workListSet; HashSet<IRInst*>& cleanInsts; - void addToWorkList( - IRInst* inst) + void addToWorkList(IRInst* inst) { if (workListSet.add(inst)) { @@ -188,8 +186,7 @@ struct SpecializationContext // that use its value. In those cases we will call `addUsersToWorkList` // on the instruction that is being modified or replaced. // - void addUsersToWorkList( - IRInst* inst) + void addUsersToWorkList(IRInst* inst) { for (auto use = inst->firstUse; use; use = use->nextUse) { @@ -224,9 +221,7 @@ struct SpecializationContext // suitable for use as a replacement for the `specialize(...)` // instruction. // - IRInst* specializeGeneric( - IRGeneric* genericVal, - IRSpecialize* specializeInst) + IRInst* specializeGeneric(IRGeneric* genericVal, IRSpecialize* specializeInst) { // We need to fold the generic arguments here in order to uniquely identify // which specializations need to be generated. @@ -316,8 +311,7 @@ struct SpecializationContext // that the generic is actually amenable to specialization, // by looking at whether it is a definition or a declaration. // - bool canSpecializeGeneric( - IRGeneric* generic) + bool canSpecializeGeneric(IRGeneric* generic) { // It is possible to have multiple "layers" of generics // (e.g., when a generic function is nested in a generic @@ -353,11 +347,13 @@ struct SpecializationContext // The solution is to remove the `$G` syntax and replace that with // resolved types too. bool intrinsicNeedsSpecialization = false; - for(const auto dec : val->getDecorations()) + for (const auto dec : val->getDecorations()) { - // TODO: We should probably take into account our target to see if the intrinsic applies - if(const auto intrinsicDec = as<IRTargetIntrinsicDecoration>(dec)) - intrinsicNeedsSpecialization = intrinsicNeedsSpecialization || intrinsicDec->hasPredicate(); + // TODO: We should probably take into account our target to see if the intrinsic + // applies + if (const auto intrinsicDec = as<IRTargetIntrinsicDecoration>(dec)) + intrinsicNeedsSpecialization = + intrinsicNeedsSpecialization || intrinsicDec->hasPredicate(); } // We can't specialize a generic if it is marked as @@ -392,8 +388,7 @@ struct SpecializationContext // `specialize(g, a, b, c, ...)` instruction and performs // specialization if it is possible. // - bool maybeSpecializeGeneric( - IRSpecialize* specInst) + bool maybeSpecializeGeneric(IRSpecialize* specInst) { // We will only attempt to specialize when all of the // operands to the `speicalize(...)` instruction are @@ -421,16 +416,16 @@ struct SpecializationContext if (!canSpecializeGeneric(genericVal)) { // We have to consider a special case here if baseVal is - // an intrinsic, and contains a custom differential. + // an intrinsic, and contains a custom differential. // This is a case where the base cannot be specialized since it has // no body, but the custom should be specialized. - // A better way to handle this would be to grab a reference to the + // A better way to handle this would be to grab a reference to the // appropriate custom differential, if one exists, at checking time // during CheckInvoke() and construct it's specialization args appropriately. - // + // // For now, we will overwrite the specialization args for the differential // using the args for the base. - // + // auto genericReturnVal = findInnerMostGenericReturnVal(genericVal); if (genericReturnVal->findDecoration<IRTargetIntrinsicDecoration>()) { @@ -464,7 +459,8 @@ struct SpecializationContext IRBuilder builder(module); - // Specialize the custom derivative function type with the original arguments. + // Specialize the custom derivative function type with the original + // arguments. builder.setInsertInto(module); auto newDiffFuncType = builder.emitSpecializeInst( builder.getTypeKind(), @@ -480,9 +476,9 @@ struct SpecializationContext argCount, args.getArrayView().getBuffer()); - // Add the new spec insts to the list so they get specialized with + // Add the new spec insts to the list so they get specialized with // the usual logic. - // + // addToWorkList(newDiffFuncType); addToWorkList(newDiffFunc); @@ -526,8 +522,7 @@ struct SpecializationContext // at a time, and try to perform whatever specialization // is appropriate based on its opcode. // - bool maybeSpecializeInst( - IRInst* inst) + bool maybeSpecializeInst(IRInst* inst) { switch (inst->getOp()) { @@ -565,45 +560,34 @@ struct SpecializationContext // but in order to realize these we often need to propagate // through local simplification on values of existential type. // - case kIROp_ExtractExistentialType: - return maybeSpecializeExtractExistentialType(inst); - case kIROp_ExtractExistentialValue: - return maybeSpecializeExtractExistentialValue(inst); + case kIROp_ExtractExistentialType: return maybeSpecializeExtractExistentialType(inst); + case kIROp_ExtractExistentialValue: return maybeSpecializeExtractExistentialValue(inst); case kIROp_ExtractExistentialWitnessTable: return maybeSpecializeExtractExistentialWitnessTable(inst); - case kIROp_Load: - return maybeSpecializeLoad(as<IRLoad>(inst)); + case kIROp_Load: return maybeSpecializeLoad(as<IRLoad>(inst)); - case kIROp_FieldExtract: - return maybeSpecializeFieldExtract(as<IRFieldExtract>(inst)); - case kIROp_FieldAddress: - return maybeSpecializeFieldAddress(as<IRFieldAddress>(inst)); + case kIROp_FieldExtract: return maybeSpecializeFieldExtract(as<IRFieldExtract>(inst)); + case kIROp_FieldAddress: return maybeSpecializeFieldAddress(as<IRFieldAddress>(inst)); - case kIROp_GetElement: - return maybeSpecializeGetElement(as<IRGetElement>(inst)); + case kIROp_GetElement: return maybeSpecializeGetElement(as<IRGetElement>(inst)); case kIROp_GetElementPtr: return maybeSpecializeGetElementAddress(as<IRGetElementPtr>(inst)); case kIROp_BindExistentialsType: return maybeSpecializeBindExistentialsType(as<IRBindExistentialsType>(inst)); - case kIROp_Expand: - return maybeSpecializeExpand(as<IRExpand>(inst)); + case kIROp_Expand: return maybeSpecializeExpand(as<IRExpand>(inst)); - case kIROp_GetTupleElement: - return maybeSpecializeFoldableInst(inst); + case kIROp_GetTupleElement: return maybeSpecializeFoldableInst(inst); case kIROp_TypePack: - case kIROp_TupleType: - return maybeSpecializeTypePackOrTupleType(inst); + case kIROp_TupleType: return maybeSpecializeTypePackOrTupleType(inst); case kIROp_MakeValuePack: - case kIROp_MakeTuple: - return maybeSpecializeMakeValuePackOrTuple(inst); + case kIROp_MakeTuple: return maybeSpecializeMakeValuePackOrTuple(inst); - case kIROp_CountOf: - return maybeSpecializeCountOf(inst); + case kIROp_CountOf: return maybeSpecializeCountOf(inst); case kIROp_Func: @@ -670,9 +654,13 @@ struct SpecializationContext builder.setInsertBefore(inst); IRInst* newInst; if (inst->getOp() == kIROp_TypePack) - newInst = builder.getTypePack(flattendOperands.getCount(), (IRType* const*)flattendOperands.getArrayView().getBuffer()); + newInst = builder.getTypePack( + flattendOperands.getCount(), + (IRType* const*)flattendOperands.getArrayView().getBuffer()); else - newInst = builder.getTupleType(flattendOperands.getCount(), (IRType* const*)flattendOperands.getArrayView().getBuffer()); + newInst = builder.getTupleType( + flattendOperands.getCount(), + (IRType* const*)flattendOperands.getArrayView().getBuffer()); inst->replaceUsesWith(newInst); inst->removeAndDeallocate(); addUsersToWorkList(newInst); @@ -709,9 +697,15 @@ struct SpecializationContext builder.setInsertBefore(inst); IRInst* newInst = nullptr; if (inst->getOp() == kIROp_MakeValuePack) - newInst = builder.emitMakeValuePack(inst->getFullType(), flattendOperands.getCount(), flattendOperands.getArrayView().getBuffer()); + newInst = builder.emitMakeValuePack( + inst->getFullType(), + flattendOperands.getCount(), + flattendOperands.getArrayView().getBuffer()); else - newInst = builder.emitMakeTuple(inst->getFullType(), flattendOperands.getCount(), flattendOperands.getArrayView().getBuffer()); + newInst = builder.emitMakeTuple( + inst->getFullType(), + flattendOperands.getCount(), + flattendOperands.getArrayView().getBuffer()); inst->replaceUsesWith(newInst); inst->removeAndDeallocate(); @@ -722,25 +716,21 @@ struct SpecializationContext bool maybeSpecializeCountOf(IRInst* inst) { auto operand = inst->getOperand(0); - + // If operand is a value, make sure we are working on its type. switch (operand->getOp()) { case kIROp_MakeValuePack: - case kIROp_MakeTuple: - operand = operand->getDataType(); - break; + case kIROp_MakeTuple: operand = operand->getDataType(); break; } // We can only figure out the count of a type pack or tuple type. switch (operand->getOp()) { case kIROp_TypePack: - case kIROp_TupleType: - break; - default: - return false; + case kIROp_TupleType: break; + default: return false; } // If none of the element type is a TypePack, we can just return the count. @@ -750,9 +740,8 @@ struct SpecializationContext { case kIROp_Param: case kIROp_TypePack: - case kIROp_ExpandTypeOrVal: - return false; - } + case kIROp_ExpandTypeOrVal: return false; + } } IRBuilder builder(module); builder.setInsertBefore(inst); @@ -765,10 +754,9 @@ struct SpecializationContext // Specializing lookup on witness tables is a general // transformation that helps with both generic and - // existential-based code. + // existential-based code. // - bool maybeSpecializeWitnessLookup( - IRLookupWitnessMethod* lookupInst) + bool maybeSpecializeWitnessLookup(IRLookupWitnessMethod* lookupInst) { // Note: While we currently have named the instruction // `lookup_witness_method`, the `method` part is a misnomer @@ -837,9 +825,7 @@ struct SpecializationContext // key in a concrete witness table, so let's // define that now. // - IRInst* findWitnessVal( - IRWitnessTable* witnessTable, - IRInst* requirementKey) + IRInst* findWitnessVal(IRWitnessTable* witnessTable, IRInst* requirementKey) { // A witness table is basically just a container // for key-value pairs, and so the best we can @@ -864,7 +850,8 @@ struct SpecializationContext for (auto child : dictInst->getChildren()) { auto item = as<IRSpecializationDictionaryItem>(child); - if (!item) continue; + if (!item) + continue; IRSimpleSpecializationKey key; bool shouldSkip = false; for (UInt i = 0; i < item->getOperandCount(); i++) @@ -891,7 +878,8 @@ struct SpecializationContext } if (shouldSkip) continue; - auto value = as<typename std::remove_pointer<typename TDict::ValueType>::type>(item->getOperand(0)); + auto value = as<typename std::remove_pointer<typename TDict::ValueType>::type>( + item->getOperand(0)); SLANG_ASSERT(value); dict[key] = value; } @@ -913,8 +901,7 @@ struct SpecializationContext case kIROp_ExistentialTypeSpecializationDictionary: _readSpecializationDictionaryImpl(existentialSpecializedStructs, child); break; - default: - continue; + default: continue; } } } @@ -933,13 +920,18 @@ struct SpecializationContext continue; for (auto keyVal : key.vals) { - if (!keyVal->parent) goto next; + if (!keyVal->parent) + goto next; } { args.clear(); args.add(value); args.addRange(key.vals); - builder.emitIntrinsicInst(nullptr, kIROp_SpecializationDictionaryItem, (UInt)args.getCount(), args.getBuffer()); + builder.emitIntrinsicInst( + nullptr, + kIROp_SpecializationDictionaryItem, + (UInt)args.getCount(), + args.getBuffer()); } next:; } @@ -947,9 +939,18 @@ struct SpecializationContext void writeSpecializationDictionaries() { auto moduleInst = module->getModuleInst(); - _writeSpecializationDictionaryImpl(genericSpecializations, kIROp_GenericSpecializationDictionary, moduleInst); - _writeSpecializationDictionaryImpl(existentialSpecializedFuncs, kIROp_ExistentialFuncSpecializationDictionary, moduleInst); - _writeSpecializationDictionaryImpl(existentialSpecializedStructs, kIROp_ExistentialTypeSpecializationDictionary, moduleInst); + _writeSpecializationDictionaryImpl( + genericSpecializations, + kIROp_GenericSpecializationDictionary, + moduleInst); + _writeSpecializationDictionaryImpl( + existentialSpecializedFuncs, + kIROp_ExistentialFuncSpecializationDictionary, + moduleInst); + _writeSpecializationDictionaryImpl( + existentialSpecializedStructs, + kIROp_ExistentialTypeSpecializationDictionary, + moduleInst); } // All of the machinery for generic specialization @@ -1028,9 +1029,7 @@ struct SpecializationContext // specialization opportunities (generic specialization, // existential specialization, simplifications, etc.) // - if (inst->hasUses() || - inst->mightHaveSideEffects() || - isWitnessTableType(inst)) + if (inst->hasUses() || inst->mightHaveSideEffects() || isWitnessTableType(inst)) { hasSpecialization |= maybeSpecializeInst(inst); } @@ -1075,7 +1074,7 @@ struct SpecializationContext // builtin type/function, or some of the type arguments are unknown at compile time, in // which case we will rely on a follow up pass the translate it into a dynamic dispatch // function. - // + // // Now we consider lower lookupWitnessMethod insts into dynamic dispatch calls, // which may open up more specialization opportunities. // @@ -1138,7 +1137,10 @@ struct SpecializationContext builder.setInsertBefore(oldSpecializedCallee); auto calleeType = builder.getFuncType(1, &newContainerType, newElementType); auto newSpecialize = builder.emitSpecializeInst( - calleeType, oldSpecialize->getBase(), 1, (IRInst**)&newElementType); + calleeType, + oldSpecialize->getBase(), + 1, + (IRInst**)&newElementType); return newSpecialize; } @@ -1155,7 +1157,7 @@ struct SpecializationContext if (auto wrapExistential = as<IRWrapExistential>(inst->getArg(0))) { if (auto sbType = as<IRHLSLStructuredBufferTypeBase>( - wrapExistential->getWrappedValue()->getDataType())) + wrapExistential->getWrappedValue()->getDataType())) { // We are seeing the instruction sequence in the form of // .operator[](wrapExistential(structuredBuffer), idx). @@ -1177,21 +1179,31 @@ struct SpecializationContext { slotOperands.add(wrapExistential->getSlotOperand(ii)); } - // The old callee should be in the form of `specialize(.operator[], IInterfaceType)`, - // we should update it to be `specialize(.operator[], elementType)`, so the return type - // of the load call is `elementType`. + // The old callee should be in the form of `specialize(.operator[], + // IInterfaceType)`, we should update it to be `specialize(.operator[], + // elementType)`, so the return type of the load call is `elementType`. - // A subscript operation on mutable buffers returns a ptr type instead of a value type. - // We need to make sure the pointer-ness is preserved correctly. + // A subscript operation on mutable buffers returns a ptr type instead of a + // value type. We need to make sure the pointer-ness is preserved correctly. auto innerResultType = elementType; if (const auto ptrResultType = as<IRPtrType>(inst->getDataType())) { innerResultType = builder.getPtrType(elementType); } - auto newCallee = getNewSpecializedBufferLoadCallee(inst->getCallee(), sbType, innerResultType); - auto newCall = builder.emitCallInst(innerResultType, newCallee, (UInt)args.getCount(), args.getArrayView().getBuffer()); + auto newCallee = getNewSpecializedBufferLoadCallee( + inst->getCallee(), + sbType, + innerResultType); + auto newCall = builder.emitCallInst( + innerResultType, + newCallee, + (UInt)args.getCount(), + args.getArrayView().getBuffer()); auto newWrapExistential = builder.emitWrapExistential( - resultType, newCall, slotOperandCount, slotOperands.getArrayView().getBuffer()); + resultType, + newCall, + slotOperandCount, + slotOperands.getArrayView().getBuffer()); inst->replaceUsesWith(newWrapExistential); inst->removeAndDeallocate(); addUsersToWorkList(newWrapExistential); @@ -1311,7 +1323,7 @@ struct SpecializationContext // specialized functions that we generate (similar to how generic // specialization works). Therefore we will construct a key // for use when caching the specialized functions. - // + // IRSimpleSpecializationKey key; // The specialized callee will always depend on the unspecialized @@ -1444,16 +1456,23 @@ struct SpecializationContext builder->setInsertBefore(inst); auto callResultType = specializedCallee->getResultType(); IRInst* newCall = builder->emitCallInst( - callResultType, specializedCallee, (UInt)newArgs.getCount(), newArgs.getArrayView().getBuffer()); + callResultType, + specializedCallee, + (UInt)newArgs.getCount(), + newArgs.getArrayView().getBuffer()); if (as<IRInterfaceType>(inst->getDataType())) { // If the result of the original call is specialized to a concrete type, // we need to wrap it back into an existential type. // - if (auto resultWitnessDecor = specializedCallee->findDecoration<IRResultWitnessDecoration>()) + if (auto resultWitnessDecor = + specializedCallee->findDecoration<IRResultWitnessDecoration>()) { - newCall = builder->emitMakeExistential(inst->getDataType(), newCall, resultWitnessDecor->getWitness()); + newCall = builder->emitMakeExistential( + inst->getDataType(), + newCall, + resultWitnessDecor->getWitness()); } } @@ -1524,10 +1543,8 @@ struct SpecializationContext case kIROp_Call: case kIROp_ExtractExistentialType: case kIROp_CreateExistentialObject: - case kIROp_Param: - return false; - default: - break; + case kIROp_Param: return false; + default: break; } for (UInt i = 0; i < curInst->getOperandCount(); ++i) @@ -1595,9 +1612,7 @@ struct SpecializationContext // in concrete types for existentials is similar to other cases of // specialization in the compiler. // - IRFunc* createExistentialSpecializedFunc( - IRCall* oldCall, - IRFunc* oldFunc) + IRFunc* createExistentialSpecializedFunc(IRCall* oldCall, IRFunc* oldFunc) { // We will make use of the infrastructure for cloning // IR code, that is defined in `ir-clone.{h,cpp}`. @@ -1680,7 +1695,8 @@ struct SpecializationContext // value for the original parameter (since it will have the // correct existential type, and stores the right witness table). // - auto newMakeExistential = builder->emitMakeExistential(oldParam->getFullType(), newParam, witnessTable); + auto newMakeExistential = + builder->emitMakeExistential(oldParam->getFullType(), newParam, witnessTable); replacementVal = newMakeExistential; } else if (auto oldWrapExistential = as<IRWrapExistential>(arg)) @@ -1733,11 +1749,7 @@ struct SpecializationContext // to perform the second phase of cloning, which will recursively // clone any nested decorations, blocks, and instructions. // - cloneInstDecorationsAndChildren( - &cloneEnv, - builder->getModule(), - oldFunc, - newFunc); + cloneInstDecorationsAndChildren(&cloneEnv, builder->getModule(), oldFunc, newFunc); // // In order to construct the type of the new function, we @@ -2149,10 +2161,7 @@ struct SpecializationContext slotOperands.add(wrapInst->getSlotOperand(slotOperandOffset + ii)); } - auto newGetField = builder.emitFieldExtract( - foundFieldType, - val, - fieldKey); + auto newGetField = builder.emitFieldExtract(foundFieldType, val, fieldKey); auto newWrapExistentialInst = builder.emitWrapExistential( resultType, @@ -2239,10 +2248,8 @@ struct SpecializationContext slotOperands.add(wrapInst->getSlotOperand(slotOperandOffset + ii)); } - auto newGetFieldAddr = builder.emitFieldAddress( - builder.getPtrType(foundFieldType), - val, - fieldKey); + auto newGetFieldAddr = + builder.emitFieldAddress(builder.getPtrType(foundFieldType), val, fieldKey); auto newWrapExistentialInst = builder.emitWrapExistential( resultType, @@ -2287,7 +2294,10 @@ struct SpecializationContext auto newGetElement = builder.emitElementExtract(elementType, val, index); auto newWrapExistentialInst = builder.emitWrapExistential( - resultType, newGetElement, slotOperandCount, slotOperands.getArrayView().getBuffer()); + resultType, + newGetElement, + slotOperandCount, + slotOperands.getArrayView().getBuffer()); addUsersToWorkList(inst); inst->replaceUsesWith(newWrapExistentialInst); @@ -2325,7 +2335,10 @@ struct SpecializationContext auto newElementAddr = builder.emitElementAddress(val, index); auto newWrapExistentialInst = builder.emitWrapExistential( - resultType, newElementAddr, slotOperandCount, slotOperands.getArrayView().getBuffer()); + resultType, + newElementAddr, + slotOperandCount, + slotOperands.getArrayView().getBuffer()); addUsersToWorkList(inst); inst->replaceUsesWith(newWrapExistentialInst); @@ -2388,21 +2401,22 @@ struct SpecializationContext // and one for the witness table. // SLANG_ASSERT(slotOperandCount == 2); - if (slotOperandCount < 2) return false; + if (slotOperandCount < 2) + return false; auto concreteType = (IRType*)type->getExistentialArg(0); auto witnessTable = type->getExistentialArg(1); - auto newVal = builder.getBoundInterfaceType(baseInterfaceType, concreteType, witnessTable); + auto newVal = + builder.getBoundInterfaceType(baseInterfaceType, concreteType, witnessTable); addUsersToWorkList(type); type->replaceUsesWith(newVal); type->removeAndDeallocate(); return true; } - else if (as<IRPointerLikeType>(baseType) || - as<IRHLSLStructuredBufferTypeBase>(baseType) || - as<IRArrayTypeBase>(baseType) || - as<IRAttributedType>(baseType)) + else if ( + as<IRPointerLikeType>(baseType) || as<IRHLSLStructuredBufferTypeBase>(baseType) || + as<IRArrayTypeBase>(baseType) || as<IRAttributedType>(baseType)) { // A `BindExistentials<P<T>, ...>` can be simplified to // `P<BindExistentials<T, ...>>` when `P` is a pointer-like @@ -2502,22 +2516,25 @@ struct SpecializationContext type->replaceUsesWith(newStructType); type->removeAndDeallocate(); return true; - } return false; } - IRInst* specializeExpandChildInst(IRCloneEnv& cloneEnv, IRBuilder* builder, IRInst* childInst, UInt index) + IRInst* specializeExpandChildInst( + IRCloneEnv& cloneEnv, + IRBuilder* builder, + IRInst* childInst, + UInt index) { IRCloneEnv freshEnv; IRCloneEnv* subEnv = &cloneEnv; switch (childInst->getOp()) { case kIROp_Expand: - { - subEnv = &freshEnv; - break; - } + { + subEnv = &freshEnv; + break; + } } auto newInst = cloneInst(subEnv, builder, childInst); if (newInst != childInst) @@ -2548,7 +2565,8 @@ struct SpecializationContext } else if (as<IRTypeKind>(type) || as<IRTypeType>(type)) { - auto newTypePack = builder.getTypePack(elements.getCount(), (IRType* const*)elements.getBuffer()); + auto newTypePack = + builder.getTypePack(elements.getCount(), (IRType* const*)elements.getBuffer()); resultPack = newTypePack; } else @@ -2579,13 +2597,14 @@ struct SpecializationContext } if (elementCount == 0) { - auto resultPack = makeSpecializedPack(builder, expandInst->getDataType(), elements.getArrayView()); + auto resultPack = + makeSpecializedPack(builder, expandInst->getDataType(), elements.getArrayView()); expandInst->replaceUsesWith(resultPack); expandInst->removeAndDeallocate(); addUsersToWorkList(resultPack); return true; } - + bool isMultiBlock = as<IRYield>(expandInst->getFirstBlock()->getTerminator()) == nullptr; for (UInt i = 0; i < elementCount; i++) @@ -2595,7 +2614,7 @@ struct SpecializationContext IRBlock* mergeBlock = nullptr; if (isMultiBlock) { - IRBlock* firstBlock = nullptr; + IRBlock* firstBlock = nullptr; for (auto childBlock : expandInst->getBlocks()) { auto newBlock = subBuilder.emitBlock(); @@ -2612,7 +2631,8 @@ struct SpecializationContext auto indexParam = expandInst->getFirstBlock()->getFirstParam(); SLANG_ASSERT(indexParam); - cloneEnv.mapOldValToNew[indexParam] = subBuilder.getIntValue(subBuilder.getIntType(), i); + cloneEnv.mapOldValToNew[indexParam] = + subBuilder.getIntValue(subBuilder.getIntType(), i); for (auto childBlock : expandInst->getBlocks()) { @@ -2636,10 +2656,10 @@ struct SpecializationContext addToWorkList(childBlock); } } - } - IRInst* resultPack = makeSpecializedPack(builder, expandInst->getDataType(), elements.getArrayView()); + IRInst* resultPack = + makeSpecializedPack(builder, expandInst->getDataType(), elements.getArrayView()); if (isMultiBlock) { auto currentBlock = builder.getBlock(); @@ -2709,8 +2729,7 @@ struct SpecializationContext switch (inst->getOp()) { - default: - break; + default: break; case kIROp_GlobalGenericParam: case kIROp_BindGlobalGenericParam: @@ -2773,7 +2792,10 @@ struct SpecializationContext newParams.add(newParam); } setInsertBeforeOrdinaryInst(&builder, param); - auto val = builder.emitMakeValuePack(typePack, (UInt)newParams.getCount(), newParams.getArrayView().getBuffer()); + auto val = builder.emitMakeValuePack( + typePack, + (UInt)newParams.getCount(), + newParams.getArrayView().getBuffer()); param->replaceUsesWith(val); param->removeAndDeallocate(); addUsersToWorkList(val); @@ -2809,9 +2831,13 @@ struct SpecializationContext auto arg = call->getArg(i); if (auto typePack = as<IRTypePack>(arg->getDataType())) { - for (UInt elementIndex = 0; elementIndex < typePack->getOperandCount(); elementIndex++) + for (UInt elementIndex = 0; elementIndex < typePack->getOperandCount(); + elementIndex++) { - auto newArg = builder.emitGetTupleElement((IRType*)typePack->getOperand(elementIndex), arg, elementIndex); + auto newArg = builder.emitGetTupleElement( + (IRType*)typePack->getOperand(elementIndex), + arg, + elementIndex); newArgs.add(newArg); } } @@ -2820,19 +2846,16 @@ struct SpecializationContext newArgs.add(arg); } } - auto newCall = builder.emitCallInst(call->getFullType(), call->getCallee(), newArgs.getArrayView()); + auto newCall = + builder.emitCallInst(call->getFullType(), call->getCallee(), newArgs.getArrayView()); call->replaceUsesWith(newCall); call->transferDecorationsTo(newCall); call->removeAndDeallocate(); return newCall; } - }; -bool specializeModule( - TargetProgram* target, - IRModule* module, - DiagnosticSink* sink) +bool specializeModule(TargetProgram* target, IRModule* module, DiagnosticSink* sink) { SLANG_PROFILE; SpecializationContext context(module, target); @@ -2855,22 +2878,18 @@ void finalizeSpecialization(IRModule* module) switch (inst->getOp()) { - default: - break; + default: break; case kIROp_StructKey: case kIROp_Func: - for (auto decor = inst->getFirstDecoration(); decor; ) + for (auto decor = inst->getFirstDecoration(); decor;) { auto nextDecor = decor->getNextDecoration(); switch (decor->getOp()) { case kIROp_DispatchFuncDecoration: - case kIROp_ResultWitnessDecoration: - decor->removeAndDeallocate(); - break; - default: - break; + case kIROp_ResultWitnessDecoration: decor->removeAndDeallocate(); break; + default: break; } decor = nextDecor; } @@ -2878,9 +2897,7 @@ void finalizeSpecialization(IRModule* module) case kIROp_ExistentialFuncSpecializationDictionary: case kIROp_ExistentialTypeSpecializationDictionary: - case kIROp_GenericSpecializationDictionary: - inst->removeAndDeallocate(); - break; + case kIROp_GenericSpecializationDictionary: inst->removeAndDeallocate(); break; } } } @@ -2903,7 +2920,7 @@ IRInst* specializeGenericImpl( // the concrete arguments that were provided // by the `specialize(...)` instruction. // - IRCloneEnv env; + IRCloneEnv env; // We will walk through the parameters of the generic and // register the corresponding argument of the `specialize` @@ -2935,11 +2952,8 @@ IRInst* specializeGenericImpl( builder->setInsertBefore(genericVal); List<IRInst*> pendingWorkList; - SLANG_DEFER - ( - for (Index ii = pendingWorkList.getCount() - 1; ii >= 0; ii--) - context->addToWorkList(pendingWorkList[ii]); - ); + SLANG_DEFER(for (Index ii = pendingWorkList.getCount() - 1; ii >= 0; ii--) + context->addToWorkList(pendingWorkList[ii]);); // Now we will run through the body of the generic and // clone each of its instructions into the global scope, @@ -2970,19 +2984,21 @@ IRInst* specializeGenericImpl( // Clone decorations on the orignal `specialize` inst over to the newly specialized // value. - cloneInstDecorationsAndChildren( - &env, module, specializeInst, specializedVal); + cloneInstDecorationsAndChildren(&env, module, specializeInst, specializedVal); - // Perform IR simplifications to fold constants in this specialized value if it is a function, so - // further specializations from the specialized function will have as simple specialization - // arguments as possible to avoid creating specializations that eventually simplified into - // the same thing. + // Perform IR simplifications to fold constants in this specialized value if it is a + // function, so further specializations from the specialized function will have as + // simple specialization arguments as possible to avoid creating specializations + // that eventually simplified into the same thing. if (context) { if (auto func = as<IRFunc>(specializedVal)) { context->tryExpandParameterPack(func); - simplifyFunc(context->targetProgram, func, IRSimplificationOptions::getFast(context->targetProgram)); + simplifyFunc( + context->targetProgram, + func, + IRSimplificationOptions::getFast(context->targetProgram)); } } pendingWorkList.add(specializedVal); @@ -3017,16 +3033,17 @@ IRInst* specializeGenericImpl( UNREACHABLE_RETURN(nullptr); } -IRInst* specializeGeneric( - IRSpecialize* specializeInst) +IRInst* specializeGeneric(IRSpecialize* specializeInst) { auto baseGeneric = as<IRGeneric>(specializeInst->getBase()); SLANG_ASSERT(baseGeneric); - if (!baseGeneric) return specializeInst; + if (!baseGeneric) + return specializeInst; auto module = specializeInst->getModule(); SLANG_ASSERT(module); - if (!module) return specializeInst; + if (!module) + return specializeInst; return specializeGenericImpl(baseGeneric, specializeInst, module, nullptr); } |
