forked from OSchip/llvm-project
[mlir][AsmPrinter] Refactor printing to only print aliases for attributes/types that will exist in the output.
This revision refactors the way that attributes/types are considered when generating aliases. Instead of considering all of the attributes/types of every operation, we perform a "fake" print step that prints the operations using a dummy printer to collect the attributes and types that would actually be printed during the real process. This removes a lot of attributes/types from consideration that generally won't end up in the final output, e.g. affine map attributes in an `affine.apply`/`affine.for`. This resolves a long standing TODO w.r.t aliases, and helps to have a much cleaner textual output format. As a datapoint to the latter, as part of this change several tests were identified as testing for the presence of attributes aliases that weren't actually referenced by the custom form of any operation. To ensure that this wouldn't cause a large degradation in compile time due to the second full print, I benchmarked this change on a very large module with a lot of operations(The file is ~673M/~4.7 million lines long). This file before this change take ~6.9 seconds to print in the custom form, and ~7 seconds after this change. In the custom assembly case, this added an average of a little over ~100 miliseconds to the compile time. This increase was due to the way that argument attributes on functions are structured and how they get printed; i.e. with a better representation the negative impact here can be greatly decreased. When printing in the generic form, this revision had no observable impact on the compile time. This benchmarking leads me to believe that the impact of this change on compile time w.r.t printing is closely related to `print` methods that perform a lot of additional/complex processing outside of the OpAsmPrinter. Differential Revision: https://reviews.llvm.org/D90512
This commit is contained in:
parent
6022a8b7e8
commit
ebcc022507
|
@ -221,90 +221,193 @@ static raw_ostream &operator<<(raw_ostream &os, NewLineCounter &newLine) {
|
|||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AliasState
|
||||
// AliasInitializer
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
/// This class manages the state for type and attribute aliases.
|
||||
class AliasState {
|
||||
/// This class represents a utility that initializes the set of attribute and
|
||||
/// type aliases, without the need to store the extra information within the
|
||||
/// main AliasState class or pass it around via function arguments.
|
||||
class AliasInitializer {
|
||||
public:
|
||||
// Initialize the internal aliases.
|
||||
void
|
||||
initialize(Operation *op,
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
|
||||
AliasInitializer(
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
|
||||
llvm::BumpPtrAllocator &aliasAllocator)
|
||||
: interfaces(interfaces), aliasAllocator(aliasAllocator),
|
||||
aliasOS(aliasBuffer) {}
|
||||
|
||||
/// Get an alias for the given attribute if it has one and print it in `os`.
|
||||
/// Returns success if an alias was printed, failure otherwise.
|
||||
LogicalResult getAlias(Attribute attr, raw_ostream &os) const;
|
||||
void initialize(
|
||||
Operation *op, const OpPrintingFlags &printerFlags,
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, Optional<int>>>
|
||||
&attrToAlias,
|
||||
llvm::MapVector<Type, std::pair<StringRef, Optional<int>>> &typeToAlias);
|
||||
|
||||
/// Print all of the referenced attribute aliases.
|
||||
void printAttributeAliases(raw_ostream &os, NewLineCounter &newLine) const;
|
||||
/// Visit the given attribute to see if it has an alias.
|
||||
void visit(Attribute attr);
|
||||
|
||||
/// Get an alias for the given type if it has one and print it in `os`.
|
||||
/// Returns success if an alias was printed, failure otherwise.
|
||||
LogicalResult getAlias(Type ty, raw_ostream &os) const;
|
||||
|
||||
/// Print all of the referenced type aliases.
|
||||
void printTypeAliases(raw_ostream &os, NewLineCounter &newLine) const;
|
||||
/// Visit the given type to see if it has an alias.
|
||||
void visit(Type type);
|
||||
|
||||
private:
|
||||
/// This class represents a utility that initializes the set of attribute and
|
||||
/// type aliases, without the need to store the extra information within the
|
||||
/// main AliasState class or pass it around via function arguments.
|
||||
class AliasInitializer {
|
||||
public:
|
||||
AliasInitializer(
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces,
|
||||
llvm::BumpPtrAllocator &aliasAllocator)
|
||||
: interfaces(interfaces), aliasAllocator(aliasAllocator),
|
||||
aliasOS(aliasBuffer) {}
|
||||
/// Try to generate an alias for the provided symbol. If an alias is
|
||||
/// generated, the provided alias mapping and reverse mapping are updated.
|
||||
template <typename T>
|
||||
void generateAlias(T symbol,
|
||||
llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol);
|
||||
|
||||
void
|
||||
initialize(Operation *op,
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, Optional<int>>>
|
||||
&attrToAlias,
|
||||
llvm::MapVector<Type, std::pair<StringRef, Optional<int>>>
|
||||
&typeToAlias);
|
||||
/// The set of asm interfaces within the context.
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
|
||||
|
||||
private:
|
||||
void visit(Attribute attr);
|
||||
void visit(Type type);
|
||||
|
||||
/// Try to generate an alias for the provided symbol. If an alias is
|
||||
/// generated, the provided alias mapping and reverse mapping are updated.
|
||||
template <typename T>
|
||||
void
|
||||
generateAlias(T symbol,
|
||||
llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol);
|
||||
|
||||
/// The set of asm interfaces within the context.
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces;
|
||||
|
||||
/// Mapping between an alias and the set of symbols mapped to it.
|
||||
llvm::MapVector<StringRef, std::vector<Attribute>> aliasToAttr;
|
||||
llvm::MapVector<StringRef, std::vector<Type>> aliasToType;
|
||||
|
||||
/// An allocator used for alias names.
|
||||
llvm::BumpPtrAllocator &aliasAllocator;
|
||||
|
||||
/// The set of visited attributes.
|
||||
DenseSet<Attribute> visitedAttributes;
|
||||
|
||||
/// The set of visited types.
|
||||
DenseSet<Type> visitedTypes;
|
||||
|
||||
/// Storage and stream used when generating an alias.
|
||||
SmallString<32> aliasBuffer;
|
||||
llvm::raw_svector_ostream aliasOS;
|
||||
};
|
||||
|
||||
/// Mapping between attribute and a pair comprised of a base alias name and a
|
||||
/// count suffix. If the suffix is set to None, it is not displayed.
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, Optional<int>>> attrToAlias;
|
||||
llvm::MapVector<Type, std::pair<StringRef, Optional<int>>> typeToAlias;
|
||||
/// Mapping between an alias and the set of symbols mapped to it.
|
||||
llvm::MapVector<StringRef, std::vector<Attribute>> aliasToAttr;
|
||||
llvm::MapVector<StringRef, std::vector<Type>> aliasToType;
|
||||
|
||||
/// An allocator used for alias names.
|
||||
llvm::BumpPtrAllocator aliasAllocator;
|
||||
llvm::BumpPtrAllocator &aliasAllocator;
|
||||
|
||||
/// The set of visited attributes.
|
||||
DenseSet<Attribute> visitedAttributes;
|
||||
|
||||
/// The set of visited types.
|
||||
DenseSet<Type> visitedTypes;
|
||||
|
||||
/// Storage and stream used when generating an alias.
|
||||
SmallString<32> aliasBuffer;
|
||||
llvm::raw_svector_ostream aliasOS;
|
||||
};
|
||||
|
||||
/// This class implements a dummy OpAsmPrinter that doesn't print any output,
|
||||
/// and merely collects the attributes and types that *would* be printed in a
|
||||
/// normal print invocation so that we can generate proper aliases. This allows
|
||||
/// for us to generate aliases only for the attributes and types that would be
|
||||
/// in the output, and trims down unnecessary output.
|
||||
class DummyAliasOperationPrinter : private OpAsmPrinter {
|
||||
public:
|
||||
explicit DummyAliasOperationPrinter(const OpPrintingFlags &flags,
|
||||
AliasInitializer &initializer)
|
||||
: printerFlags(flags), initializer(initializer) {}
|
||||
|
||||
/// Print the given operation.
|
||||
void print(Operation *op) {
|
||||
// TODO: Consider the operation location for an alias.
|
||||
|
||||
// If requested, always print the generic form.
|
||||
if (!printerFlags.shouldPrintGenericOpForm()) {
|
||||
// Check to see if this is a known operation. If so, use the registered
|
||||
// custom printer hook.
|
||||
if (auto *opInfo = op->getAbstractOperation()) {
|
||||
opInfo->printAssembly(op, *this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise print with the generic assembly form.
|
||||
printGenericOp(op);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Print the given operation in the generic form.
|
||||
void printGenericOp(Operation *op) override {
|
||||
// Consider nested opertions for aliases.
|
||||
if (op->getNumRegions() != 0) {
|
||||
for (Region ®ion : op->getRegions())
|
||||
printRegion(region, /*printEntryBlockArgs=*/true,
|
||||
/*printBlockTerminators=*/true);
|
||||
}
|
||||
|
||||
// Visit all the types used in the operation.
|
||||
for (Type type : op->getOperandTypes())
|
||||
printType(type);
|
||||
for (Type type : op->getResultTypes())
|
||||
printType(type);
|
||||
|
||||
// Consider the attributes of the operation for aliases.
|
||||
for (const NamedAttribute &attr : op->getAttrs())
|
||||
printAttribute(attr.second);
|
||||
}
|
||||
|
||||
/// Print the given block. If 'printBlockArgs' is false, the arguments of the
|
||||
/// block are not printed. If 'printBlockTerminator' is false, the terminator
|
||||
/// operation of the block is not printed.
|
||||
void print(Block *block, bool printBlockArgs = true,
|
||||
bool printBlockTerminator = true) {
|
||||
// Consider the types of the block arguments for aliases if 'printBlockArgs'
|
||||
// is set to true.
|
||||
if (printBlockArgs) {
|
||||
for (Type type : block->getArgumentTypes())
|
||||
printType(type);
|
||||
}
|
||||
|
||||
// Consider the operations within this block, ignoring the terminator if
|
||||
// requested.
|
||||
auto range = llvm::make_range(
|
||||
block->begin(), std::prev(block->end(), printBlockTerminator ? 0 : 1));
|
||||
for (Operation &op : range)
|
||||
print(&op);
|
||||
}
|
||||
|
||||
/// Print the given region.
|
||||
void printRegion(Region ®ion, bool printEntryBlockArgs,
|
||||
bool printBlockTerminators) override {
|
||||
if (region.empty())
|
||||
return;
|
||||
|
||||
auto *entryBlock = ®ion.front();
|
||||
print(entryBlock, printEntryBlockArgs, printBlockTerminators);
|
||||
for (Block &b : llvm::drop_begin(region, 1))
|
||||
print(&b);
|
||||
}
|
||||
|
||||
/// Consider the given type to be printed for an alias.
|
||||
void printType(Type type) override { initializer.visit(type); }
|
||||
|
||||
/// Consider the given attribute to be printed for an alias.
|
||||
void printAttribute(Attribute attr) override { initializer.visit(attr); }
|
||||
void printAttributeWithoutType(Attribute attr) override {
|
||||
printAttribute(attr);
|
||||
}
|
||||
|
||||
/// Print the given set of attributes with names not included within
|
||||
/// 'elidedAttrs'.
|
||||
void printOptionalAttrDict(ArrayRef<NamedAttribute> attrs,
|
||||
ArrayRef<StringRef> elidedAttrs = {}) override {
|
||||
// Filter out any attributes that shouldn't be included.
|
||||
SmallVector<NamedAttribute, 8> filteredAttrs(
|
||||
llvm::make_filter_range(attrs, [&](NamedAttribute attr) {
|
||||
return !llvm::is_contained(elidedAttrs, attr.first.strref());
|
||||
}));
|
||||
for (const NamedAttribute &attr : filteredAttrs)
|
||||
printAttribute(attr.second);
|
||||
}
|
||||
void printOptionalAttrDictWithKeyword(
|
||||
ArrayRef<NamedAttribute> attrs,
|
||||
ArrayRef<StringRef> elidedAttrs = {}) override {
|
||||
printOptionalAttrDict(attrs, elidedAttrs);
|
||||
}
|
||||
|
||||
/// Return 'nulls' as the output stream, this will ignore any data fed to it.
|
||||
raw_ostream &getStream() const override { return llvm::nulls(); }
|
||||
|
||||
/// The following are hooks of `OpAsmPrinter` that are not necessary for
|
||||
/// determining potential aliases.
|
||||
void printAffineMapOfSSAIds(AffineMapAttr, ValueRange) override {}
|
||||
void printOperand(Value) override {}
|
||||
void printOperand(Value, raw_ostream &os) override {
|
||||
// Users expect the output string to have at least the prefixed % to signal
|
||||
// a value name. To maintain this invariant, emit a name even if it is
|
||||
// guaranteed to go unused.
|
||||
os << "%";
|
||||
}
|
||||
void printSymbolName(StringRef) override {}
|
||||
void printSuccessor(Block *) override {}
|
||||
void printSuccessorAndUseList(Block *, ValueRange) override {}
|
||||
void shadowRegionArgs(Region &, ValueRange) override {}
|
||||
|
||||
/// The printer flags to use when determining potential aliases.
|
||||
const OpPrintingFlags &printerFlags;
|
||||
|
||||
/// The initializer to use when identifying aliases.
|
||||
AliasInitializer &initializer;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
|
@ -381,39 +484,32 @@ static void initializeAliases(
|
|||
}
|
||||
}
|
||||
|
||||
void AliasState::AliasInitializer::initialize(
|
||||
Operation *op,
|
||||
void AliasInitializer::initialize(
|
||||
Operation *op, const OpPrintingFlags &printerFlags,
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, Optional<int>>>
|
||||
&attrToAlias,
|
||||
llvm::MapVector<Type, std::pair<StringRef, Optional<int>>> &typeToAlias) {
|
||||
op->walk([&](Operation *op) {
|
||||
// Visit all the types used in the operation.
|
||||
for (auto type : op->getOperandTypes())
|
||||
visit(type);
|
||||
for (auto type : op->getResultTypes())
|
||||
visit(type);
|
||||
for (auto ®ion : op->getRegions())
|
||||
for (auto &block : region)
|
||||
for (auto arg : block.getArguments())
|
||||
visit(arg.getType());
|
||||
|
||||
// Visit each of the attributes.
|
||||
for (auto elt : op->getAttrs())
|
||||
visit(elt.second);
|
||||
});
|
||||
// Use a dummy printer when walking the IR so that we can collect the
|
||||
// attributes/types that will actually be used during printing when
|
||||
// considering aliases.
|
||||
DummyAliasOperationPrinter aliasPrinter(printerFlags, *this);
|
||||
aliasPrinter.print(op);
|
||||
|
||||
// Initialize the aliases sorted by name.
|
||||
initializeAliases(aliasToAttr, attrToAlias);
|
||||
initializeAliases(aliasToType, typeToAlias);
|
||||
}
|
||||
|
||||
void AliasState::AliasInitializer::visit(Attribute attr) {
|
||||
void AliasInitializer::visit(Attribute attr) {
|
||||
if (!visitedAttributes.insert(attr).second)
|
||||
return;
|
||||
|
||||
if (auto arrayAttr = attr.dyn_cast<ArrayAttr>()) {
|
||||
for (Attribute element : arrayAttr.getValue())
|
||||
visit(element);
|
||||
} else if (auto dictAttr = attr.dyn_cast<DictionaryAttr>()) {
|
||||
for (const NamedAttribute &attr : dictAttr)
|
||||
visit(attr.second);
|
||||
} else if (auto typeAttr = attr.dyn_cast<TypeAttr>()) {
|
||||
visit(typeAttr.getValue());
|
||||
}
|
||||
|
@ -422,7 +518,7 @@ void AliasState::AliasInitializer::visit(Attribute attr) {
|
|||
generateAlias(attr, aliasToAttr);
|
||||
}
|
||||
|
||||
void AliasState::AliasInitializer::visit(Type type) {
|
||||
void AliasInitializer::visit(Type type) {
|
||||
if (!visitedTypes.insert(type).second)
|
||||
return;
|
||||
|
||||
|
@ -447,7 +543,7 @@ void AliasState::AliasInitializer::visit(Type type) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
void AliasState::AliasInitializer::generateAlias(
|
||||
void AliasInitializer::generateAlias(
|
||||
T symbol, llvm::MapVector<StringRef, std::vector<T>> &aliasToSymbol) {
|
||||
SmallString<16> tempBuffer;
|
||||
for (const auto &interface : interfaces) {
|
||||
|
@ -465,11 +561,49 @@ void AliasState::AliasInitializer::generateAlias(
|
|||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AliasState
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
/// This class manages the state for type and attribute aliases.
|
||||
class AliasState {
|
||||
public:
|
||||
// Initialize the internal aliases.
|
||||
void
|
||||
initialize(Operation *op, const OpPrintingFlags &printerFlags,
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces);
|
||||
|
||||
/// Get an alias for the given attribute if it has one and print it in `os`.
|
||||
/// Returns success if an alias was printed, failure otherwise.
|
||||
LogicalResult getAlias(Attribute attr, raw_ostream &os) const;
|
||||
|
||||
/// Print all of the referenced attribute aliases.
|
||||
void printAttributeAliases(raw_ostream &os, NewLineCounter &newLine) const;
|
||||
|
||||
/// Get an alias for the given type if it has one and print it in `os`.
|
||||
/// Returns success if an alias was printed, failure otherwise.
|
||||
LogicalResult getAlias(Type ty, raw_ostream &os) const;
|
||||
|
||||
/// Print all of the referenced type aliases.
|
||||
void printTypeAliases(raw_ostream &os, NewLineCounter &newLine) const;
|
||||
|
||||
private:
|
||||
/// Mapping between attribute and a pair comprised of a base alias name and a
|
||||
/// count suffix. If the suffix is set to None, it is not displayed.
|
||||
llvm::MapVector<Attribute, std::pair<StringRef, Optional<int>>> attrToAlias;
|
||||
llvm::MapVector<Type, std::pair<StringRef, Optional<int>>> typeToAlias;
|
||||
|
||||
/// An allocator used for alias names.
|
||||
llvm::BumpPtrAllocator aliasAllocator;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void AliasState::initialize(
|
||||
Operation *op,
|
||||
Operation *op, const OpPrintingFlags &printerFlags,
|
||||
DialectInterfaceCollection<OpAsmDialectInterface> &interfaces) {
|
||||
AliasInitializer initializer(interfaces, aliasAllocator);
|
||||
initializer.initialize(op, attrToAlias, typeToAlias);
|
||||
initializer.initialize(op, printerFlags, attrToAlias, typeToAlias);
|
||||
}
|
||||
|
||||
static void printAlias(raw_ostream &os,
|
||||
|
@ -873,8 +1007,8 @@ public:
|
|||
locationMap(locationMap) {}
|
||||
|
||||
/// Initialize the alias state to enable the printing of aliases.
|
||||
void initializeAliases(Operation *op) {
|
||||
aliasState.initialize(op, interfaces);
|
||||
void initializeAliases(Operation *op, const OpPrintingFlags &printerFlags) {
|
||||
aliasState.initialize(op, printerFlags, interfaces);
|
||||
}
|
||||
|
||||
/// Get an instance of the OpAsmDialectInterface for the given dialect, or
|
||||
|
@ -2243,8 +2377,7 @@ void OperationPrinter::print(Block *block, bool printBlockArgs,
|
|||
|
||||
currentIndent += indentWidth;
|
||||
auto range = llvm::make_range(
|
||||
block->getOperations().begin(),
|
||||
std::prev(block->getOperations().end(), printBlockTerminator ? 0 : 1));
|
||||
block->begin(), std::prev(block->end(), printBlockTerminator ? 0 : 1));
|
||||
for (auto &op : range) {
|
||||
print(&op);
|
||||
os << newLine;
|
||||
|
@ -2461,7 +2594,7 @@ void ModuleOp::print(raw_ostream &os, OpPrintingFlags flags) {
|
|||
|
||||
// Don't populate aliases when printing at local scope.
|
||||
if (!flags.shouldUseLocalScope())
|
||||
state.getImpl().initializeAliases(*this);
|
||||
state.getImpl().initializeAliases(*this, flags);
|
||||
print(os, state, flags);
|
||||
}
|
||||
void ModuleOp::print(raw_ostream &os, AsmState &state, OpPrintingFlags flags) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
// CHECK-DAG: #[[$map2:.*]] = affine_map<(d0, d1) -> (d0 + d1)>
|
||||
// CHECK-DAG: #[[$map3:.*]] = affine_map<(d0, d1)[s0] -> (3, -d0 - d1 + s0)>
|
||||
// CHECK-DAG: #[[$map4:.*]] = affine_map<(d0)[s0] -> (3, -d0 + s0)>
|
||||
// CHECK-DAG: #[[$map5:.*]] = affine_map<(d0) -> (d0)>
|
||||
|
||||
func @conv_1d(%arg0: memref<?xf32>, %arg1: memref<?xf32>, %arg2: memref<?xf32>) {
|
||||
linalg.conv_1d ins(%arg0, %arg1 : memref<?xf32>, memref<?xf32>)
|
||||
|
|
|
@ -54,7 +54,7 @@ func @materialize_read_1d_partially_specialized(%dyn1 : index, %dyn2 : index, %d
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: #[[$ADD:map[0-9]+]] = affine_map<(d0, d1) -> (d0 + d1)>
|
||||
// CHECK: #[[$ADD:map.*]] = affine_map<(d0, d1) -> (d0 + d1)>
|
||||
|
||||
// CHECK-LABEL: func @materialize_read(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
|
||||
func @materialize_read(%M: index, %N: index, %O: index, %P: index) {
|
||||
|
@ -113,7 +113,7 @@ func @materialize_read(%M: index, %N: index, %O: index, %P: index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: #[[$ADD:map[0-9]+]] = affine_map<(d0, d1) -> (d0 + d1)>
|
||||
// CHECK: #[[$ADD:map.*]] = affine_map<(d0, d1) -> (d0 + d1)>
|
||||
|
||||
// CHECK-LABEL:func @materialize_write(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: index) {
|
||||
func @materialize_write(%M: index, %N: index, %O: index, %P: index) {
|
||||
|
@ -174,9 +174,7 @@ func @materialize_write(%M: index, %N: index, %O: index, %P: index) {
|
|||
// -----
|
||||
|
||||
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
|
||||
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
|
||||
// FULL-UNROLL-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP1:.*]] = affine_map<()[s0] -> (s0 + 1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP2:.*]] = affine_map<()[s0] -> (s0 + 2)>
|
||||
|
||||
|
@ -253,9 +251,7 @@ func @transfer_read_progressive(%A : memref<?x?xf32>, %base: index) -> vector<3x
|
|||
// -----
|
||||
|
||||
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
|
||||
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
|
||||
// FULL-UNROLL-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP1:.*]] = affine_map<()[s0] -> (s0 + 1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP2:.*]] = affine_map<()[s0] -> (s0 + 2)>
|
||||
|
||||
|
@ -309,9 +305,7 @@ func @transfer_write_progressive(%A : memref<?x?xf32>, %base: index, %vec: vecto
|
|||
// -----
|
||||
|
||||
// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
|
||||
// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
|
||||
// FULL-UNROLL-DAG: #[[$MAP0:.*]] = affine_map<(d0, d1) -> (d1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP1:.*]] = affine_map<()[s0] -> (s0 + 1)>
|
||||
// FULL-UNROLL-DAG: #[[$MAP2:.*]] = affine_map<()[s0] -> (s0 + 2)>
|
||||
|
||||
|
|
|
@ -3,11 +3,9 @@
|
|||
|
||||
// Permutation maps used in vectorization.
|
||||
// CHECK-DAG: #[[$map_id1:map[0-9]+]] = affine_map<(d0) -> (d0)>
|
||||
// CHECK-DAG: #[[$map_id2:map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
// CHECK-DAG: #[[$map_proj_d0d1_zerod1:map[0-9]+]] = affine_map<(d0, d1) -> (0, d1)>
|
||||
// CHECK-DAG: #[[$map_proj_d0d1_d0zero:map[0-9]+]] = affine_map<(d0, d1) -> (d0, 0)>
|
||||
// VECT-DAG: #[[$map_id1:map[0-9]+]] = affine_map<(d0) -> (d0)>
|
||||
// VECT-DAG: #[[$map_id2:map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
// VECT-DAG: #[[$map_proj_d0d1_zerod1:map[0-9]+]] = affine_map<(d0, d1) -> (0, d1)>
|
||||
// VECT-DAG: #[[$map_proj_d0d1_d0zero:map[0-9]+]] = affine_map<(d0, d1) -> (d0, 0)>
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// RUN: mlir-opt %s -affine-super-vectorize="virtual-vector-size=32,64,256 test-fastest-varying=2,1,0" | FileCheck %s
|
||||
|
||||
// Permutation maps used in vectorization.
|
||||
// CHECK: #[[map_proj_d0d1d2_d0d1d2:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
|
||||
|
||||
func @vec3d(%A : memref<?x?x?xf32>) {
|
||||
%c0 = constant 0 : index
|
||||
%c1 = constant 1 : index
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: mlir-opt %s -affine-super-vectorize="virtual-vector-size=32,256 test-fastest-varying=2,0" | FileCheck %s
|
||||
|
||||
// Permutation maps used in vectorization.
|
||||
// CHECK: #[[map_proj_d0d1d2_d0d2:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0, d2)>
|
||||
// CHECK: #[[map_proj_d0d1d2_d0d2:map[0-9]*]] = affine_map<(d0, d1, d2) -> (d0, d2)>
|
||||
|
||||
func @vec2d(%A : memref<?x?x?xf32>) {
|
||||
%c0 = constant 0 : index
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: mlir-opt %s -affine-super-vectorize="virtual-vector-size=32,256 test-fastest-varying=0,2" | FileCheck %s
|
||||
|
||||
// Permutation maps used in vectorization.
|
||||
// CHECK: #[[map_proj_d0d1d2_d2d0:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d2, d0)>
|
||||
// CHECK: #[[map_proj_d0d1d2_d2d0:map[0-9]*]] = affine_map<(d0, d1, d2) -> (d2, d0)>
|
||||
|
||||
func @vec2d(%A : memref<?x?x?xf32>) {
|
||||
%c0 = constant 0 : index
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: mlir-opt %s -affine-super-vectorize="virtual-vector-size=32,256 test-fastest-varying=0,1" | FileCheck %s
|
||||
|
||||
// Permutation maps used in vectorization.
|
||||
// CHECK-DAG: #[[map_proj_d0d1d2_d2d1:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d2, d1)>
|
||||
// CHECK-DAG: #[[map_proj_d0d1d2_d2d1:map[0-9]*]] = affine_map<(d0, d1, d2) -> (d2, d1)>
|
||||
|
||||
func @vec2d(%A : memref<?x?x?xf32>) {
|
||||
%c0 = constant 0 : index
|
||||
|
|
|
@ -38,7 +38,7 @@ func @store_affine_apply() -> memref<10xf32> {
|
|||
// CHECK: %cst = constant 7.000000e+00 : f32
|
||||
// CHECK-NEXT: %0 = alloc() : memref<10xf32>
|
||||
// CHECK-NEXT: affine.for %arg0 = 0 to 10 {
|
||||
// CHECK-NEXT: %1 = affine.apply #map{{[0-9]+}}(%arg0)
|
||||
// CHECK-NEXT: %1 = affine.apply #map{{[0-9]*}}(%arg0)
|
||||
// CHECK-NEXT: affine.store %cst, %0[%1] : memref<10xf32>
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return %0 : memref<10xf32>
|
||||
|
@ -106,7 +106,7 @@ func @invariant_code_inside_affine_if() {
|
|||
// CHECK: %0 = alloc() : memref<10xf32>
|
||||
// CHECK-NEXT: %cst = constant 8.000000e+00 : f32
|
||||
// CHECK-NEXT: affine.for %arg0 = 0 to 10 {
|
||||
// CHECK-NEXT: %1 = affine.apply #map{{[0-9]+}}(%arg0)
|
||||
// CHECK-NEXT: %1 = affine.apply #map{{[0-9]*}}(%arg0)
|
||||
// CHECK-NEXT: affine.if #set(%arg0, %1) {
|
||||
// CHECK-NEXT: %2 = addf %cst, %cst : f32
|
||||
// CHECK-NEXT: affine.store %2, %0[%arg0] : memref<10xf32>
|
||||
|
|
|
@ -477,8 +477,6 @@ func @canonicalize_bounds(%M : index, %N : index) {
|
|||
|
||||
// Compose maps into affine load and store ops.
|
||||
|
||||
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0) -> (d0 + 1)>
|
||||
|
||||
// CHECK-LABEL: @compose_into_affine_load_store
|
||||
func @compose_into_affine_load_store(%A : memref<1024xf32>, %u : index) {
|
||||
// CHECK: affine.for %[[IV:.*]] = 0 to 1024
|
||||
|
@ -594,7 +592,7 @@ func @rep(%arg0 : index, %arg1 : index) -> index {
|
|||
}
|
||||
|
||||
// -----
|
||||
// CHECK-DAG: #[[lb:.*]] = affine_map<()[s0] -> (s0)>
|
||||
|
||||
// CHECK-DAG: #[[ub:.*]] = affine_map<()[s0] -> (s0 + 2)>
|
||||
|
||||
func @drop_duplicate_bounds(%N : index) {
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
|
||||
// -----
|
||||
|
||||
// Index of the buffer for the second DMA is remapped.
|
||||
// CHECK-DAG: [[MAP0:#map[0-9]+]] = affine_map<(d0) -> (d0)>
|
||||
|
||||
// CHECK-LABEL: func @loop_nest_1d() {
|
||||
func @loop_nest_1d() {
|
||||
%A = alloc() : memref<256 x f32>
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
// Test with loop IVs.
|
||||
func @test0(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -25,8 +23,6 @@ func @test0(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
// Test with loop IVs and optional stride arguments.
|
||||
func @test1(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -50,9 +46,6 @@ func @test1(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0, d1 + d2 + 5)>
|
||||
// CHECK: [[MAP1:#map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 + d1, d2)>
|
||||
|
||||
// Test with loop IVs and symbols (without symbol keyword).
|
||||
func @test2(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -75,10 +68,6 @@ func @test2(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0, d1 + s0 + 7)>
|
||||
// CHECK: [[MAP1:#map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 + s0, d1)>
|
||||
// CHECK: [[MAP1:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + d1 + 11)>
|
||||
|
||||
// Test with loop IVs and symbols (with symbol keyword).
|
||||
func @test3(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -102,10 +91,6 @@ func @test3(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0, (d1 + s0) mod 9 + 7)>
|
||||
// CHECK: [[MAP1:#map[0-9]+]] = affine_map<(d0, d1)[s0] -> ((d0 + s0) floordiv 3, d1)>
|
||||
// CHECK: [[MAP2:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + d1 + 11)>
|
||||
|
||||
// Test with loop IVs, symbols and constants in nested affine expressions.
|
||||
func @test4(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
// Test with just loop IVs.
|
||||
func @test0(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -18,8 +16,6 @@ func @test0(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + 3, d1 + 7)>
|
||||
|
||||
// Test with loop IVs and constants.
|
||||
func @test1(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -36,8 +32,6 @@ func @test1(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1, d2, d3) -> (d0 + d1, d2 + d3)>
|
||||
|
||||
// Test with loop IVs and function args without 'symbol' keyword (should
|
||||
// be parsed as dim identifiers).
|
||||
func @test2(%arg0 : index, %arg1 : index) {
|
||||
|
@ -55,8 +49,6 @@ func @test2(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d0 + s0, d1 + s1)>
|
||||
|
||||
// Test with loop IVs and function args with 'symbol' keyword (should
|
||||
// be parsed as symbol identifiers).
|
||||
func @test3(%arg0 : index, %arg1 : index) {
|
||||
|
@ -76,8 +68,6 @@ func @test3(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> ((d0 + s0) floordiv 3 + 11, (d1 + s1) mod 4 + 7)>
|
||||
|
||||
// Test with loop IVs, symbols and constants in nested affine expressions.
|
||||
func @test4(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -96,8 +86,6 @@ func @test4(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
|
||||
|
||||
// Test with swizzled loop IVs.
|
||||
func @test5(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<10x10x10xf32>
|
||||
|
@ -116,8 +104,6 @@ func @test5(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4) -> (d0 + d1, d2 + d3, d3 + d1 + d4)>
|
||||
|
||||
// Test with swizzled loop IVs, duplicate args, and function args used as dims.
|
||||
// Dim identifiers are assigned in parse order:
|
||||
// d0 = %i2, d1 = %arg0, d2 = %i0, d3 = %i1, d4 = %arg1
|
||||
|
@ -140,8 +126,6 @@ func @test6(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1] -> (d0 + s0, d1 + d2, d2 + s0 + s1)>
|
||||
|
||||
// Test with swizzled loop IVs, duplicate args, and function args used as syms.
|
||||
// Dim and symbol identifiers are assigned in parse order:
|
||||
// d0 = %i2, d1 = %i0, d2 = %i1
|
||||
|
@ -169,7 +153,7 @@ func @test6(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0) -> (d0 + 1)>
|
||||
// CHECK: [[MAP0:#map[0-9]*]] = affine_map<(d0) -> (d0 + 1)>
|
||||
|
||||
// Test with operands without special SSA name.
|
||||
func @test7() {
|
||||
|
@ -197,9 +181,6 @@ func @zero_dim(%arg0 : memref<i32>, %arg1 : memref<i32>) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + 3, d1 + 7)>
|
||||
// CHECK: [[MAP1:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + 3, d1 + 11)>
|
||||
|
||||
// Test with loop IVs and constants.
|
||||
func @test_prefetch(%arg0 : index, %arg1 : index) {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -217,8 +198,6 @@ func @test_prefetch(%arg0 : index, %arg1 : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP_ID:#map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
// Test with just loop IVs.
|
||||
func @vector_load_vector_store_iv() {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -238,8 +217,6 @@ func @vector_load_vector_store_iv() {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 + 3, d1 + 7)>
|
||||
|
||||
// Test with loop IVs and constants.
|
||||
func @vector_load_vector_store_iv_constant() {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
|
@ -259,8 +236,6 @@ func @vector_load_vector_store_iv_constant() {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK: [[MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
func @vector_load_vector_store_2d() {
|
||||
%0 = alloc() : memref<100x100xf32>
|
||||
affine.for %i0 = 0 to 16 step 2{
|
||||
|
|
|
@ -232,7 +232,6 @@ func @tile_with_loop_upper_bounds_in_two_symbols(%t11 : index, %arg0: memref<?xf
|
|||
// CHECK-DAG: [[LBI0:#map[0-9]+]] = affine_map<(d0)[s0] -> (d0 * s0)>
|
||||
// CHECK-DAG: [[UBI1:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d1 * s1 + s1, d0 + s0 + 4)>
|
||||
// CHECK-DAG: [[UBI0:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d1 * s1 + s1, d0 + s0 + 2)>
|
||||
// CHECK-DAG: [[LBO0:#map[0-9]+]] = affine_map<() -> (0)>
|
||||
// CHECK-DAG: [[UBO1:#map[0-9]+]] = affine_map<(d0)[s0, s1] -> ((d0 + s0 + 4) ceildiv s1)>
|
||||
// CHECK-DAG: [[UBO0:#map[0-9]+]] = affine_map<(d0)[s0, s1] -> ((d0 + s0 + 2) ceildiv s1)>
|
||||
|
||||
|
@ -255,7 +254,6 @@ func @tile_with_upper_bounds_in_dimensions_and_symbols(%t12 : index, %t13 :index
|
|||
// CHECK-DAG: [[LBI0:#map[0-9]+]] = affine_map<(d0)[s0] -> (d0 * s0)>
|
||||
// CHECK-DAG: [[UBI1:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d1 * s1 + s1 * 4, d0 + s0 + 4)>
|
||||
// CHECK-DAG: [[UBI0:#map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d1 * s1 + s1 * 2, d0 + s0 + 2)>
|
||||
// CHECK-DAG: [[LBO0:#map[0-9]+]] = affine_map<() -> (0)>
|
||||
// CHECK-DAG: [[UBO1:#map[0-9]+]] = affine_map<(d0)[s0, s1] -> ((d0 + s0 + 4) ceildiv s1)>
|
||||
// CHECK-DAG: [[UBO0:#map[0-9]+]] = affine_map<(d0)[s0, s1] -> ((d0 + s0 + 2) ceildiv s1)>
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
// CHECK-DAG: [[$LB:#map[0-9]+]] = affine_map<(d0) -> (d0)>
|
||||
// CHECK-DAG: [[$UB:#map[0-9]+]] = affine_map<(d0) -> (d0 + 32)>
|
||||
// CHECK-DAG: [[$ID:#map[0-9]+]] = affine_map<() -> (0)>
|
||||
// CHECK-DAG: [[$ID_PLUS_21:#map[0-9]+]] = affine_map<() -> (64)>
|
||||
|
||||
// CHECK-LABEL: func @legal_loop()
|
||||
func @legal_loop() {
|
||||
|
@ -19,7 +17,7 @@ func @legal_loop() {
|
|||
affine.store %2, %0[%i] : memref<64xf32>
|
||||
}
|
||||
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK: affine.for %{{.*}} = 0 to 64 step 32 {
|
||||
|
@ -27,7 +25,7 @@ func @legal_loop() {
|
|||
|
||||
// -----
|
||||
|
||||
// There are dependences along the diagonal of the 2d iteration space,
|
||||
// There are dependences along the diagonal of the 2d iteration space,
|
||||
// specifically, they are of direction (+, -).
|
||||
// The default tiling method (hyper-rect) will violate tiling legality.
|
||||
// We expect a remark that points that issue out to be emitted.
|
||||
|
@ -46,5 +44,5 @@ func @illegal_loop_with_diag_dependence() {
|
|||
}
|
||||
}
|
||||
|
||||
return
|
||||
return
|
||||
}
|
||||
|
|
|
@ -133,8 +133,8 @@ func @tile_with_symbolic_loop_upper_bounds(%arg0: memref<?x?xf32>, %arg1: memref
|
|||
// CHECK: dim %{{.*}}, %c0 : memref<?x?xf32>
|
||||
// CHECK-NEXT: affine.for %{{.*}} = 0 to %{{.*}} step 32 {
|
||||
// CHECK-NEXT: affine.for %{{.*}} = 0 to %{{.*}} step 32 {
|
||||
// CHECK-NEXT: affine.for %{{.*}} = #map3(%{{.*}}) to min [[$UBMAP]](%{{.*}})[%{{.*}}] {
|
||||
// CHECK-NEXT: affine.for %{{.*}} = #map3(%{{.*}}) to min [[$UBMAP]](%{{.*}})[%{{.*}}] {
|
||||
// CHECK-NEXT: affine.for %{{.*}} = #map0(%{{.*}}) to min [[$UBMAP]](%{{.*}})[%{{.*}}] {
|
||||
// CHECK-NEXT: affine.for %{{.*}} = #map0(%{{.*}}) to min [[$UBMAP]](%{{.*}})[%{{.*}}] {
|
||||
// CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<?x?xf32>
|
||||
// CHECK-NEXT: affine.for %{{.*}} = 0 to %{{.*}} {
|
||||
// CHECK-NEXT: affine.load
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// RUN: mlir-opt %s -allow-unregistered-dialect -affine-parallelize| FileCheck %s
|
||||
|
||||
// For multiple nested for-loops.
|
||||
// CHECK-DAG: [[MAP5:#map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0 + d1, d2 * 2 + d3, d4 * 2 + d5, d6 + d7)>
|
||||
// CHECK-LABEL: func @reduce_window_max() {
|
||||
func @reduce_window_max() {
|
||||
%cst = constant 0.000000e+00 : f32
|
||||
|
|
|
@ -274,8 +274,6 @@ func @affine.apply(%N : index) {
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK-DAG: #[[MAP_0D:.*]] = affine_map<() -> ()>
|
||||
|
||||
// CHECK-LABEL: func @simplify_zero_dim_map
|
||||
func @simplify_zero_dim_map(%in : memref<f32>) -> f32 {
|
||||
%out = affine.load %in[] : memref<f32>
|
||||
|
|
|
@ -14,13 +14,14 @@ func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index,
|
|||
return
|
||||
}
|
||||
|
||||
// CHECK: #[[$MAP:.*]] = affine_map<(d0) -> (d0)>
|
||||
// CHECK-LABEL: func @parallel_loop(
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: {mapping = [{bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 3 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 4 : i64}]}
|
||||
// CHECK: {mapping = [{bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 0 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 1 : i64}]}
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: {mapping = [{bound = #[[$MAP]], map = #[[$MAP]], processor = 3 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 4 : i64}]}
|
||||
// CHECK: {mapping = [{bound = #[[$MAP]], map = #[[$MAP]], processor = 0 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 1 : i64}]}
|
||||
// CHECK-NOT: mapping
|
||||
|
||||
// -----
|
||||
|
@ -42,20 +43,21 @@ func @parallel_loop_4d(%arg0 : index, %arg1 : index, %arg2 : index,
|
|||
return
|
||||
}
|
||||
|
||||
// CHECK: #[[$MAP:.*]] = affine_map<(d0) -> (d0)>
|
||||
// CHECK-LABEL: func @parallel_loop_4d(
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: scf.parallel
|
||||
// CHECK: {mapping = [{bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64}]}
|
||||
// CHECK: {mapping = [{bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 3 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 4 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 5 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64}]}
|
||||
// CHECK: {mapping = [{bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 0 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 1 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 2 : i64},
|
||||
// CHECK-SAME: {bound = affine_map<(d0) -> (d0)>, map = affine_map<(d0) -> (d0)>, processor = 6 : i64}]}
|
||||
// CHECK: {mapping = [{bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64}]}
|
||||
// CHECK: {mapping = [{bound = #[[$MAP]], map = #[[$MAP]], processor = 3 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 4 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 5 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64}]}
|
||||
// CHECK: {mapping = [{bound = #[[$MAP]], map = #[[$MAP]], processor = 0 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 1 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 2 : i64},
|
||||
// CHECK-SAME: {bound = #[[$MAP]], map = #[[$MAP]], processor = 6 : i64}]}
|
||||
// CHECK-NOT: mapping
|
||||
|
|
|
@ -635,6 +635,10 @@ func @reshape_dynamic(%arg0: memref<?x?x?xf32>,
|
|||
memref<?x?x?xf32, offset : ?, strides : [?, ?, 1]>
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-DAG: #[[$reshapeD01:.*]] = affine_map<(d0, d1, d2) -> (d0, d1)>
|
||||
// CHECK-DAG: #[[$reshapeD2:.*]] = affine_map<(d0, d1, d2) -> (d2)>
|
||||
|
||||
// CHECK-LABEL: func @reshape
|
||||
// CHECK: linalg.reshape {{.*}} [#[[$reshapeD01]], #[[$reshapeD2]]]
|
||||
// CHECK-SAME: memref<?x?x?xf32> into memref<?x?xf32>
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
// CHECK-DAG: #[[$map0:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
|
||||
// CHECK-DAG: #[[$map1:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2 + d2)>
|
||||
// CHECK-DAG: #[[$map2:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d0 * s1 + s0 + d2 * s2 + d1)>
|
||||
// CHECK-DAG: #[[$map3:.*]] = affine_map<(d0, d1, d2) -> (d0, d2, d1)>
|
||||
// CHECK-DAG: #[[$map4:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2] -> (d2 * s1 + s0 + d1 * s2 + d0)>
|
||||
// CHECK-DAG: #[[$map5:.*]] = affine_map<(d0, d1, d2) -> (d2, d1, d0)>
|
||||
// CHECK-DAG: #[[$map6:.*]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)>
|
||||
// CHECK-DAG: #[[$map7:.*]] = affine_map<()[s0] -> (s0)>
|
||||
// CHECK-DAG: #[[$map8:.*]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
// RUN: mlir-opt %s | mlir-opt | FileCheck %s
|
||||
|
||||
// CHECK-DAG: #[[MAP0:map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
|
||||
// CHECK-LABEL: func @vector_transfer_ops(
|
||||
func @vector_transfer_ops(%arg0: memref<?x?xf32>,
|
||||
%arg1 : memref<?x?xvector<4x3xf32>>,
|
||||
|
|
|
@ -38,7 +38,7 @@ func @vector_add_read_write(%id : index, %A: memref<32xf32>, %B: memref<32xf32>,
|
|||
|
||||
// -----
|
||||
|
||||
// CHECK-DAG: #[[MAP0:map[0-9]+]] = affine_map<()[s0] -> (s0 * 2)>
|
||||
// CHECK-DAG: #[[MAP0:map[0-9]*]] = affine_map<()[s0] -> (s0 * 2)>
|
||||
|
||||
// CHECK: func @vector_add_cycle
|
||||
// CHECK-SAME: (%[[ID:.*]]: index
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// RUN: mlir-opt %s -test-vector-to-vector-conversion | FileCheck %s
|
||||
// RUN: mlir-opt %s -test-vector-unrolling-patterns | FileCheck %s
|
||||
|
||||
// CHECK-DAG: #[[MAP0:map[0-9]+]] = affine_map<(d0, d1) -> (d0, d1)>
|
||||
// CHECK-DAG: #[[MAP1:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d1, d2)>
|
||||
|
||||
// CHECK-LABEL: func @add4x2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='func(cse)' | FileCheck %s
|
||||
|
||||
// CHECK-DAG: #map0 = affine_map<(d0) -> (d0 mod 2)>
|
||||
// CHECK-DAG: #[[$MAP:.*]] = affine_map<(d0) -> (d0 mod 2)>
|
||||
#map0 = affine_map<(d0) -> (d0 mod 2)>
|
||||
|
||||
// CHECK-LABEL: @simple_constant
|
||||
|
@ -19,7 +19,7 @@ func @basic() -> (index, index) {
|
|||
%c0 = constant 0 : index
|
||||
%c1 = constant 0 : index
|
||||
|
||||
// CHECK-NEXT: %0 = affine.apply #map0(%c0)
|
||||
// CHECK-NEXT: %0 = affine.apply #[[$MAP]](%c0)
|
||||
%0 = affine.apply #map0(%c0)
|
||||
%1 = affine.apply #map0(%c1)
|
||||
|
||||
|
|
|
@ -785,7 +785,7 @@ func @should_fuse_at_src_depth1_and_dst_depth1() {
|
|||
}
|
||||
|
||||
// -----
|
||||
// CHECK: [[$MAP0:#map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 10 + d1)>
|
||||
// CHECK: [[$MAP0:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 * 10 + d1)>
|
||||
|
||||
// CHECK-LABEL: func @should_fuse_src_depth1_at_dst_depth2
|
||||
func @should_fuse_src_depth1_at_dst_depth2() {
|
||||
|
@ -1935,16 +1935,16 @@ func @fuse_across_dim_mismatch(%arg0: memref<4x4x16x1xf32>, %arg1: memref<144x9x
|
|||
}
|
||||
return
|
||||
}
|
||||
// MAXIMAL: #map0 = affine_map<(d0, d1) -> (d0 * 16 + d1)>
|
||||
// MAXIMAL: #map = affine_map<(d0, d1) -> (d0 * 16 + d1)>
|
||||
// MAXIMAL-LABEL: func @fuse_across_dim_mismatch
|
||||
// MAXIMAL: alloc() : memref<1x1xf32>
|
||||
// MAXIMAL: affine.for %{{.*}} = 0 to 9 {
|
||||
// MAXIMAL-NEXT: affine.for %{{.*}} = 0 to 9 {
|
||||
// MAXIMAL-NEXT: affine.for %{{.*}} = 0 to 4 {
|
||||
// MAXIMAL-NEXT: affine.for %{{.*}} = 0 to 16 {
|
||||
// MAXIMAL-NEXT: affine.apply #map0(%{{.*}}, %{{.*}})
|
||||
// MAXIMAL-NEXT: affine.apply #map(%{{.*}}, %{{.*}})
|
||||
// MAXIMAL-NEXT: affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>
|
||||
// MAXIMAL-NEXT: affine.apply #map0(%{{.*}}, %{{.*}})
|
||||
// MAXIMAL-NEXT: affine.apply #map(%{{.*}}, %{{.*}})
|
||||
// MAXIMAL-NEXT: affine.load %{{.*}}[0, 0] : memref<1x1xf32>
|
||||
// MAXIMAL-NEXT: }
|
||||
// MAXIMAL-NEXT: }
|
||||
|
|
|
@ -87,7 +87,7 @@ func @invariant_code_inside_affine_if() {
|
|||
// CHECK: %0 = alloc() : memref<10xf32>
|
||||
// CHECK-NEXT: %cst = constant 8.000000e+00 : f32
|
||||
// CHECK-NEXT: affine.for %arg0 = 0 to 10 {
|
||||
// CHECK-NEXT: %1 = affine.apply #map0(%arg0)
|
||||
// CHECK-NEXT: %1 = affine.apply #map(%arg0)
|
||||
// CHECK-NEXT: affine.if #set(%arg0, %1) {
|
||||
// CHECK-NEXT: %2 = addf %cst, %cst : f32
|
||||
// CHECK-NEXT: affine.store %2, %0[%arg0] : memref<10xf32>
|
||||
|
|
|
@ -29,15 +29,15 @@ func @test_norm(%arg0 : memref<1x16x14x14xf32, #map0>) -> () {
|
|||
// Same test with op_nonnorm, with maps in the arguments and the operations in the function.
|
||||
|
||||
// CHECK-LABEL: test_nonnorm
|
||||
// CHECK-SAME: (%[[ARG0:[a-z0-9]*]]: memref<1x16x14x14xf32, #map0>)
|
||||
// CHECK-SAME: (%[[ARG0:[a-z0-9]*]]: memref<1x16x14x14xf32, #map>)
|
||||
func @test_nonnorm(%arg0 : memref<1x16x14x14xf32, #map0>) -> () {
|
||||
%0 = alloc() : memref<1x16x14x14xf32, #map0>
|
||||
"test.op_nonnorm"(%arg0, %0) : (memref<1x16x14x14xf32, #map0>, memref<1x16x14x14xf32, #map0>) -> ()
|
||||
dealloc %0 : memref<1x16x14x14xf32, #map0>
|
||||
|
||||
// CHECK: %[[v0:[a-z0-9]*]] = alloc() : memref<1x16x14x14xf32, #map0>
|
||||
// CHECK: "test.op_nonnorm"(%[[ARG0]], %[[v0]]) : (memref<1x16x14x14xf32, #map0>, memref<1x16x14x14xf32, #map0>) -> ()
|
||||
// CHECK: dealloc %[[v0]] : memref<1x16x14x14xf32, #map0>
|
||||
// CHECK: %[[v0:[a-z0-9]*]] = alloc() : memref<1x16x14x14xf32, #map>
|
||||
// CHECK: "test.op_nonnorm"(%[[ARG0]], %[[v0]]) : (memref<1x16x14x14xf32, #map>, memref<1x16x14x14xf32, #map>) -> ()
|
||||
// CHECK: dealloc %[[v0]] : memref<1x16x14x14xf32, #map>
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue