90#include <mlir/Dialect/SCF/IR/SCF.h>
91#include <mlir/IR/BuiltinOps.h>
92#include <mlir/Pass/PassManager.h>
93#include <mlir/Transforms/DialectConversion.h>
94#include <mlir/Transforms/Passes.h>
96#include <llvm/Support/Debug.h>
102#define GEN_PASS_DEF_ARRAYTOSCALARPASS
113#define DEBUG_TYPE "llzk-array-to-scalar"
119 return at.hasStaticShape() && !llvm::isa<NoneType>(at.
getElementType()) ? at :
nullptr;
123inline ArrayType splittableArray(Type t) {
124 if (
ArrayType at = dyn_cast<ArrayType>(t)) {
125 return splittableArray(at);
133inline bool containsSplittableArrayType(ArrayRef<Type> types) {
134 for (Type t : types) {
135 if (splittableArray(t)) {
143template <
typename T>
bool containsSplittableArrayType(ValueTypeRange<T> types) {
144 for (Type t : types) {
145 if (splittableArray(t)) {
154size_t splitArrayTypeTo(Type t, SmallVector<Type> &collect) {
160 collect.push_back(t);
166template <
typename TypeCollection>
167inline void splitArrayTypeTo(
168 TypeCollection types, SmallVector<Type> &collect, SmallVector<size_t> *originalIdxToSize
170 for (Type t : types) {
171 size_t count = splitArrayTypeTo(t, collect);
172 if (originalIdxToSize) {
173 originalIdxToSize->push_back(count);
180template <
typename TypeCollection>
181inline SmallVector<Type>
182splitArrayType(TypeCollection types, SmallVector<size_t> *originalIdxToSize =
nullptr) {
183 SmallVector<Type> collect;
184 splitArrayTypeTo(types, collect, originalIdxToSize);
189static std::string formatSplitArrayIndexSuffix(ArrayAttr index) {
191 llvm::raw_string_ostream os(suffix);
192 for (Attribute attr : index) {
194 attr.print(os,
true);
201static SmallVector<std::string> getSplitArrayIndexSuffixes(Type type) {
202 SmallVector<std::string> suffixes;
203 if (
ArrayType at = splittableArray(type)) {
205 assert(indices.has_value() &&
"static-shape arrays must provide subelement indices");
206 suffixes.reserve(indices->size());
207 for (ArrayAttr index : *indices) {
208 suffixes.push_back(formatSplitArrayIndexSuffix(index));
215CallOp newCallOpWithSplitResults(
218 OpBuilder::InsertionGuard guard(rewriter);
219 rewriter.setInsertionPointAfter(oldCall);
221 Operation::result_range oldResults = oldCall.getResults();
223 oldCall.getLoc(), splitArrayType(oldResults.getTypes()), oldCall, adaptor.
getMapOperands(),
227 auto newResults = newCall.getResults().begin();
228 for (Value oldVal : oldResults) {
229 if (
ArrayType at = splittableArray(oldVal.getType())) {
230 Location loc = oldVal.getLoc();
233 rewriter.replaceAllUsesWith(oldVal, newArray);
239 assert(std::cmp_equal(allIndices->size(), at.getNumElements()));
240 for (ArrayAttr subIdx : allIndices.value()) {
245 rewriter.replaceAllUsesWith(oldVal, *newResults);
250 rewriter.eraseOp(oldCall);
257void processInputOperand(
258 Location loc, Value operand, SmallVector<Value> &newOperands,
259 ConversionPatternRewriter &rewriter
261 if (
ArrayType at = splittableArray(operand.getType())) {
263 assert(indices.has_value() &&
"passed earlier hasStaticShape() check");
264 for (ArrayAttr index : indices.value()) {
268 newOperands.push_back(operand);
273void processInputOperands(
274 ValueRange operands, MutableOperandRange outputOpRef, Operation *op,
275 ConversionPatternRewriter &rewriter
277 SmallVector<Value> newOperands;
278 for (Value v : operands) {
279 processInputOperand(op->getLoc(), v, newOperands, rewriter);
281 rewriter.modifyOpInPlace(op, [&outputOpRef, &newOperands]() {
282 outputOpRef.assign(ValueRange(newOperands));
288enum Direction : std::uint8_t {
297template <Direction dir>
298inline void rewriteImpl(
300 ConversionPatternRewriter &rewriter
303 Location loc = op.getLoc();
304 MLIRContext *ctx = op.getContext();
313 assert(std::cmp_equal(subIndices->size(), smallType.getNumElements()));
314 for (ArrayAttr indexingTail : subIndices.value()) {
315 SmallVector<Attribute> joined;
316 joined.append(indexAsAttr.begin(), indexAsAttr.end());
317 joined.append(indexingTail.begin(), indexingTail.end());
318 ArrayAttr fullIndex = ArrayAttr::get(ctx, joined);
320 if constexpr (dir == Direction::SMALL_TO_LARGE) {
323 }
else if constexpr (dir == Direction::LARGE_TO_SMALL) {
333class SplitInsertArrayOp :
public OpConversionPattern<InsertArrayOp> {
335 using OpConversionPattern<
InsertArrayOp>::OpConversionPattern;
338 return !containsSplittableArrayType(op.
getRvalue().getType());
341 LogicalResult matchAndRewrite(
342 InsertArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
348 rewriteImpl<SMALL_TO_LARGE>(
349 llvm::cast<ArrayAccessOpInterface>(op.getOperation()), at, adaptor.getRvalue(),
350 adaptor.getArrRef(), rewriter
352 rewriter.eraseOp(op);
358class SplitExtractArrayOp :
public OpConversionPattern<ExtractArrayOp> {
363 return !containsSplittableArrayType(op.
getResult().getType());
366 LogicalResult matchAndRewrite(
367 ExtractArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
374 auto newArray = rewriter.replaceOpWithNewOp<
CreateArrayOp>(op, at);
375 rewriteImpl<LARGE_TO_SMALL>(
376 llvm::cast<ArrayAccessOpInterface>(op.getOperation()), at, newArray, adaptor.getArrRef(),
384class SplitInitFromCreateArrayOp :
public OpConversionPattern<CreateArrayOp> {
386 using OpConversionPattern<
CreateArrayOp>::OpConversionPattern;
390 LogicalResult matchAndRewrite(
391 CreateArrayOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
399 rewriter.setInsertionPointAfter(op);
400 Location loc = op.getLoc();
402 for (
auto [i, init] : llvm::enumerate(adaptor.getElements())) {
404 std::optional<SmallVector<Value>> multiDimIdxVals =
408 assert(multiDimIdxVals.has_value());
417class SplitArrayInFuncDefOp :
public OpConversionPattern<FuncDefOp> {
419 using OpConversionPattern<
FuncDefOp>::OpConversionPattern;
427 matchAndRewrite(
FuncDefOp op, OpAdaptor, ConversionPatternRewriter &rewriter)
const override {
433 SmallVector<size_t> originalInputIdxToSize, originalResultIdxToSize;
438 SmallVector<Type> convertInputs(ArrayRef<Type> origTypes)
override {
439 return splitArrayType(origTypes, &originalInputIdxToSize);
441 SmallVector<Type> convertResults(ArrayRef<Type> origTypes)
override {
442 return splitArrayType(origTypes, &originalResultIdxToSize);
444 ArrayAttr convertInputAttrs(ArrayAttr origAttrs, SmallVector<Type> newTypes)
override {
451 ArrayAttr convertResultAttrs(ArrayAttr origAttrs, SmallVector<Type> newTypes)
override {
463 void processBlockArgs(Block &entryBlock, RewriterBase &rewriter)
override {
464 OpBuilder::InsertionGuard guard(rewriter);
465 rewriter.setInsertionPointToStart(&entryBlock);
467 for (
unsigned i = 0; i < entryBlock.getNumArguments();) {
468 Value oldV = entryBlock.getArgument(i);
469 if (
ArrayType at = splittableArray(oldV.getType())) {
470 Location loc = oldV.getLoc();
473 rewriter.replaceAllUsesWith(oldV, newArray);
475 entryBlock.eraseArgument(i);
480 assert(std::cmp_equal(allIndices->size(), at.getNumElements()));
481 for (ArrayAttr subIdx : allIndices.value()) {
482 BlockArgument newArg = entryBlock.insertArgument(i, at.
getElementType(), loc);
494 ArrayAttr resultAttrs = op.getAllResultAttrs();
496 return op.getArgNameAttr(i);
497 }, getSplitArrayIndexSuffixes);
499 return getAttrAtIndexWithName(resultAttrs, i, RES_NAME_ATTR_NAME);
500 }, getSplitArrayIndexSuffixes);
503 Impl(op).convert(op, rewriter);
509class SplitArrayInReturnOp :
public OpConversionPattern<ReturnOp> {
511 using OpConversionPattern<
ReturnOp>::OpConversionPattern;
513 inline static bool legal(
ReturnOp op) {
514 return !containsSplittableArrayType(op.
getOperands().getTypes());
517 LogicalResult matchAndRewrite(
518 ReturnOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
529class SplitArrayInCallOp :
public OpConversionPattern<CallOp> {
531 using OpConversionPattern<
CallOp>::OpConversionPattern;
533 inline static bool legal(
CallOp op) {
534 return !containsSplittableArrayType(op.
getArgOperands().getTypes()) &&
535 !containsSplittableArrayType(op.getResultTypes());
538 LogicalResult matchAndRewrite(
539 CallOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
545 CallOp newCall = newCallOpWithSplitResults(op, adaptor, rewriter);
546 processInputOperands(
554class ReplaceKnownArrayLengthOp :
public OpConversionPattern<ArrayLengthOp> {
556 using OpConversionPattern<
ArrayLengthOp>::OpConversionPattern;
559 static std::optional<llvm::APInt> getDimSizeIfKnown(Value dimIdx,
ArrayType baseArrType) {
560 if (baseArrType.hasStaticShape()) {
562 if (mlir::matchPattern(dimIdx, mlir::m_ConstantInt(&idxAP))) {
563 std::optional<int64_t> signedIdx = idxAP.trySExtValue();
564 if (!signedIdx || *signedIdx < 0) {
569 if (idx >= dimSizes.size()) {
572 Attribute dimSizeAttr = dimSizes[idx];
573 if (mlir::matchPattern(dimSizeAttr, mlir::m_ConstantInt(&idxAP))) {
586 LogicalResult matchAndRewrite(
587 ArrayLengthOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter
592 ArrayType arrTy = dyn_cast<ArrayType>(adaptor.getArrRef().getType());
594 std::optional<llvm::APInt> len = getDimSizeIfKnown(adaptor.getDim(), arrTy);
595 assert(len.has_value());
596 rewriter.replaceOpWithNewOp<arith::ConstantIndexOp>(op,
llzk::fromAPInt(len.value()));
602using MemberInfo = std::pair<StringAttr, Type>;
604using LocalMemberReplacementMap = DenseMap<ArrayAttr, MemberInfo>;
606using MemberReplacementMap = DenseMap<StructDefOp, DenseMap<StringAttr, LocalMemberReplacementMap>>;
609class SplitArrayInMemberDefOp :
public OpConversionPattern<MemberDefOp> {
610 SymbolTableCollection &tables;
611 MemberReplacementMap &repMapRef;
614 SplitArrayInMemberDefOp(
615 MLIRContext *ctx, SymbolTableCollection &symTables, MemberReplacementMap &memberRepMap
617 : OpConversionPattern<MemberDefOp>(ctx), tables(symTables), repMapRef(memberRepMap) {}
619 inline static bool legal(
MemberDefOp op) {
return !containsSplittableArrayType(op.
getType()); }
622 matchAndRewrite(
MemberDefOp op, OpAdaptor, ConversionPatternRewriter &rewriter)
const override {
628 LocalMemberReplacementMap &localRepMapRef = repMapRef[inStruct][op.
getSymNameAttr()];
633 assert(subIdxs.has_value());
636 SymbolTable &structSymbolTable = tables.getSymbolTable(inStruct);
637 for (ArrayAttr idx : subIdxs.value()) {
644 localRepMapRef[idx] = std::make_pair(structSymbolTable.insert(newMember), elemTy);
646 rewriter.eraseOp(op);
653 SplitArrayInMemberWriteOp, MemberWriteOp, void *, ArrayAttr> {
659 return !containsSplittableArrayType(op.
getVal().getType());
662 static void *genHeader(
MemberWriteOp, ConversionPatternRewriter &) {
return nullptr; }
665 Location loc,
void *, ArrayAttr idx, MemberInfo newMember, OpAdaptor adaptor,
666 ConversionPatternRewriter &rewriter
670 loc, adaptor.getComponent(), FlatSymbolRefAttr::get(newMember.first), scalarRead
677class SplitArrayInMemberReadOp
679 SplitArrayInMemberReadOp, MemberReadOp, CreateArrayOp, ArrayAttr> {
686 return !containsSplittableArrayType(op.getResult().getType());
691 rewriter.create<
CreateArrayOp>(op.getLoc(), llvm::cast<ArrayType>(op.getType()));
692 rewriter.replaceAllUsesWith(op, newArray);
697 Location loc,
CreateArrayOp newArray, ArrayAttr idx, MemberInfo newMember, OpAdaptor adaptor,
698 ConversionPatternRewriter &rewriter
701 loc, newMember.second, adaptor.getComponent(), newMember.first
708static void baseTargetSetup(ConversionTarget &target) {
709 target.addLegalDialect<
715 target.addLegalOp<ModuleOp>();
719class NondetToNewArray :
public OpConversionPattern<NonDetOp> {
720 using OpConversionPattern<
NonDetOp>::OpConversionPattern;
721 LogicalResult matchAndRewrite(
722 NonDetOp nondetOp, OpAdaptor, ConversionPatternRewriter &rewriter
724 if (
auto at = dyn_cast<ArrayType>(nondetOp.getType())) {
725 auto wildcardTy = llvm::cast<ArrayType>(replaceAffineMapArrayDimsWithWildcards(at));
726 auto newArray = rewriter.create<
CreateArrayOp>(nondetOp.getLoc(), wildcardTy);
727 if (wildcardTy == at) {
728 rewriter.replaceOp(nondetOp, newArray);
731 rewriter.replaceOp(nondetOp,
cast.getResult());
740static LogicalResult step0(ModuleOp modOp) {
741 MLIRContext *ctx = modOp.getContext();
742 RewritePatternSet patterns {ctx};
743 patterns.add<NondetToNewArray>(ctx);
744 ConversionTarget target {*ctx};
746 baseTargetSetup(target);
747 target.addDynamicallyLegalOp<
NonDetOp>([](
NonDetOp op) {
return !isa<ArrayType>(op.getType()); });
749 return applyFullConversion(modOp, target, std::move(patterns));
754step1(ModuleOp modOp, SymbolTableCollection &symTables, MemberReplacementMap &memberRepMap) {
755 MLIRContext *ctx = modOp.getContext();
757 RewritePatternSet patterns(ctx);
759 patterns.add<SplitArrayInMemberDefOp>(ctx, symTables, memberRepMap);
761 ConversionTarget target(*ctx);
762 baseTargetSetup(target);
763 target.addDynamicallyLegalOp<
MemberDefOp>(SplitArrayInMemberDefOp::legal);
765 LLVM_DEBUG(llvm::dbgs() <<
"Begin step 1: split array-type members\n";);
766 return applyFullConversion(modOp, target, std::move(patterns));
772step2(ModuleOp modOp, SymbolTableCollection &symTables,
const MemberReplacementMap &memberRepMap) {
773 MLIRContext *ctx = modOp.getContext();
775 RewritePatternSet patterns(ctx);
778 SplitInitFromCreateArrayOp,
781 SplitArrayInFuncDefOp,
782 SplitArrayInReturnOp,
784 ReplaceKnownArrayLengthOp
790 SplitArrayInMemberWriteOp,
791 SplitArrayInMemberReadOp
793 >(ctx, symTables, memberRepMap);
795 ConversionTarget target(*ctx);
796 baseTargetSetup(target);
797 target.addDynamicallyLegalOp<
CreateArrayOp>(SplitInitFromCreateArrayOp::legal);
798 target.addDynamicallyLegalOp<
InsertArrayOp>(SplitInsertArrayOp::legal);
799 target.addDynamicallyLegalOp<
ExtractArrayOp>(SplitExtractArrayOp::legal);
800 target.addDynamicallyLegalOp<
FuncDefOp>(SplitArrayInFuncDefOp::legal);
801 target.addDynamicallyLegalOp<
ReturnOp>(SplitArrayInReturnOp::legal);
802 target.addDynamicallyLegalOp<
CallOp>(SplitArrayInCallOp::legal);
803 target.addDynamicallyLegalOp<
ArrayLengthOp>(ReplaceKnownArrayLengthOp::legal);
804 target.addDynamicallyLegalOp<
MemberWriteOp>(SplitArrayInMemberWriteOp::legal);
805 target.addDynamicallyLegalOp<
MemberReadOp>(SplitArrayInMemberReadOp::legal);
807 LLVM_DEBUG(llvm::dbgs() <<
"Begin step 2: update/split other array ops\n";);
808 return applyFullConversion(modOp, target, std::move(patterns));
817static bool mayWriteToIndex(
WriteArrayOp writeOp, ArrayAttr index) {
818 ArrayAttr writeIndex = getIndexAsAttr(writeOp);
819 return !writeIndex || writeIndex == index;
823static bool hasEarlierWriteInBlock(
ReadArrayOp readOp, ArrayAttr readIndex) {
825 for (Operation &op : *readOp->getBlock()) {
826 if (&op == readOp.getOperation()) {
830 if (
auto writeOp = dyn_cast<WriteArrayOp>(&op)) {
831 if (writeOp.
getArrRef() == arrRef && mayWriteToIndex(writeOp, readIndex)) {
839 if (writeOp.getArrRef() == arrRef && mayWriteToIndex(writeOp, readIndex)) {
840 return WalkResult::interrupt();
842 return WalkResult::advance();
843 }).wasInterrupted()) {
851static std::optional<WriteArrayOp> findPrecedingWriteForIfRead(
ReadArrayOp readOp) {
852 ArrayAttr readIndex = getIndexAsAttr(readOp);
858 auto ifOp = readOp->getParentOfType<scf::IfOp>();
859 if (!ifOp || readOp->getBlock()->getParentOp() != ifOp.getOperation()) {
862 if (hasEarlierWriteInBlock(readOp, readIndex)) {
866 Block *ifBlock = ifOp->getBlock();
873 for (Operation &op : *ifBlock) {
874 if (&op == ifOp.getOperation()) {
878 if (
auto writeOp = dyn_cast<WriteArrayOp>(&op)) {
879 if (writeOp.getArrRef() != arrRef) {
883 if (mayWriteToIndex(writeOp, readIndex)) {
884 ArrayAttr writeIndex = getIndexAsAttr(writeOp);
885 replacement = writeIndex == readIndex ? writeOp :
WriteArrayOp();
891 if (op.walk([arrRef, readIndex, &replacement](
WriteArrayOp writeOp) {
892 if (writeOp.getArrRef() == arrRef && mayWriteToIndex(writeOp, readIndex)) {
893 replacement = WriteArrayOp();
894 return WalkResult::interrupt();
896 return WalkResult::advance();
897 }).wasInterrupted()) {
902 return replacement ? std::make_optional(replacement) : std::nullopt;
907static void step3(ModuleOp modOp) {
908 SmallVector<std::pair<ReadArrayOp, Value>> replacements;
910 if (std::optional<WriteArrayOp> writeOp = findPrecedingWriteForIfRead(readOp)) {
911 replacements.emplace_back(readOp, writeOp->getRvalue());
915 for (
auto [readOp, value] : replacements) {
916 readOp.
getResult().replaceAllUsesWith(value);
923 using Base = ArrayToScalarPassBase<PassImpl>;
926 void runOnOperation()
override {
927 ModuleOp module = getOperation();
929 if (failed(step0(module))) {
930 return signalPassFailure();
933 llvm::dbgs() <<
"After step 0:\n";
942 SymbolTableCollection symTables;
943 MemberReplacementMap memberRepMap;
944 if (failed(step1(module, symTables, memberRepMap))) {
945 return signalPassFailure();
948 llvm::dbgs() <<
"After step 1:\n";
952 if (failed(step2(module, symTables, memberRepMap))) {
953 return signalPassFailure();
956 llvm::dbgs() <<
"After step 2:\n";
963 llvm::dbgs() <<
"After step 3:\n";
967 OpPassManager nestedPM(ModuleOp::getOperationName());
976 RemoveUnusedDiscardableAllocationsPassOptions {
982 if (failed(runPipeline(nestedPM, module))) {
987 llvm::dbgs() <<
"After SROA+Mem2Reg pipeline:\n";
Provides SpecializedSROA<AllocOpTy> and SpecializedMem2Reg<AllocOpTy>: pass templates that replicate ...
General helper for converting a FuncDefOp by changing its input and/or result types and the associate...
Common implementation for handling MemberWriteOp and MemberReadOp while destructuring an aggregate ty...
static void genWrite(::mlir::OpBuilder &bldr, ::mlir::Location loc, ::mlir::Value arrayRef, ::mlir::ValueRange indices, ::mlir::Value value)
Create an array.write or array.insert for one concrete element or subarray.
::mlir::Value genRead(::mlir::OpBuilder &bldr, ::mlir::Location loc, ::mlir::Value arrayRef, ::mlir::ValueRange indices)
Create an array.read or array.extract for one concrete element or subarray.
::mlir::ArrayAttr indexOperandsToAttributeArray()
Returns the multi-dimensional indices of the array access as an Attribute array or a null pointer if ...
Helper for converting between linear and multi-dimensional indexing with checks to ensure indices are...
static ArrayIndexGen from(ArrayType)
Construct new ArrayIndexGen. Will assert if hasStaticShape() is false.
std::optional< llvm::SmallVector< mlir::Value > > delinearize(int64_t, mlir::Location, mlir::OpBuilder &) const
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
::mlir::TypedValue<::mlir::IndexType > getDim()
std::optional<::llvm::SmallVector<::mlir::ArrayAttr > > getSubelementIndices() const
Return a list of all valid indices for this ArrayType.
::mlir::Type getElementType() const
::llvm::ArrayRef<::mlir::Attribute > getDimensionSizes() const
::mlir::TypedValue<::llzk::array::ArrayType > getResult()
static constexpr ::llvm::StringLiteral getOperationName()
::mlir::MutableOperandRange getElementsMutable()
::mlir::Operation::operand_range getElements()
::mlir::TypedValue<::llzk::array::ArrayType > getRvalue()
::mlir::TypedValue<::mlir::Type > getResult()
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
bool hasPublicAttr()
Returns whether this member is a public output.
void setPublicAttr(bool newValue=true)
Adds or removes the unit llzk.pub attribute according to newValue.
::mlir::StringAttr getSymNameAttr()
::mlir::TypedValue<::mlir::Type > getVal()
::llvm::SmallVector< RangeT > getMapOperands()
::mlir::MutableOperandRange getArgOperandsMutable()
::mlir::Operation::operand_range getArgOperands()
::llvm::ArrayRef<::mlir::Type > getArgumentTypes()
Required by FunctionOpInterface.
::llvm::ArrayRef<::mlir::Type > getResultTypes()
Required by FunctionOpInterface.
::mlir::MutableOperandRange getOperandsMutable()
::mlir::Operation::operand_range getOperands()
constexpr char ARG_NAME_ATTR_NAME[]
Attribute name for source-level function argument names.
constexpr char RES_NAME_ATTR_NAME[]
Attribute name for source-level function result names.
std::unique_ptr<::mlir::Pass > createRemoveUnusedDiscardableAllocationsPass()
std::unique_ptr< mlir::Pass > createRemoveDeadValuesWorkaroundPass()
mlir::ArrayAttr replicateFunctionNameAttrsAsNeeded(mlir::ArrayAttr origAttrs, const llvm::SmallVector< size_t > &originalIdxToSize, const llvm::SmallVector< mlir::Type > &newTypes, llvm::StringRef functionNameAttrName, llvm::ArrayRef< std::optional< llvm::StringRef > > origNames={}, llvm::ArrayRef< llvm::StringRef > existingNames={}, llvm::ArrayRef< llvm::SmallVector< std::string > > splitNameSuffixes={})
Expand function arg/result attribute arrays to match a split signature, rewriting name attrs with the...
constexpr T checkedCast(U u) noexcept
std::unique_ptr< SpecializedMem2Reg< AllocOpTy > > createSpecializedMem2RegPass()
int64_t fromAPInt(const llvm::APInt &i)
function::CallOp createCallPreservingInstantiationOperands(mlir::Location loc, mlir::TypeRange newResultTypes, function::CallOp oldCall, llvm::ArrayRef< mlir::ValueRange > mapOperands, mlir::ValueRange argOperands, mlir::ConversionPatternRewriter &rewriter)
Rebuild a function.call while preserving explicit instantiation state from oldCall.
SplitFunctionNameInfo collectSplitFunctionNameInfo(mlir::ArrayRef< mlir::Type > origTypes, GetNameAttrFn &&getNameAttr, GetSplitSuffixesFn &&getSplitSuffixes)
Collect function arg/result names and split suffixes from a list of original types.
std::unique_ptr< SpecializedSROA< AllocOpTy > > createSpecializedSROAPass()
Cached function arg/result names and split suffixes used while rewriting a function signature.
llvm::SmallVector< std::optional< llvm::StringRef > > originalNames
llvm::SmallVector< llvm::StringRef > existingNames
llvm::SmallVector< llvm::SmallVector< std::string > > splitNameSuffixes