diff --git a/mlir/docs/SymbolsAndSymbolTables.md b/mlir/docs/SymbolsAndSymbolTables.md index d7bcfa46d4e5..90e0fab47c2c 100644 --- a/mlir/docs/SymbolsAndSymbolTables.md +++ b/mlir/docs/SymbolsAndSymbolTables.md @@ -1,221 +1,227 @@ # Symbols and Symbol Tables [TOC] With [Regions](LangRef.md#regions), the multi-level aspect of MLIR is structural in the IR. A lot of infrastructure within the compiler is built around this nesting structure; including the processing of operations within the [pass manager](PassManagement.md#pass-manager). One advantage of the MLIR design is that it is able to process operations in parallel, utilizing multiple threads. This is possible due to a property of the IR known as [`IsolatedFromAbove`](Traits.md#isolatedfromabove). Without this property, any operation could affect or mutate the use-list of operations defined above. Making this thread-safe requires expensive locking in some of the core IR data structures, which becomes quite inefficient. To enable multi-threaded compilation without this locking, MLIR uses local pools for constant values as well as `Symbol` accesses for global values and variables. This document details the design of `Symbol`s, what they are and how they fit into the system. The `Symbol` infrastructure essentially provides a non-SSA mechanism in which to refer to an operation symbolically with a name. This allows for referring to operations defined above regions that were defined as `IsolatedFromAbove` in a safe way. It also allows for symbolically referencing operations define below other regions as well. ## Symbol A `Symbol` is a named operation that resides immediately within a region that defines a [`SymbolTable`](#symbol-table). The name of a symbol *must* be unique within the parent `SymbolTable`. This name is semantically similarly to an SSA result value, and may be referred to by other operations to provide a symbolic link, or use, to the symbol. An example of a `Symbol` operation is [`func`](LangRef.md#functions). `func` defines a symbol name, which is [referred to](#referencing-a-symbol) by operations like [`std.call`](Dialects/Standard.md#call). -### Defining a Symbol +### Defining or declaring a Symbol A `Symbol` operation should use the `SymbolOpInterface` interface to provide the necessary verification and accessors; it also supports operations, such as `module`, that conditionally define a symbol. `Symbol`s must have the following properties: * A `StringAttr` attribute named 'SymbolTable::getSymbolAttrName()'(`sym_name`). - This attribute defines the symbolic 'name' of the operation. * An optional `StringAttr` attribute named 'SymbolTable::getVisibilityAttrName()'(`sym_visibility`) - This attribute defines the [visibility](#symbol-visibility) of the symbol, or more specifically in-which scopes it may be accessed. * No SSA results - Intermixing the different ways to `use` an operation quickly becomes unwieldy and difficult to analyze. +* Whether this operation is a declaration or definition (`isDeclaration`) + - Declarations do not define a new symbol but reference a symbol defined + outside the visible IR. ## Symbol Table Described above are `Symbol`s, which reside within a region of an operation defining a `SymbolTable`. A `SymbolTable` operation provides the container for the [`Symbol`](#symbol) operations. It verifies that all `Symbol` operations have a unique name, and provides facilities for looking up symbols by name. Operations defining a `SymbolTable` must use the `OpTrait::SymbolTable` trait. ### Referencing a Symbol `Symbol`s are referenced symbolically by name via the [`SymbolRefAttr`](LangRef.md#symbol-reference-attribute) attribute. A symbol reference attribute contains a named reference to an operation that is nested within a symbol table. It may optionally contain a set of nested references that further resolve to a symbol nested within a different symbol table. When resolving a nested reference, each non-leaf reference must refer to a symbol operation that is also a [symbol table](#symbol-table). Below is an example of how an operation can reference a symbol operation: ```mlir // This `func` operation defines a symbol named `symbol`. func @symbol() // Our `foo.user` operation contains a SymbolRefAttr with the name of the // `symbol` func. "foo.user"() {uses = [@symbol]} : () -> () // Symbol references resolve to the nearest parent operation that defines a // symbol table, so we can have references with arbitrary nesting levels. func @other_symbol() { affine.for %i0 = 0 to 10 { // Our `foo.user` operation resolves to the same `symbol` func as defined // above. "foo.user"() {uses = [@symbol]} : () -> () } return } // Here we define a nested symbol table. References within this operation will // not resolve to any symbols defined above. module { // Error. We resolve references with respect to the closest parent operation // that defines a symbol table, so this reference can't be resolved. "foo.user"() {uses = [@symbol]} : () -> () } // Here we define another nested symbol table, except this time it also defines // a symbol. module @module_symbol { // This `func` operation defines a symbol named `nested_symbol`. func @nested_symbol() } // Our `foo.user` operation may refer to the nested symbol, by resolving through // the parent. "foo.user"() {uses = [@module_symbol::@nested_symbol]} : () -> () ``` Using an attribute, as opposed to an SSA value, has several benefits: * References may appear in more places than the operand list; including [nested attribute dictionaries](LangRef.md#dictionary-attribute), [array attributes](LangRef.md#array-attribute), etc. * Handling of SSA dominance remains unchanged. - If we were to use SSA values, we would need to create some mechanism in which to opt-out of certain properties of it such as dominance. Attributes allow for referencing the operations irregardless of the order in which they were defined. - Attributes simplify referencing operations within nested symbol tables, which are traditionally not visible outside of the parent region. The impact of this choice to use attributes as opposed to SSA values is that we now have two mechanisms with reference operations. This means that some dialects must either support both `SymbolRefs` and SSA value references, or provide operations that materialize SSA values from a symbol reference. Each has different trade offs depending on the situation. A function call may directly use a `SymbolRef` as the callee, whereas a reference to a global variable might use a materialization operation so that the variable can be used in other operations like `std.addi`. [`llvm.mlir.addressof`](Dialects/LLVM.md#llvmmliraddressof) is one example of such an operation. See the `LangRef` definition of the [`SymbolRefAttr`](LangRef.md#symbol-reference-attribute) for more information about the structure of this attribute. Operations that reference a `Symbol` and want to perform verification and general mutation of the symbol should implement the `SymbolUserOpInterface` to ensure that symbol accesses are legal and efficient. ### Manipulating a Symbol As described above, `SymbolRefs` act as an auxiliary way of defining uses of operations to the traditional SSA use-list. As such, it is imperative to provide similar functionality to manipulate and inspect the list of uses and the users. The following are a few of the utilities provided by the `SymbolTable`: * `SymbolTable::getSymbolUses` - Access an iterator range over all of the uses on and nested within a particular operation. * `SymbolTable::symbolKnownUseEmpty` - Check if a particular symbol is known to be unused within a specific section of the IR. * `SymbolTable::replaceAllSymbolUses` - Replace all of the uses of one symbol with a new one within a specific section of the IR. * `SymbolTable::lookupNearestSymbolFrom` - Lookup the definition of a symbol in the nearest symbol table from some anchor operation. ## Symbol Visibility Along with a name, a `Symbol` also has a `visibility` attached to it. The `visibility` of a symbol defines its structural reachability within the IR. A symbol has one of the following visibilities: * Public (Default) - The symbol may be referenced from outside of the visible IR. We cannot - assume that all of the uses of this symbol are observable. + assume that all of the uses of this symbol are observable. If the + operation declares a symbol (as opposed to defining it), public + visibility is not allowed because symbol declarations are not intended + to be used from outside the visible IR. * Private - The symbol may only be referenced from within the current symbol table. * Nested - The symbol may be referenced by operations outside of the current symbol table, but not outside of the visible IR, as long as each symbol table parent also defines a non-private symbol. For Functions, the visibility is printed after the operation name without a quote. A few examples of what this looks like in the IR are shown below: ```mlir module @public_module { // This function can be accessed by 'live.user', but cannot be referenced // externally; all uses are known to reside within parent regions. func nested @nested_function() // This function cannot be accessed outside of 'public_module'. func private @private_function() } // This function can only be accessed from within the top-level module. func private @private_function() // This function may be referenced externally. func @public_function() "live.user"() {uses = [ @public_module::@nested_function, @private_function, @public_function ]} : () -> () ``` diff --git a/mlir/include/mlir/IR/Function.h b/mlir/include/mlir/IR/Function.h index 3ea546cd52a3..3ff2700a3380 100644 --- a/mlir/include/mlir/IR/Function.h +++ b/mlir/include/mlir/IR/Function.h @@ -1,143 +1,149 @@ //===- Function.h - MLIR Function Class -------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Functions are the basic unit of composition in MLIR. // //===----------------------------------------------------------------------===// #ifndef MLIR_IR_FUNCTION_H #define MLIR_IR_FUNCTION_H #include "mlir/IR/Block.h" #include "mlir/IR/FunctionSupport.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/SymbolTable.h" #include "mlir/Interfaces/CallInterfaces.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace mlir { //===--------------------------------------------------------------------===// // Function Operation. //===--------------------------------------------------------------------===// /// FuncOp represents a function, or an operation containing one region that /// forms a CFG(Control Flow Graph). The region of a function is not allowed to /// implicitly capture global values, and all external references must use /// Function arguments or attributes that establish a symbolic connection(e.g. /// symbols referenced by name via a string attribute). class FuncOp : public Op { public: using Op::Op; using Op::print; static StringRef getOperationName() { return "func"; } static FuncOp create(Location location, StringRef name, FunctionType type, ArrayRef attrs = {}); static FuncOp create(Location location, StringRef name, FunctionType type, iterator_range attrs); static FuncOp create(Location location, StringRef name, FunctionType type, ArrayRef attrs, ArrayRef argAttrs); static void build(OpBuilder &builder, OperationState &result, StringRef name, FunctionType type, ArrayRef attrs = {}, ArrayRef argAttrs = {}); /// Operation hooks. static ParseResult parse(OpAsmParser &parser, OperationState &result); void print(OpAsmPrinter &p); LogicalResult verify(); /// Create a deep copy of this function and all of its blocks, remapping /// any operands that use values outside of the function using the map that is /// provided (leaving them alone if no entry is present). If the mapper /// contains entries for function arguments, these arguments are not included /// in the new function. Replaces references to cloned sub-values with the /// corresponding value that is copied, and adds those mappings to the mapper. FuncOp clone(BlockAndValueMapping &mapper); FuncOp clone(); /// Clone the internal blocks and attributes from this function into dest. Any /// cloned blocks are appended to the back of dest. This function asserts that /// the attributes of the current function and dest are compatible. void cloneInto(FuncOp dest, BlockAndValueMapping &mapper); //===--------------------------------------------------------------------===// // CallableOpInterface //===--------------------------------------------------------------------===// /// Returns the region on the current operation that is callable. This may /// return null in the case of an external callable object, e.g. an external /// function. Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); } /// Returns the results types that the callable region produces when executed. ArrayRef getCallableResults() { return getType().getResults(); } + //===--------------------------------------------------------------------===// + // SymbolOpInterface Methods + //===--------------------------------------------------------------------===// + + bool isDeclaration() { return isExternal(); } + private: // This trait needs access to the hooks defined below. friend class OpTrait::FunctionLike; /// Returns the number of arguments. This is a hook for OpTrait::FunctionLike. unsigned getNumFuncArguments() { return getType().getInputs().size(); } /// Returns the number of results. This is a hook for OpTrait::FunctionLike. unsigned getNumFuncResults() { return getType().getResults().size(); } /// Hook for OpTrait::FunctionLike, called after verifying that the 'type' /// attribute is present and checks if it holds a function type. Ensures /// getType, getNumFuncArguments, and getNumFuncResults can be called safely. LogicalResult verifyType() { auto type = getTypeAttr().getValue(); if (!type.isa()) return emitOpError("requires '" + getTypeAttrName() + "' attribute of function type"); return success(); } }; } // end namespace mlir namespace llvm { // Functions hash just like pointers. template <> struct DenseMapInfo { static mlir::FuncOp getEmptyKey() { auto pointer = llvm::DenseMapInfo::getEmptyKey(); return mlir::FuncOp::getFromOpaquePointer(pointer); } static mlir::FuncOp getTombstoneKey() { auto pointer = llvm::DenseMapInfo::getTombstoneKey(); return mlir::FuncOp::getFromOpaquePointer(pointer); } static unsigned getHashValue(mlir::FuncOp val) { return hash_value(val.getAsOpaquePointer()); } static bool isEqual(mlir::FuncOp LHS, mlir::FuncOp RHS) { return LHS == RHS; } }; /// Allow stealing the low bits of FuncOp. template <> struct PointerLikeTypeTraits { public: static inline void *getAsVoidPointer(mlir::FuncOp I) { return const_cast(I.getAsOpaquePointer()); } static inline mlir::FuncOp getFromVoidPointer(void *P) { return mlir::FuncOp::getFromOpaquePointer(P); } static constexpr int NumLowBitsAvailable = 3; }; } // namespace llvm #endif // MLIR_IR_FUNCTION_H diff --git a/mlir/include/mlir/IR/SymbolInterfaces.td b/mlir/include/mlir/IR/SymbolInterfaces.td index a997acee07f7..83cd6bdbd861 100644 --- a/mlir/include/mlir/IR/SymbolInterfaces.td +++ b/mlir/include/mlir/IR/SymbolInterfaces.td @@ -1,207 +1,222 @@ //===- SymbolInterfaces.td - Interfaces for symbol ops -----*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file contains a set of interfaces and traits that can be used to define // properties of symbol and symbol table operations. // //===----------------------------------------------------------------------===// #ifndef MLIR_IR_SYMBOLINTERFACES #define MLIR_IR_SYMBOLINTERFACES include "mlir/IR/OpBase.td" //===----------------------------------------------------------------------===// // SymbolOpInterface //===----------------------------------------------------------------------===// def Symbol : OpInterface<"SymbolOpInterface"> { let description = [{ This interface describes an operation that may define a `Symbol`. A `Symbol` operation resides immediately within a region that defines a `SymbolTable`. See [Symbols and SymbolTables](SymbolsAndSymbolTables.md) for more details and constraints on `Symbol` operations. }]; let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<"Returns the name of this symbol.", "StringRef", "getName", (ins), [{ // Don't rely on the trait implementation as optional symbol operations // may override this. return mlir::SymbolTable::getSymbolName($_op); }], /*defaultImplementation=*/[{ return mlir::SymbolTable::getSymbolName(this->getOperation()); }] >, InterfaceMethod<"Sets the name of this symbol.", "void", "setName", (ins "StringRef":$name), [{}], /*defaultImplementation=*/[{ this->getOperation()->setAttr( mlir::SymbolTable::getSymbolAttrName(), StringAttr::get(name, this->getOperation()->getContext())); }] >, InterfaceMethod<"Gets the visibility of this symbol.", "mlir::SymbolTable::Visibility", "getVisibility", (ins), [{}], /*defaultImplementation=*/[{ return mlir::SymbolTable::getSymbolVisibility(this->getOperation()); }] >, InterfaceMethod<"Returns true if this symbol has nested visibility.", "bool", "isNested", (ins), [{}], /*defaultImplementation=*/[{ return getVisibility() == mlir::SymbolTable::Visibility::Nested; }] >, InterfaceMethod<"Returns true if this symbol has private visibility.", "bool", "isPrivate", (ins), [{}], /*defaultImplementation=*/[{ return getVisibility() == mlir::SymbolTable::Visibility::Private; }] >, InterfaceMethod<"Returns true if this symbol has public visibility.", "bool", "isPublic", (ins), [{}], /*defaultImplementation=*/[{ return getVisibility() == mlir::SymbolTable::Visibility::Public; }] >, InterfaceMethod<"Sets the visibility of this symbol.", "void", "setVisibility", (ins "mlir::SymbolTable::Visibility":$vis), [{}], /*defaultImplementation=*/[{ mlir::SymbolTable::setSymbolVisibility(this->getOperation(), vis); }] >, InterfaceMethod<"Sets the visibility of this symbol to be nested.", "void", "setNested", (ins), [{}], /*defaultImplementation=*/[{ setVisibility(mlir::SymbolTable::Visibility::Nested); }] >, InterfaceMethod<"Sets the visibility of this symbol to be private.", "void", "setPrivate", (ins), [{}], /*defaultImplementation=*/[{ setVisibility(mlir::SymbolTable::Visibility::Private); }] >, InterfaceMethod<"Sets the visibility of this symbol to be public.", "void", "setPublic", (ins), [{}], /*defaultImplementation=*/[{ setVisibility(mlir::SymbolTable::Visibility::Public); }] >, InterfaceMethod<[{ Get all of the uses of the current symbol that are nested within the given operation 'from'. Note: See mlir::SymbolTable::getSymbolUses for more details. }], "Optional<::mlir::SymbolTable::UseRange>", "getSymbolUses", (ins "Operation *":$from), [{}], /*defaultImplementation=*/[{ return ::mlir::SymbolTable::getSymbolUses(this->getOperation(), from); }] >, InterfaceMethod<[{ Return if the current symbol is known to have no uses that are nested within the given operation 'from'. Note: See mlir::SymbolTable::symbolKnownUseEmpty for more details. }], "bool", "symbolKnownUseEmpty", (ins "Operation *":$from), [{}], /*defaultImplementation=*/[{ return ::mlir::SymbolTable::symbolKnownUseEmpty(this->getOperation(), from); }] >, InterfaceMethod<[{ Attempt to replace all uses of the current symbol with the provided symbol 'newSymbol' that are nested within the given operation 'from'. Note: See mlir::SymbolTable::replaceAllSymbolUses for more details. }], "LogicalResult", "replaceAllSymbolUses", (ins "StringRef":$newSymbol, "Operation *":$from), [{}], /*defaultImplementation=*/[{ return ::mlir::SymbolTable::replaceAllSymbolUses(this->getOperation(), newSymbol, from); }] >, InterfaceMethod<[{ Returns true if this operation optionally defines a symbol based on the presence of the symbol name. }], "bool", "isOptionalSymbol", (ins), [{}], /*defaultImplementation=*/[{ return false; }] >, InterfaceMethod<[{ Returns true if this operation can be discarded if it has no remaining symbol uses. }], "bool", "canDiscardOnUseEmpty", (ins), [{}], /*defaultImplementation=*/[{ // By default, base this on the visibility alone. A symbol can be // discarded as long as it is not public. Only public symbols may be // visible from outside of the IR. return getVisibility() != ::mlir::SymbolTable::Visibility::Public; }] >, + InterfaceMethod<[{ + Returns true if this operation is a declaration of a symbol (as opposed + to a definition). + }], + "bool", "isDeclaration", (ins), [{}], + /*defaultImplementation=*/[{ + // By default, assume that the operation defines a symbol. + return false; + }] + >, ]; let verify = [{ // If this is an optional symbol, bail out early if possible. auto concreteOp = cast($_op); if (concreteOp.isOptionalSymbol()) { if(!concreteOp.getAttr(::mlir::SymbolTable::getSymbolAttrName())) return success(); } - return ::mlir::detail::verifySymbol($_op); + if (::mlir::failed(::mlir::detail::verifySymbol($_op))) + return ::mlir::failure(); + if (concreteOp.isDeclaration() && concreteOp.isPublic()) + return concreteOp.emitOpError("symbol declaration cannot have public " + "visibility"); + return success(); }]; let extraClassDeclaration = [{ /// Custom classof that handles the case where the symbol is optional. static bool classof(Operation *op) { auto *concept = getInterfaceFor(op); if (!concept) return false; return !concept->isOptionalSymbol(op) || op->getAttr(::mlir::SymbolTable::getSymbolAttrName()); } }]; let extraTraitClassDeclaration = [{ using Visibility = mlir::SymbolTable::Visibility; }]; } //===----------------------------------------------------------------------===// // SymbolUserOpInterface //===----------------------------------------------------------------------===// def SymbolUserOpInterface : OpInterface<"SymbolUserOpInterface"> { let description = [{ This interface describes an operation that may use a `Symbol`. This interface allows for users of symbols to hook into verification and other symbol related utilities that are either costly or otherwise disallowed within a traditional operation. }]; let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<"Verify the symbol uses held by this operation.", "LogicalResult", "verifySymbolUses", (ins "::mlir::SymbolTableCollection &":$symbolTable) >, ]; } //===----------------------------------------------------------------------===// // Symbol Traits //===----------------------------------------------------------------------===// // Op defines a symbol table. def SymbolTable : NativeOpTrait<"SymbolTable">; #endif // MLIR_IR_SYMBOLINTERFACES diff --git a/mlir/integration_test/Dialect/Linalg/CPU/matmul-vs-matvec.mlir b/mlir/integration_test/Dialect/Linalg/CPU/matmul-vs-matvec.mlir index 9157f9abaab9..7aa875a3cf53 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/matmul-vs-matvec.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/matmul-vs-matvec.mlir @@ -1,74 +1,74 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -O3 -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) func @matmul(%A: memref, %B: memref) -> (memref) { %c0 = constant 0 : index %c1 = constant 1 : index %f0 = constant 0.0 : f32 %x = dim %A, %c0 : memref %y = dim %B, %c1 : memref %C = alloc(%x, %y) : memref linalg.fill(%C, %f0) : memref, f32 linalg.matmul ins(%A, %B: memref, memref) outs(%C: memref) return %C : memref } func @matvec(%A: memref, %B: memref) -> (memref) { %c0 = constant 0 : index %c1 = constant 1 : index %f0 = constant 0.0 : f32 %m = dim %A, %c0 : memref %x = dim %A, %c1 : memref %n = dim %B, %c1 : memref %C = alloc(%m, %n) : memref linalg.fill(%C, %f0) : memref, f32 scf.for %i = %c0 to %n step %c1 { %b = subview %B[0, %i][%x, 1][1, 1] : memref to memref %c = subview %C[0, %i][%m, 1][1, 1] : memref to memref linalg.matvec ins(%A, %b: memref, memref) outs(%c: memref) } return %C : memref } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %m = constant 5 : index %x = constant 3 : index %n = constant 2 : index %val1 = constant 13.0 : f32 %val2 = constant 17.0 : f32 %A = alloc(%m, %x) : memref %B = alloc(%x, %n) : memref linalg.fill(%A, %val1) : memref, f32 linalg.fill(%B, %val2) : memref, f32 store %val1, %B[%c0, %c0] : memref %C1 = call @matmul(%A, %B) : (memref, memref) -> memref %C2 = call @matvec(%A, %B) : (memref, memref) -> memref scf.for %i = %c0 to %m step %c1 { scf.for %j = %c0 to %n step %c1 { %e1 = load %C1[%i, %j] : memref %e2 = load %C2[%i, %j] : memref %c = cmpf "oeq", %e1, %e2 : f32 assert %c, "Matmul does not produce same output as matvec" } } %C2_ = memref_cast %C2 : memref to memref<*xf32> call @print_memref_f32(%C2_) : (memref<*xf32>) -> () return } // CHECK: Unranked Memref base@ = {{.*}} rank = 2 offset = 0 sizes = [5, 2] strides = [2, 1] data = // CHECK-NEXT: [ // CHECK-SAME: [611, 663], // CHECK-NEXT: [611, 663], // CHECK-NEXT: [611, 663], // CHECK-NEXT: [611, 663], // CHECK-NEXT: [611, 663] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/rank-reducing-subview.mlir b/mlir/integration_test/Dialect/Linalg/CPU/rank-reducing-subview.mlir index ceffd6f79d23..2cfe02b7d88b 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/rank-reducing-subview.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/rank-reducing-subview.mlir @@ -1,38 +1,38 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -O3 -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %f0 = constant 0.0 : f32 %f1 = constant 1.0 : f32 %f2 = constant 2.0 : f32 %f3 = constant 3.0 : f32 %A = alloc(%c2, %c2) : memref store %f0, %A[%c0, %c0] : memref store %f1, %A[%c0, %c1] : memref store %f2, %A[%c1, %c0] : memref store %f3, %A[%c1, %c1] : memref %B = subview %A[%c1, 0][1, %c2][1, 1] : memref to memref %C = subview %A[0, %c1][%c2, 1][1, 1] : memref to memref %A_ = memref_cast %A : memref to memref<*xf32> call @print_memref_f32(%A_) : (memref<*xf32>) -> () %B_ = memref_cast %B : memref to memref<*xf32> call @print_memref_f32(%B_) : (memref<*xf32>) -> () %C_ = memref_cast %C : memref to memref<*xf32> call @print_memref_f32(%C_) : (memref<*xf32>) -> () return } // CHECK: Unranked Memref base@ = {{.*}} rank = 2 offset = 0 sizes = [2, 2] strides = [2, 1] data = // CHECK-NEXT: [ // CHECK-SAME: [0, 1], // CHECK-NEXT: [2, 3] // CHECK-SAME: ] // CHECK: [2, 3] // CHECK: [1, 3] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-call.mlir index 7cc0875b3353..c67308fb6d8a 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-call.mlir @@ -1,62 +1,62 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=4" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=4" \ // RUN: -test-conv-vectorization="tile-sizes=1,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns a 1-D buffer of size %s1 filled with the value %f func @alloc_1d_filled_f32(%s1 : index, %f : f32) -> memref { %buf = alloc(%s1) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_1d(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_1d ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter1D = call @alloc_1d_filled_f32(%c3, %val) : (index, f32) -> (memref) %in1D = call @alloc_1d_filled_f32(%c8, %val) : (index, f32) -> (memref) %out1D = call @alloc_1d_filled_f32(%c6, %zero) : (index, f32) -> (memref) store %f10, %in1D[%c3] : memref call @conv_1d(%in1D, %filter1D, %out1D) : (memref, memref, memref) -> () %out1D_ = memref_cast %out1D : memref to memref<*xf32> call @print_memref_f32(%out1D_): (memref<*xf32>) -> () dealloc %filter1D : memref dealloc %in1D : memref dealloc %out1D : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [12, 28, 28, 28, 12, 12] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-ncw-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-ncw-call.mlir index 7f90ac675f72..db97bc40538c 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-ncw-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-ncw-call.mlir @@ -1,68 +1,68 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,0,4" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,0,4" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 3-D buffer of size (%s1, %s2, %s3) filled with the value %f func @alloc_3d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_1d_ncw(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_1d_ncw ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter1D_ncw = call @alloc_3d_filled_f32(%c1, %c1, %c3, %val) : (index, index, index, f32) -> (memref) %in1D_ncw = call @alloc_3d_filled_f32(%c1, %c1, %c8, %val) : (index, index, index, f32) -> (memref) %out1D_ncw = call @alloc_3d_filled_f32(%c1, %c1, %c6, %zero) : (index, index, index, f32) -> (memref) store %f10, %in1D_ncw[%c0, %c0, %c3] : memref call @conv_1d_ncw(%in1D_ncw, %filter1D_ncw, %out1D_ncw) : (memref, memref, memref) -> () %out1D_ncw_ = memref_cast %out1D_ncw : memref to memref<*xf32> call @print_memref_f32(%out1D_ncw_): (memref<*xf32>) -> () dealloc %filter1D_ncw : memref dealloc %in1D_ncw : memref dealloc %out1D_ncw : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [12, 28, 28, 28, 12, 12] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-nwc-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-nwc-call.mlir index 3eb0959ddda1..808763002018 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-nwc-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-1d-nwc-call.mlir @@ -1,79 +1,79 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,4" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,4" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 3-D buffer of size (%s1, %s2, %s3) filled with the value %f func @alloc_3d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_1d_nwc(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_1d_nwc ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter1D_nwc = call @alloc_3d_filled_f32(%c1, %c3, %c1, %val) : (index, index, index, f32) -> (memref) %in1D_nwc = call @alloc_3d_filled_f32(%c3, %c8, %c1, %val) : (index, index, index, f32) -> (memref) %out1D_nwc = call @alloc_3d_filled_f32(%c3, %c6, %c1, %zero) : (index, index, index, f32) -> (memref) store %f10, %in1D_nwc[%c0, %c3, %c0] : memref call @conv_1d_nwc(%in1D_nwc, %filter1D_nwc, %out1D_nwc) : (memref, memref, memref) -> () %out1D_nwc_ = memref_cast %out1D_nwc : memref to memref<*xf32> call @print_memref_f32(%out1D_nwc_): (memref<*xf32>) -> () dealloc %filter1D_nwc : memref dealloc %in1D_nwc : memref dealloc %out1D_nwc : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [12], // CHECK-COUNT-3: [28], // CHECK-NEXT: [12], // CHECK-NEXT: [12] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-5: [12], // CHECK-NEXT: [12] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-5: [12], // CHECK-NEXT: [12] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-call.mlir index 787cbf5d268b..f85471ce2324 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-call.mlir @@ -1,67 +1,67 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,2" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,2" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns a 2-D buffer of size (%s1, %s2) filled with the value %f func @alloc_2d_filled_f32(%s1 : index, %s2 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_2d(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_2d ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter2D = call @alloc_2d_filled_f32(%c3, %c3, %val) : (index, index, f32) -> (memref) %in2D = call @alloc_2d_filled_f32(%c8, %c8, %val) : (index, index, f32) -> (memref) %out2D = call @alloc_2d_filled_f32(%c6, %c6, %zero) : (index, index, f32) -> (memref) store %f10, %in2D[%c0, %c3] : memref call @conv_2d(%in2D, %filter2D, %out2D) : (memref, memref, memref) -> () %out2D_ = memref_cast %out2D : memref to memref<*xf32> call @print_memref_f32(%out2D_): (memref<*xf32>) -> () dealloc %filter2D : memref dealloc %in2D : memref dealloc %out2D : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [36, 52, 52, 52, 36, 36], // CHECK-COUNT-5: [36, 36, 36, 36, 36, 36] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nchw-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nchw-call.mlir index c6236db6a05a..d18a6becbcf3 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nchw-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nchw-call.mlir @@ -1,81 +1,81 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,0,4,4" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,0,4,4" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 4-D buffer of size (%s1, %s2, %s3, %s4) filled with the value %f func @alloc_4d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %s4 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3, %s4) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_2d_nchw(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_2d_nchw ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter2D_nchw = call @alloc_4d_filled_f32(%c1, %c1, %c3, %c3, %val) : (index, index, index, index, f32) -> (memref) %in2D_nchw = call @alloc_4d_filled_f32(%c3, %c1, %c8, %c8, %val) : (index, index, index, index, f32) -> (memref) %out2D_nchw = call @alloc_4d_filled_f32(%c3, %c1, %c6, %c6, %zero) : (index, index, index, index, f32) -> (memref) store %f10, %in2D_nchw[%c0, %c0, %c0, %c3] : memref call @conv_2d_nchw(%in2D_nchw, %filter2D_nchw, %out2D_nchw) : (memref, memref, memref) -> () %out2D_nchw_ = memref_cast %out2D_nchw : memref to memref<*xf32> call @print_memref_f32(%out2D_nchw_): (memref<*xf32>) -> () dealloc %filter2D_nchw : memref dealloc %in2D_nchw : memref dealloc %out2D_nchw : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [36, 52, 52, 52, 36, 36], // CHECK-COUNT-5: [36, 36, 36, 36, 36, 36] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [36, 36, 36, 36, 36, 36] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [36, 36, 36, 36, 36, 36] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nhwc-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nhwc-call.mlir index 3213b7dc5fe2..a3d8cdc0524e 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nhwc-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-2d-nhwc-call.mlir @@ -1,127 +1,127 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,3,3,2" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,3,3,2" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 4-D buffer of size (%s1, %s2, %s3, %s4) filled with the value %f func @alloc_4d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %s4 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3, %s4) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_2d_nhwc(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_2d_nhwc ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter2D_nhwc = call @alloc_4d_filled_f32(%c1, %c3, %c3, %c3, %val) :(index, index, index, index, f32) -> (memref) %in2D_nhwc = call @alloc_4d_filled_f32(%c3, %c8, %c8, %c3, %val) : (index, index, index, index, f32) -> (memref) %out2D_nhwc = call @alloc_4d_filled_f32(%c3, %c6, %c6, %c1, %zero) : (index, index, index, index, f32) -> (memref) store %f10, %in2D_nhwc[%c0, %c0, %c3, %c0] : memref call @conv_2d_nhwc(%in2D_nhwc, %filter2D_nhwc, %out2D_nhwc) : (memref, memref, memref) -> () %out2D_nhwc_ = memref_cast %out2D_nhwc : memref to memref<*xf32> call @print_memref_f32(%out2D_nhwc_): (memref<*xf32>) -> () dealloc %filter2D_nhwc : memref dealloc %in2D_nhwc : memref dealloc %out2D_nhwc : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [108], // CHECK-COUNT-3: [124], // CHECK-COUNT-2: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-call.mlir index 8020f3ac017f..daa81d56c168 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-call.mlir @@ -1,84 +1,84 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,2,2" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=2,2,2" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 3-D buffer of size (%s1, %s2, %s3) filled with the value %f func @alloc_3d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_3d(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_3d ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter3D = call @alloc_3d_filled_f32(%c3, %c3, %c3, %val) : (index, index, index, f32) -> (memref) %in3D = call @alloc_3d_filled_f32(%c8, %c8, %c8, %val) : (index, index, index, f32) -> (memref) %out3D = call @alloc_3d_filled_f32(%c6, %c6, %c6, %zero) : (index, index, index, f32) -> (memref) store %f10, %in3D[%c0, %c0, %c3] : memref call @conv_3d(%in3D, %filter3D, %out3D) : (memref, memref, memref) -> () %out3D_ = memref_cast %out3D : memref to memref<*xf32> call @print_memref_f32(%out3D_): (memref<*xf32>) -> () dealloc %filter3D : memref dealloc %in3D : memref dealloc %out3D : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [108, 124, 124, 124, 108, 108], // CHECK-COUNT-5: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ncdhw-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ncdhw-call.mlir index 830b5402c2a4..df5838cf2bfa 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ncdhw-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ncdhw-call.mlir @@ -1,88 +1,88 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,0,5,5,5" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,1,1,3,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,0,5,5,5" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,1,1,3,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 5-D buffer of size (%s1, %s2, %s3, %s4, %s5) filled with the value %f func @alloc_5d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %s4 : index, %s5 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3, %s4, %s5) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_3d_ncdhw(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_3d_ncdhw ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter3D_ncdhw = call @alloc_5d_filled_f32(%c1, %c1, %c3, %c3, %c3, %val) : (index, index, index, index, index, f32) -> (memref) %in3D_ncdhw = call @alloc_5d_filled_f32(%c1, %c1, %c8, %c8, %c8, %val) : (index, index, index, index, index, f32) -> (memref) %out3D_ncdhw = call @alloc_5d_filled_f32(%c1, %c1, %c6, %c6, %c6, %zero) : (index, index, index, index, index, f32) -> (memref) store %f10, %in3D_ncdhw[%c0, %c0, %c0, %c0, %c3] : memref call @conv_3d_ncdhw(%in3D_ncdhw, %filter3D_ncdhw, %out3D_ncdhw) : (memref, memref, memref) -> () %out3D_ncdhw_ = memref_cast %out3D_ncdhw : memref to memref<*xf32> call @print_memref_f32(%out3D_ncdhw_): (memref<*xf32>) -> () dealloc %filter3D_ncdhw : memref dealloc %in3D_ncdhw : memref dealloc %out3D_ncdhw : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [108, 124, 124, 124, 108, 108], // CHECK-COUNT-5: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108, 108, 108, 108, 108, 108] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ndhwc-call.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ndhwc-call.mlir index 0b25ea09157c..ddece94e114a 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ndhwc-call.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-conv-3d-ndhwc-call.mlir @@ -1,190 +1,190 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,5,5,5" -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -test-conv-vectorization="tile-sizes=1,1,1,1,1,3,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=0,5,5,5" \ // RUN: -test-conv-vectorization="tile-sizes=1,1,1,1,1,3,3,3,3" -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) // Creates and returns 5-D buffer of size (%s1, %s2, %s3, %s4, %s5) filled with the value %f func @alloc_5d_filled_f32(%s1 : index, %s2 : index, %s3 : index, %s4 : index, %s5 : index, %f : f32) -> memref { %buf = alloc(%s1, %s2, %s3, %s4, %s5) : memref linalg.fill(%buf, %f) : memref, f32 return %buf : memref } func @conv_3d_ndhwc(%arg0: memref, %arg1: memref, %arg2: memref) { linalg.conv_3d_ndhwc ins (%arg0, %arg1: memref, memref) outs (%arg2: memref) return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c3 = constant 3 : index %c6 = constant 6 : index %c8 = constant 8 : index %f10 = constant 10.00000e+00 : f32 %val = constant 2.00000e+00 : f32 %zero = constant 0.00000e+00 : f32 %filter3D_ndhwc = call @alloc_5d_filled_f32(%c1, %c3, %c3, %c3, %c1, %val) : (index, index, index, index, index, f32) -> (memref) %in3D_ndhwc = call @alloc_5d_filled_f32(%c1, %c8, %c8, %c8, %c1, %val) : (index, index, index, index, index, f32) -> (memref) %out3D_ndhwc = call @alloc_5d_filled_f32(%c1, %c6, %c6, %c6, %c1, %zero) : (index, index, index, index, index, f32) -> (memref) store %f10, %in3D_ndhwc[%c0, %c0, %c0, %c3, %c0] : memref call @conv_3d_ndhwc(%in3D_ndhwc, %filter3D_ndhwc, %out3D_ndhwc) : (memref, memref, memref) -> () %out3D_ndhwc_ = memref_cast %out3D_ndhwc : memref to memref<*xf32> call @print_memref_f32(%out3D_ndhwc_): (memref<*xf32>) -> () dealloc %filter3D_ndhwc : memref dealloc %in3D_ndhwc : memref dealloc %out3D_ndhwc : memref return } // CHECK: Unranked Memref {{.*}} // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [ // CHECK-SAME: [108], // CHECK-COUNT-3: [124], // CHECK-COUNT-2: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-SAME: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ], // CHECK-NEXT: [ // CHECK-COUNT-6: [108] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] // CHECK-SAME: ] diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-elementwise.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-elementwise.mlir index 08bb81246793..81fcc70e91be 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-elementwise.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-elementwise.mlir @@ -1,19 +1,19 @@ // RUN: mlir-opt %s -convert-elementwise-to-linalg -std-bufferize -tensor-constant-bufferize -linalg-bufferize -func-bufferize -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s func @main() { %a = constant dense<[1.0, 2.0, 3.0]> : tensor<3xf32> %b = constant dense<[10.0, 20.0, 30.0]> : tensor<3xf32> %addf = addf %a, %b : tensor<3xf32> %addf_unranked = tensor_cast %addf : tensor<3xf32> to tensor<*xf32> call @print_memref_f32(%addf_unranked) : (tensor<*xf32>) -> () // CHECK: Unranked Memref base@ = {{.*}} rank = 1 offset = 0 sizes = [3] strides = [1] data = // CHECK-NEXT: [11, 22, 33] return } -func @print_memref_f32(%ptr : tensor<*xf32>) +func private @print_memref_f32(%ptr : tensor<*xf32>) diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-e2e.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-e2e.mlir index 67e490009194..a6f24e45dbc1 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-e2e.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-e2e.mlir @@ -1,34 +1,34 @@ // RUN: mlir-opt %s -tensor-constant-bufferize -std-bufferize -linalg-bufferize -func-bufferize -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s func @foo() -> tensor<4xf32> { %0 = constant dense<[1.0, 2.0, 3.0, 4.0]> : tensor<4xf32> return %0 : tensor<4xf32> } func @main() { %0 = call @foo() : () -> tensor<4xf32> // Instead of relying on tensor_store which introduces aliasing, we rely on // the conversion of print_memref_f32(tensor<*xf32>) to // print_memref_f32(memref<*xf32>). // Note that this is skipping a step and we would need at least some function // attribute to declare that this conversion is valid (e.g. when we statically // know that things will play nicely at the C ABI boundary). %unranked = tensor_cast %0 : tensor<4xf32> to tensor<*xf32> call @print_memref_f32(%unranked) : (tensor<*xf32>) -> () // CHECK: Unranked Memref base@ = {{0x[-9a-f]*}} // CHECK-SAME: rank = 1 offset = 0 sizes = [4] strides = [1] data = // CHECK-NEXT: [1, 2, 3, 4] return } // This gets converted to a function operating on memref<*xf32>. // Note that this is skipping a step and we would need at least some function // attribute to declare that this conversion is valid (e.g. when we statically // know that things will play nicely at the C ABI boundary). -func @print_memref_f32(%ptr : tensor<*xf32>) +func private @print_memref_f32(%ptr : tensor<*xf32>) diff --git a/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-matmul.mlir b/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-matmul.mlir index 7a828b64b731..4bcb3acdc162 100644 --- a/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-matmul.mlir +++ b/mlir/integration_test/Dialect/Linalg/CPU/test-tensor-matmul.mlir @@ -1,35 +1,35 @@ // RUN: mlir-opt %s -linalg-bufferize -std-bufferize -tensor-constant-bufferize -func-bufferize \ // RUN: -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s // RUN: mlir-opt %s -linalg-tile="linalg-tile-sizes=1,2,3" -linalg-bufferize \ // RUN: -scf-bufferize -std-bufferize -tensor-constant-bufferize -func-bufferize -convert-linalg-to-loops \ // RUN: -convert-scf-to-std -convert-linalg-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext \ // RUN: | FileCheck %s func @main() { %A = constant dense<[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]> : tensor<2x3xf32> %B = constant dense<[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0]]> : tensor<3x4xf32> %C = constant dense<1000.0> : tensor<2x4xf32> %D = linalg.matmul ins(%A, %B: tensor<2x3xf32>, tensor<3x4xf32>) init(%C: tensor<2x4xf32>) -> tensor<2x4xf32> %unranked = tensor_cast %D : tensor<2x4xf32> to tensor<*xf32> call @print_memref_f32(%unranked) : (tensor<*xf32>) -> () // CHECK: Unranked Memref base@ = {{0x[-9a-f]*}} // CHECK-SAME: rank = 2 offset = 0 sizes = [2, 4] strides = [4, 1] data = // CHECK-NEXT: [1038, 1044, 1050, 1056] // CHECK-NEXT: [1083, 1098, 1113, 1128] return } -func @print_memref_f32(%ptr : tensor<*xf32>) +func private @print_memref_f32(%ptr : tensor<*xf32>) diff --git a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-to-loops.mlir b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-to-loops.mlir index 38cbabc32998..b8f4045495ff 100644 --- a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-to-loops.mlir +++ b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-to-loops.mlir @@ -1,105 +1,105 @@ // RUN: mlir-opt %s -convert-vector-to-scf -lower-affine -convert-scf-to-std -convert-vector-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext,%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext | \ // RUN: FileCheck %s #map0 = affine_map<(d0, d1) -> (d1, d0)> #map1 = affine_map<(d0, d1) -> (d1)> -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) func @alloc_2d_filled_f32(%arg0: index, %arg1: index) -> memref { %c0 = constant 0 : index %c1 = constant 1 : index %c10 = constant 10 : index %c100 = constant 100 : index %0 = alloc(%arg0, %arg1) : memref scf.for %arg5 = %c0 to %arg0 step %c1 { scf.for %arg6 = %c0 to %arg1 step %c1 { %arg66 = muli %arg6, %c100 : index %tmp1 = addi %arg5, %arg66 : index %tmp2 = index_cast %tmp1 : index to i32 %tmp3 = sitofp %tmp2 : i32 to f32 store %tmp3, %0[%arg5, %arg6] : memref } } return %0 : memref } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c6 = constant 6 : index %cst = constant -4.2e+01 : f32 %0 = call @alloc_2d_filled_f32(%c6, %c6) : (index, index) -> memref %converted = memref_cast %0 : memref to memref<*xf32> call @print_memref_f32(%converted): (memref<*xf32>) -> () // CHECK: Unranked{{.*}}data = // CHECK: [ // CHECK-SAME: [0, 100, 200, 300, 400, 500], // CHECK-NEXT: [1, 101, 201, 301, 401, 501], // CHECK-NEXT: [2, 102, 202, 302, 402, 502], // CHECK-NEXT: [3, 103, 203, 303, 403, 503], // CHECK-NEXT: [4, 104, 204, 304, 404, 504], // CHECK-NEXT: [5, 105, 205, 305, 405, 505]] %init = vector.transfer_read %0[%c1, %c1], %cst : memref, vector<5x5xf32> vector.print %init : vector<5x5xf32> // 5x5 block rooted at {1, 1} // CHECK-NEXT: ( ( 101, 201, 301, 401, 501 ), // CHECK-SAME: ( 102, 202, 302, 402, 502 ), // CHECK-SAME: ( 103, 203, 303, 403, 503 ), // CHECK-SAME: ( 104, 204, 304, 404, 504 ), // CHECK-SAME: ( 105, 205, 305, 405, 505 ) ) %1 = vector.transfer_read %0[%c1, %c1], %cst {permutation_map = #map0} : memref, vector<5x5xf32> vector.print %1 : vector<5x5xf32> // Transposed 5x5 block rooted @{1, 1} in memory. // CHECK-NEXT: ( ( 101, 102, 103, 104, 105 ), // CHECK-SAME: ( 201, 202, 203, 204, 205 ), // CHECK-SAME: ( 301, 302, 303, 304, 305 ), // CHECK-SAME: ( 401, 402, 403, 404, 405 ), // CHECK-SAME: ( 501, 502, 503, 504, 505 ) ) // Transpose-write the transposed 5x5 block @{0, 0} in memory. vector.transfer_write %1, %0[%c0, %c0] {permutation_map = #map0} : vector<5x5xf32>, memref %2 = vector.transfer_read %0[%c1, %c1], %cst : memref, vector<5x5xf32> vector.print %2 : vector<5x5xf32> // New 5x5 block rooted @{1, 1} in memory. // Here we expect the boundaries from the original data // (i.e. last row: 105 .. 505, last col: 501 .. 505) // and the 4x4 subblock 202 .. 505 rooted @{0, 0} in the vector // CHECK-NEXT: ( ( 202, 302, 402, 502, 501 ), // CHECK-SAME: ( 203, 303, 403, 503, 502 ), // CHECK-SAME: ( 204, 304, 404, 504, 503 ), // CHECK-SAME: ( 205, 305, 405, 505, 504 ), // CHECK-SAME: ( 105, 205, 305, 405, 505 ) ) %3 = vector.transfer_read %0[%c2, %c3], %cst : memref, vector<5x5xf32> vector.print %3 : vector<5x5xf32> // New 5x5 block rooted @{2, 3} in memory. // CHECK-NEXT: ( ( 403, 503, 502, -42, -42 ), // CHECK-SAME: ( 404, 504, 503, -42, -42 ), // CHECK-SAME: ( 405, 505, 504, -42, -42 ), // CHECK-SAME: ( 305, 405, 505, -42, -42 ), // CHECK-SAME: ( -42, -42, -42, -42, -42 ) ) %4 = vector.transfer_read %0[%c2, %c3], %cst {permutation_map = #map0} : memref, vector<5x5xf32> vector.print %4 : vector<5x5xf32> // Transposed 5x5 block rooted @{2, 3} in memory. // CHECK-NEXT: ( ( 403, 404, 405, 305, -42 ), // CHECK-SAME: ( 503, 504, 505, 405, -42 ), // CHECK-SAME: ( 502, 503, 504, 505, -42 ), // CHECK-SAME: ( -42, -42, -42, -42, -42 ), // CHECK-SAME: ( -42, -42, -42, -42, -42 ) ) %5 = vector.transfer_read %0[%c2, %c3], %cst {permutation_map = #map1} : memref, vector<5xf32> vector.print %5 : vector<5xf32> // CHECK-NEXT: ( 403, 503, 502, -42, -42 ) dealloc %0 : memref return } diff --git a/mlir/integration_test/Dialect/Vector/CPU/test-vector-distribute.mlir b/mlir/integration_test/Dialect/Vector/CPU/test-vector-distribute.mlir index b83b1f653900..fb4b1029c790 100644 --- a/mlir/integration_test/Dialect/Vector/CPU/test-vector-distribute.mlir +++ b/mlir/integration_test/Dialect/Vector/CPU/test-vector-distribute.mlir @@ -1,68 +1,68 @@ // RUN: mlir-opt %s -test-vector-to-forloop -convert-vector-to-scf \ // RUN: -lower-affine -convert-scf-to-std -convert-vector-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext | \ // RUN: FileCheck %s // RUN: mlir-opt %s -convert-vector-to-scf -lower-affine \ // RUN: -convert-scf-to-std -convert-vector-to-llvm | mlir-cpu-runner -e main \ // RUN: -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_runner_utils%shlibext | \ // RUN: FileCheck %s // RUN: mlir-opt %s -test-vector-to-forloop | FileCheck %s -check-prefix=TRANSFORM -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) func @alloc_1d_filled_inc_f32(%arg0: index, %arg1: f32) -> memref { %c0 = constant 0 : index %c1 = constant 1 : index %0 = alloc(%arg0) : memref scf.for %arg2 = %c0 to %arg0 step %c1 { %tmp = index_cast %arg2 : index to i32 %tmp1 = sitofp %tmp : i32 to f32 %tmp2 = addf %tmp1, %arg1 : f32 store %tmp2, %0[%arg2] : memref } return %0 : memref } // Large vector addf that can be broken down into a loop of smaller vector addf. func @main() { %cf0 = constant 0.0 : f32 %cf1 = constant 1.0 : f32 %cf2 = constant 2.0 : f32 %c0 = constant 0 : index %c1 = constant 1 : index %c32 = constant 32 : index %c64 = constant 64 : index %out = alloc(%c64) : memref %in1 = call @alloc_1d_filled_inc_f32(%c64, %cf1) : (index, f32) -> memref %in2 = call @alloc_1d_filled_inc_f32(%c64, %cf2) : (index, f32) -> memref // Check that the tansformatio correctly happened. // TRANSFORM: scf.for // TRANSFORM: vector.transfer_read {{.*}} : memref, vector<2xf32> // TRANSFORM: vector.transfer_read {{.*}} : memref, vector<2xf32> // TRANSFORM: %{{.*}} = addf %{{.*}}, %{{.*}} : vector<2xf32> // TRANSFORM: vector.transfer_write {{.*}} : vector<2xf32>, memref // TRANSFORM: } %a = vector.transfer_read %in1[%c0], %cf0: memref, vector<64xf32> %b = vector.transfer_read %in2[%c0], %cf0: memref, vector<64xf32> %acc = addf %a, %b: vector<64xf32> vector.transfer_write %acc, %out[%c0]: vector<64xf32>, memref %converted = memref_cast %out : memref to memref<*xf32> call @print_memref_f32(%converted): (memref<*xf32>) -> () // CHECK: Unranked{{.*}}data = // CHECK: [ // CHECK-SAME: 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, // CHECK-SAME: 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, // CHECK-SAME: 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, // CHECK-SAME: 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, // CHECK-SAME: 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, // CHECK-SAME: 121, 123, 125, 127, 129] dealloc %out : memref dealloc %in1 : memref dealloc %in2 : memref return } diff --git a/mlir/integration_test/Sparse/CPU/matrix-market-example.mlir b/mlir/integration_test/Sparse/CPU/matrix-market-example.mlir index 56c392e8133b..b03c5b111d98 100644 --- a/mlir/integration_test/Sparse/CPU/matrix-market-example.mlir +++ b/mlir/integration_test/Sparse/CPU/matrix-market-example.mlir @@ -1,100 +1,100 @@ // RUN: mlir-opt %s \ // RUN: -convert-scf-to-std -convert-vector-to-scf \ // RUN: -convert-linalg-to-llvm -convert-vector-to-llvm | \ // RUN: MATRIX0="%mlir_integration_test_dir/data/test.mtx" \ // RUN: mlir-cpu-runner \ // RUN: -e entry -entry-point-result=void \ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext | \ // RUN: FileCheck %s module { - func @openMatrix(!llvm.ptr, memref, memref, memref) -> () - func @readMatrixItem(memref, memref, memref) -> () - func @closeMatrix() -> () - func @getMatrix(index) -> (!llvm.ptr) + func private @openMatrix(!llvm.ptr, memref, memref, memref) -> () + func private @readMatrixItem(memref, memref, memref) -> () + func private @closeMatrix() -> () + func private @getMatrix(index) -> (!llvm.ptr) func @entry() { %d0 = constant 0.0 : f64 %c0 = constant 0 : index %c1 = constant 1 : index %c5 = constant 5 : index %m = alloc() : memref %n = alloc() : memref %nnz = alloc() : memref %i = alloc() : memref %j = alloc() : memref %d = alloc() : memref // // Read the header of a sparse matrix. This yields the // size (m x n) and number of nonzero elements (nnz). // %file = call @getMatrix(%c0) : (index) -> (!llvm.ptr) call @openMatrix(%file, %m, %n, %nnz) : (!llvm.ptr, memref, memref, memref) -> () %M = load %m[] : memref %N = load %n[] : memref %Z = load %nnz[] : memref // // At this point, code should prepare a proper sparse storage // scheme for an m x n matrix with nnz nonzero elements. For // simplicity, however, here we simply set up a dense matrix. // %a = alloc(%M, %N) : memref scf.for %ii = %c0 to %M step %c1 { scf.for %jj = %c0 to %N step %c1 { store %d0, %a[%ii, %jj] : memref } } // // Now we are ready to read in the nonzero elements of the // sparse matrix and insert these into a sparse storage // scheme. In this example, we simply insert them in the // dense matrix. // scf.for %k = %c0 to %Z step %c1 { call @readMatrixItem(%i, %j, %d) : (memref, memref, memref) -> () %I = load %i[] : memref %J = load %j[] : memref %D = load %d[] : memref store %D, %a[%I, %J] : memref } call @closeMatrix() : () -> () // // Verify that the results are as expected. // %A = vector.transfer_read %a[%c0, %c0], %d0 : memref, vector<5x5xf64> vector.print %M : index vector.print %N : index vector.print %Z : index vector.print %A : vector<5x5xf64> // // CHECK: 5 // CHECK: 5 // CHECK: 9 // // CHECK: ( ( 1, 0, 0, 1.4, 0 ), // CHECK-SAME: ( 0, 2, 0, 0, 2.5 ), // CHECK-SAME: ( 0, 0, 3, 0, 0 ), // CHECK-SAME: ( 4.1, 0, 0, 4, 0 ), // CHECK-SAME: ( 0, 5.2, 0, 0, 5 ) ) // // Free. // dealloc %m : memref dealloc %n : memref dealloc %nnz : memref dealloc %i : memref dealloc %j : memref dealloc %d : memref dealloc %a : memref return } } diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp index f0bd72028184..8195e17fe0c3 100644 --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -1,814 +1,814 @@ //===- AsyncToLLVM.cpp - Convert Async to LLVM dialect --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h" #include "../PassDetail.h" #include "mlir/Dialect/Async/IR/Async.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/BlockAndValueMapping.h" #include "mlir/IR/Builders.h" #include "mlir/IR/TypeUtilities.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/DialectConversion.h" #include "mlir/Transforms/RegionUtils.h" #include "llvm/ADT/SetVector.h" #include "llvm/Support/FormatVariadic.h" #define DEBUG_TYPE "convert-async-to-llvm" using namespace mlir; using namespace mlir::async; // Prefix for functions outlined from `async.execute` op regions. static constexpr const char kAsyncFnPrefix[] = "async_execute_fn"; //===----------------------------------------------------------------------===// // Async Runtime C API declaration. //===----------------------------------------------------------------------===// static constexpr const char *kCreateToken = "mlirAsyncRuntimeCreateToken"; static constexpr const char *kCreateGroup = "mlirAsyncRuntimeCreateGroup"; static constexpr const char *kEmplaceToken = "mlirAsyncRuntimeEmplaceToken"; static constexpr const char *kAwaitToken = "mlirAsyncRuntimeAwaitToken"; static constexpr const char *kAwaitGroup = "mlirAsyncRuntimeAwaitAllInGroup"; static constexpr const char *kExecute = "mlirAsyncRuntimeExecute"; static constexpr const char *kAddTokenToGroup = "mlirAsyncRuntimeAddTokenToGroup"; static constexpr const char *kAwaitAndExecute = "mlirAsyncRuntimeAwaitTokenAndExecute"; static constexpr const char *kAwaitAllAndExecute = "mlirAsyncRuntimeAwaitAllInGroupAndExecute"; namespace { // Async Runtime API function types. struct AsyncAPI { static FunctionType createTokenFunctionType(MLIRContext *ctx) { return FunctionType::get({}, {TokenType::get(ctx)}, ctx); } static FunctionType createGroupFunctionType(MLIRContext *ctx) { return FunctionType::get({}, {GroupType::get(ctx)}, ctx); } static FunctionType emplaceTokenFunctionType(MLIRContext *ctx) { return FunctionType::get({TokenType::get(ctx)}, {}, ctx); } static FunctionType awaitTokenFunctionType(MLIRContext *ctx) { return FunctionType::get({TokenType::get(ctx)}, {}, ctx); } static FunctionType awaitGroupFunctionType(MLIRContext *ctx) { return FunctionType::get({GroupType::get(ctx)}, {}, ctx); } static FunctionType executeFunctionType(MLIRContext *ctx) { auto hdl = LLVM::LLVMType::getInt8PtrTy(ctx); auto resume = resumeFunctionType(ctx).getPointerTo(); return FunctionType::get({hdl, resume}, {}, ctx); } static FunctionType addTokenToGroupFunctionType(MLIRContext *ctx) { auto i64 = IntegerType::get(64, ctx); return FunctionType::get({TokenType::get(ctx), GroupType::get(ctx)}, {i64}, ctx); } static FunctionType awaitAndExecuteFunctionType(MLIRContext *ctx) { auto hdl = LLVM::LLVMType::getInt8PtrTy(ctx); auto resume = resumeFunctionType(ctx).getPointerTo(); return FunctionType::get({TokenType::get(ctx), hdl, resume}, {}, ctx); } static FunctionType awaitAllAndExecuteFunctionType(MLIRContext *ctx) { auto hdl = LLVM::LLVMType::getInt8PtrTy(ctx); auto resume = resumeFunctionType(ctx).getPointerTo(); return FunctionType::get({GroupType::get(ctx), hdl, resume}, {}, ctx); } // Auxiliary coroutine resume intrinsic wrapper. static LLVM::LLVMType resumeFunctionType(MLIRContext *ctx) { auto voidTy = LLVM::LLVMType::getVoidTy(ctx); auto i8Ptr = LLVM::LLVMType::getInt8PtrTy(ctx); return LLVM::LLVMType::getFunctionTy(voidTy, {i8Ptr}, false); } }; } // namespace // Adds Async Runtime C API declarations to the module. static void addAsyncRuntimeApiDeclarations(ModuleOp module) { auto builder = OpBuilder::atBlockTerminator(module.getBody()); auto addFuncDecl = [&](StringRef name, FunctionType type) { if (module.lookupSymbol(name)) return; - builder.create(module.getLoc(), name, type); + builder.create(module.getLoc(), name, type).setPrivate(); }; MLIRContext *ctx = module.getContext(); addFuncDecl(kCreateToken, AsyncAPI::createTokenFunctionType(ctx)); addFuncDecl(kCreateGroup, AsyncAPI::createGroupFunctionType(ctx)); addFuncDecl(kEmplaceToken, AsyncAPI::emplaceTokenFunctionType(ctx)); addFuncDecl(kAwaitToken, AsyncAPI::awaitTokenFunctionType(ctx)); addFuncDecl(kAwaitGroup, AsyncAPI::awaitGroupFunctionType(ctx)); addFuncDecl(kExecute, AsyncAPI::executeFunctionType(ctx)); addFuncDecl(kAddTokenToGroup, AsyncAPI::addTokenToGroupFunctionType(ctx)); addFuncDecl(kAwaitAndExecute, AsyncAPI::awaitAndExecuteFunctionType(ctx)); addFuncDecl(kAwaitAllAndExecute, AsyncAPI::awaitAllAndExecuteFunctionType(ctx)); } //===----------------------------------------------------------------------===// // LLVM coroutines intrinsics declarations. //===----------------------------------------------------------------------===// static constexpr const char *kCoroId = "llvm.coro.id"; static constexpr const char *kCoroSizeI64 = "llvm.coro.size.i64"; static constexpr const char *kCoroBegin = "llvm.coro.begin"; static constexpr const char *kCoroSave = "llvm.coro.save"; static constexpr const char *kCoroSuspend = "llvm.coro.suspend"; static constexpr const char *kCoroEnd = "llvm.coro.end"; static constexpr const char *kCoroFree = "llvm.coro.free"; static constexpr const char *kCoroResume = "llvm.coro.resume"; /// Adds an LLVM function declaration to a module. static void addLLVMFuncDecl(ModuleOp module, OpBuilder &builder, StringRef name, LLVM::LLVMType ret, ArrayRef params) { if (module.lookupSymbol(name)) return; LLVM::LLVMType type = LLVM::LLVMType::getFunctionTy(ret, params, false); builder.create(module.getLoc(), name, type); } /// Adds coroutine intrinsics declarations to the module. static void addCoroutineIntrinsicsDeclarations(ModuleOp module) { using namespace mlir::LLVM; MLIRContext *ctx = module.getContext(); OpBuilder builder(module.getBody()->getTerminator()); auto token = LLVMTokenType::get(ctx); auto voidTy = LLVMType::getVoidTy(ctx); auto i8 = LLVMType::getInt8Ty(ctx); auto i1 = LLVMType::getInt1Ty(ctx); auto i32 = LLVMType::getInt32Ty(ctx); auto i64 = LLVMType::getInt64Ty(ctx); auto i8Ptr = LLVMType::getInt8PtrTy(ctx); addLLVMFuncDecl(module, builder, kCoroId, token, {i32, i8Ptr, i8Ptr, i8Ptr}); addLLVMFuncDecl(module, builder, kCoroSizeI64, i64, {}); addLLVMFuncDecl(module, builder, kCoroBegin, i8Ptr, {token, i8Ptr}); addLLVMFuncDecl(module, builder, kCoroSave, token, {i8Ptr}); addLLVMFuncDecl(module, builder, kCoroSuspend, i8, {token, i1}); addLLVMFuncDecl(module, builder, kCoroEnd, i1, {i8Ptr, i1}); addLLVMFuncDecl(module, builder, kCoroFree, i8Ptr, {token, i8Ptr}); addLLVMFuncDecl(module, builder, kCoroResume, voidTy, {i8Ptr}); } //===----------------------------------------------------------------------===// // Add malloc/free declarations to the module. //===----------------------------------------------------------------------===// static constexpr const char *kMalloc = "malloc"; static constexpr const char *kFree = "free"; /// Adds malloc/free declarations to the module. static void addCRuntimeDeclarations(ModuleOp module) { using namespace mlir::LLVM; MLIRContext *ctx = module.getContext(); OpBuilder builder(module.getBody()->getTerminator()); auto voidTy = LLVMType::getVoidTy(ctx); auto i64 = LLVMType::getInt64Ty(ctx); auto i8Ptr = LLVMType::getInt8PtrTy(ctx); addLLVMFuncDecl(module, builder, kMalloc, i8Ptr, {i64}); addLLVMFuncDecl(module, builder, kFree, voidTy, {i8Ptr}); } //===----------------------------------------------------------------------===// // Coroutine resume function wrapper. //===----------------------------------------------------------------------===// static constexpr const char *kResume = "__resume"; // A function that takes a coroutine handle and calls a `llvm.coro.resume` // intrinsics. We need this function to be able to pass it to the async // runtime execute API. static void addResumeFunction(ModuleOp module) { MLIRContext *ctx = module.getContext(); OpBuilder moduleBuilder(module.getBody()->getTerminator()); Location loc = module.getLoc(); if (module.lookupSymbol(kResume)) return; auto voidTy = LLVM::LLVMType::getVoidTy(ctx); auto i8Ptr = LLVM::LLVMType::getInt8PtrTy(ctx); auto resumeOp = moduleBuilder.create( loc, kResume, LLVM::LLVMType::getFunctionTy(voidTy, {i8Ptr}, false)); resumeOp.setPrivate(); auto *block = resumeOp.addEntryBlock(); OpBuilder blockBuilder = OpBuilder::atBlockEnd(block); blockBuilder.create(loc, Type(), blockBuilder.getSymbolRefAttr(kCoroResume), resumeOp.getArgument(0)); blockBuilder.create(loc, ValueRange()); } //===----------------------------------------------------------------------===// // async.execute op outlining to the coroutine functions. //===----------------------------------------------------------------------===// // Function targeted for coroutine transformation has two additional blocks at // the end: coroutine cleanup and coroutine suspension. // // async.await op lowering additionaly creates a resume block for each // operation to enable non-blocking waiting via coroutine suspension. namespace { struct CoroMachinery { Value asyncToken; Value coroHandle; Block *cleanup; Block *suspend; }; } // namespace // Builds an coroutine template compatible with LLVM coroutines lowering. // // - `entry` block sets up the coroutine. // - `cleanup` block cleans up the coroutine state. // - `suspend block after the @llvm.coro.end() defines what value will be // returned to the initial caller of a coroutine. Everything before the // @llvm.coro.end() will be executed at every suspension point. // // Coroutine structure (only the important bits): // // func @async_execute_fn() -> !async.token { // ^entryBlock(): // %token = : !async.token // create async runtime token // %hdl = llvm.call @llvm.coro.id(...) // create a coroutine handle // br ^cleanup // // ^cleanup: // llvm.call @llvm.coro.free(...) // delete coroutine state // br ^suspend // // ^suspend: // llvm.call @llvm.coro.end(...) // marks the end of a coroutine // return %token : !async.token // } // // The actual code for the async.execute operation body region will be inserted // before the entry block terminator. // // static CoroMachinery setupCoroMachinery(FuncOp func) { assert(func.getBody().empty() && "Function must have empty body"); MLIRContext *ctx = func.getContext(); auto token = LLVM::LLVMTokenType::get(ctx); auto i1 = LLVM::LLVMType::getInt1Ty(ctx); auto i32 = LLVM::LLVMType::getInt32Ty(ctx); auto i64 = LLVM::LLVMType::getInt64Ty(ctx); auto i8Ptr = LLVM::LLVMType::getInt8PtrTy(ctx); Block *entryBlock = func.addEntryBlock(); Location loc = func.getBody().getLoc(); OpBuilder builder = OpBuilder::atBlockBegin(entryBlock); // ------------------------------------------------------------------------ // // Allocate async tokens/values that we will return from a ramp function. // ------------------------------------------------------------------------ // auto createToken = builder.create(loc, kCreateToken, TokenType::get(ctx)); // ------------------------------------------------------------------------ // // Initialize coroutine: allocate frame, get coroutine handle. // ------------------------------------------------------------------------ // // Constants for initializing coroutine frame. auto constZero = builder.create(loc, i32, builder.getI32IntegerAttr(0)); auto constFalse = builder.create(loc, i1, builder.getBoolAttr(false)); auto nullPtr = builder.create(loc, i8Ptr); // Get coroutine id: @llvm.coro.id auto coroId = builder.create( loc, token, builder.getSymbolRefAttr(kCoroId), ValueRange({constZero, nullPtr, nullPtr, nullPtr})); // Get coroutine frame size: @llvm.coro.size.i64 auto coroSize = builder.create( loc, i64, builder.getSymbolRefAttr(kCoroSizeI64), ValueRange()); // Allocate memory for coroutine frame. auto coroAlloc = builder.create( loc, i8Ptr, builder.getSymbolRefAttr(kMalloc), ValueRange(coroSize.getResult(0))); // Begin a coroutine: @llvm.coro.begin auto coroHdl = builder.create( loc, i8Ptr, builder.getSymbolRefAttr(kCoroBegin), ValueRange({coroId.getResult(0), coroAlloc.getResult(0)})); Block *cleanupBlock = func.addBlock(); Block *suspendBlock = func.addBlock(); // ------------------------------------------------------------------------ // // Coroutine cleanup block: deallocate coroutine frame, free the memory. // ------------------------------------------------------------------------ // builder.setInsertionPointToStart(cleanupBlock); // Get a pointer to the coroutine frame memory: @llvm.coro.free. auto coroMem = builder.create( loc, i8Ptr, builder.getSymbolRefAttr(kCoroFree), ValueRange({coroId.getResult(0), coroHdl.getResult(0)})); // Free the memory. builder.create(loc, Type(), builder.getSymbolRefAttr(kFree), ValueRange(coroMem.getResult(0))); // Branch into the suspend block. builder.create(loc, suspendBlock); // ------------------------------------------------------------------------ // // Coroutine suspend block: mark the end of a coroutine and return allocated // async token. // ------------------------------------------------------------------------ // builder.setInsertionPointToStart(suspendBlock); // Mark the end of a coroutine: @llvm.coro.end. builder.create(loc, i1, builder.getSymbolRefAttr(kCoroEnd), ValueRange({coroHdl.getResult(0), constFalse})); // Return created `async.token` from the suspend block. This will be the // return value of a coroutine ramp function. builder.create(loc, createToken.getResult(0)); // Branch from the entry block to the cleanup block to create a valid CFG. builder.setInsertionPointToEnd(entryBlock); builder.create(loc, cleanupBlock); // `async.await` op lowering will create resume blocks for async // continuations, and will conditionally branch to cleanup or suspend blocks. return {createToken.getResult(0), coroHdl.getResult(0), cleanupBlock, suspendBlock}; } // Adds a suspension point before the `op`, and moves `op` and all operations // after it into the resume block. Returns a pointer to the resume block. // // `coroState` must be a value returned from the call to @llvm.coro.save(...) // intrinsic (saved coroutine state). // // Before: // // ^bb0: // "opBefore"(...) // "op"(...) // ^cleanup: ... // ^suspend: ... // // After: // // ^bb0: // "opBefore"(...) // %suspend = llmv.call @llvm.coro.suspend(...) // switch %suspend [-1: ^suspend, 0: ^resume, 1: ^cleanup] // ^resume: // "op"(...) // ^cleanup: ... // ^suspend: ... // static Block *addSuspensionPoint(CoroMachinery coro, Value coroState, Operation *op) { MLIRContext *ctx = op->getContext(); auto i1 = LLVM::LLVMType::getInt1Ty(ctx); auto i8 = LLVM::LLVMType::getInt8Ty(ctx); Location loc = op->getLoc(); Block *splitBlock = op->getBlock(); // Split the block before `op`, newly added block is the resume block. Block *resume = splitBlock->splitBlock(op); // Add a coroutine suspension in place of original `op` in the split block. OpBuilder builder = OpBuilder::atBlockEnd(splitBlock); auto constFalse = builder.create(loc, i1, builder.getBoolAttr(false)); // Suspend a coroutine: @llvm.coro.suspend auto coroSuspend = builder.create( loc, i8, builder.getSymbolRefAttr(kCoroSuspend), ValueRange({coroState, constFalse})); // After a suspension point decide if we should branch into resume, cleanup // or suspend block of the coroutine (see @llvm.coro.suspend return code // documentation). auto constZero = builder.create(loc, i8, builder.getI8IntegerAttr(0)); auto constNegOne = builder.create(loc, i8, builder.getI8IntegerAttr(-1)); Block *resumeOrCleanup = builder.createBlock(resume); // Suspend the coroutine ...? builder.setInsertionPointToEnd(splitBlock); auto isNegOne = builder.create( loc, LLVM::ICmpPredicate::eq, coroSuspend.getResult(0), constNegOne); builder.create(loc, isNegOne, /*trueDest=*/coro.suspend, /*falseDest=*/resumeOrCleanup); // ... or resume or cleanup the coroutine? builder.setInsertionPointToStart(resumeOrCleanup); auto isZero = builder.create( loc, LLVM::ICmpPredicate::eq, coroSuspend.getResult(0), constZero); builder.create(loc, isZero, /*trueDest=*/resume, /*falseDest=*/coro.cleanup); return resume; } // Outline the body region attached to the `async.execute` op into a standalone // function. static std::pair outlineExecuteOp(SymbolTable &symbolTable, ExecuteOp execute) { ModuleOp module = execute.getParentOfType(); MLIRContext *ctx = module.getContext(); Location loc = execute.getLoc(); OpBuilder moduleBuilder(module.getBody()->getTerminator()); // Collect all outlined function inputs. llvm::SetVector functionInputs(execute.dependencies().begin(), execute.dependencies().end()); getUsedValuesDefinedAbove(execute.body(), functionInputs); // Collect types for the outlined function inputs and outputs. auto typesRange = llvm::map_range( functionInputs, [](Value value) { return value.getType(); }); SmallVector inputTypes(typesRange.begin(), typesRange.end()); auto outputTypes = execute.getResultTypes(); auto funcType = moduleBuilder.getFunctionType(inputTypes, outputTypes); auto funcAttrs = ArrayRef(); // TODO: Derive outlined function name from the parent FuncOp (support // multiple nested async.execute operations). FuncOp func = FuncOp::create(loc, kAsyncFnPrefix, funcType, funcAttrs); symbolTable.insert(func, moduleBuilder.getInsertionPoint()); SymbolTable::setSymbolVisibility(func, SymbolTable::Visibility::Private); // Prepare a function for coroutine lowering by adding entry/cleanup/suspend // blocks, adding llvm.coro instrinsics and setting up control flow. CoroMachinery coro = setupCoroMachinery(func); // Suspend async function at the end of an entry block, and resume it using // Async execute API (execution will be resumed in a thread managed by the // async runtime). Block *entryBlock = &func.getBlocks().front(); OpBuilder builder = OpBuilder::atBlockTerminator(entryBlock); // A pointer to coroutine resume intrinsic wrapper. auto resumeFnTy = AsyncAPI::resumeFunctionType(ctx); auto resumePtr = builder.create( loc, resumeFnTy.getPointerTo(), kResume); // Save the coroutine state: @llvm.coro.save auto coroSave = builder.create( loc, LLVM::LLVMTokenType::get(ctx), builder.getSymbolRefAttr(kCoroSave), ValueRange({coro.coroHandle})); // Call async runtime API to execute a coroutine in the managed thread. SmallVector executeArgs = {coro.coroHandle, resumePtr.res()}; builder.create(loc, Type(), kExecute, executeArgs); // Split the entry block before the terminator. Block *resume = addSuspensionPoint(coro, coroSave.getResult(0), entryBlock->getTerminator()); // Await on all dependencies before starting to execute the body region. builder.setInsertionPointToStart(resume); for (size_t i = 0; i < execute.dependencies().size(); ++i) builder.create(loc, func.getArgument(i)); // Map from function inputs defined above the execute op to the function // arguments. BlockAndValueMapping valueMapping; valueMapping.map(functionInputs, func.getArguments()); // Clone all operations from the execute operation body into the outlined // function body, and replace all `async.yield` operations with a call // to async runtime to emplace the result token. for (Operation &op : execute.body().getOps()) { if (isa(op)) { builder.create(loc, kEmplaceToken, Type(), coro.asyncToken); continue; } builder.clone(op, valueMapping); } // Replace the original `async.execute` with a call to outlined function. OpBuilder callBuilder(execute); auto callOutlinedFunc = callBuilder.create(loc, func.getName(), execute.getResultTypes(), functionInputs.getArrayRef()); execute.replaceAllUsesWith(callOutlinedFunc.getResults()); execute.erase(); return {func, coro}; } //===----------------------------------------------------------------------===// // Convert Async dialect types to LLVM types. //===----------------------------------------------------------------------===// namespace { class AsyncRuntimeTypeConverter : public TypeConverter { public: AsyncRuntimeTypeConverter() { addConversion(convertType); } static Type convertType(Type type) { MLIRContext *ctx = type.getContext(); // Convert async tokens and groups to opaque pointers. if (type.isa()) return LLVM::LLVMType::getInt8PtrTy(ctx); return type; } }; } // namespace //===----------------------------------------------------------------------===// // Convert types for all call operations to lowered async types. //===----------------------------------------------------------------------===// namespace { class CallOpOpConversion : public ConversionPattern { public: explicit CallOpOpConversion(MLIRContext *ctx) : ConversionPattern(CallOp::getOperationName(), 1, ctx) {} LogicalResult matchAndRewrite(Operation *op, ArrayRef operands, ConversionPatternRewriter &rewriter) const override { AsyncRuntimeTypeConverter converter; SmallVector resultTypes; converter.convertTypes(op->getResultTypes(), resultTypes); CallOp call = cast(op); rewriter.replaceOpWithNewOp(op, resultTypes, call.callee(), call.getOperands()); return success(); } }; } // namespace //===----------------------------------------------------------------------===// // async.create_group op lowering to mlirAsyncRuntimeCreateGroup function call. //===----------------------------------------------------------------------===// namespace { class CreateGroupOpLowering : public ConversionPattern { public: explicit CreateGroupOpLowering(MLIRContext *ctx) : ConversionPattern(CreateGroupOp::getOperationName(), 1, ctx) {} LogicalResult matchAndRewrite(Operation *op, ArrayRef operands, ConversionPatternRewriter &rewriter) const override { auto retTy = GroupType::get(op->getContext()); rewriter.replaceOpWithNewOp(op, kCreateGroup, retTy); return success(); } }; } // namespace //===----------------------------------------------------------------------===// // async.add_to_group op lowering to runtime function call. //===----------------------------------------------------------------------===// namespace { class AddToGroupOpLowering : public ConversionPattern { public: explicit AddToGroupOpLowering(MLIRContext *ctx) : ConversionPattern(AddToGroupOp::getOperationName(), 1, ctx) {} LogicalResult matchAndRewrite(Operation *op, ArrayRef operands, ConversionPatternRewriter &rewriter) const override { // Currently we can only add tokens to the group. auto addToGroup = cast(op); if (!addToGroup.operand().getType().isa()) return failure(); auto i64 = IntegerType::get(64, op->getContext()); rewriter.replaceOpWithNewOp(op, kAddTokenToGroup, i64, operands); return success(); } }; } // namespace //===----------------------------------------------------------------------===// // async.await and async.await_all op lowerings to the corresponding async // runtime function calls. //===----------------------------------------------------------------------===// namespace { template class AwaitOpLoweringBase : public ConversionPattern { protected: explicit AwaitOpLoweringBase( MLIRContext *ctx, const llvm::DenseMap &outlinedFunctions, StringRef blockingAwaitFuncName, StringRef coroAwaitFuncName) : ConversionPattern(AwaitType::getOperationName(), 1, ctx), outlinedFunctions(outlinedFunctions), blockingAwaitFuncName(blockingAwaitFuncName), coroAwaitFuncName(coroAwaitFuncName) {} public: LogicalResult matchAndRewrite(Operation *op, ArrayRef operands, ConversionPatternRewriter &rewriter) const override { // We can only await on one the `AwaitableType` (for `await` it can be // only a `token`, for `await_all` it is a `group`). auto await = cast(op); if (!await.operand().getType().template isa()) return failure(); // Check if await operation is inside the outlined coroutine function. auto func = await.template getParentOfType(); auto outlined = outlinedFunctions.find(func); const bool isInCoroutine = outlined != outlinedFunctions.end(); Location loc = op->getLoc(); // Inside regular function we convert await operation to the blocking // async API await function call. if (!isInCoroutine) rewriter.create(loc, Type(), blockingAwaitFuncName, ValueRange(op->getOperand(0))); // Inside the coroutine we convert await operation into coroutine suspension // point, and resume execution asynchronously. if (isInCoroutine) { const CoroMachinery &coro = outlined->getSecond(); OpBuilder builder(op); MLIRContext *ctx = op->getContext(); // A pointer to coroutine resume intrinsic wrapper. auto resumeFnTy = AsyncAPI::resumeFunctionType(ctx); auto resumePtr = builder.create( loc, resumeFnTy.getPointerTo(), kResume); // Save the coroutine state: @llvm.coro.save auto coroSave = builder.create( loc, LLVM::LLVMTokenType::get(ctx), builder.getSymbolRefAttr(kCoroSave), ValueRange(coro.coroHandle)); // Call async runtime API to resume a coroutine in the managed thread when // the async await argument becomes ready. SmallVector awaitAndExecuteArgs = { await.getOperand(), coro.coroHandle, resumePtr.res()}; builder.create(loc, Type(), coroAwaitFuncName, awaitAndExecuteArgs); // Split the entry block before the await operation. addSuspensionPoint(coro, coroSave.getResult(0), op); } // Original operation was replaced by function call or suspension point. rewriter.eraseOp(op); return success(); } private: const llvm::DenseMap &outlinedFunctions; StringRef blockingAwaitFuncName; StringRef coroAwaitFuncName; }; // Lowering for `async.await` operation (only token operands are supported). class AwaitOpLowering : public AwaitOpLoweringBase { using Base = AwaitOpLoweringBase; public: explicit AwaitOpLowering( MLIRContext *ctx, const llvm::DenseMap &outlinedFunctions) : Base(ctx, outlinedFunctions, kAwaitToken, kAwaitAndExecute) {} }; // Lowering for `async.await_all` operation. class AwaitAllOpLowering : public AwaitOpLoweringBase { using Base = AwaitOpLoweringBase; public: explicit AwaitAllOpLowering( MLIRContext *ctx, const llvm::DenseMap &outlinedFunctions) : Base(ctx, outlinedFunctions, kAwaitGroup, kAwaitAllAndExecute) {} }; } // namespace //===----------------------------------------------------------------------===// namespace { struct ConvertAsyncToLLVMPass : public ConvertAsyncToLLVMBase { void runOnOperation() override; }; void ConvertAsyncToLLVMPass::runOnOperation() { ModuleOp module = getOperation(); SymbolTable symbolTable(module); // Outline all `async.execute` body regions into async functions (coroutines). llvm::DenseMap outlinedFunctions; WalkResult outlineResult = module.walk([&](ExecuteOp execute) { // We currently do not support execute operations that have async value // operands or produce async results. if (!execute.operands().empty() || !execute.results().empty()) { execute.emitOpError("can't outline async.execute op with async value " "operands or returned async results"); return WalkResult::interrupt(); } outlinedFunctions.insert(outlineExecuteOp(symbolTable, execute)); return WalkResult::advance(); }); // Failed to outline all async execute operations. if (outlineResult.wasInterrupted()) { signalPassFailure(); return; } LLVM_DEBUG({ llvm::dbgs() << "Outlined " << outlinedFunctions.size() << " async functions\n"; }); // Add declarations for all functions required by the coroutines lowering. addResumeFunction(module); addAsyncRuntimeApiDeclarations(module); addCoroutineIntrinsicsDeclarations(module); addCRuntimeDeclarations(module); MLIRContext *ctx = &getContext(); // Convert async dialect types and operations to LLVM dialect. AsyncRuntimeTypeConverter converter; OwningRewritePatternList patterns; populateFuncOpTypeConversionPattern(patterns, ctx, converter); patterns.insert(ctx); patterns.insert(ctx); patterns.insert(ctx, outlinedFunctions); ConversionTarget target(*ctx); target.addLegalDialect(); target.addIllegalDialect(); target.addDynamicallyLegalOp( [&](FuncOp op) { return converter.isSignatureLegal(op.getType()); }); target.addDynamicallyLegalOp( [&](CallOp op) { return converter.isLegal(op.getResultTypes()); }); if (failed(applyPartialConversion(module, target, std::move(patterns)))) signalPassFailure(); } } // namespace std::unique_ptr> mlir::createConvertAsyncToLLVMPass() { return std::make_unique(); } diff --git a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp index bfc8b6d6dec4..f0fff751c91b 100644 --- a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp +++ b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp @@ -1,195 +1,194 @@ //===- ConvertGPULaunchFuncToVulkanLaunchFunc.cpp - MLIR conversion pass --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements a pass to convert gpu launch function into a vulkan // launch function. Creates a SPIR-V binary shader from the `spirv::ModuleOp` // using `spirv::serialize` function, attaches binary data and entry point name // as an attributes to vulkan launch call op. // //===----------------------------------------------------------------------===// #include "../PassDetail.h" #include "mlir/Conversion/GPUToVulkan/ConvertGPUToVulkanPass.h" #include "mlir/Dialect/GPU/GPUDialect.h" #include "mlir/Dialect/SPIRV/SPIRVDialect.h" #include "mlir/Dialect/SPIRV/SPIRVOps.h" #include "mlir/Dialect/SPIRV/Serialization.h" #include "mlir/Dialect/StandardOps/IR/Ops.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Function.h" #include "mlir/IR/Module.h" #include "mlir/IR/StandardTypes.h" using namespace mlir; static constexpr const char *kSPIRVBlobAttrName = "spirv_blob"; static constexpr const char *kSPIRVEntryPointAttrName = "spirv_entry_point"; static constexpr const char *kVulkanLaunch = "vulkanLaunch"; namespace { /// A pass to convert gpu launch op to vulkan launch call op, by creating a /// SPIR-V binary shader from `spirv::ModuleOp` using `spirv::serialize` /// function and attaching binary data and entry point name as an attributes to /// created vulkan launch call op. class ConvertGpuLaunchFuncToVulkanLaunchFunc : public ConvertGpuLaunchFuncToVulkanLaunchFuncBase< ConvertGpuLaunchFuncToVulkanLaunchFunc> { public: void runOnOperation() override; private: /// Creates a SPIR-V binary shader from the given `module` using /// `spirv::serialize` function. LogicalResult createBinaryShader(ModuleOp module, std::vector &binaryShader); /// Converts the given `launchOp` to vulkan launch call. void convertGpuLaunchFunc(gpu::LaunchFuncOp launchOp); /// Checks where the given type is supported by Vulkan runtime. bool isSupportedType(Type type) { if (auto memRefType = type.dyn_cast_or_null()) { auto elementType = memRefType.getElementType(); return memRefType.hasRank() && (memRefType.getRank() >= 1 && memRefType.getRank() <= 3) && (elementType.isIntOrFloat()); } return false; } /// Declares the vulkan launch function. Returns an error if the any type of /// operand is unsupported by Vulkan runtime. LogicalResult declareVulkanLaunchFunc(Location loc, gpu::LaunchFuncOp launchOp); private: /// The number of vulkan launch configuration operands, placed at the leading /// positions of the operand list. static constexpr unsigned kVulkanLaunchNumConfigOperands = 3; }; } // anonymous namespace void ConvertGpuLaunchFuncToVulkanLaunchFunc::runOnOperation() { bool done = false; getOperation().walk([this, &done](gpu::LaunchFuncOp op) { if (done) { op.emitError("should only contain one 'gpu::LaunchFuncOp' op"); return signalPassFailure(); } done = true; convertGpuLaunchFunc(op); }); // Erase `gpu::GPUModuleOp` and `spirv::Module` operations. for (auto gpuModule : llvm::make_early_inc_range(getOperation().getOps())) gpuModule.erase(); for (auto spirvModule : llvm::make_early_inc_range(getOperation().getOps())) spirvModule.erase(); } LogicalResult ConvertGpuLaunchFuncToVulkanLaunchFunc::declareVulkanLaunchFunc( Location loc, gpu::LaunchFuncOp launchOp) { OpBuilder builder(getOperation().getBody()->getTerminator()); // Workgroup size is written into the kernel. So to properly modelling // vulkan launch, we have to skip local workgroup size configuration here. SmallVector gpuLaunchTypes(launchOp.getOperandTypes()); // The first kVulkanLaunchNumConfigOperands of the gpu.launch_func op are the // same as the config operands for the vulkan launch call op. SmallVector vulkanLaunchTypes(gpuLaunchTypes.begin(), gpuLaunchTypes.begin() + kVulkanLaunchNumConfigOperands); vulkanLaunchTypes.append(gpuLaunchTypes.begin() + gpu::LaunchOp::kNumConfigOperands, gpuLaunchTypes.end()); // Check that all operands have supported types except those for the // launch configuration. for (auto type : llvm::drop_begin(vulkanLaunchTypes, kVulkanLaunchNumConfigOperands)) { if (!isSupportedType(type)) return launchOp.emitError() << type << " is unsupported to run on Vulkan"; } // Declare vulkan launch function. - builder.create( - loc, kVulkanLaunch, - FunctionType::get(vulkanLaunchTypes, {}, loc->getContext())); + auto funcType = FunctionType::get(vulkanLaunchTypes, {}, loc->getContext()); + builder.create(loc, kVulkanLaunch, funcType).setPrivate(); return success(); } LogicalResult ConvertGpuLaunchFuncToVulkanLaunchFunc::createBinaryShader( ModuleOp module, std::vector &binaryShader) { bool done = false; SmallVector binary; for (auto spirvModule : module.getOps()) { if (done) return spirvModule.emitError("should only contain one 'spv.module' op"); done = true; if (failed(spirv::serialize(spirvModule, binary))) return failure(); } binaryShader.resize(binary.size() * sizeof(uint32_t)); std::memcpy(binaryShader.data(), reinterpret_cast(binary.data()), binaryShader.size()); return success(); } void ConvertGpuLaunchFuncToVulkanLaunchFunc::convertGpuLaunchFunc( gpu::LaunchFuncOp launchOp) { ModuleOp module = getOperation(); OpBuilder builder(launchOp); Location loc = launchOp.getLoc(); // Serialize `spirv::Module` into binary form. std::vector binary; if (failed(createBinaryShader(module, binary))) return signalPassFailure(); // Declare vulkan launch function. if (failed(declareVulkanLaunchFunc(loc, launchOp))) return signalPassFailure(); SmallVector gpuLaunchOperands(launchOp.getOperands()); SmallVector vulkanLaunchOperands( gpuLaunchOperands.begin(), gpuLaunchOperands.begin() + kVulkanLaunchNumConfigOperands); vulkanLaunchOperands.append(gpuLaunchOperands.begin() + gpu::LaunchOp::kNumConfigOperands, gpuLaunchOperands.end()); // Create vulkan launch call op. auto vulkanLaunchCallOp = builder.create( loc, TypeRange{}, builder.getSymbolRefAttr(kVulkanLaunch), vulkanLaunchOperands); // Set SPIR-V binary shader data as an attribute. vulkanLaunchCallOp.setAttr( kSPIRVBlobAttrName, StringAttr::get({binary.data(), binary.size()}, loc->getContext())); // Set entry point name as an attribute. vulkanLaunchCallOp.setAttr( kSPIRVEntryPointAttrName, StringAttr::get(launchOp.getKernelName(), loc->getContext())); launchOp.erase(); } std::unique_ptr> mlir::createConvertGpuLaunchFuncToVulkanLaunchFuncPass() { return std::make_unique(); } diff --git a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp index 5037f50b1f7c..5bb1db46e4af 100644 --- a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp +++ b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp @@ -1,221 +1,222 @@ //===- LinalgToStandard.cpp - conversion from Linalg to Standard dialect --===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Conversion/LinalgToStandard/LinalgToStandard.h" #include "../PassDetail.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Linalg/IR/LinalgOps.h" #include "mlir/Dialect/Linalg/Transforms/Transforms.h" #include "mlir/Dialect/SCF/SCF.h" #include "mlir/Dialect/StandardOps/IR/Ops.h" using namespace mlir; using namespace mlir::linalg; /// Helper function to extract the operand types that are passed to the /// generated CallOp. MemRefTypes have their layout canonicalized since the /// information is not used in signature generation. /// Note that static size information is not modified. static SmallVector extractOperandTypes(Operation *op) { SmallVector result; result.reserve(op->getNumOperands()); if (auto indexedGenericOp = dyn_cast(op)) { auto *ctx = op->getContext(); auto numLoops = indexedGenericOp.getNumLoops(); result.reserve(op->getNumOperands() + numLoops); result.assign(numLoops, IndexType::get(ctx)); } for (auto type : op->getOperandTypes()) { // The underlying descriptor type (e.g. LLVM) does not have layout // information. Canonicalizing the type at the level of std when going into // a library call avoids needing to introduce DialectCastOp. if (auto memrefType = type.dyn_cast()) result.push_back(eraseStridedLayout(memrefType)); else result.push_back(type); } return result; } // Get a SymbolRefAttr containing the library function name for the LinalgOp. // If the library function does not exist, insert a declaration. static FlatSymbolRefAttr getLibraryCallSymbolRef(Operation *op, PatternRewriter &rewriter) { auto linalgOp = cast(op); auto fnName = linalgOp.getLibraryCallName(); if (fnName.empty()) { op->emitWarning("No library call defined for: ") << *op; return {}; } // fnName is a dynamic std::string, unique it via a SymbolRefAttr. FlatSymbolRefAttr fnNameAttr = rewriter.getSymbolRefAttr(fnName); auto module = op->getParentOfType(); if (module.lookupSymbol(fnName)) { return fnNameAttr; } SmallVector inputTypes(extractOperandTypes(op)); assert(op->getNumResults() == 0 && "Library call for linalg operation can be generated only for ops that " "have void return types"); auto libFnType = FunctionType::get(inputTypes, {}, rewriter.getContext()); OpBuilder::InsertionGuard guard(rewriter); // Insert before module terminator. rewriter.setInsertionPoint(module.getBody(), std::prev(module.getBody()->end())); FuncOp funcOp = rewriter.create(op->getLoc(), fnNameAttr.getValue(), libFnType); // Insert a function attribute that will trigger the emission of the // corresponding `_mlir_ciface_xxx` interface so that external libraries see // a normalized ABI. This interface is added during std to llvm conversion. funcOp.setAttr("llvm.emit_c_interface", UnitAttr::get(op->getContext())); + funcOp.setPrivate(); return fnNameAttr; } static SmallVector createTypeCanonicalizedMemRefOperands(OpBuilder &b, Location loc, ValueRange operands) { SmallVector res; res.reserve(operands.size()); for (auto op : operands) { auto memrefType = op.getType().dyn_cast(); if (!memrefType) { res.push_back(op); continue; } Value cast = b.create(loc, eraseStridedLayout(memrefType), op); res.push_back(cast); } return res; } LogicalResult mlir::linalg::LinalgOpToLibraryCallRewrite::matchAndRewrite( Operation *op, PatternRewriter &rewriter) const { // Only LinalgOp for which there is no specialized pattern go through this. if (!isa(op) || isa(op) || isa(op)) return failure(); auto libraryCallName = getLibraryCallSymbolRef(op, rewriter); if (!libraryCallName) return failure(); rewriter.replaceOpWithNewOp( op, libraryCallName.getValue(), TypeRange(), createTypeCanonicalizedMemRefOperands(rewriter, op->getLoc(), op->getOperands())); return success(); } LogicalResult mlir::linalg::CopyOpToLibraryCallRewrite::matchAndRewrite( CopyOp op, PatternRewriter &rewriter) const { auto inputPerm = op.inputPermutation(); if (inputPerm.hasValue() && !inputPerm->isIdentity()) return failure(); auto outputPerm = op.outputPermutation(); if (outputPerm.hasValue() && !outputPerm->isIdentity()) return failure(); auto libraryCallName = getLibraryCallSymbolRef(op, rewriter); if (!libraryCallName) return failure(); rewriter.replaceOpWithNewOp( op, libraryCallName.getValue(), TypeRange(), createTypeCanonicalizedMemRefOperands(rewriter, op.getLoc(), op.getOperands())); return success(); } LogicalResult mlir::linalg::CopyTransposeRewrite::matchAndRewrite( CopyOp op, PatternRewriter &rewriter) const { Value in = op.input(), out = op.output(); // If either inputPerm or outputPerm are non-identities, insert transposes. auto inputPerm = op.inputPermutation(); if (inputPerm.hasValue() && !inputPerm->isIdentity()) in = rewriter.create(op.getLoc(), in, AffineMapAttr::get(*inputPerm)); auto outputPerm = op.outputPermutation(); if (outputPerm.hasValue() && !outputPerm->isIdentity()) out = rewriter.create(op.getLoc(), out, AffineMapAttr::get(*outputPerm)); // If nothing was transposed, fail and let the conversion kick in. if (in == op.input() && out == op.output()) return failure(); rewriter.replaceOpWithNewOp(op, in, out); return success(); } LogicalResult mlir::linalg::IndexedGenericOpToLibraryCallRewrite::matchAndRewrite( IndexedGenericOp op, PatternRewriter &rewriter) const { auto libraryCallName = getLibraryCallSymbolRef(op, rewriter); if (!libraryCallName) return failure(); // TODO: Use induction variables values instead of zeros, when // IndexedGenericOp is tiled. auto zero = rewriter.create( op.getLoc(), rewriter.getIntegerAttr(rewriter.getIndexType(), 0)); auto indexedGenericOp = cast(op); auto numLoops = indexedGenericOp.getNumLoops(); SmallVector operands; operands.reserve(numLoops + op.getNumOperands()); for (unsigned i = 0; i < numLoops; ++i) operands.push_back(zero); for (auto operand : op.getOperands()) operands.push_back(operand); rewriter.replaceOpWithNewOp( op, libraryCallName.getValue(), TypeRange(), createTypeCanonicalizedMemRefOperands(rewriter, op.getLoc(), operands)); return success(); } /// Populate the given list with patterns that convert from Linalg to Standard. void mlir::linalg::populateLinalgToStandardConversionPatterns( OwningRewritePatternList &patterns, MLIRContext *ctx) { // TODO: ConvOp conversion needs to export a descriptor with relevant // attribute values such as kernel striding and dilation. // clang-format off patterns.insert< CopyOpToLibraryCallRewrite, CopyTransposeRewrite, IndexedGenericOpToLibraryCallRewrite>(ctx); patterns.insert(); // clang-format on } namespace { struct ConvertLinalgToStandardPass : public ConvertLinalgToStandardBase { void runOnOperation() override; }; } // namespace void ConvertLinalgToStandardPass::runOnOperation() { auto module = getOperation(); ConversionTarget target(getContext()); target.addLegalDialect(); target.addLegalOp(); target.addLegalOp(); OwningRewritePatternList patterns; populateLinalgToStandardConversionPatterns(patterns, &getContext()); if (failed(applyFullConversion(module, target, std::move(patterns)))) signalPassFailure(); } std::unique_ptr> mlir::createConvertLinalgToStandardPass() { return std::make_unique(); } diff --git a/mlir/test/Analysis/test-callgraph.mlir b/mlir/test/Analysis/test-callgraph.mlir index bb5ba6074200..1befa5338100 100644 --- a/mlir/test/Analysis/test-callgraph.mlir +++ b/mlir/test/Analysis/test-callgraph.mlir @@ -1,71 +1,71 @@ -// RUN: mlir-opt %s -test-print-callgraph -split-input-file 2>&1 | FileCheck %s +// RUN: mlir-opt %s -test-print-callgraph -split-input-file -allow-unregistered-dialect 2>&1 | FileCheck %s // CHECK-LABEL: Testing : "simple" module attributes {test.name = "simple"} { // CHECK: Node{{.*}}func_a func @func_a() { return } - func @func_b() + func private @func_b() // CHECK: Node{{.*}}func_c // CHECK-NEXT: Call-Edge{{.*}}External-Node func @func_c() { call @func_b() : () -> () return } // CHECK: Node{{.*}}func_d // CHECK-NEXT: Call-Edge{{.*}}func_c func @func_d() { call @func_c() : () -> () return } // CHECK: Node{{.*}}func_e // CHECK-DAG: Call-Edge{{.*}}func_c // CHECK-DAG: Call-Edge{{.*}}func_d // CHECK-DAG: Call-Edge{{.*}}func_e func @func_e() { call @func_c() : () -> () call @func_d() : () -> () call @func_e() : () -> () return } // CHECK: Node{{.*}}func_f // CHECK: Child-Edge{{.*}}test.functional_region_op // CHECK: Call-Edge{{.*}}test.functional_region_op func @func_f() { // CHECK: Node{{.*}}test.functional_region_op // CHECK: Call-Edge{{.*}}func_f %fn = "test.functional_region_op"() ({ call @func_f() : () -> () "test.return"() : () -> () }) : () -> (() -> ()) call_indirect %fn() : () -> () return } } // ----- // CHECK-LABEL: Testing : "nested" module attributes {test.name = "nested"} { module @nested_module { // CHECK: Node{{.*}}func_a func @func_a() { return } } // CHECK: Node{{.*}}func_b // CHECK: Call-Edge{{.*}}func_a func @func_b() { "test.conversion_call_op"() { callee = @nested_module::@func_a } : () -> () return } } diff --git a/mlir/test/Conversion/AffineToStandard/lower-affine.mlir b/mlir/test/Conversion/AffineToStandard/lower-affine.mlir index 7aac76b870b7..f89d913cb64a 100644 --- a/mlir/test/Conversion/AffineToStandard/lower-affine.mlir +++ b/mlir/test/Conversion/AffineToStandard/lower-affine.mlir @@ -1,676 +1,676 @@ // RUN: mlir-opt -lower-affine %s | FileCheck %s // CHECK-LABEL: func @empty() { func @empty() { return // CHECK: return } // CHECK: } -func @body(index) -> () +func private @body(index) -> () // Simple loops are properly converted. // CHECK-LABEL: func @simple_loop // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c1_0:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c1]] to %[[c42]] step %[[c1_0]] { // CHECK-NEXT: call @body(%{{.*}}) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @simple_loop() { affine.for %i = 1 to 42 { call @body(%i) : (index) -> () } return } ///////////////////////////////////////////////////////////////////// -func @pre(index) -> () -func @body2(index, index) -> () -func @post(index) -> () +func private @pre(index) -> () +func private @body2(index, index) -> () +func private @post(index) -> () // CHECK-LABEL: func @imperfectly_nested_loops // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] { // CHECK-NEXT: call @pre(%{{.*}}) : (index) -> () // CHECK-NEXT: %[[c7:.*]] = constant 7 : index // CHECK-NEXT: %[[c56:.*]] = constant 56 : index // CHECK-NEXT: %[[c2:.*]] = constant 2 : index // CHECK-NEXT: for %{{.*}} = %[[c7]] to %[[c56]] step %[[c2]] { // CHECK-NEXT: call @body2(%{{.*}}, %{{.*}}) : (index, index) -> () // CHECK-NEXT: } // CHECK-NEXT: call @post(%{{.*}}) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @imperfectly_nested_loops() { affine.for %i = 0 to 42 { call @pre(%i) : (index) -> () affine.for %j = 7 to 56 step 2 { call @body2(%i, %j) : (index, index) -> () } call @post(%i) : (index) -> () } return } ///////////////////////////////////////////////////////////////////// -func @mid(index) -> () -func @body3(index, index) -> () +func private @mid(index) -> () +func private @body3(index, index) -> () // CHECK-LABEL: func @more_imperfectly_nested_loops // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] { // CHECK-NEXT: call @pre(%{{.*}}) : (index) -> () // CHECK-NEXT: %[[c7:.*]] = constant 7 : index // CHECK-NEXT: %[[c56:.*]] = constant 56 : index // CHECK-NEXT: %[[c2:.*]] = constant 2 : index // CHECK-NEXT: for %{{.*}} = %[[c7]] to %[[c56]] step %[[c2]] { // CHECK-NEXT: call @body2(%{{.*}}, %{{.*}}) : (index, index) -> () // CHECK-NEXT: } // CHECK-NEXT: call @mid(%{{.*}}) : (index) -> () // CHECK-NEXT: %[[c18:.*]] = constant 18 : index // CHECK-NEXT: %[[c37:.*]] = constant 37 : index // CHECK-NEXT: %[[c3:.*]] = constant 3 : index // CHECK-NEXT: for %{{.*}} = %[[c18]] to %[[c37]] step %[[c3]] { // CHECK-NEXT: call @body3(%{{.*}}, %{{.*}}) : (index, index) -> () // CHECK-NEXT: } // CHECK-NEXT: call @post(%{{.*}}) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @more_imperfectly_nested_loops() { affine.for %i = 0 to 42 { call @pre(%i) : (index) -> () affine.for %j = 7 to 56 step 2 { call @body2(%i, %j) : (index, index) -> () } call @mid(%i) : (index) -> () affine.for %k = 18 to 37 step 3 { call @body3(%i, %k) : (index, index) -> () } call @post(%i) : (index) -> () } return } // CHECK-LABEL: func @affine_apply_loops_shorthand // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0]] to %{{.*}} step %[[c1]] { // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c1_0:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %{{.*}} to %[[c42]] step %[[c1_0]] { // CHECK-NEXT: call @body2(%{{.*}}, %{{.*}}) : (index, index) -> () // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @affine_apply_loops_shorthand(%N : index) { affine.for %i = 0 to %N { affine.for %j = affine_map<(d0)[]->(d0)>(%i)[] to 42 { call @body2(%i, %j) : (index, index) -> () } } return } ///////////////////////////////////////////////////////////////////// -func @get_idx() -> (index) +func private @get_idx() -> (index) #set1 = affine_set<(d0) : (20 - d0 >= 0)> #set2 = affine_set<(d0) : (d0 - 10 >= 0)> // CHECK-LABEL: func @if_only // CHECK-NEXT: %[[v0:.*]] = call @get_idx() : () -> index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v1:.*]] = muli %[[v0]], %[[cm1]] : index // CHECK-NEXT: %[[c20:.*]] = constant 20 : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v1]], %[[c20]] : index // CHECK-NEXT: %[[v3:.*]] = cmpi "sge", %[[v2]], %[[c0]] : index // CHECK-NEXT: if %[[v3]] { // CHECK-NEXT: call @body(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @if_only() { %i = call @get_idx() : () -> (index) affine.if #set1(%i) { call @body(%i) : (index) -> () } return } // CHECK-LABEL: func @if_else // CHECK-NEXT: %[[v0:.*]] = call @get_idx() : () -> index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v1:.*]] = muli %[[v0]], %[[cm1]] : index // CHECK-NEXT: %[[c20:.*]] = constant 20 : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v1]], %[[c20]] : index // CHECK-NEXT: %[[v3:.*]] = cmpi "sge", %[[v2]], %[[c0]] : index // CHECK-NEXT: if %[[v3]] { // CHECK-NEXT: call @body(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } else { // CHECK-NEXT: call @mid(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @if_else() { %i = call @get_idx() : () -> (index) affine.if #set1(%i) { call @body(%i) : (index) -> () } else { call @mid(%i) : (index) -> () } return } // CHECK-LABEL: func @nested_ifs // CHECK-NEXT: %[[v0:.*]] = call @get_idx() : () -> index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v1:.*]] = muli %[[v0]], %[[cm1]] : index // CHECK-NEXT: %[[c20:.*]] = constant 20 : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v1]], %[[c20]] : index // CHECK-NEXT: %[[v3:.*]] = cmpi "sge", %[[v2]], %[[c0]] : index // CHECK-NEXT: if %[[v3]] { // CHECK-NEXT: %[[c0_0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm10:.*]] = constant -10 : index // CHECK-NEXT: %[[v4:.*]] = addi %[[v0]], %[[cm10]] : index // CHECK-NEXT: %[[v5:.*]] = cmpi "sge", %[[v4]], %[[c0_0]] : index // CHECK-NEXT: if %[[v5]] { // CHECK-NEXT: call @body(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: } else { // CHECK-NEXT: %[[c0_0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm10:.*]] = constant -10 : index // CHECK-NEXT: %{{.*}} = addi %[[v0]], %[[cm10]] : index // CHECK-NEXT: %{{.*}} = cmpi "sge", %{{.*}}, %[[c0_0]] : index // CHECK-NEXT: if %{{.*}} { // CHECK-NEXT: call @mid(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @nested_ifs() { %i = call @get_idx() : () -> (index) affine.if #set1(%i) { affine.if #set2(%i) { call @body(%i) : (index) -> () } } else { affine.if #set2(%i) { call @mid(%i) : (index) -> () } } return } #setN = affine_set<(d0)[N,M,K,L] : (N - d0 + 1 >= 0, N - 1 >= 0, M - 1 >= 0, K - 1 >= 0, L - 42 == 0)> // CHECK-LABEL: func @multi_cond // CHECK-NEXT: %[[v0:.*]] = call @get_idx() : () -> index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v1:.*]] = muli %[[v0]], %[[cm1]] : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v1]], %{{.*}} : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: %[[v3:.*]] = addi %[[v2]], %[[c1]] : index // CHECK-NEXT: %[[v4:.*]] = cmpi "sge", %[[v3]], %[[c0]] : index // CHECK-NEXT: %[[cm1_0:.*]] = constant -1 : index // CHECK-NEXT: %[[v5:.*]] = addi %{{.*}}, %[[cm1_0]] : index // CHECK-NEXT: %[[v6:.*]] = cmpi "sge", %[[v5]], %[[c0]] : index // CHECK-NEXT: %[[v7:.*]] = and %[[v4]], %[[v6]] : i1 // CHECK-NEXT: %[[cm1_1:.*]] = constant -1 : index // CHECK-NEXT: %[[v8:.*]] = addi %{{.*}}, %[[cm1_1]] : index // CHECK-NEXT: %[[v9:.*]] = cmpi "sge", %[[v8]], %[[c0]] : index // CHECK-NEXT: %[[v10:.*]] = and %[[v7]], %[[v9]] : i1 // CHECK-NEXT: %[[cm1_2:.*]] = constant -1 : index // CHECK-NEXT: %[[v11:.*]] = addi %{{.*}}, %[[cm1_2]] : index // CHECK-NEXT: %[[v12:.*]] = cmpi "sge", %[[v11]], %[[c0]] : index // CHECK-NEXT: %[[v13:.*]] = and %[[v10]], %[[v12]] : i1 // CHECK-NEXT: %[[cm42:.*]] = constant -42 : index // CHECK-NEXT: %[[v14:.*]] = addi %{{.*}}, %[[cm42]] : index // CHECK-NEXT: %[[v15:.*]] = cmpi "eq", %[[v14]], %[[c0]] : index // CHECK-NEXT: %[[v16:.*]] = and %[[v13]], %[[v15]] : i1 // CHECK-NEXT: if %[[v16]] { // CHECK-NEXT: call @body(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } else { // CHECK-NEXT: call @mid(%[[v0:.*]]) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @multi_cond(%N : index, %M : index, %K : index, %L : index) { %i = call @get_idx() : () -> (index) affine.if #setN(%i)[%N,%M,%K,%L] { call @body(%i) : (index) -> () } else { call @mid(%i) : (index) -> () } return } // CHECK-LABEL: func @if_for func @if_for() { // CHECK-NEXT: %[[v0:.*]] = call @get_idx() : () -> index %i = call @get_idx() : () -> (index) // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v1:.*]] = muli %[[v0]], %[[cm1]] : index // CHECK-NEXT: %[[c20:.*]] = constant 20 : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v1]], %[[c20]] : index // CHECK-NEXT: %[[v3:.*]] = cmpi "sge", %[[v2]], %[[c0]] : index // CHECK-NEXT: if %[[v3]] { // CHECK-NEXT: %[[c0:.*]]{{.*}} = constant 0 : index // CHECK-NEXT: %[[c42:.*]]{{.*}} = constant 42 : index // CHECK-NEXT: %[[c1:.*]]{{.*}} = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0:.*]]{{.*}} to %[[c42:.*]]{{.*}} step %[[c1:.*]]{{.*}} { // CHECK-NEXT: %[[c0_:.*]]{{.*}} = constant 0 : index // CHECK-NEXT: %[[cm10:.*]] = constant -10 : index // CHECK-NEXT: %[[v4:.*]] = addi %{{.*}}, %[[cm10]] : index // CHECK-NEXT: %[[v5:.*]] = cmpi "sge", %[[v4]], %[[c0_:.*]]{{.*}} : index // CHECK-NEXT: if %[[v5]] { // CHECK-NEXT: call @body2(%[[v0]], %{{.*}}) : (index, index) -> () affine.if #set1(%i) { affine.for %j = 0 to 42 { affine.if #set2(%j) { call @body2(%i, %j) : (index, index) -> () } } } // CHECK: %[[c0:.*]]{{.*}} = constant 0 : index // CHECK-NEXT: %[[c42:.*]]{{.*}} = constant 42 : index // CHECK-NEXT: %[[c1:.*]]{{.*}} = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0:.*]]{{.*}} to %[[c42:.*]]{{.*}} step %[[c1:.*]]{{.*}} { // CHECK-NEXT: %[[c0:.*]]{{.*}} = constant 0 : index // CHECK-NEXT: %[[cm10:.*]]{{.*}} = constant -10 : index // CHECK-NEXT: %{{.*}} = addi %{{.*}}, %[[cm10:.*]]{{.*}} : index // CHECK-NEXT: %{{.*}} = cmpi "sge", %{{.*}}, %[[c0:.*]]{{.*}} : index // CHECK-NEXT: if %{{.*}} { // CHECK-NEXT: %[[c0_:.*]]{{.*}} = constant 0 : index // CHECK-NEXT: %[[c42_:.*]]{{.*}} = constant 42 : index // CHECK-NEXT: %[[c1_:.*]]{{.*}} = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0_:.*]]{{.*}} to %[[c42_:.*]]{{.*}} step %[[c1_:.*]]{{.*}} { affine.for %k = 0 to 42 { affine.if #set2(%k) { affine.for %l = 0 to 42 { call @body3(%k, %l) : (index, index) -> () } } } // CHECK: return return } #lbMultiMap = affine_map<(d0)[s0] -> (d0, s0 - d0)> #ubMultiMap = affine_map<(d0)[s0] -> (s0, d0 + 10)> // CHECK-LABEL: func @loop_min_max // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0]] to %[[c42]] step %[[c1]] { // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[a:.*]] = muli %{{.*}}, %[[cm1]] : index // CHECK-NEXT: %[[b:.*]] = addi %[[a]], %{{.*}} : index // CHECK-NEXT: %[[c:.*]] = cmpi "sgt", %{{.*}}, %[[b]] : index // CHECK-NEXT: %[[d:.*]] = select %[[c]], %{{.*}}, %[[b]] : index // CHECK-NEXT: %[[c10:.*]] = constant 10 : index // CHECK-NEXT: %[[e:.*]] = addi %{{.*}}, %[[c10]] : index // CHECK-NEXT: %[[f:.*]] = cmpi "slt", %{{.*}}, %[[e]] : index // CHECK-NEXT: %[[g:.*]] = select %[[f]], %{{.*}}, %[[e]] : index // CHECK-NEXT: %[[c1_0:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[d]] to %[[g]] step %[[c1_0]] { // CHECK-NEXT: call @body2(%{{.*}}, %{{.*}}) : (index, index) -> () // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @loop_min_max(%N : index) { affine.for %i = 0 to 42 { affine.for %j = max #lbMultiMap(%i)[%N] to min #ubMultiMap(%i)[%N] { call @body2(%i, %j) : (index, index) -> () } } return } #map_7_values = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d0, d1, d2, d3, d4, d5, d6)> // Check that the "min" (cmpi "slt" + select) reduction sequence is emitted // correctly for an affine map with 7 results. // CHECK-LABEL: func @min_reduction_tree // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c01:.+]] = cmpi "slt", %{{.*}}, %{{.*}} : index // CHECK-NEXT: %[[r01:.+]] = select %[[c01]], %{{.*}}, %{{.*}} : index // CHECK-NEXT: %[[c012:.+]] = cmpi "slt", %[[r01]], %{{.*}} : index // CHECK-NEXT: %[[r012:.+]] = select %[[c012]], %[[r01]], %{{.*}} : index // CHECK-NEXT: %[[c0123:.+]] = cmpi "slt", %[[r012]], %{{.*}} : index // CHECK-NEXT: %[[r0123:.+]] = select %[[c0123]], %[[r012]], %{{.*}} : index // CHECK-NEXT: %[[c01234:.+]] = cmpi "slt", %[[r0123]], %{{.*}} : index // CHECK-NEXT: %[[r01234:.+]] = select %[[c01234]], %[[r0123]], %{{.*}} : index // CHECK-NEXT: %[[c012345:.+]] = cmpi "slt", %[[r01234]], %{{.*}} : index // CHECK-NEXT: %[[r012345:.+]] = select %[[c012345]], %[[r01234]], %{{.*}} : index // CHECK-NEXT: %[[c0123456:.+]] = cmpi "slt", %[[r012345]], %{{.*}} : index // CHECK-NEXT: %[[r0123456:.+]] = select %[[c0123456]], %[[r012345]], %{{.*}} : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: for %{{.*}} = %[[c0]] to %[[r0123456]] step %[[c1]] { // CHECK-NEXT: call @body(%{{.*}}) : (index) -> () // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-NEXT: } func @min_reduction_tree(%v1 : index, %v2 : index, %v3 : index, %v4 : index, %v5 : index, %v6 : index, %v7 : index) { affine.for %i = 0 to min #map_7_values(%v1, %v2, %v3, %v4, %v5, %v6, %v7)[] { call @body(%i) : (index) -> () } return } ///////////////////////////////////////////////////////////////////// #map0 = affine_map<() -> (0)> #map1 = affine_map<()[s0] -> (s0)> #map2 = affine_map<(d0) -> (d0)> #map3 = affine_map<(d0)[s0] -> (d0 + s0 + 1)> #map4 = affine_map<(d0,d1,d2,d3)[s0,s1,s2] -> (d0 + 2*d1 + 3*d2 + 4*d3 + 5*s0 + 6*s1 + 7*s2)> #map5 = affine_map<(d0,d1,d2) -> (d0,d1,d2)> #map6 = affine_map<(d0,d1,d2) -> (d0 + d1 + d2)> // CHECK-LABEL: func @affine_applies( func @affine_applies(%arg0 : index) { // CHECK: %[[c0:.*]] = constant 0 : index %zero = affine.apply #map0() // Identity maps are just discarded. // CHECK-NEXT: %[[c101:.*]] = constant 101 : index %101 = constant 101 : index %symbZero = affine.apply #map1()[%zero] // CHECK-NEXT: %[[c102:.*]] = constant 102 : index %102 = constant 102 : index %copy = affine.apply #map2(%zero) // CHECK-NEXT: %[[v0:.*]] = addi %[[c0]], %[[c0]] : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: %[[v1:.*]] = addi %[[v0]], %[[c1]] : index %one = affine.apply #map3(%symbZero)[%zero] // CHECK-NEXT: %[[c2:.*]] = constant 2 : index // CHECK-NEXT: %[[v2:.*]] = muli %arg0, %[[c2]] : index // CHECK-NEXT: %[[v3:.*]] = addi %arg0, %[[v2]] : index // CHECK-NEXT: %[[c3:.*]] = constant 3 : index // CHECK-NEXT: %[[v4:.*]] = muli %arg0, %[[c3]] : index // CHECK-NEXT: %[[v5:.*]] = addi %[[v3]], %[[v4]] : index // CHECK-NEXT: %[[c4:.*]] = constant 4 : index // CHECK-NEXT: %[[v6:.*]] = muli %arg0, %[[c4]] : index // CHECK-NEXT: %[[v7:.*]] = addi %[[v5]], %[[v6]] : index // CHECK-NEXT: %[[c5:.*]] = constant 5 : index // CHECK-NEXT: %[[v8:.*]] = muli %arg0, %[[c5]] : index // CHECK-NEXT: %[[v9:.*]] = addi %[[v7]], %[[v8]] : index // CHECK-NEXT: %[[c6:.*]] = constant 6 : index // CHECK-NEXT: %[[v10:.*]] = muli %arg0, %[[c6]] : index // CHECK-NEXT: %[[v11:.*]] = addi %[[v9]], %[[v10]] : index // CHECK-NEXT: %[[c7:.*]] = constant 7 : index // CHECK-NEXT: %[[v12:.*]] = muli %arg0, %[[c7]] : index // CHECK-NEXT: %[[v13:.*]] = addi %[[v11]], %[[v12]] : index %four = affine.apply #map4(%arg0, %arg0, %arg0, %arg0)[%arg0, %arg0, %arg0] return } // CHECK-LABEL: func @args_ret_affine_apply( func @args_ret_affine_apply(index, index) -> (index, index) { ^bb0(%0 : index, %1 : index): // CHECK-NEXT: return %{{.*}}, %{{.*}} : index, index %00 = affine.apply #map2 (%0) %11 = affine.apply #map1 ()[%1] return %00, %11 : index, index } //===---------------------------------------------------------------------===// // Test lowering of Euclidean (floor) division, ceil division and modulo // operation used in affine expressions. In addition to testing the // operation-level output, check that the obtained results are correct by // applying constant folding transformation after affine lowering. //===---------------------------------------------------------------------===// #mapmod = affine_map<(i) -> (i mod 42)> // --------------------------------------------------------------------------// // IMPORTANT NOTE: if you change this test, also change the @lowered_affine_mod // test in the "constant-fold.mlir" test to reflect the expected output of // affine.apply lowering. // --------------------------------------------------------------------------// // CHECK-LABEL: func @affine_apply_mod func @affine_apply_mod(%arg0 : index) -> (index) { // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[v0:.*]] = remi_signed %{{.*}}, %[[c42]] : index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[v1:.*]] = cmpi "slt", %[[v0]], %[[c0]] : index // CHECK-NEXT: %[[v2:.*]] = addi %[[v0]], %[[c42]] : index // CHECK-NEXT: %[[v3:.*]] = select %[[v1]], %[[v2]], %[[v0]] : index %0 = affine.apply #mapmod (%arg0) return %0 : index } #mapfloordiv = affine_map<(i) -> (i floordiv 42)> // --------------------------------------------------------------------------// // IMPORTANT NOTE: if you change this test, also change the @lowered_affine_mod // test in the "constant-fold.mlir" test to reflect the expected output of // affine.apply lowering. // --------------------------------------------------------------------------// // CHECK-LABEL: func @affine_apply_floordiv func @affine_apply_floordiv(%arg0 : index) -> (index) { // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[cm1:.*]] = constant -1 : index // CHECK-NEXT: %[[v0:.*]] = cmpi "slt", %{{.*}}, %[[c0]] : index // CHECK-NEXT: %[[v1:.*]] = subi %[[cm1]], %{{.*}} : index // CHECK-NEXT: %[[v2:.*]] = select %[[v0]], %[[v1]], %{{.*}} : index // CHECK-NEXT: %[[v3:.*]] = divi_signed %[[v2]], %[[c42]] : index // CHECK-NEXT: %[[v4:.*]] = subi %[[cm1]], %[[v3]] : index // CHECK-NEXT: %[[v5:.*]] = select %[[v0]], %[[v4]], %[[v3]] : index %0 = affine.apply #mapfloordiv (%arg0) return %0 : index } #mapceildiv = affine_map<(i) -> (i ceildiv 42)> // --------------------------------------------------------------------------// // IMPORTANT NOTE: if you change this test, also change the @lowered_affine_mod // test in the "constant-fold.mlir" test to reflect the expected output of // affine.apply lowering. // --------------------------------------------------------------------------// // CHECK-LABEL: func @affine_apply_ceildiv func @affine_apply_ceildiv(%arg0 : index) -> (index) { // CHECK-NEXT: %[[c42:.*]] = constant 42 : index // CHECK-NEXT: %[[c0:.*]] = constant 0 : index // CHECK-NEXT: %[[c1:.*]] = constant 1 : index // CHECK-NEXT: %[[v0:.*]] = cmpi "sle", %{{.*}}, %[[c0]] : index // CHECK-NEXT: %[[v1:.*]] = subi %[[c0]], %{{.*}} : index // CHECK-NEXT: %[[v2:.*]] = subi %{{.*}}, %[[c1]] : index // CHECK-NEXT: %[[v3:.*]] = select %[[v0]], %[[v1]], %[[v2]] : index // CHECK-NEXT: %[[v4:.*]] = divi_signed %[[v3]], %[[c42]] : index // CHECK-NEXT: %[[v5:.*]] = subi %[[c0]], %[[v4]] : index // CHECK-NEXT: %[[v6:.*]] = addi %[[v4]], %[[c1]] : index // CHECK-NEXT: %[[v7:.*]] = select %[[v0]], %[[v5]], %[[v6]] : index %0 = affine.apply #mapceildiv (%arg0) return %0 : index } // CHECK-LABEL: func @affine_load func @affine_load(%arg0 : index) { %0 = alloc() : memref<10xf32> affine.for %i0 = 0 to 10 { %1 = affine.load %0[%i0 + symbol(%arg0) + 7] : memref<10xf32> } // CHECK: %[[a:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: %[[c7:.*]] = constant 7 : index // CHECK-NEXT: %[[b:.*]] = addi %[[a]], %[[c7]] : index // CHECK-NEXT: %{{.*}} = load %[[v0:.*]][%[[b]]] : memref<10xf32> return } // CHECK-LABEL: func @affine_store func @affine_store(%arg0 : index) { %0 = alloc() : memref<10xf32> %1 = constant 11.0 : f32 affine.for %i0 = 0 to 10 { affine.store %1, %0[%i0 - symbol(%arg0) + 7] : memref<10xf32> } // CHECK: %c-1 = constant -1 : index // CHECK-NEXT: %[[a:.*]] = muli %arg0, %c-1 : index // CHECK-NEXT: %[[b:.*]] = addi %{{.*}}, %[[a]] : index // CHECK-NEXT: %c7 = constant 7 : index // CHECK-NEXT: %[[c:.*]] = addi %[[b]], %c7 : index // CHECK-NEXT: store %cst, %0[%[[c]]] : memref<10xf32> return } // CHECK-LABEL: func @affine_load_store_zero_dim func @affine_load_store_zero_dim(%arg0 : memref, %arg1 : memref) { %0 = affine.load %arg0[] : memref affine.store %0, %arg1[] : memref // CHECK: %[[x:.*]] = load %arg0[] : memref // CHECK: store %[[x]], %arg1[] : memref return } // CHECK-LABEL: func @affine_prefetch func @affine_prefetch(%arg0 : index) { %0 = alloc() : memref<10xf32> affine.for %i0 = 0 to 10 { affine.prefetch %0[%i0 + symbol(%arg0) + 7], read, locality<3>, data : memref<10xf32> } // CHECK: %[[a:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: %[[c7:.*]] = constant 7 : index // CHECK-NEXT: %[[b:.*]] = addi %[[a]], %[[c7]] : index // CHECK-NEXT: prefetch %[[v0:.*]][%[[b]]], read, locality<3>, data : memref<10xf32> return } // CHECK-LABEL: func @affine_dma_start func @affine_dma_start(%arg0 : index) { %0 = alloc() : memref<100xf32> %1 = alloc() : memref<100xf32, 2> %2 = alloc() : memref<1xi32> %c0 = constant 0 : index %c64 = constant 64 : index affine.for %i0 = 0 to 10 { affine.dma_start %0[%i0 + 7], %1[%arg0 + 11], %2[%c0], %c64 : memref<100xf32>, memref<100xf32, 2>, memref<1xi32> } // CHECK: %c7 = constant 7 : index // CHECK-NEXT: %[[a:.*]] = addi %{{.*}}, %c7 : index // CHECK-NEXT: %c11 = constant 11 : index // CHECK-NEXT: %[[b:.*]] = addi %arg0, %c11 : index // CHECK-NEXT: dma_start %0[%[[a]]], %1[%[[b]]], %c64, %2[%c0] : memref<100xf32>, memref<100xf32, 2>, memref<1xi32> return } // CHECK-LABEL: func @affine_dma_wait func @affine_dma_wait(%arg0 : index) { %2 = alloc() : memref<1xi32> %c64 = constant 64 : index affine.for %i0 = 0 to 10 { affine.dma_wait %2[%i0 + %arg0 + 17], %c64 : memref<1xi32> } // CHECK: %[[a:.*]] = addi %{{.*}}, %arg0 : index // CHECK-NEXT: %c17 = constant 17 : index // CHECK-NEXT: %[[b:.*]] = addi %[[a]], %c17 : index // CHECK-NEXT: dma_wait %0[%[[b]]], %c64 : memref<1xi32> return } // CHECK-LABEL: func @affine_min // CHECK-SAME: %[[ARG0:.*]]: index, %[[ARG1:.*]]: index func @affine_min(%arg0: index, %arg1: index) -> index{ // CHECK: %[[Cm1:.*]] = constant -1 // CHECK: %[[neg1:.*]] = muli %[[ARG1]], %[[Cm1:.*]] // CHECK: %[[first:.*]] = addi %[[ARG0]], %[[neg1]] // CHECK: %[[Cm2:.*]] = constant -1 // CHECK: %[[neg2:.*]] = muli %[[ARG0]], %[[Cm2:.*]] // CHECK: %[[second:.*]] = addi %[[ARG1]], %[[neg2]] // CHECK: %[[cmp:.*]] = cmpi "slt", %[[first]], %[[second]] // CHECK: select %[[cmp]], %[[first]], %[[second]] %0 = affine.min affine_map<(d0,d1) -> (d0 - d1, d1 - d0)>(%arg0, %arg1) return %0 : index } // CHECK-LABEL: func @affine_max // CHECK-SAME: %[[ARG0:.*]]: index, %[[ARG1:.*]]: index func @affine_max(%arg0: index, %arg1: index) -> index{ // CHECK: %[[Cm1:.*]] = constant -1 // CHECK: %[[neg1:.*]] = muli %[[ARG1]], %[[Cm1:.*]] // CHECK: %[[first:.*]] = addi %[[ARG0]], %[[neg1]] // CHECK: %[[Cm2:.*]] = constant -1 // CHECK: %[[neg2:.*]] = muli %[[ARG0]], %[[Cm2:.*]] // CHECK: %[[second:.*]] = addi %[[ARG1]], %[[neg2]] // CHECK: %[[cmp:.*]] = cmpi "sgt", %[[first]], %[[second]] // CHECK: select %[[cmp]], %[[first]], %[[second]] %0 = affine.max affine_map<(d0,d1) -> (d0 - d1, d1 - d0)>(%arg0, %arg1) return %0 : index } // CHECK-LABEL: func @affine_parallel( // CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>) { func @affine_parallel(%o: memref<100x100xf32>, %a: memref<100x100xf32>) { affine.parallel (%i, %j) = (0, 0) to (100, 100) { } return } // CHECK-DAG: %[[C100:.*]] = constant 100 // CHECK-DAG: %[[C100_1:.*]] = constant 100 // CHECK-DAG: %[[C0:.*]] = constant 0 // CHECK-DAG: %[[C0_1:.*]] = constant 0 // CHECK-DAG: %[[C1:.*]] = constant 1 // CHECK-DAG: %[[C1_1:.*]] = constant 1 // CHECK-DAG: scf.parallel (%arg2, %arg3) = (%[[C0]], %[[C0_1]]) to (%[[C100]], %[[C100_1]]) step (%[[C1]], %[[C1_1]]) { // CHECK-LABEL: func @affine_parallel_tiled( // CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>, %[[ARG2:.*]]: memref<100x100xf32>) { func @affine_parallel_tiled(%o: memref<100x100xf32>, %a: memref<100x100xf32>, %b: memref<100x100xf32>) { affine.parallel (%i0, %j0, %k0) = (0, 0, 0) to (100, 100, 100) step (10, 10, 10) { affine.parallel (%i1, %j1, %k1) = (%i0, %j0, %k0) to (%i0 + 10, %j0 + 10, %k0 + 10) { %0 = affine.load %a[%i1, %k1] : memref<100x100xf32> %1 = affine.load %b[%k1, %j1] : memref<100x100xf32> %2 = mulf %0, %1 : f32 } } return } // CHECK-DAG: %[[C100:.*]] = constant 100 // CHECK-DAG: %[[C100_0:.*]] = constant 100 // CHECK-DAG: %[[C100_1:.*]] = constant 100 // CHECK-DAG: %[[C0:.*]] = constant 0 // CHECK-DAG: %[[C0_2:.*]] = constant 0 // CHECK-DAG: %[[C0_3:.*]] = constant 0 // CHECK-DAG: %[[C10:.*]] = constant 10 // CHECK-DAG: %[[C10_4:.*]] = constant 10 // CHECK-DAG: %[[C10_5:.*]] = constant 10 // CHECK: scf.parallel (%[[arg3:.*]], %[[arg4:.*]], %[[arg5:.*]]) = (%[[C0]], %[[C0_2]], %[[C0_3]]) to (%[[C100]], %[[C100_0]], %[[C100_1]]) step (%[[C10]], %[[C10_4]], %[[C10_5]]) { // CHECK-DAG: %[[C10_6:.*]] = constant 10 // CHECK-DAG: %[[A0:.*]] = addi %[[arg3]], %[[C10_6]] // CHECK-DAG: %[[C10_7:.*]] = constant 10 // CHECK-DAG: %[[A1:.*]] = addi %[[arg4]], %[[C10_7]] // CHECK-DAG: %[[C10_8:.*]] = constant 10 // CHECK-DAG: %[[A2:.*]] = addi %[[arg5]], %[[C10_8]] // CHECK-DAG: %[[C1:.*]] = constant 1 // CHECK-DAG: %[[C1_9:.*]] = constant 1 // CHECK-DAG: %[[C1_10:.*]] = constant 1 // CHECK: scf.parallel (%[[arg6:.*]], %[[arg7:.*]], %[[arg8:.*]]) = (%[[arg3]], %[[arg4]], %[[arg5]]) to (%[[A0]], %[[A1]], %[[A2]]) step (%[[C1]], %[[C1_9]], %[[C1_10]]) { // CHECK: %[[A3:.*]] = load %[[ARG1]][%[[arg6]], %[[arg8]]] : memref<100x100xf32> // CHECK: %[[A4:.*]] = load %[[ARG2]][%[[arg8]], %[[arg7]]] : memref<100x100xf32> // CHECK: mulf %[[A3]], %[[A4]] : f32 // CHECK: scf.yield diff --git a/mlir/test/Conversion/SCFToStandard/convert-to-cfg.mlir b/mlir/test/Conversion/SCFToStandard/convert-to-cfg.mlir index c3f1325a549b..7e0671b93607 100644 --- a/mlir/test/Conversion/SCFToStandard/convert-to-cfg.mlir +++ b/mlir/test/Conversion/SCFToStandard/convert-to-cfg.mlir @@ -1,548 +1,548 @@ // RUN: mlir-opt -allow-unregistered-dialect -convert-scf-to-std %s | FileCheck %s // CHECK-LABEL: func @simple_std_for_loop(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) { // CHECK-NEXT: br ^bb1(%{{.*}} : index) // CHECK-NEXT: ^bb1(%{{.*}}: index): // 2 preds: ^bb0, ^bb2 // CHECK-NEXT: %{{.*}} = cmpi "slt", %{{.*}}, %{{.*}} : index // CHECK-NEXT: cond_br %{{.*}}, ^bb2, ^bb3 // CHECK-NEXT: ^bb2: // pred: ^bb1 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: %[[iv:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: br ^bb1(%[[iv]] : index) // CHECK-NEXT: ^bb3: // pred: ^bb1 // CHECK-NEXT: return func @simple_std_for_loop(%arg0 : index, %arg1 : index, %arg2 : index) { scf.for %i0 = %arg0 to %arg1 step %arg2 { %c1 = constant 1 : index } return } // CHECK-LABEL: func @simple_std_2_for_loops(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index) { // CHECK-NEXT: br ^bb1(%{{.*}} : index) // CHECK-NEXT: ^bb1(%[[ub0:.*]]: index): // 2 preds: ^bb0, ^bb5 // CHECK-NEXT: %[[cond0:.*]] = cmpi "slt", %[[ub0]], %{{.*}} : index // CHECK-NEXT: cond_br %[[cond0]], ^bb2, ^bb6 // CHECK-NEXT: ^bb2: // pred: ^bb1 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb3(%{{.*}} : index) // CHECK-NEXT: ^bb3(%[[ub1:.*]]: index): // 2 preds: ^bb2, ^bb4 // CHECK-NEXT: %[[cond1:.*]] = cmpi "slt", %{{.*}}, %{{.*}} : index // CHECK-NEXT: cond_br %[[cond1]], ^bb4, ^bb5 // CHECK-NEXT: ^bb4: // pred: ^bb3 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: %[[iv1:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: br ^bb3(%[[iv1]] : index) // CHECK-NEXT: ^bb5: // pred: ^bb3 // CHECK-NEXT: %[[iv0:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: br ^bb1(%[[iv0]] : index) // CHECK-NEXT: ^bb6: // pred: ^bb1 // CHECK-NEXT: return func @simple_std_2_for_loops(%arg0 : index, %arg1 : index, %arg2 : index) { scf.for %i0 = %arg0 to %arg1 step %arg2 { %c1 = constant 1 : index scf.for %i1 = %arg0 to %arg1 step %arg2 { %c1_0 = constant 1 : index } } return } // CHECK-LABEL: func @simple_std_if(%{{.*}}: i1) { // CHECK-NEXT: cond_br %{{.*}}, ^bb1, ^bb2 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb2 // CHECK-NEXT: ^bb2: // 2 preds: ^bb0, ^bb1 // CHECK-NEXT: return func @simple_std_if(%arg0: i1) { scf.if %arg0 { %c1 = constant 1 : index } return } // CHECK-LABEL: func @simple_std_if_else(%{{.*}}: i1) { // CHECK-NEXT: cond_br %{{.*}}, ^bb1, ^bb2 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb3 // CHECK-NEXT: ^bb2: // pred: ^bb0 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb3 // CHECK-NEXT: ^bb3: // 2 preds: ^bb1, ^bb2 // CHECK-NEXT: return func @simple_std_if_else(%arg0: i1) { scf.if %arg0 { %c1 = constant 1 : index } else { %c1_0 = constant 1 : index } return } // CHECK-LABEL: func @simple_std_2_ifs(%{{.*}}: i1) { // CHECK-NEXT: cond_br %{{.*}}, ^bb1, ^bb5 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: cond_br %{{.*}}, ^bb2, ^bb3 // CHECK-NEXT: ^bb2: // pred: ^bb1 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb4 // CHECK-NEXT: ^bb3: // pred: ^bb1 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb4 // CHECK-NEXT: ^bb4: // 2 preds: ^bb2, ^bb3 // CHECK-NEXT: br ^bb5 // CHECK-NEXT: ^bb5: // 2 preds: ^bb0, ^bb4 // CHECK-NEXT: return func @simple_std_2_ifs(%arg0: i1) { scf.if %arg0 { %c1 = constant 1 : index scf.if %arg0 { %c1_0 = constant 1 : index } else { %c1_1 = constant 1 : index } } return } // CHECK-LABEL: func @simple_std_for_loop_with_2_ifs(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index, %{{.*}}: i1) { // CHECK-NEXT: br ^bb1(%{{.*}} : index) // CHECK-NEXT: ^bb1(%{{.*}}: index): // 2 preds: ^bb0, ^bb7 // CHECK-NEXT: %{{.*}} = cmpi "slt", %{{.*}}, %{{.*}} : index // CHECK-NEXT: cond_br %{{.*}}, ^bb2, ^bb8 // CHECK-NEXT: ^bb2: // pred: ^bb1 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: cond_br %{{.*}}, ^bb3, ^bb7 // CHECK-NEXT: ^bb3: // pred: ^bb2 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: cond_br %{{.*}}, ^bb4, ^bb5 // CHECK-NEXT: ^bb4: // pred: ^bb3 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb6 // CHECK-NEXT: ^bb5: // pred: ^bb3 // CHECK-NEXT: %{{.*}} = constant 1 : index // CHECK-NEXT: br ^bb6 // CHECK-NEXT: ^bb6: // 2 preds: ^bb4, ^bb5 // CHECK-NEXT: br ^bb7 // CHECK-NEXT: ^bb7: // 2 preds: ^bb2, ^bb6 // CHECK-NEXT: %[[iv0:.*]] = addi %{{.*}}, %{{.*}} : index // CHECK-NEXT: br ^bb1(%[[iv0]] : index) // CHECK-NEXT: ^bb8: // pred: ^bb1 // CHECK-NEXT: return // CHECK-NEXT: } func @simple_std_for_loop_with_2_ifs(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : i1) { scf.for %i0 = %arg0 to %arg1 step %arg2 { %c1 = constant 1 : index scf.if %arg3 { %c1_0 = constant 1 : index scf.if %arg3 { %c1_1 = constant 1 : index } else { %c1_2 = constant 1 : index } } } return } // CHECK-LABEL: func @simple_if_yield func @simple_if_yield(%arg0: i1) -> (i1, i1) { // CHECK: cond_br %{{.*}}, ^[[then:.*]], ^[[else:.*]] %0:2 = scf.if %arg0 -> (i1, i1) { // CHECK: ^[[then]]: // CHECK: %[[v0:.*]] = constant false // CHECK: %[[v1:.*]] = constant true // CHECK: br ^[[dom:.*]](%[[v0]], %[[v1]] : i1, i1) %c0 = constant false %c1 = constant true scf.yield %c0, %c1 : i1, i1 } else { // CHECK: ^[[else]]: // CHECK: %[[v2:.*]] = constant false // CHECK: %[[v3:.*]] = constant true // CHECK: br ^[[dom]](%[[v3]], %[[v2]] : i1, i1) %c0 = constant false %c1 = constant true scf.yield %c1, %c0 : i1, i1 } // CHECK: ^[[dom]](%[[arg1:.*]]: i1, %[[arg2:.*]]: i1): // CHECK: br ^[[cont:.*]] // CHECK: ^[[cont]]: // CHECK: return %[[arg1]], %[[arg2]] return %0#0, %0#1 : i1, i1 } // CHECK-LABEL: func @nested_if_yield func @nested_if_yield(%arg0: i1) -> (index) { // CHECK: cond_br %{{.*}}, ^[[first_then:.*]], ^[[first_else:.*]] %0 = scf.if %arg0 -> i1 { // CHECK: ^[[first_then]]: %1 = constant true // CHECK: br ^[[first_dom:.*]]({{.*}}) scf.yield %1 : i1 } else { // CHECK: ^[[first_else]]: %2 = constant false // CHECK: br ^[[first_dom]]({{.*}}) scf.yield %2 : i1 } // CHECK: ^[[first_dom]](%[[arg1:.*]]: i1): // CHECK: br ^[[first_cont:.*]] // CHECK: ^[[first_cont]]: // CHECK: cond_br %[[arg1]], ^[[second_outer_then:.*]], ^[[second_outer_else:.*]] %1 = scf.if %0 -> index { // CHECK: ^[[second_outer_then]]: // CHECK: cond_br %arg0, ^[[second_inner_then:.*]], ^[[second_inner_else:.*]] %3 = scf.if %arg0 -> index { // CHECK: ^[[second_inner_then]]: %4 = constant 40 : index // CHECK: br ^[[second_inner_dom:.*]]({{.*}}) scf.yield %4 : index } else { // CHECK: ^[[second_inner_else]]: %5 = constant 41 : index // CHECK: br ^[[second_inner_dom]]({{.*}}) scf.yield %5 : index } // CHECK: ^[[second_inner_dom]](%[[arg2:.*]]: index): // CHECK: br ^[[second_inner_cont:.*]] // CHECK: ^[[second_inner_cont]]: // CHECK: br ^[[second_outer_dom:.*]]({{.*}}) scf.yield %3 : index } else { // CHECK: ^[[second_outer_else]]: %6 = constant 42 : index // CHECK: br ^[[second_outer_dom]]({{.*}} scf.yield %6 : index } // CHECK: ^[[second_outer_dom]](%[[arg3:.*]]: index): // CHECK: br ^[[second_outer_cont:.*]] // CHECK: ^[[second_outer_cont]]: // CHECK: return %[[arg3]] : index return %1 : index } // CHECK-LABEL: func @parallel_loop( // CHECK-SAME: [[VAL_0:%.*]]: index, [[VAL_1:%.*]]: index, [[VAL_2:%.*]]: index, [[VAL_3:%.*]]: index, [[VAL_4:%.*]]: index) { // CHECK: [[VAL_5:%.*]] = constant 1 : index // CHECK: br ^bb1([[VAL_0]] : index) // CHECK: ^bb1([[VAL_6:%.*]]: index): // CHECK: [[VAL_7:%.*]] = cmpi "slt", [[VAL_6]], [[VAL_2]] : index // CHECK: cond_br [[VAL_7]], ^bb2, ^bb6 // CHECK: ^bb2: // CHECK: br ^bb3([[VAL_1]] : index) // CHECK: ^bb3([[VAL_8:%.*]]: index): // CHECK: [[VAL_9:%.*]] = cmpi "slt", [[VAL_8]], [[VAL_3]] : index // CHECK: cond_br [[VAL_9]], ^bb4, ^bb5 // CHECK: ^bb4: // CHECK: [[VAL_10:%.*]] = constant 1 : index // CHECK: [[VAL_11:%.*]] = addi [[VAL_8]], [[VAL_5]] : index // CHECK: br ^bb3([[VAL_11]] : index) // CHECK: ^bb5: // CHECK: [[VAL_12:%.*]] = addi [[VAL_6]], [[VAL_4]] : index // CHECK: br ^bb1([[VAL_12]] : index) // CHECK: ^bb6: // CHECK: return // CHECK: } func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index) { %step = constant 1 : index scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %step) { %c1 = constant 1 : index } return } // CHECK-LABEL: @for_yield // CHECK-SAME: (%[[LB:.*]]: index, %[[UB:.*]]: index, %[[STEP:.*]]: index) // CHECK: %[[INIT0:.*]] = constant 0 // CHECK: %[[INIT1:.*]] = constant 1 // CHECK: br ^[[COND:.*]](%[[LB]], %[[INIT0]], %[[INIT1]] : index, f32, f32) // // CHECK: ^[[COND]](%[[ITER:.*]]: index, %[[ITER_ARG0:.*]]: f32, %[[ITER_ARG1:.*]]: f32): // CHECK: %[[CMP:.*]] = cmpi "slt", %[[ITER]], %[[UB]] : index // CHECK: cond_br %[[CMP]], ^[[BODY:.*]], ^[[CONTINUE:.*]] // // CHECK: ^[[BODY]]: // CHECK: %[[SUM:.*]] = addf %[[ITER_ARG0]], %[[ITER_ARG1]] : f32 // CHECK: %[[STEPPED:.*]] = addi %[[ITER]], %[[STEP]] : index // CHECK: br ^[[COND]](%[[STEPPED]], %[[SUM]], %[[SUM]] : index, f32, f32) // // CHECK: ^[[CONTINUE]]: // CHECK: return %[[ITER_ARG0]], %[[ITER_ARG1]] : f32, f32 func @for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> (f32, f32) { %s0 = constant 0.0 : f32 %s1 = constant 1.0 : f32 %result:2 = scf.for %i0 = %arg0 to %arg1 step %arg2 iter_args(%si = %s0, %sj = %s1) -> (f32, f32) { %sn = addf %si, %sj : f32 scf.yield %sn, %sn : f32, f32 } return %result#0, %result#1 : f32, f32 } // CHECK-LABEL: @nested_for_yield // CHECK-SAME: (%[[LB:.*]]: index, %[[UB:.*]]: index, %[[STEP:.*]]: index) // CHECK: %[[INIT:.*]] = constant // CHECK: br ^[[COND_OUT:.*]](%[[LB]], %[[INIT]] : index, f32) // CHECK: ^[[COND_OUT]](%[[ITER_OUT:.*]]: index, %[[ARG_OUT:.*]]: f32): // CHECK: cond_br %{{.*}}, ^[[BODY_OUT:.*]], ^[[CONT_OUT:.*]] // CHECK: ^[[BODY_OUT]]: // CHECK: br ^[[COND_IN:.*]](%[[LB]], %[[ARG_OUT]] : index, f32) // CHECK: ^[[COND_IN]](%[[ITER_IN:.*]]: index, %[[ARG_IN:.*]]: f32): // CHECK: cond_br %{{.*}}, ^[[BODY_IN:.*]], ^[[CONT_IN:.*]] // CHECK: ^[[BODY_IN]] // CHECK: %[[RES:.*]] = addf // CHECK: br ^[[COND_IN]](%{{.*}}, %[[RES]] : index, f32) // CHECK: ^[[CONT_IN]]: // CHECK: br ^[[COND_OUT]](%{{.*}}, %[[ARG_IN]] : index, f32) // CHECK: ^[[CONT_OUT]]: // CHECK: return %[[ARG_OUT]] : f32 func @nested_for_yield(%arg0 : index, %arg1 : index, %arg2 : index) -> f32 { %s0 = constant 1.0 : f32 %r = scf.for %i0 = %arg0 to %arg1 step %arg2 iter_args(%iter = %s0) -> (f32) { %result = scf.for %i1 = %arg0 to %arg1 step %arg2 iter_args(%si = %iter) -> (f32) { %sn = addf %si, %si : f32 scf.yield %sn : f32 } scf.yield %result : f32 } return %r : f32 } -func @generate() -> i64 +func private @generate() -> i64 // CHECK-LABEL: @simple_parallel_reduce_loop // CHECK-SAME: %[[LB:.*]]: index, %[[UB:.*]]: index, %[[STEP:.*]]: index, %[[INIT:.*]]: f32 func @simple_parallel_reduce_loop(%arg0: index, %arg1: index, %arg2: index, %arg3: f32) -> f32 { // A parallel loop with reduction is converted through sequential loops with // reductions into a CFG of blocks where the partially reduced value is // passed across as a block argument. // Branch to the condition block passing in the initial reduction value. // CHECK: br ^[[COND:.*]](%[[LB]], %[[INIT]] // Condition branch takes as arguments the current value of the iteration // variable and the current partially reduced value. // CHECK: ^[[COND]](%[[ITER:.*]]: index, %[[ITER_ARG:.*]]: f32 // CHECK: %[[COMP:.*]] = cmpi "slt", %[[ITER]], %[[UB]] // CHECK: cond_br %[[COMP]], ^[[BODY:.*]], ^[[CONTINUE:.*]] // Bodies of scf.reduce operations are folded into the main loop body. The // result of this partial reduction is passed as argument to the condition // block. // CHECK: ^[[BODY]]: // CHECK: %[[CST:.*]] = constant 4.2 // CHECK: %[[PROD:.*]] = mulf %[[ITER_ARG]], %[[CST]] // CHECK: %[[INCR:.*]] = addi %[[ITER]], %[[STEP]] // CHECK: br ^[[COND]](%[[INCR]], %[[PROD]] // The continuation block has access to the (last value of) reduction. // CHECK: ^[[CONTINUE]]: // CHECK: return %[[ITER_ARG]] %0 = scf.parallel (%i) = (%arg0) to (%arg1) step (%arg2) init(%arg3) -> f32 { %cst = constant 42.0 : f32 scf.reduce(%cst) : f32 { ^bb0(%lhs: f32, %rhs: f32): %1 = mulf %lhs, %rhs : f32 scf.reduce.return %1 : f32 } } return %0 : f32 } // CHECK-LABEL: parallel_reduce_loop // CHECK-SAME: %[[INIT1:[0-9A-Za-z_]*]]: f32) func @parallel_reduce_loop(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index, %arg4 : index, %arg5 : f32) -> (f32, i64) { // Multiple reduction blocks should be folded in the same body, and the // reduction value must be forwarded through block structures. // CHECK: %[[INIT2:.*]] = constant 42 // CHECK: br ^[[COND_OUT:.*]](%{{.*}}, %[[INIT1]], %[[INIT2]] // CHECK: ^[[COND_OUT]](%{{.*}}: index, %[[ITER_ARG1_OUT:.*]]: f32, %[[ITER_ARG2_OUT:.*]]: i64 // CHECK: cond_br %{{.*}}, ^[[BODY_OUT:.*]], ^[[CONT_OUT:.*]] // CHECK: ^[[BODY_OUT]]: // CHECK: br ^[[COND_IN:.*]](%{{.*}}, %[[ITER_ARG1_OUT]], %[[ITER_ARG2_OUT]] // CHECK: ^[[COND_IN]](%{{.*}}: index, %[[ITER_ARG1_IN:.*]]: f32, %[[ITER_ARG2_IN:.*]]: i64 // CHECK: cond_br %{{.*}}, ^[[BODY_IN:.*]], ^[[CONT_IN:.*]] // CHECK: ^[[BODY_IN]]: // CHECK: %[[REDUCE1:.*]] = addf %[[ITER_ARG1_IN]], %{{.*}} // CHECK: %[[REDUCE2:.*]] = or %[[ITER_ARG2_IN]], %{{.*}} // CHECK: br ^[[COND_IN]](%{{.*}}, %[[REDUCE1]], %[[REDUCE2]] // CHECK: ^[[CONT_IN]]: // CHECK: br ^[[COND_OUT]](%{{.*}}, %[[ITER_ARG1_IN]], %[[ITER_ARG2_IN]] // CHECK: ^[[CONT_OUT]]: // CHECK: return %[[ITER_ARG1_OUT]], %[[ITER_ARG2_OUT]] %step = constant 1 : index %init = constant 42 : i64 %0:2 = scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%arg4, %step) init(%arg5, %init) -> (f32, i64) { %cf = constant 42.0 : f32 scf.reduce(%cf) : f32 { ^bb0(%lhs: f32, %rhs: f32): %1 = addf %lhs, %rhs : f32 scf.reduce.return %1 : f32 } %2 = call @generate() : () -> i64 scf.reduce(%2) : i64 { ^bb0(%lhs: i64, %rhs: i64): %3 = or %lhs, %rhs : i64 scf.reduce.return %3 : i64 } } return %0#0, %0#1 : f32, i64 } // Check that the conversion is not overly conservative wrt unknown ops, i.e. // that the presence of unknown ops does not prevent the conversion from being // applied. // CHECK-LABEL: @unknown_op_inside_loop func @unknown_op_inside_loop(%arg0: index, %arg1: index, %arg2: index) { // CHECK-NOT: scf.for scf.for %i = %arg0 to %arg1 step %arg2 { // CHECK: unknown.op "unknown.op"() : () -> () scf.yield } return } // CHECK-LABEL: @minimal_while func @minimal_while() { // CHECK: %[[COND:.*]] = "test.make_condition"() : () -> i1 // CHECK: br ^[[BEFORE:.*]] %0 = "test.make_condition"() : () -> i1 scf.while : () -> () { // CHECK: ^[[BEFORE]]: // CHECK: cond_br %[[COND]], ^[[AFTER:.*]], ^[[CONT:.*]] scf.condition(%0) } do { // CHECK: ^[[AFTER]]: // CHECK: "test.some_payload"() : () -> () "test.some_payload"() : () -> () // CHECK: br ^[[BEFORE]] scf.yield } // CHECK: ^[[CONT]]: // CHECK: return return } // CHECK-LABEL: @do_while func @do_while(%arg0: f32) { // CHECK: br ^[[BEFORE:.*]]({{.*}}: f32) scf.while (%arg1 = %arg0) : (f32) -> (f32) { // CHECK: ^[[BEFORE]](%[[VAL:.*]]: f32): // CHECK: %[[COND:.*]] = "test.make_condition"() : () -> i1 %0 = "test.make_condition"() : () -> i1 // CHECK: cond_br %[[COND]], ^[[BEFORE]](%[[VAL]] : f32), ^[[CONT:.*]] scf.condition(%0) %arg1 : f32 } do { ^bb0(%arg2: f32): // CHECK-NOT: br ^[[BEFORE]] scf.yield %arg2 : f32 } // CHECK: ^[[CONT]]: // CHECK: return return } // CHECK-LABEL: @while_values // CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: f32) func @while_values(%arg0: i32, %arg1: f32) { // CHECK: %[[COND:.*]] = "test.make_condition"() : () -> i1 %0 = "test.make_condition"() : () -> i1 %c0_i32 = constant 0 : i32 %cst = constant 0.000000e+00 : f32 // CHECK: br ^[[BEFORE:.*]](%[[ARG0]], %[[ARG1]] : i32, f32) %1:2 = scf.while (%arg2 = %arg0, %arg3 = %arg1) : (i32, f32) -> (i64, f64) { // CHECK: ^bb1(%[[ARG2:.*]]: i32, %[[ARG3:.]]: f32): // CHECK: %[[VAL1:.*]] = zexti %[[ARG0]] : i32 to i64 %2 = zexti %arg0 : i32 to i64 // CHECK: %[[VAL2:.*]] = fpext %[[ARG3]] : f32 to f64 %3 = fpext %arg3 : f32 to f64 // CHECK: cond_br %[[COND]], // CHECK: ^[[AFTER:.*]](%[[VAL1]], %[[VAL2]] : i64, f64), // CHECK: ^[[CONT:.*]] scf.condition(%0) %2, %3 : i64, f64 } do { // CHECK: ^[[AFTER]](%[[ARG4:.*]]: i64, %[[ARG5:.*]]: f64): ^bb0(%arg2: i64, %arg3: f64): // no predecessors // CHECK: br ^[[BEFORE]](%{{.*}}, %{{.*}} : i32, f32) scf.yield %c0_i32, %cst : i32, f32 } // CHECK: ^bb3: // CHECK: return return } // CHECK-LABEL: @nested_while_ops func @nested_while_ops(%arg0: f32) -> i64 { // CHECK: br ^[[OUTER_BEFORE:.*]](%{{.*}} : f32) %0 = scf.while(%outer = %arg0) : (f32) -> i64 { // CHECK: ^[[OUTER_BEFORE]](%{{.*}}: f32): // CHECK: %[[OUTER_COND:.*]] = "test.outer_before_pre"() : () -> i1 %cond = "test.outer_before_pre"() : () -> i1 // CHECK: br ^[[INNER_BEFORE_BEFORE:.*]](%{{.*}} : f32) %1 = scf.while(%inner = %outer) : (f32) -> i64 { // CHECK: ^[[INNER_BEFORE_BEFORE]](%{{.*}}: f32): // CHECK: %[[INNER1:.*]]:2 = "test.inner_before"(%{{.*}}) : (f32) -> (i1, i64) %2:2 = "test.inner_before"(%inner) : (f32) -> (i1, i64) // CHECK: cond_br %[[INNER1]]#0, // CHECK: ^[[INNER_BEFORE_AFTER:.*]](%[[INNER1]]#1 : i64), // CHECK: ^[[OUTER_BEFORE_LAST:.*]] scf.condition(%2#0) %2#1 : i64 } do { // CHECK: ^[[INNER_BEFORE_AFTER]](%{{.*}}: i64): ^bb0(%arg1: i64): // CHECK: %[[INNER2:.*]] = "test.inner_after"(%{{.*}}) : (i64) -> f32 %3 = "test.inner_after"(%arg1) : (i64) -> f32 // CHECK: br ^[[INNER_BEFORE_BEFORE]](%[[INNER2]] : f32) scf.yield %3 : f32 } // CHECK: ^[[OUTER_BEFORE_LAST]]: // CHECK: "test.outer_before_post"() : () -> () "test.outer_before_post"() : () -> () // CHECK: cond_br %[[OUTER_COND]], // CHECK: ^[[OUTER_AFTER:.*]](%[[INNER1]]#1 : i64), // CHECK: ^[[CONTINUATION:.*]] scf.condition(%cond) %1 : i64 } do { // CHECK: ^[[OUTER_AFTER]](%{{.*}}: i64): ^bb2(%arg2: i64): // CHECK: "test.outer_after_pre"(%{{.*}}) : (i64) -> () "test.outer_after_pre"(%arg2) : (i64) -> () // CHECK: br ^[[INNER_AFTER_BEFORE:.*]](%{{.*}} : i64) %4 = scf.while(%inner = %arg2) : (i64) -> f32 { // CHECK: ^[[INNER_AFTER_BEFORE]](%{{.*}}: i64): // CHECK: %[[INNER3:.*]]:2 = "test.inner2_before"(%{{.*}}) : (i64) -> (i1, f32) %5:2 = "test.inner2_before"(%inner) : (i64) -> (i1, f32) // CHECK: cond_br %[[INNER3]]#0, // CHECK: ^[[INNER_AFTER_AFTER:.*]](%[[INNER3]]#1 : f32), // CHECK: ^[[OUTER_AFTER_LAST:.*]] scf.condition(%5#0) %5#1 : f32 } do { // CHECK: ^[[INNER_AFTER_AFTER]](%{{.*}}: f32): ^bb3(%arg3: f32): // CHECK: %{{.*}} = "test.inner2_after"(%{{.*}}) : (f32) -> i64 %6 = "test.inner2_after"(%arg3) : (f32) -> i64 // CHECK: br ^[[INNER_AFTER_BEFORE]](%{{.*}} : i64) scf.yield %6 : i64 } // CHECK: ^[[OUTER_AFTER_LAST]]: // CHECK: "test.outer_after_post"() : () -> () "test.outer_after_post"() : () -> () // CHECK: br ^[[OUTER_BEFORE]](%[[INNER3]]#1 : f32) scf.yield %4 : f32 } // CHECK: ^[[CONTINUATION]]: // CHECK: return %{{.*}} : i64 return %0 : i64 } diff --git a/mlir/test/Conversion/StandardToLLVM/calling-convention.mlir b/mlir/test/Conversion/StandardToLLVM/calling-convention.mlir index 4c318c14a95e..238cd39577b8 100644 --- a/mlir/test/Conversion/StandardToLLVM/calling-convention.mlir +++ b/mlir/test/Conversion/StandardToLLVM/calling-convention.mlir @@ -1,242 +1,242 @@ // RUN: mlir-opt -convert-std-to-llvm='emit-c-wrappers=1' %s | FileCheck %s // RUN: mlir-opt -convert-std-to-llvm %s | FileCheck %s --check-prefix=EMIT_C_ATTRIBUTE // This tests the default memref calling convention and the emission of C // wrappers. We don't need to separate runs because the wrapper-emission // version subsumes the calling convention and only adds new functions, that we // can also file-check in the same run. // An external function is transformed into the glue around calling an interface function. // CHECK-LABEL: @external // CHECK: %[[ALLOC0:.*]]: !llvm.ptr, %[[ALIGN0:.*]]: !llvm.ptr, %[[OFFSET0:.*]]: !llvm.i64, %[[SIZE00:.*]]: !llvm.i64, %[[SIZE01:.*]]: !llvm.i64, %[[STRIDE00:.*]]: !llvm.i64, %[[STRIDE01:.*]]: !llvm.i64, // CHECK: %[[ALLOC1:.*]]: !llvm.ptr, %[[ALIGN1:.*]]: !llvm.ptr, %[[OFFSET1:.*]]: !llvm.i64) -func @external(%arg0: memref, %arg1: memref) +func private @external(%arg0: memref, %arg1: memref) // Populate the descriptor for arg0. // CHECK: %[[DESC00:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC01:.*]] = llvm.insertvalue %arg0, %[[DESC00]][0] // CHECK: %[[DESC02:.*]] = llvm.insertvalue %arg1, %[[DESC01]][1] // CHECK: %[[DESC03:.*]] = llvm.insertvalue %arg2, %[[DESC02]][2] // CHECK: %[[DESC04:.*]] = llvm.insertvalue %arg3, %[[DESC03]][3, 0] // CHECK: %[[DESC05:.*]] = llvm.insertvalue %arg5, %[[DESC04]][4, 0] // CHECK: %[[DESC06:.*]] = llvm.insertvalue %arg4, %[[DESC05]][3, 1] // CHECK: %[[DESC07:.*]] = llvm.insertvalue %arg6, %[[DESC06]][4, 1] // Allocate on stack and store to comply with C calling convention. // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : index) // CHECK: %[[DESC0_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.store %[[DESC07]], %[[DESC0_ALLOCA]] // Populate the descriptor for arg1. // CHECK: %[[DESC10:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64)> // CHECK: %[[DESC11:.*]] = llvm.insertvalue %arg7, %[[DESC10]][0] : !llvm.struct<(ptr, ptr, i64)> // CHECK: %[[DESC12:.*]] = llvm.insertvalue %arg8, %[[DESC11]][1] : !llvm.struct<(ptr, ptr, i64)> // CHECK: %[[DESC13:.*]] = llvm.insertvalue %arg9, %[[DESC12]][2] : !llvm.struct<(ptr, ptr, i64)> // Allocate on stack and store to comply with C calling convention. // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : index) // CHECK: %[[DESC1_ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr, ptr, i64)> // CHECK: llvm.store %[[DESC13]], %[[DESC1_ALLOCA]] // Call the interface function. // CHECK: llvm.call @_mlir_ciface_external // Verify that an interface function is emitted. // CHECK-LABEL: llvm.func @_mlir_ciface_external // CHECK: (!llvm.ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>>, !llvm.ptr, ptr, i64)>>) // Verify that the return value is not affected. // CHECK-LABEL: @returner // CHECK: -> !llvm.struct<(struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)>, struct<(ptr, ptr, i64)>)> -func @returner() -> (memref, memref) +func private @returner() -> (memref, memref) // CHECK-LABEL: @caller func @caller() { %0:2 = call @returner() : () -> (memref, memref) // Extract individual values from the descriptor for the first memref. // CHECK: %[[ALLOC0:.*]] = llvm.extractvalue %[[DESC0:.*]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[ALIGN0:.*]] = llvm.extractvalue %[[DESC0]][1] // CHECK: %[[OFFSET0:.*]] = llvm.extractvalue %[[DESC0]][2] // CHECK: %[[SIZE00:.*]] = llvm.extractvalue %[[DESC0]][3, 0] // CHECK: %[[SIZE01:.*]] = llvm.extractvalue %[[DESC0]][3, 1] // CHECK: %[[STRIDE00:.*]] = llvm.extractvalue %[[DESC0]][4, 0] // CHECK: %[[STRIDE01:.*]] = llvm.extractvalue %[[DESC0]][4, 1] // Extract individual values from the descriptor for the second memref. // CHECK: %[[ALLOC1:.*]] = llvm.extractvalue %[[DESC1:.*]][0] : !llvm.struct<(ptr, ptr, i64)> // CHECK: %[[ALIGN1:.*]] = llvm.extractvalue %[[DESC1]][1] // CHECK: %[[OFFSET1:.*]] = llvm.extractvalue %[[DESC1]][2] // Forward the values to the call. // CHECK: llvm.call @external(%[[ALLOC0]], %[[ALIGN0]], %[[OFFSET0]], %[[SIZE00]], %[[SIZE01]], %[[STRIDE00]], %[[STRIDE01]], %[[ALLOC1]], %[[ALIGN1]], %[[OFFSET1]]) : (!llvm.ptr, !llvm.ptr, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.ptr, !llvm.ptr, !llvm.i64) -> () call @external(%0#0, %0#1) : (memref, memref) -> () return } // CHECK-LABEL: @callee // EMIT_C_ATTRIBUTE-LABEL: @callee func @callee(%arg0: memref, %arg1: index) { %0 = load %arg0[%arg1] : memref return } // Verify that an interface function is emitted. // CHECK-LABEL: @_mlir_ciface_callee // CHECK: %[[ARG0:.*]]: !llvm.ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>> // Load the memref descriptor pointer. // CHECK: %[[DESC:.*]] = llvm.load %[[ARG0]] : !llvm.ptr, ptr, i64, array<1 x i64>, array<1 x i64>)>> // Extract individual components of the descriptor. // CHECK: %[[ALLOC:.*]] = llvm.extractvalue %[[DESC]][0] // CHECK: %[[ALIGN:.*]] = llvm.extractvalue %[[DESC]][1] // CHECK: %[[OFFSET:.*]] = llvm.extractvalue %[[DESC]][2] // CHECK: %[[SIZE:.*]] = llvm.extractvalue %[[DESC]][3, 0] // CHECK: %[[STRIDE:.*]] = llvm.extractvalue %[[DESC]][4, 0] // Forward the descriptor components to the call. // CHECK: llvm.call @callee(%[[ALLOC]], %[[ALIGN]], %[[OFFSET]], %[[SIZE]], %[[STRIDE]], %{{.*}}) : (!llvm.ptr, !llvm.ptr, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64) -> () // EMIT_C_ATTRIBUTE-NOT: @mlir_ciface_callee // CHECK-LABEL: @other_callee // EMIT_C_ATTRIBUTE-LABEL: @other_callee func @other_callee(%arg0: memref, %arg1: index) attributes { llvm.emit_c_interface } { %0 = load %arg0[%arg1] : memref return } // CHECK: @_mlir_ciface_other_callee // CHECK: llvm.call @other_callee // EMIT_C_ATTRIBUTE: @_mlir_ciface_other_callee // EMIT_C_ATTRIBUTE: llvm.call @other_callee //===========================================================================// // Calling convention on returning unranked memrefs. //===========================================================================// // CHECK-LABEL: llvm.func @return_var_memref_caller func @return_var_memref_caller(%arg0: memref<4x3xf32>) { // CHECK: %[[CALL_RES:.*]] = llvm.call @return_var_memref %0 = call @return_var_memref(%arg0) : (memref<4x3xf32>) -> memref<*xf32> // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : index) // CHECK: %[[TWO:.*]] = llvm.mlir.constant(2 : index) // These sizes may depend on the data layout, not matching specific values. // CHECK: %[[PTR_SIZE:.*]] = llvm.mlir.constant // CHECK: %[[IDX_SIZE:.*]] = llvm.mlir.constant // CHECK: %[[DOUBLE_PTR_SIZE:.*]] = llvm.mul %[[TWO]], %[[PTR_SIZE]] // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[DOUBLE_RANK:.*]] = llvm.mul %[[TWO]], %[[RANK]] // CHECK: %[[DOUBLE_RANK_INC:.*]] = llvm.add %[[DOUBLE_RANK]], %[[ONE]] // CHECK: %[[TABLES_SIZE:.*]] = llvm.mul %[[DOUBLE_RANK_INC]], %[[IDX_SIZE]] // CHECK: %[[ALLOC_SIZE:.*]] = llvm.add %[[DOUBLE_PTR_SIZE]], %[[TABLES_SIZE]] // CHECK: %[[FALSE:.*]] = llvm.mlir.constant(false) // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOC_SIZE]] x !llvm.i8 // CHECK: %[[SOURCE:.*]] = llvm.extractvalue %[[CALL_RES]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[SOURCE]], %[[ALLOC_SIZE]], %[[FALSE]]) // CHECK: llvm.call @free(%[[SOURCE]]) // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[CALL_RES]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %[[RANK]], %[[DESC]][0] // CHECK: llvm.insertvalue %[[ALLOCA]], %[[DESC_1]][1] return } // CHECK-LABEL: llvm.func @return_var_memref func @return_var_memref(%arg0: memref<4x3xf32>) -> memref<*xf32> { // Match the construction of the unranked descriptor. // CHECK: %[[ALLOCA:.*]] = llvm.alloca // CHECK: %[[MEMORY:.*]] = llvm.bitcast %[[ALLOCA]] // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %{{.*}}, %[[DESC_0]][0] // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[MEMORY]], %[[DESC_1]][1] %0 = memref_cast %arg0: memref<4x3xf32> to memref<*xf32> // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : index) // CHECK: %[[TWO:.*]] = llvm.mlir.constant(2 : index) // These sizes may depend on the data layout, not matching specific values. // CHECK: %[[PTR_SIZE:.*]] = llvm.mlir.constant // CHECK: %[[IDX_SIZE:.*]] = llvm.mlir.constant // CHECK: %[[DOUBLE_PTR_SIZE:.*]] = llvm.mul %[[TWO]], %[[PTR_SIZE]] // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[DESC_2]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[DOUBLE_RANK:.*]] = llvm.mul %[[TWO]], %[[RANK]] // CHECK: %[[DOUBLE_RANK_INC:.*]] = llvm.add %[[DOUBLE_RANK]], %[[ONE]] // CHECK: %[[TABLES_SIZE:.*]] = llvm.mul %[[DOUBLE_RANK_INC]], %[[IDX_SIZE]] // CHECK: %[[ALLOC_SIZE:.*]] = llvm.add %[[DOUBLE_PTR_SIZE]], %[[TABLES_SIZE]] // CHECK: %[[FALSE:.*]] = llvm.mlir.constant(false) // CHECK: %[[ALLOCATED:.*]] = llvm.call @malloc(%[[ALLOC_SIZE]]) // CHECK: %[[SOURCE:.*]] = llvm.extractvalue %[[DESC_2]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED]], %[[SOURCE]], %[[ALLOC_SIZE]], %[[FALSE]]) // CHECK: %[[NEW_DESC:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[RANK:.*]] = llvm.extractvalue %[[DESC_2]][0] : !llvm.struct<(i64, ptr)> // CHECK: %[[NEW_DESC_1:.*]] = llvm.insertvalue %[[RANK]], %[[NEW_DESC]][0] // CHECK: %[[NEW_DESC_2:.*]] = llvm.insertvalue %[[ALLOCATED]], %[[NEW_DESC_1]][1] // CHECK: llvm.return %[[NEW_DESC_2]] return %0 : memref<*xf32> } // CHECK-LABEL: llvm.func @return_two_var_memref_caller func @return_two_var_memref_caller(%arg0: memref<4x3xf32>) { // Only check that we create two different descriptors using different // memory, and deallocate both sources. The size computation is same as for // the single result. // CHECK: %[[CALL_RES:.*]] = llvm.call @return_two_var_memref // CHECK: %[[RES_1:.*]] = llvm.extractvalue %[[CALL_RES]][0] // CHECK: %[[RES_2:.*]] = llvm.extractvalue %[[CALL_RES]][1] %0:2 = call @return_two_var_memref(%arg0) : (memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) // CHECK: %[[ALLOCA_1:.*]] = llvm.alloca %{{.*}} x !llvm.i8 // CHECK: %[[SOURCE_1:.*]] = llvm.extractvalue %[[RES_1:.*]][1] : ![[DESC_TYPE:.*]] // CHECK: "llvm.intr.memcpy"(%[[ALLOCA_1]], %[[SOURCE_1]], %{{.*}}, %[[FALSE:.*]]) // CHECK: llvm.call @free(%[[SOURCE_1]]) // CHECK: %[[DESC_1:.*]] = llvm.mlir.undef : ![[DESC_TYPE]] // CHECK: %[[DESC_11:.*]] = llvm.insertvalue %{{.*}}, %[[DESC_1]][0] // CHECK: llvm.insertvalue %[[ALLOCA_1]], %[[DESC_11]][1] // CHECK: %[[ALLOCA_2:.*]] = llvm.alloca %{{.*}} x !llvm.i8 // CHECK: %[[SOURCE_2:.*]] = llvm.extractvalue %[[RES_2:.*]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCA_2]], %[[SOURCE_2]], %{{.*}}, %[[FALSE]]) // CHECK: llvm.call @free(%[[SOURCE_2]]) // CHECK: %[[DESC_2:.*]] = llvm.mlir.undef : ![[DESC_TYPE]] // CHECK: %[[DESC_21:.*]] = llvm.insertvalue %{{.*}}, %[[DESC_2]][0] // CHECK: llvm.insertvalue %[[ALLOCA_2]], %[[DESC_21]][1] return } // CHECK-LABEL: llvm.func @return_two_var_memref func @return_two_var_memref(%arg0: memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) { // Match the construction of the unranked descriptor. // CHECK: %[[ALLOCA:.*]] = llvm.alloca // CHECK: %[[MEMORY:.*]] = llvm.bitcast %[[ALLOCA]] // CHECK: %[[DESC_0:.*]] = llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK: %[[DESC_1:.*]] = llvm.insertvalue %{{.*}}, %[[DESC_0]][0] // CHECK: %[[DESC_2:.*]] = llvm.insertvalue %[[MEMORY]], %[[DESC_1]][1] %0 = memref_cast %arg0 : memref<4x3xf32> to memref<*xf32> // Only check that we allocate the memory for each operand of the "return" // separately, even if both operands are the same value. The calling // convention requires the caller to free them and the caller cannot know // whether they are the same value or not. // CHECK: %[[ALLOCATED_1:.*]] = llvm.call @malloc(%{{.*}}) // CHECK: %[[SOURCE_1:.*]] = llvm.extractvalue %[[DESC_2]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_1]], %[[SOURCE_1]], %{{.*}}, %[[FALSE:.*]]) // CHECK: %[[RES_1:.*]] = llvm.mlir.undef // CHECK: %[[RES_11:.*]] = llvm.insertvalue %{{.*}}, %[[RES_1]][0] // CHECK: %[[RES_12:.*]] = llvm.insertvalue %[[ALLOCATED_1]], %[[RES_11]][1] // CHECK: %[[ALLOCATED_2:.*]] = llvm.call @malloc(%{{.*}}) // CHECK: %[[SOURCE_2:.*]] = llvm.extractvalue %[[DESC_2]][1] // CHECK: "llvm.intr.memcpy"(%[[ALLOCATED_2]], %[[SOURCE_2]], %{{.*}}, %[[FALSE]]) // CHECK: %[[RES_2:.*]] = llvm.mlir.undef // CHECK: %[[RES_21:.*]] = llvm.insertvalue %{{.*}}, %[[RES_2]][0] // CHECK: %[[RES_22:.*]] = llvm.insertvalue %[[ALLOCATED_2]], %[[RES_21]][1] // CHECK: %[[RESULTS:.*]] = llvm.mlir.undef : !llvm.struct<(struct<(i64, ptr)>, struct<(i64, ptr)>)> // CHECK: %[[RESULTS_1:.*]] = llvm.insertvalue %[[RES_12]], %[[RESULTS]] // CHECK: %[[RESULTS_2:.*]] = llvm.insertvalue %[[RES_22]], %[[RESULTS_1]] // CHECK: llvm.return %[[RESULTS_2]] return %0, %0 : memref<*xf32>, memref<*xf32> } diff --git a/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir b/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir index d2a88ed952f7..6d2419692750 100644 --- a/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir +++ b/mlir/test/Conversion/StandardToLLVM/convert-funcs.mlir @@ -1,61 +1,61 @@ // RUN: mlir-opt -convert-std-to-llvm %s | FileCheck %s //CHECK: llvm.func @second_order_arg(!llvm.ptr>) -func @second_order_arg(%arg0 : () -> ()) +func private @second_order_arg(%arg0 : () -> ()) //CHECK: llvm.func @second_order_result() -> !llvm.ptr> -func @second_order_result() -> (() -> ()) +func private @second_order_result() -> (() -> ()) //CHECK: llvm.func @second_order_multi_result() -> !llvm.struct<(ptr>, ptr>, ptr>)> -func @second_order_multi_result() -> (() -> (i32), () -> (i64), () -> (f32)) +func private @second_order_multi_result() -> (() -> (i32), () -> (i64), () -> (f32)) //CHECK: llvm.func @third_order(!llvm.ptr> (ptr>)>>) -> !llvm.ptr> (ptr>)>> -func @third_order(%arg0 : (() -> ()) -> (() -> ())) -> ((() -> ()) -> (() -> ())) +func private @third_order(%arg0 : (() -> ()) -> (() -> ())) -> ((() -> ()) -> (() -> ())) //CHECK: llvm.func @fifth_order_left(!llvm.ptr>)>>)>>)>>) -func @fifth_order_left(%arg0: (((() -> ()) -> ()) -> ()) -> ()) +func private @fifth_order_left(%arg0: (((() -> ()) -> ()) -> ()) -> ()) //CHECK: llvm.func @fifth_order_right(!llvm.ptr> ()>> ()>> ()>>) -func @fifth_order_right(%arg0: () -> (() -> (() -> (() -> ())))) +func private @fifth_order_right(%arg0: () -> (() -> (() -> (() -> ())))) // Check that memrefs are converted to argument packs if appear as function arguments. // CHECK: llvm.func @memref_call_conv(!llvm.ptr, !llvm.ptr, !llvm.i64, !llvm.i64, !llvm.i64) -func @memref_call_conv(%arg0: memref) +func private @memref_call_conv(%arg0: memref) // Same in nested functions. // CHECK: llvm.func @memref_call_conv_nested(!llvm.ptr, ptr, i64, i64, i64)>>) -func @memref_call_conv_nested(%arg0: (memref) -> ()) +func private @memref_call_conv_nested(%arg0: (memref) -> ()) //CHECK-LABEL: llvm.func @pass_through(%arg0: !llvm.ptr>) -> !llvm.ptr> { func @pass_through(%arg0: () -> ()) -> (() -> ()) { // CHECK-NEXT: llvm.br ^bb1(%arg0 : !llvm.ptr>) br ^bb1(%arg0 : () -> ()) //CHECK-NEXT: ^bb1(%0: !llvm.ptr>): ^bb1(%bbarg: () -> ()): // CHECK-NEXT: llvm.return %0 : !llvm.ptr> return %bbarg : () -> () } // CHECK-LABEL: llvm.func @body(!llvm.i32) -func @body(i32) +func private @body(i32) // CHECK-LABEL: llvm.func @indirect_const_call // CHECK-SAME: (%[[ARG0:.*]]: !llvm.i32) { func @indirect_const_call(%arg0: i32) { // CHECK-NEXT: %[[ADDR:.*]] = llvm.mlir.addressof @body : !llvm.ptr> %0 = constant @body : (i32) -> () // CHECK-NEXT: llvm.call %[[ADDR]](%[[ARG0:.*]]) : (!llvm.i32) -> () call_indirect %0(%arg0) : (i32) -> () // CHECK-NEXT: llvm.return return } // CHECK-LABEL: llvm.func @indirect_call(%arg0: !llvm.ptr>, %arg1: !llvm.float) -> !llvm.i32 { func @indirect_call(%arg0: (f32) -> i32, %arg1: f32) -> i32 { // CHECK-NEXT: %0 = llvm.call %arg0(%arg1) : (!llvm.float) -> !llvm.i32 %0 = call_indirect %arg0(%arg1) : (f32) -> i32 // CHECK-NEXT: llvm.return %0 : !llvm.i32 return %0 : i32 } diff --git a/mlir/test/Conversion/StandardToLLVM/convert-static-memref-ops.mlir b/mlir/test/Conversion/StandardToLLVM/convert-static-memref-ops.mlir index d9d93b7823b8..956e1fcf692b 100644 --- a/mlir/test/Conversion/StandardToLLVM/convert-static-memref-ops.mlir +++ b/mlir/test/Conversion/StandardToLLVM/convert-static-memref-ops.mlir @@ -1,443 +1,443 @@ // RUN: mlir-opt -convert-std-to-llvm %s | FileCheck %s // RUN: mlir-opt -convert-std-to-llvm='use-bare-ptr-memref-call-conv=1' -split-input-file %s | FileCheck %s --check-prefix=BAREPTR // BAREPTR-LABEL: func @check_noalias // BAREPTR-SAME: %{{.*}}: !llvm.ptr {llvm.noalias = true}, %{{.*}}: !llvm.ptr {llvm.noalias = true} func @check_noalias(%static : memref<2xf32> {llvm.noalias = true}, %other : memref<2xf32> {llvm.noalias = true}) { return } // ----- // CHECK-LABEL: func @check_static_return // CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: !llvm.i64 // CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-LABEL: func @check_static_return // BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { func @check_static_return(%static : memref<32x18xf32>) -> memref<32x18xf32> { // CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val2:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val3:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val4:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr return %static : memref<32x18xf32> } // ----- // CHECK-LABEL: func @check_static_return_with_offset // CHECK-COUNT-2: !llvm.ptr // CHECK-COUNT-5: !llvm.i64 // CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-LABEL: func @check_static_return_with_offset // BAREPTR-SAME: (%[[arg:.*]]: !llvm.ptr) -> !llvm.ptr { func @check_static_return_with_offset(%static : memref<32x18xf32, offset:7, strides:[22,1]>) -> memref<32x18xf32, offset:7, strides:[22,1]> { // CHECK: llvm.return %{{.*}} : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR: %[[udf:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[base0:.*]] = llvm.insertvalue %[[arg]], %[[udf]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[aligned:.*]] = llvm.insertvalue %[[arg]], %[[base0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val0:.*]] = llvm.mlir.constant(7 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins0:.*]] = llvm.insertvalue %[[val0]], %[[aligned]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins1:.*]] = llvm.insertvalue %[[val1]], %[[ins0]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val2:.*]] = llvm.mlir.constant(22 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins2:.*]] = llvm.insertvalue %[[val2]], %[[ins1]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val3:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins3:.*]] = llvm.insertvalue %[[val3]], %[[ins2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[val4:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[ins4:.*]] = llvm.insertvalue %[[val4]], %[[ins3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[base1:.*]] = llvm.extractvalue %[[ins4]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: llvm.return %[[base1]] : !llvm.ptr return %static : memref<32x18xf32, offset:7, strides:[22,1]> } // ----- // CHECK-LABEL: func @zero_d_alloc() -> !llvm.struct<(ptr, ptr, i64)> { // BAREPTR-LABEL: func @zero_d_alloc() -> !llvm.ptr { func @zero_d_alloc() -> memref { // CHECK-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: llvm.mul %{{.*}}, %[[sizeof]] : !llvm.i64 // CHECK-NEXT: llvm.call @malloc(%{{.*}}) : (!llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[ptr:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK-NEXT: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: llvm.insertvalue %[[c0]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // BAREPTR-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // BAREPTR-NEXT: llvm.mul %{{.*}}, %[[sizeof]] : !llvm.i64 // BAREPTR-NEXT: llvm.call @malloc(%{{.*}}) : (!llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: %[[ptr:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // BAREPTR-NEXT: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: llvm.insertvalue %[[c0]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64)> %0 = alloc() : memref return %0 : memref } // ----- // CHECK-LABEL: func @zero_d_dealloc // BAREPTR-LABEL: func @zero_d_dealloc(%{{.*}}: !llvm.ptr) { func @zero_d_dealloc(%arg0: memref) { // CHECK: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: %[[bc:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr to !llvm.ptr // CHECK-NEXT: llvm.call @free(%[[bc]]) : (!llvm.ptr) -> () // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: %[[bc:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr to !llvm.ptr // BAREPTR-NEXT: llvm.call @free(%[[bc]]) : (!llvm.ptr) -> () dealloc %arg0 : memref return } // ----- // CHECK-LABEL: func @aligned_1d_alloc( // BAREPTR-LABEL: func @aligned_1d_alloc( func @aligned_1d_alloc() -> memref<42xf32> { // CHECK: llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: llvm.mul %{{.*}}, %[[sizeof]] : !llvm.i64 // CHECK-NEXT: %[[alignment:.*]] = llvm.mlir.constant(8 : index) : !llvm.i64 // CHECK-NEXT: %[[allocsize:.*]] = llvm.add {{.*}}, %[[alignment]] : !llvm.i64 // CHECK-NEXT: %[[allocated:.*]] = llvm.call @malloc(%[[allocsize]]) : (!llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[ptr:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK-NEXT: %[[allocatedAsInt:.*]] = llvm.ptrtoint %[[ptr]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: %[[one_1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[bump:.*]] = llvm.sub %[[alignment]], %[[one_1]] : !llvm.i64 // CHECK-NEXT: %[[bumped:.*]] = llvm.add %[[allocatedAsInt]], %[[bump]] : !llvm.i64 // CHECK-NEXT: %[[mod:.*]] = llvm.urem %[[bumped]], %[[alignment]] : !llvm.i64 // CHECK-NEXT: %[[aligned:.*]] = llvm.sub %[[bumped]], %[[mod]] : !llvm.i64 // CHECK-NEXT: %[[alignedBitCast:.*]] = llvm.inttoptr %[[aligned]] : !llvm.i64 to !llvm.ptr // CHECK-NEXT: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK-NEXT: llvm.insertvalue %[[alignedBitCast]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: llvm.insertvalue %[[c0]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: llvm.mlir.constant(42 : index) : !llvm.i64 // BAREPTR-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // BAREPTR-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // BAREPTR-NEXT: llvm.mul %{{.*}}, %[[sizeof]] : !llvm.i64 // BAREPTR-NEXT: %[[alignment:.*]] = llvm.mlir.constant(8 : index) : !llvm.i64 // BAREPTR-NEXT: %[[allocsize:.*]] = llvm.add {{.*}}, %[[alignment]] : !llvm.i64 // BAREPTR-NEXT: %[[allocated:.*]] = llvm.call @malloc(%[[allocsize]]) : (!llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: %[[ptr:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // BAREPTR-NEXT: %[[allocatedAsInt:.*]] = llvm.ptrtoint %[[ptr]] : !llvm.ptr to !llvm.i64 // BAREPTR-NEXT: %[[one_2:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[bump:.*]] = llvm.sub %[[alignment]], %[[one_2]] : !llvm.i64 // BAREPTR-NEXT: %[[bumped:.*]] = llvm.add %[[allocatedAsInt]], %[[bump]] : !llvm.i64 // BAREPTR-NEXT: %[[mod:.*]] = llvm.urem %[[bumped]], %[[alignment]] : !llvm.i64 // BAREPTR-NEXT: %[[aligned:.*]] = llvm.sub %[[bumped]], %[[mod]] : !llvm.i64 // BAREPTR-NEXT: %[[alignedBitCast:.*]] = llvm.inttoptr %[[aligned]] : !llvm.i64 to !llvm.ptr // BAREPTR-NEXT: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: llvm.insertvalue %[[ptr]], %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: llvm.insertvalue %[[alignedBitCast]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: llvm.insertvalue %[[c0]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> %0 = alloc() {alignment = 8} : memref<42xf32> return %0 : memref<42xf32> } // ----- // CHECK-LABEL: func @static_alloc() -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> { // BAREPTR-LABEL: func @static_alloc() -> !llvm.ptr { func @static_alloc() -> memref<32x18xf32> { // CHECK: %[[sz1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64 // CHECK-NEXT: %[[sz2:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // CHECK-NEXT: %[[num_elems:.*]] = llvm.mul %0, %1 : !llvm.i64 // CHECK-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: %[[bytes:.*]] = llvm.mul %[[num_elems]], %[[sizeof]] : !llvm.i64 // CHECK-NEXT: %[[allocated:.*]] = llvm.call @malloc(%[[bytes]]) : (!llvm.i64) -> !llvm.ptr // CHECK-NEXT: llvm.bitcast %[[allocated]] : !llvm.ptr to !llvm.ptr // BAREPTR-NEXT: %[[sz1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64 // BAREPTR-NEXT: %[[sz2:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // BAREPTR-NEXT: %[[num_elems:.*]] = llvm.mul %[[sz1]], %[[sz2]] : !llvm.i64 // BAREPTR-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // BAREPTR-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // BAREPTR-NEXT: %[[bytes:.*]] = llvm.mul %[[num_elems]], %[[sizeof]] : !llvm.i64 // BAREPTR-NEXT: %[[allocated:.*]] = llvm.call @malloc(%[[bytes]]) : (!llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: llvm.bitcast %[[allocated]] : !llvm.ptr to !llvm.ptr %0 = alloc() : memref<32x18xf32> return %0 : memref<32x18xf32> } // ----- // CHECK-LABEL: func @static_alloca() -> !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> { func @static_alloca() -> memref<32x18xf32> { // CHECK-NEXT: %[[sz1:.*]] = llvm.mlir.constant(32 : index) : !llvm.i64 // CHECK-NEXT: %[[sz2:.*]] = llvm.mlir.constant(18 : index) : !llvm.i64 // CHECK-NEXT: %[[num_elems:.*]] = llvm.mul %0, %1 : !llvm.i64 // CHECK-NEXT: %[[null:.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: %[[one:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[gep:.*]] = llvm.getelementptr %[[null]][%[[one]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[sizeof:.*]] = llvm.ptrtoint %[[gep]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: %[[bytes:.*]] = llvm.mul %[[num_elems]], %[[sizeof]] : !llvm.i64 // CHECK-NEXT: %[[allocated:.*]] = llvm.alloca %[[bytes]] x !llvm.float : (!llvm.i64) -> !llvm.ptr %0 = alloca() : memref<32x18xf32> // Test with explicitly specified alignment. llvm.alloca takes care of the // alignment. The same pointer is thus used for allocation and aligned // accesses. // CHECK: %[[alloca_aligned:.*]] = llvm.alloca %{{.*}} x !llvm.float {alignment = 32 : i64} : (!llvm.i64) -> !llvm.ptr // CHECK: %[[desc:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[desc1:.*]] = llvm.insertvalue %[[alloca_aligned]], %[[desc]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.insertvalue %[[alloca_aligned]], %[[desc1]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> alloca() {alignment = 32} : memref<32x18xf32> return %0 : memref<32x18xf32> } // ----- // CHECK-LABEL: func @static_dealloc // BAREPTR-LABEL: func @static_dealloc(%{{.*}}: !llvm.ptr) { func @static_dealloc(%static: memref<10x8xf32>) { // CHECK: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK-NEXT: %[[bc:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr to !llvm.ptr // CHECK-NEXT: llvm.call @free(%[[bc]]) : (!llvm.ptr) -> () // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[bc:.*]] = llvm.bitcast %[[ptr]] : !llvm.ptr to !llvm.ptr // BAREPTR-NEXT: llvm.call @free(%[[bc]]) : (!llvm.ptr) -> () dealloc %static : memref<10x8xf32> return } // ----- // CHECK-LABEL: func @zero_d_load // BAREPTR-LABEL: func @zero_d_load(%{{.*}}: !llvm.ptr) -> !llvm.float func @zero_d_load(%arg0: memref) -> f32 { // CHECK: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[c0]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %{{.*}} = llvm.load %[[addr]] : !llvm.ptr // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[c0]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: llvm.load %[[addr:.*]] : !llvm.ptr %0 = load %arg0[] : memref return %0 : f32 } // ----- // CHECK-LABEL: func @static_load( // CHECK-COUNT-2: !llvm.ptr, // CHECK-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i64 // CHECK: %[[I:.*]]: !llvm.i64, // CHECK: %[[J:.*]]: !llvm.i64) // BAREPTR-LABEL: func @static_load // BAREPTR-SAME: (%[[A:.*]]: !llvm.ptr, %[[I:.*]]: !llvm.i64, %[[J:.*]]: !llvm.i64) { func @static_load(%static : memref<10x42xf32>, %i : index, %j : index) { // CHECK: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[st0:.*]] = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64 // CHECK-NEXT: %[[off0:.*]] = llvm.add %[[off]], %[[offI]] : !llvm.i64 // CHECK-NEXT: %[[st1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[offJ:.*]] = llvm.mul %[[J]], %[[st1]] : !llvm.i64 // CHECK-NEXT: %[[off1:.*]] = llvm.add %[[off0]], %[[offJ]] : !llvm.i64 // CHECK-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: llvm.load %[[addr]] : !llvm.ptr // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[st0:.*]] = llvm.mlir.constant(42 : index) : !llvm.i64 // BAREPTR-NEXT: %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64 // BAREPTR-NEXT: %[[off0:.*]] = llvm.add %[[off]], %[[offI]] : !llvm.i64 // BAREPTR-NEXT: %[[st1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[offJ:.*]] = llvm.mul %[[J]], %[[st1]] : !llvm.i64 // BAREPTR-NEXT: %[[off1:.*]] = llvm.add %[[off0]], %[[offJ]] : !llvm.i64 // BAREPTR-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: llvm.load %[[addr]] : !llvm.ptr %0 = load %static[%i, %j] : memref<10x42xf32> return } // ----- // CHECK-LABEL: func @zero_d_store // BAREPTR-LABEL: func @zero_d_store // BAREPTR-SAME: (%[[A:.*]]: !llvm.ptr, %[[val:.*]]: !llvm.float) func @zero_d_store(%arg0: memref, %arg1: f32) { // CHECK: %[[ptr:.*]] = llvm.extractvalue %[[ld:.*]][1] : !llvm.struct<(ptr, ptr, i64)> // CHECK-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: llvm.store %{{.*}}, %[[addr]] : !llvm.ptr // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64)> // BAREPTR-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: llvm.store %[[val]], %[[addr]] : !llvm.ptr store %arg1, %arg0[] : memref return } // ----- // CHECK-LABEL: func @static_store // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[I:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[J:[a-zA-Z0-9]*]]: !llvm.i64 // BAREPTR-LABEL: func @static_store // BAREPTR-SAME: %[[A:.*]]: !llvm.ptr // BAREPTR-SAME: %[[I:[a-zA-Z0-9]*]]: !llvm.i64 // BAREPTR-SAME: %[[J:[a-zA-Z0-9]*]]: !llvm.i64 func @static_store(%static : memref<10x42xf32>, %i : index, %j : index, %val : f32) { // CHECK: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[st0:.*]] = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64 // CHECK-NEXT: %[[off0:.*]] = llvm.add %[[off]], %[[offI]] : !llvm.i64 // CHECK-NEXT: %[[st1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[offJ:.*]] = llvm.mul %[[J]], %[[st1]] : !llvm.i64 // CHECK-NEXT: %[[off1:.*]] = llvm.add %[[off0]], %[[offJ]] : !llvm.i64 // CHECK-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: llvm.store %{{.*}}, %[[addr]] : !llvm.ptr // BAREPTR: %[[ptr:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // BAREPTR-NEXT: %[[off:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[st0:.*]] = llvm.mlir.constant(42 : index) : !llvm.i64 // BAREPTR-NEXT: %[[offI:.*]] = llvm.mul %[[I]], %[[st0]] : !llvm.i64 // BAREPTR-NEXT: %[[off0:.*]] = llvm.add %[[off]], %[[offI]] : !llvm.i64 // BAREPTR-NEXT: %[[st1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[offJ:.*]] = llvm.mul %[[J]], %[[st1]] : !llvm.i64 // BAREPTR-NEXT: %[[off1:.*]] = llvm.add %[[off0]], %[[offJ]] : !llvm.i64 // BAREPTR-NEXT: %[[addr:.*]] = llvm.getelementptr %[[ptr]][%[[off1]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // BAREPTR-NEXT: llvm.store %{{.*}}, %[[addr]] : !llvm.ptr store %val, %static[%i, %j] : memref<10x42xf32> return } // ----- // CHECK-LABEL: func @static_memref_dim // BAREPTR-LABEL: func @static_memref_dim(%{{.*}}: !llvm.ptr) { func @static_memref_dim(%static : memref<42x32x15x13x27xf32>) { // CHECK: llvm.mlir.constant(42 : index) : !llvm.i64 // BAREPTR: llvm.insertvalue %{{.*}}, %{{.*}}[4, 4] : !llvm.struct<(ptr, ptr, i64, array<5 x i64>, array<5 x i64>)> // BAREPTR: llvm.mlir.constant(42 : index) : !llvm.i64 %c0 = constant 0 : index %0 = dim %static, %c0 : memref<42x32x15x13x27xf32> // CHECK: llvm.mlir.constant(32 : index) : !llvm.i64 // BAREPTR: llvm.mlir.constant(32 : index) : !llvm.i64 %c1 = constant 1 : index %1 = dim %static, %c1 : memref<42x32x15x13x27xf32> // CHECK: llvm.mlir.constant(15 : index) : !llvm.i64 // BAREPTR: llvm.mlir.constant(15 : index) : !llvm.i64 %c2 = constant 2 : index %2 = dim %static, %c2 : memref<42x32x15x13x27xf32> // CHECK: llvm.mlir.constant(13 : index) : !llvm.i64 // BAREPTR: llvm.mlir.constant(13 : index) : !llvm.i64 %c3 = constant 3 : index %3 = dim %static, %c3 : memref<42x32x15x13x27xf32> // CHECK: llvm.mlir.constant(27 : index) : !llvm.i64 // BAREPTR: llvm.mlir.constant(27 : index) : !llvm.i64 %c4 = constant 4 : index %4 = dim %static, %c4 : memref<42x32x15x13x27xf32> return } // ----- // BAREPTR: llvm.func @foo(!llvm.ptr) -> !llvm.ptr -func @foo(memref<10xi8>) -> memref<20xi8> +func private @foo(memref<10xi8>) -> memref<20xi8> // BAREPTR-LABEL: func @check_memref_func_call // BAREPTR-SAME: %[[in:.*]]: !llvm.ptr) -> !llvm.ptr func @check_memref_func_call(%in : memref<10xi8>) -> memref<20xi8> { // BAREPTR: %[[inDesc:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] // BAREPTR-NEXT: %[[barePtr:.*]] = llvm.extractvalue %[[inDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[call:.*]] = llvm.call @foo(%[[barePtr]]) : (!llvm.ptr) -> !llvm.ptr // BAREPTR-NEXT: %[[desc0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[desc1:.*]] = llvm.insertvalue %[[call]], %[[desc0]][0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[desc2:.*]] = llvm.insertvalue %[[call]], %[[desc1]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // BAREPTR-NEXT: %[[desc4:.*]] = llvm.insertvalue %[[c0]], %[[desc2]][2] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c20:.*]] = llvm.mlir.constant(20 : index) : !llvm.i64 // BAREPTR-NEXT: %[[desc6:.*]] = llvm.insertvalue %[[c20]], %[[desc4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: %[[c1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // BAREPTR-NEXT: %[[outDesc:.*]] = llvm.insertvalue %[[c1]], %[[desc6]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> %res = call @foo(%in) : (memref<10xi8>) -> (memref<20xi8>) // BAREPTR-NEXT: %[[res:.*]] = llvm.extractvalue %[[outDesc]][1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // BAREPTR-NEXT: llvm.return %[[res]] : !llvm.ptr return %res : memref<20xi8> } // ----- // BAREPTR: llvm.func @goo(!llvm.float) -> !llvm.float -func @goo(f32) -> f32 +func private @goo(f32) -> f32 // BAREPTR-LABEL: func @check_scalar_func_call // BAREPTR-SAME: %[[in:.*]]: !llvm.float) func @check_scalar_func_call(%in : f32) { // BAREPTR-NEXT: %[[call:.*]] = llvm.call @goo(%[[in]]) : (!llvm.float) -> !llvm.float %res = call @goo(%in) : (f32) -> (f32) return } // ----- // Unranked memrefs are currently not supported in the bare-ptr calling // convention. Check that the conversion to the LLVM-IR dialect doesn't happen // in the presence of unranked memrefs when using such a calling convention. -// BAREPTR: func @hoo(memref<*xi8>) -> memref<*xi8> -func @hoo(memref<*xi8>) -> memref<*xi8> +// BAREPTR: func private @hoo(memref<*xi8>) -> memref<*xi8> +func private @hoo(memref<*xi8>) -> memref<*xi8> // BAREPTR-LABEL: func @check_unranked_memref_func_call(%{{.*}}: memref<*xi8>) -> memref<*xi8> func @check_unranked_memref_func_call(%in: memref<*xi8>) -> memref<*xi8> { // BAREPTR-NEXT: call @hoo(%{{.*}}) : (memref<*xi8>) -> memref<*xi8> %res = call @hoo(%in) : (memref<*xi8>) -> memref<*xi8> // BAREPTR-NEXT: return %{{.*}} : memref<*xi8> return %res : memref<*xi8> } diff --git a/mlir/test/Conversion/StandardToLLVM/convert-to-llvmir.mlir b/mlir/test/Conversion/StandardToLLVM/convert-to-llvmir.mlir index bb0363b1cba5..2dcc3114b4d0 100644 --- a/mlir/test/Conversion/StandardToLLVM/convert-to-llvmir.mlir +++ b/mlir/test/Conversion/StandardToLLVM/convert-to-llvmir.mlir @@ -1,1477 +1,1477 @@ // RUN: mlir-opt -convert-std-to-llvm %s -split-input-file | FileCheck %s // RUN: mlir-opt -convert-std-to-llvm='index-bitwidth=32' %s -split-input-file | FileCheck --check-prefix=CHECK32 %s // CHECK-LABEL: func @empty() { // CHECK-NEXT: llvm.return // CHECK-NEXT: } func @empty() { ^bb0: return } -// CHECK-LABEL: func @body(!llvm.i64) -func @body(index) +// CHECK-LABEL: llvm.func @body(!llvm.i64) +func private @body(index) // CHECK-LABEL: func @simple_loop() { // CHECK32-LABEL: func @simple_loop() { func @simple_loop() { ^bb0: // CHECK-NEXT: llvm.br ^bb1 // CHECK32-NEXT: llvm.br ^bb1 br ^bb1 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK32-NEXT: ^bb1: // pred: ^bb0 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i32 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : !llvm.i32) ^bb1: // pred: ^bb0 %c1 = constant 1 : index %c42 = constant 42 : index br ^bb2(%c1 : index) // CHECK: ^bb2({{.*}}: !llvm.i64): // 2 preds: ^bb1, ^bb3 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4 // CHECK32: ^bb2({{.*}}: !llvm.i32): // 2 preds: ^bb1, ^bb3 // CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i32 // CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4 ^bb2(%0: index): // 2 preds: ^bb1, ^bb3 %1 = cmpi "slt", %0, %c42 : index cond_br %1, ^bb3, ^bb4 // CHECK: ^bb3: // pred: ^bb2 // CHECK-NEXT: llvm.call @body({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK32: ^bb3: // pred: ^bb2 // CHECK32-NEXT: llvm.call @body({{.*}}) : (!llvm.i32) -> () // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i32 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : !llvm.i32) ^bb3: // pred: ^bb2 call @body(%0) : (index) -> () %c1_0 = constant 1 : index %2 = addi %0, %c1_0 : index br ^bb2(%2 : index) // CHECK: ^bb4: // pred: ^bb2 // CHECK-NEXT: llvm.return ^bb4: // pred: ^bb2 return } // CHECK-LABEL: llvm.func @complex_numbers() // CHECK-NEXT: %[[REAL0:.*]] = llvm.mlir.constant(1.200000e+00 : f32) : !llvm.float // CHECK-NEXT: %[[IMAG0:.*]] = llvm.mlir.constant(3.400000e+00 : f32) : !llvm.float // CHECK-NEXT: %[[CPLX0:.*]] = llvm.mlir.undef : !llvm.struct<(float, float)> // CHECK-NEXT: %[[CPLX1:.*]] = llvm.insertvalue %[[REAL0]], %[[CPLX0]][0] : !llvm.struct<(float, float)> // CHECK-NEXT: %[[CPLX2:.*]] = llvm.insertvalue %[[IMAG0]], %[[CPLX1]][1] : !llvm.struct<(float, float)> // CHECK-NEXT: %[[REAL1:.*]] = llvm.extractvalue %[[CPLX2:.*]][0] : !llvm.struct<(float, float)> // CHECK-NEXT: %[[IMAG1:.*]] = llvm.extractvalue %[[CPLX2:.*]][1] : !llvm.struct<(float, float)> // CHECK-NEXT: llvm.return func @complex_numbers() { %real0 = constant 1.2 : f32 %imag0 = constant 3.4 : f32 %cplx2 = create_complex %real0, %imag0 : complex %real1 = re %cplx2 : complex %imag1 = im %cplx2 : complex return } // CHECK-LABEL: llvm.func @complex_addition() // CHECK-DAG: %[[A_REAL:.*]] = llvm.extractvalue %[[A:.*]][0] : !llvm.struct<(double, double)> // CHECK-DAG: %[[B_REAL:.*]] = llvm.extractvalue %[[B:.*]][0] : !llvm.struct<(double, double)> // CHECK-DAG: %[[A_IMAG:.*]] = llvm.extractvalue %[[A]][1] : !llvm.struct<(double, double)> // CHECK-DAG: %[[B_IMAG:.*]] = llvm.extractvalue %[[B]][1] : !llvm.struct<(double, double)> // CHECK: %[[C0:.*]] = llvm.mlir.undef : !llvm.struct<(double, double)> // CHECK-DAG: %[[C_REAL:.*]] = llvm.fadd %[[A_REAL]], %[[B_REAL]] : !llvm.double // CHECK-DAG: %[[C_IMAG:.*]] = llvm.fadd %[[A_IMAG]], %[[B_IMAG]] : !llvm.double // CHECK: %[[C1:.*]] = llvm.insertvalue %[[C_REAL]], %[[C0]][0] : !llvm.struct<(double, double)> // CHECK: %[[C2:.*]] = llvm.insertvalue %[[C_IMAG]], %[[C1]][1] : !llvm.struct<(double, double)> func @complex_addition() { %a_re = constant 1.2 : f64 %a_im = constant 3.4 : f64 %a = create_complex %a_re, %a_im : complex %b_re = constant 5.6 : f64 %b_im = constant 7.8 : f64 %b = create_complex %b_re, %b_im : complex %c = addcf %a, %b : complex return } // CHECK-LABEL: llvm.func @complex_substraction() // CHECK-DAG: %[[A_REAL:.*]] = llvm.extractvalue %[[A:.*]][0] : !llvm.struct<(double, double)> // CHECK-DAG: %[[B_REAL:.*]] = llvm.extractvalue %[[B:.*]][0] : !llvm.struct<(double, double)> // CHECK-DAG: %[[A_IMAG:.*]] = llvm.extractvalue %[[A]][1] : !llvm.struct<(double, double)> // CHECK-DAG: %[[B_IMAG:.*]] = llvm.extractvalue %[[B]][1] : !llvm.struct<(double, double)> // CHECK: %[[C0:.*]] = llvm.mlir.undef : !llvm.struct<(double, double)> // CHECK-DAG: %[[C_REAL:.*]] = llvm.fsub %[[A_REAL]], %[[B_REAL]] : !llvm.double // CHECK-DAG: %[[C_IMAG:.*]] = llvm.fsub %[[A_IMAG]], %[[B_IMAG]] : !llvm.double // CHECK: %[[C1:.*]] = llvm.insertvalue %[[C_REAL]], %[[C0]][0] : !llvm.struct<(double, double)> // CHECK: %[[C2:.*]] = llvm.insertvalue %[[C_IMAG]], %[[C1]][1] : !llvm.struct<(double, double)> func @complex_substraction() { %a_re = constant 1.2 : f64 %a_im = constant 3.4 : f64 %a = create_complex %a_re, %a_im : complex %b_re = constant 5.6 : f64 %b_im = constant 7.8 : f64 %b = create_complex %b_re, %b_im : complex %c = subcf %a, %b : complex return } // CHECK-LABEL: func @simple_caller() { // CHECK-NEXT: llvm.call @simple_loop() : () -> () // CHECK-NEXT: llvm.return // CHECK-NEXT: } func @simple_caller() { ^bb0: call @simple_loop() : () -> () return } // Check that function call attributes persist during conversion. // CHECK-LABEL: @call_with_attributes func @call_with_attributes() { // CHECK: llvm.call @simple_loop() {baz = [1, 2, 3, 4], foo = "bar"} : () -> () call @simple_loop() {foo="bar", baz=[1,2,3,4]} : () -> () return } // CHECK-LABEL: func @ml_caller() { // CHECK-NEXT: llvm.call @simple_loop() : () -> () // CHECK-NEXT: llvm.call @more_imperfectly_nested_loops() : () -> () // CHECK-NEXT: llvm.return // CHECK-NEXT: } func @ml_caller() { ^bb0: call @simple_loop() : () -> () call @more_imperfectly_nested_loops() : () -> () return } -// CHECK-LABEL: func @body_args(!llvm.i64) -> !llvm.i64 -// CHECK32-LABEL: func @body_args(!llvm.i32) -> !llvm.i32 -func @body_args(index) -> index -// CHECK-LABEL: func @other(!llvm.i64, !llvm.i32) -> !llvm.i32 -// CHECK32-LABEL: func @other(!llvm.i32, !llvm.i32) -> !llvm.i32 -func @other(index, i32) -> i32 +// CHECK-LABEL: llvm.func @body_args(!llvm.i64) -> !llvm.i64 +// CHECK32-LABEL: llvm.func @body_args(!llvm.i32) -> !llvm.i32 +func private @body_args(index) -> index +// CHECK-LABEL: llvm.func @other(!llvm.i64, !llvm.i32) -> !llvm.i32 +// CHECK32-LABEL: llvm.func @other(!llvm.i32, !llvm.i32) -> !llvm.i32 +func private @other(index, i32) -> i32 // CHECK-LABEL: func @func_args(%arg0: !llvm.i32, %arg1: !llvm.i32) -> !llvm.i32 { // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : !llvm.i32 // CHECK-NEXT: llvm.br ^bb1 // CHECK32-LABEL: func @func_args(%arg0: !llvm.i32, %arg1: !llvm.i32) -> !llvm.i32 { // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : !llvm.i32 // CHECK32-NEXT: llvm.br ^bb1 func @func_args(i32, i32) -> i32 { ^bb0(%arg0: i32, %arg1: i32): %c0_i32 = constant 0 : i32 br ^bb1 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK32-NEXT: ^bb1: // pred: ^bb0 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i32 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : !llvm.i32) ^bb1: // pred: ^bb0 %c0 = constant 0 : index %c42 = constant 42 : index br ^bb2(%c0 : index) // CHECK-NEXT: ^bb2({{.*}}: !llvm.i64): // 2 preds: ^bb1, ^bb3 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4 // CHECK32-NEXT: ^bb2({{.*}}: !llvm.i32): // 2 preds: ^bb1, ^bb3 // CHECK32-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i32 // CHECK32-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb4 ^bb2(%0: index): // 2 preds: ^bb1, ^bb3 %1 = cmpi "slt", %0, %c42 : index cond_br %1, ^bb3, ^bb4 // CHECK-NEXT: ^bb3: // pred: ^bb2 // CHECK-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (!llvm.i64) -> !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (!llvm.i64, !llvm.i32) -> !llvm.i32 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm.i64, !llvm.i32) -> !llvm.i32 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (!llvm.i64, !llvm.i32) -> !llvm.i32 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK32-NEXT: ^bb3: // pred: ^bb2 // CHECK32-NEXT: {{.*}} = llvm.call @body_args({{.*}}) : (!llvm.i32) -> !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg0) : (!llvm.i32, !llvm.i32) -> !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm.i32, !llvm.i32) -> !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, %arg1) : (!llvm.i32, !llvm.i32) -> !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i32 // CHECK32-NEXT: llvm.br ^bb2({{.*}} : !llvm.i32) ^bb3: // pred: ^bb2 %2 = call @body_args(%0) : (index) -> index %3 = call @other(%2, %arg0) : (index, i32) -> i32 %4 = call @other(%2, %3) : (index, i32) -> i32 %5 = call @other(%2, %arg1) : (index, i32) -> i32 %c1 = constant 1 : index %6 = addi %0, %c1 : index br ^bb2(%6 : index) // CHECK-NEXT: ^bb4: // pred: ^bb2 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm.i64, !llvm.i32) -> !llvm.i32 // CHECK-NEXT: llvm.return {{.*}} : !llvm.i32 // CHECK32-NEXT: ^bb4: // pred: ^bb2 // CHECK32-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i32 // CHECK32-NEXT: {{.*}} = llvm.call @other({{.*}}, {{.*}}) : (!llvm.i32, !llvm.i32) -> !llvm.i32 // CHECK32-NEXT: llvm.return {{.*}} : !llvm.i32 ^bb4: // pred: ^bb2 %c0_0 = constant 0 : index %7 = call @other(%c0_0, %c0_i32) : (index, i32) -> i32 return %7 : i32 } -// CHECK-LABEL: func @pre(!llvm.i64) -// CHECK32-LABEL: func @pre(!llvm.i32) -func @pre(index) +// CHECK-LABEL: llvm.func @pre(!llvm.i64) +// CHECK32-LABEL: llvm.func @pre(!llvm.i32) +func private @pre(index) -// CHECK-LABEL: func @body2(!llvm.i64, !llvm.i64) -// CHECK32-LABEL: func @body2(!llvm.i32, !llvm.i32) -func @body2(index, index) +// CHECK-LABEL: llvm.func @body2(!llvm.i64, !llvm.i64) +// CHECK32-LABEL: llvm.func @body2(!llvm.i32, !llvm.i32) +func private @body2(index, index) -// CHECK-LABEL: func @post(!llvm.i64) -// CHECK32-LABEL: func @post(!llvm.i32) -func @post(index) +// CHECK-LABEL: llvm.func @post(!llvm.i64) +// CHECK32-LABEL: llvm.func @post(!llvm.i32) +func private @post(index) // CHECK-LABEL: func @imperfectly_nested_loops() { // CHECK-NEXT: llvm.br ^bb1 func @imperfectly_nested_loops() { ^bb0: br ^bb1 // CHECK-NEXT: ^bb1: // pred: ^bb0 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) ^bb1: // pred: ^bb0 %c0 = constant 0 : index %c42 = constant 42 : index br ^bb2(%c0 : index) // CHECK-NEXT: ^bb2({{.*}}: !llvm.i64): // 2 preds: ^bb1, ^bb7 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb8 ^bb2(%0: index): // 2 preds: ^bb1, ^bb7 %1 = cmpi "slt", %0, %c42 : index cond_br %1, ^bb3, ^bb8 // CHECK-NEXT: ^bb3: // CHECK-NEXT: llvm.call @pre({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: llvm.br ^bb4 ^bb3: // pred: ^bb2 call @pre(%0) : (index) -> () br ^bb4 // CHECK-NEXT: ^bb4: // pred: ^bb3 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm.i64) ^bb4: // pred: ^bb3 %c7 = constant 7 : index %c56 = constant 56 : index br ^bb5(%c7 : index) // CHECK-NEXT: ^bb5({{.*}}: !llvm.i64): // 2 preds: ^bb4, ^bb6 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7 ^bb5(%2: index): // 2 preds: ^bb4, ^bb6 %3 = cmpi "slt", %2, %c56 : index cond_br %3, ^bb6, ^bb7 // CHECK-NEXT: ^bb6: // pred: ^bb5 // CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (!llvm.i64, !llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm.i64) ^bb6: // pred: ^bb5 call @body2(%0, %2) : (index, index) -> () %c2 = constant 2 : index %4 = addi %2, %c2 : index br ^bb5(%4 : index) // CHECK-NEXT: ^bb7: // pred: ^bb5 // CHECK-NEXT: llvm.call @post({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) ^bb7: // pred: ^bb5 call @post(%0) : (index) -> () %c1 = constant 1 : index %5 = addi %0, %c1 : index br ^bb2(%5 : index) // CHECK-NEXT: ^bb8: // pred: ^bb2 // CHECK-NEXT: llvm.return ^bb8: // pred: ^bb2 return } -// CHECK-LABEL: func @mid(!llvm.i64) -func @mid(index) +// CHECK-LABEL: llvm.func @mid(!llvm.i64) +func private @mid(index) -// CHECK-LABEL: func @body3(!llvm.i64, !llvm.i64) -func @body3(index, index) +// CHECK-LABEL: llvm.func @body3(!llvm.i64, !llvm.i64) +func private @body3(index, index) // A complete function transformation check. // CHECK-LABEL: func @more_imperfectly_nested_loops() { // CHECK-NEXT: llvm.br ^bb1 // CHECK-NEXT:^bb1: // pred: ^bb0 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(42 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK-NEXT:^bb2({{.*}}: !llvm.i64): // 2 preds: ^bb1, ^bb11 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb3, ^bb12 // CHECK-NEXT:^bb3: // pred: ^bb2 // CHECK-NEXT: llvm.call @pre({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: llvm.br ^bb4 // CHECK-NEXT:^bb4: // pred: ^bb3 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(7 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(56 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm.i64) // CHECK-NEXT:^bb5({{.*}}: !llvm.i64): // 2 preds: ^bb4, ^bb6 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb6, ^bb7 // CHECK-NEXT:^bb6: // pred: ^bb5 // CHECK-NEXT: llvm.call @body2({{.*}}, {{.*}}) : (!llvm.i64, !llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(2 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb5({{.*}} : !llvm.i64) // CHECK-NEXT:^bb7: // pred: ^bb5 // CHECK-NEXT: llvm.call @mid({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: llvm.br ^bb8 // CHECK-NEXT:^bb8: // pred: ^bb7 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(18 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.mlir.constant(37 : index) : !llvm.i64 // CHECK-NEXT: llvm.br ^bb9({{.*}} : !llvm.i64) // CHECK-NEXT:^bb9({{.*}}: !llvm.i64): // 2 preds: ^bb8, ^bb10 // CHECK-NEXT: {{.*}} = llvm.icmp "slt" {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.cond_br {{.*}}, ^bb10, ^bb11 // CHECK-NEXT:^bb10: // pred: ^bb9 // CHECK-NEXT: llvm.call @body3({{.*}}, {{.*}}) : (!llvm.i64, !llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(3 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb9({{.*}} : !llvm.i64) // CHECK-NEXT:^bb11: // pred: ^bb9 // CHECK-NEXT: llvm.call @post({{.*}}) : (!llvm.i64) -> () // CHECK-NEXT: {{.*}} = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 // CHECK-NEXT: llvm.br ^bb2({{.*}} : !llvm.i64) // CHECK-NEXT:^bb12: // pred: ^bb2 // CHECK-NEXT: llvm.return // CHECK-NEXT: } func @more_imperfectly_nested_loops() { ^bb0: br ^bb1 ^bb1: // pred: ^bb0 %c0 = constant 0 : index %c42 = constant 42 : index br ^bb2(%c0 : index) ^bb2(%0: index): // 2 preds: ^bb1, ^bb11 %1 = cmpi "slt", %0, %c42 : index cond_br %1, ^bb3, ^bb12 ^bb3: // pred: ^bb2 call @pre(%0) : (index) -> () br ^bb4 ^bb4: // pred: ^bb3 %c7 = constant 7 : index %c56 = constant 56 : index br ^bb5(%c7 : index) ^bb5(%2: index): // 2 preds: ^bb4, ^bb6 %3 = cmpi "slt", %2, %c56 : index cond_br %3, ^bb6, ^bb7 ^bb6: // pred: ^bb5 call @body2(%0, %2) : (index, index) -> () %c2 = constant 2 : index %4 = addi %2, %c2 : index br ^bb5(%4 : index) ^bb7: // pred: ^bb5 call @mid(%0) : (index) -> () br ^bb8 ^bb8: // pred: ^bb7 %c18 = constant 18 : index %c37 = constant 37 : index br ^bb9(%c18 : index) ^bb9(%5: index): // 2 preds: ^bb8, ^bb10 %6 = cmpi "slt", %5, %c37 : index cond_br %6, ^bb10, ^bb11 ^bb10: // pred: ^bb9 call @body3(%0, %5) : (index, index) -> () %c3 = constant 3 : index %7 = addi %5, %c3 : index br ^bb9(%7 : index) ^bb11: // pred: ^bb9 call @post(%0) : (index) -> () %c1 = constant 1 : index %8 = addi %0, %c1 : index br ^bb2(%8 : index) ^bb12: // pred: ^bb2 return } -// CHECK-LABEL: func @get_i64() -> !llvm.i64 -func @get_i64() -> (i64) -// CHECK-LABEL: func @get_f32() -> !llvm.float -func @get_f32() -> (f32) -// CHECK-LABEL: func @get_c16() -> !llvm.struct<(half, half)> -func @get_c16() -> (complex) -// CHECK-LABEL: func @get_c32() -> !llvm.struct<(float, float)> -func @get_c32() -> (complex) -// CHECK-LABEL: func @get_c64() -> !llvm.struct<(double, double)> -func @get_c64() -> (complex) -// CHECK-LABEL: func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> -// CHECK32-LABEL: func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> -func @get_memref() -> (memref<42x?x10x?xf32>) - -// CHECK-LABEL: func @multireturn() -> !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> { -// CHECK32-LABEL: func @multireturn() -> !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> { +// CHECK-LABEL: llvm.func @get_i64() -> !llvm.i64 +func private @get_i64() -> (i64) +// CHECK-LABEL: llvm.func @get_f32() -> !llvm.float +func private @get_f32() -> (f32) +// CHECK-LABEL: llvm.func @get_c16() -> !llvm.struct<(half, half)> +func private @get_c16() -> (complex) +// CHECK-LABEL: llvm.func @get_c32() -> !llvm.struct<(float, float)> +func private @get_c32() -> (complex) +// CHECK-LABEL: llvm.func @get_c64() -> !llvm.struct<(double, double)> +func private @get_c64() -> (complex) +// CHECK-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> +// CHECK32-LABEL: llvm.func @get_memref() -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> +func private @get_memref() -> (memref<42x?x10x?xf32>) + +// CHECK-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> { +// CHECK32-LABEL: llvm.func @multireturn() -> !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> { func @multireturn() -> (i64, f32, memref<42x?x10x?xf32>) { ^bb0: // CHECK-NEXT: {{.*}} = llvm.call @get_i64() : () -> !llvm.i64 // CHECK-NEXT: {{.*}} = llvm.call @get_f32() : () -> !llvm.float // CHECK-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)> // CHECK32-NEXT: {{.*}} = llvm.call @get_i64() : () -> !llvm.i64 // CHECK32-NEXT: {{.*}} = llvm.call @get_f32() : () -> !llvm.float // CHECK32-NEXT: {{.*}} = llvm.call @get_memref() : () -> !llvm.struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)> %0 = call @get_i64() : () -> (i64) %1 = call @get_f32() : () -> (f32) %2 = call @get_memref() : () -> (memref<42x?x10x?xf32>) // CHECK-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK32-NEXT: {{.*}} = llvm.mlir.undef : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[0] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[1] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.insertvalue {{.*}}, {{.*}}[2] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: llvm.return {{.*}} : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> return %0, %1, %2 : i64, f32, memref<42x?x10x?xf32> } -// CHECK-LABEL: func @multireturn_caller() { -// CHECK32-LABEL: func @multireturn_caller() { +// CHECK-LABEL: llvm.func @multireturn_caller() { +// CHECK32-LABEL: llvm.func @multireturn_caller() { func @multireturn_caller() { ^bb0: // CHECK-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, float, struct<(ptr, ptr, i64, array<4 x i64>, array<4 x i64>)>)> // CHECK32-NEXT: {{.*}} = llvm.call @multireturn() : () -> !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[0] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[1] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> // CHECK32-NEXT: {{.*}} = llvm.extractvalue {{.*}}[2] : !llvm.struct<(i64, float, struct<(ptr, ptr, i32, array<4 x i32>, array<4 x i32>)>)> %0:3 = call @multireturn() : () -> (i64, f32, memref<42x?x10x?xf32>) %1 = constant 42 : i64 // CHECK: {{.*}} = llvm.add {{.*}}, {{.*}} : !llvm.i64 %2 = addi %0#0, %1 : i64 %3 = constant 42.0 : f32 // CHECK: {{.*}} = llvm.fadd {{.*}}, {{.*}} : !llvm.float %4 = addf %0#1, %3 : f32 %5 = constant 0 : index return } -// CHECK-LABEL: func @vector_ops(%arg0: !llvm.vec<4 x float>, %arg1: !llvm.vec<4 x i1>, %arg2: !llvm.vec<4 x i64>, %arg3: !llvm.vec<4 x i64>) -> !llvm.vec<4 x float> { +// CHECK-LABEL: llvm.func @vector_ops(%arg0: !llvm.vec<4 x float>, %arg1: !llvm.vec<4 x i1>, %arg2: !llvm.vec<4 x i64>, %arg3: !llvm.vec<4 x i64>) -> !llvm.vec<4 x float> { func @vector_ops(%arg0: vector<4xf32>, %arg1: vector<4xi1>, %arg2: vector<4xi64>, %arg3: vector<4xi64>) -> vector<4xf32> { // CHECK-NEXT: %0 = llvm.mlir.constant(dense<4.200000e+01> : vector<4xf32>) : !llvm.vec<4 x float> %0 = constant dense<42.> : vector<4xf32> // CHECK-NEXT: %1 = llvm.fadd %arg0, %0 : !llvm.vec<4 x float> %1 = addf %arg0, %0 : vector<4xf32> // CHECK-NEXT: %2 = llvm.sdiv %arg2, %arg2 : !llvm.vec<4 x i64> %3 = divi_signed %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %3 = llvm.udiv %arg2, %arg2 : !llvm.vec<4 x i64> %4 = divi_unsigned %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %4 = llvm.srem %arg2, %arg2 : !llvm.vec<4 x i64> %5 = remi_signed %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %5 = llvm.urem %arg2, %arg2 : !llvm.vec<4 x i64> %6 = remi_unsigned %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %6 = llvm.fdiv %arg0, %0 : !llvm.vec<4 x float> %7 = divf %arg0, %0 : vector<4xf32> // CHECK-NEXT: %7 = llvm.frem %arg0, %0 : !llvm.vec<4 x float> %8 = remf %arg0, %0 : vector<4xf32> // CHECK-NEXT: %8 = llvm.and %arg2, %arg3 : !llvm.vec<4 x i64> %9 = and %arg2, %arg3 : vector<4xi64> // CHECK-NEXT: %9 = llvm.or %arg2, %arg3 : !llvm.vec<4 x i64> %10 = or %arg2, %arg3 : vector<4xi64> // CHECK-NEXT: %10 = llvm.xor %arg2, %arg3 : !llvm.vec<4 x i64> %11 = xor %arg2, %arg3 : vector<4xi64> // CHECK-NEXT: %11 = llvm.shl %arg2, %arg2 : !llvm.vec<4 x i64> %12 = shift_left %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %12 = llvm.ashr %arg2, %arg2 : !llvm.vec<4 x i64> %13 = shift_right_signed %arg2, %arg2 : vector<4xi64> // CHECK-NEXT: %13 = llvm.lshr %arg2, %arg2 : !llvm.vec<4 x i64> %14 = shift_right_unsigned %arg2, %arg2 : vector<4xi64> return %1 : vector<4xf32> } // CHECK-LABEL: @ops func @ops(f32, f32, i32, i32, f64) -> (f32, i32) { ^bb0(%arg0: f32, %arg1: f32, %arg2: i32, %arg3: i32, %arg4: f64): // CHECK-NEXT: %0 = llvm.fsub %arg0, %arg1 : !llvm.float %0 = subf %arg0, %arg1: f32 // CHECK-NEXT: %1 = llvm.sub %arg2, %arg3 : !llvm.i32 %1 = subi %arg2, %arg3: i32 // CHECK-NEXT: %2 = llvm.icmp "slt" %arg2, %1 : !llvm.i32 %2 = cmpi "slt", %arg2, %1 : i32 // CHECK-NEXT: %3 = llvm.sdiv %arg2, %arg3 : !llvm.i32 %3 = divi_signed %arg2, %arg3 : i32 // CHECK-NEXT: %4 = llvm.udiv %arg2, %arg3 : !llvm.i32 %4 = divi_unsigned %arg2, %arg3 : i32 // CHECK-NEXT: %5 = llvm.srem %arg2, %arg3 : !llvm.i32 %5 = remi_signed %arg2, %arg3 : i32 // CHECK-NEXT: %6 = llvm.urem %arg2, %arg3 : !llvm.i32 %6 = remi_unsigned %arg2, %arg3 : i32 // CHECK-NEXT: %7 = llvm.select %2, %arg2, %arg3 : !llvm.i1, !llvm.i32 %7 = select %2, %arg2, %arg3 : i32 // CHECK-NEXT: %8 = llvm.fdiv %arg0, %arg1 : !llvm.float %8 = divf %arg0, %arg1 : f32 // CHECK-NEXT: %9 = llvm.frem %arg0, %arg1 : !llvm.float %9 = remf %arg0, %arg1 : f32 // CHECK-NEXT: %10 = llvm.and %arg2, %arg3 : !llvm.i32 %10 = and %arg2, %arg3 : i32 // CHECK-NEXT: %11 = llvm.or %arg2, %arg3 : !llvm.i32 %11 = or %arg2, %arg3 : i32 // CHECK-NEXT: %12 = llvm.xor %arg2, %arg3 : !llvm.i32 %12 = xor %arg2, %arg3 : i32 // CHECK-NEXT: %13 = "llvm.intr.exp"(%arg0) : (!llvm.float) -> !llvm.float %13 = std.exp %arg0 : f32 // CHECK-NEXT: %14 = "llvm.intr.exp2"(%arg0) : (!llvm.float) -> !llvm.float %14 = std.exp2 %arg0 : f32 // CHECK-NEXT: %15 = llvm.mlir.constant(7.900000e-01 : f64) : !llvm.double %15 = constant 7.9e-01 : f64 // CHECK-NEXT: %16 = llvm.shl %arg2, %arg3 : !llvm.i32 %16 = shift_left %arg2, %arg3 : i32 // CHECK-NEXT: %17 = llvm.ashr %arg2, %arg3 : !llvm.i32 %17 = shift_right_signed %arg2, %arg3 : i32 // CHECK-NEXT: %18 = llvm.lshr %arg2, %arg3 : !llvm.i32 %18 = shift_right_unsigned %arg2, %arg3 : i32 // CHECK-NEXT: %{{[0-9]+}} = "llvm.intr.sqrt"(%arg0) : (!llvm.float) -> !llvm.float %19 = std.sqrt %arg0 : f32 // CHECK-NEXT: %{{[0-9]+}} = "llvm.intr.sqrt"(%arg4) : (!llvm.double) -> !llvm.double %20 = std.sqrt %arg4 : f64 return %0, %4 : f32, i32 } // Checking conversion of index types to integers using i1, assuming no target // system would have a 1-bit address space. Otherwise, we would have had to // make this test dependent on the pointer size on the target system. // CHECK-LABEL: @index_cast func @index_cast(%arg0: index, %arg1: i1) { // CHECK-NEXT: = llvm.trunc %arg0 : !llvm.i{{.*}} to !llvm.i1 %0 = index_cast %arg0: index to i1 // CHECK-NEXT: = llvm.sext %arg1 : !llvm.i1 to !llvm.i{{.*}} %1 = index_cast %arg1: i1 to index return } // Checking conversion of signed integer types to floating point. // CHECK-LABEL: @sitofp func @sitofp(%arg0 : i32, %arg1 : i64) { // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.i32 to !llvm.float %0 = sitofp %arg0: i32 to f32 // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.i32 to !llvm.double %1 = sitofp %arg0: i32 to f64 // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.i64 to !llvm.float %2 = sitofp %arg1: i64 to f32 // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.i64 to !llvm.double %3 = sitofp %arg1: i64 to f64 return } // Checking conversion of integer vectors to floating point vector types. // CHECK-LABEL: @sitofp_vector func @sitofp_vector(%arg0 : vector<2xi16>, %arg1 : vector<2xi32>, %arg2 : vector<2xi64>) { // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i16> to !llvm.vec<2 x float> %0 = sitofp %arg0: vector<2xi16> to vector<2xf32> // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i16> to !llvm.vec<2 x double> %1 = sitofp %arg0: vector<2xi16> to vector<2xf64> // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i32> to !llvm.vec<2 x float> %2 = sitofp %arg1: vector<2xi32> to vector<2xf32> // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i32> to !llvm.vec<2 x double> %3 = sitofp %arg1: vector<2xi32> to vector<2xf64> // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i64> to !llvm.vec<2 x float> %4 = sitofp %arg2: vector<2xi64> to vector<2xf32> // CHECK-NEXT: = llvm.sitofp {{.*}} : !llvm.vec<2 x i64> to !llvm.vec<2 x double> %5 = sitofp %arg2: vector<2xi64> to vector<2xf64> return } // Checking conversion of unsigned integer types to floating point. // CHECK-LABEL: @uitofp func @uitofp(%arg0 : i32, %arg1 : i64) { // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.i32 to !llvm.float %0 = uitofp %arg0: i32 to f32 // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.i32 to !llvm.double %1 = uitofp %arg0: i32 to f64 // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.i64 to !llvm.float %2 = uitofp %arg1: i64 to f32 // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.i64 to !llvm.double %3 = uitofp %arg1: i64 to f64 return } // Checking conversion of integer types to floating point. // CHECK-LABEL: @fpext func @fpext(%arg0 : f16, %arg1 : f32) { // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.half to !llvm.float %0 = fpext %arg0: f16 to f32 // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.half to !llvm.double %1 = fpext %arg0: f16 to f64 // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.float to !llvm.double %2 = fpext %arg1: f32 to f64 return } // Checking conversion of integer types to floating point. // CHECK-LABEL: @fpext func @fpext_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>) { // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x float> %0 = fpext %arg0: vector<2xf16> to vector<2xf32> // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x double> %1 = fpext %arg0: vector<2xf16> to vector<2xf64> // CHECK-NEXT: = llvm.fpext {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x double> %2 = fpext %arg1: vector<2xf32> to vector<2xf64> return } // Checking conversion of floating point to integer types. // CHECK-LABEL: @fptosi func @fptosi(%arg0 : f32, %arg1 : f64) { // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.float to !llvm.i32 %0 = fptosi %arg0: f32 to i32 // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.float to !llvm.i64 %1 = fptosi %arg0: f32 to i64 // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.double to !llvm.i32 %2 = fptosi %arg1: f64 to i32 // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.double to !llvm.i64 %3 = fptosi %arg1: f64 to i64 return } // Checking conversion of floating point vectors to integer vector types. // CHECK-LABEL: @fptosi_vector func @fptosi_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>, %arg2 : vector<2xf64>) { // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x i32> %0 = fptosi %arg0: vector<2xf16> to vector<2xi32> // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x i64> %1 = fptosi %arg0: vector<2xf16> to vector<2xi64> // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x i32> %2 = fptosi %arg1: vector<2xf32> to vector<2xi32> // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x i64> %3 = fptosi %arg1: vector<2xf32> to vector<2xi64> // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x i32> %4 = fptosi %arg2: vector<2xf64> to vector<2xi32> // CHECK-NEXT: = llvm.fptosi {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x i64> %5 = fptosi %arg2: vector<2xf64> to vector<2xi64> return } // Checking conversion of floating point to integer types. // CHECK-LABEL: @fptoui func @fptoui(%arg0 : f32, %arg1 : f64) { // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.float to !llvm.i32 %0 = fptoui %arg0: f32 to i32 // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.float to !llvm.i64 %1 = fptoui %arg0: f32 to i64 // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.double to !llvm.i32 %2 = fptoui %arg1: f64 to i32 // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.double to !llvm.i64 %3 = fptoui %arg1: f64 to i64 return } // Checking conversion of floating point vectors to integer vector types. // CHECK-LABEL: @fptoui_vector func @fptoui_vector(%arg0 : vector<2xf16>, %arg1 : vector<2xf32>, %arg2 : vector<2xf64>) { // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x i32> %0 = fptoui %arg0: vector<2xf16> to vector<2xi32> // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x half> to !llvm.vec<2 x i64> %1 = fptoui %arg0: vector<2xf16> to vector<2xi64> // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x i32> %2 = fptoui %arg1: vector<2xf32> to vector<2xi32> // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x i64> %3 = fptoui %arg1: vector<2xf32> to vector<2xi64> // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x i32> %4 = fptoui %arg2: vector<2xf64> to vector<2xi32> // CHECK-NEXT: = llvm.fptoui {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x i64> %5 = fptoui %arg2: vector<2xf64> to vector<2xi64> return } // Checking conversion of integer vectors to floating point vector types. // CHECK-LABEL: @uitofp_vector func @uitofp_vector(%arg0 : vector<2xi16>, %arg1 : vector<2xi32>, %arg2 : vector<2xi64>) { // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i16> to !llvm.vec<2 x float> %0 = uitofp %arg0: vector<2xi16> to vector<2xf32> // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i16> to !llvm.vec<2 x double> %1 = uitofp %arg0: vector<2xi16> to vector<2xf64> // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i32> to !llvm.vec<2 x float> %2 = uitofp %arg1: vector<2xi32> to vector<2xf32> // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i32> to !llvm.vec<2 x double> %3 = uitofp %arg1: vector<2xi32> to vector<2xf64> // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i64> to !llvm.vec<2 x float> %4 = uitofp %arg2: vector<2xi64> to vector<2xf32> // CHECK-NEXT: = llvm.uitofp {{.*}} : !llvm.vec<2 x i64> to !llvm.vec<2 x double> %5 = uitofp %arg2: vector<2xi64> to vector<2xf64> return } // Checking conversion of integer types to floating point. // CHECK-LABEL: @fptrunc func @fptrunc(%arg0 : f32, %arg1 : f64) { // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.float to !llvm.half %0 = fptrunc %arg0: f32 to f16 // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.double to !llvm.half %1 = fptrunc %arg1: f64 to f16 // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.double to !llvm.float %2 = fptrunc %arg1: f64 to f32 return } // Checking conversion of integer types to floating point. // CHECK-LABEL: @fptrunc func @fptrunc_vector(%arg0 : vector<2xf32>, %arg1 : vector<2xf64>) { // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.vec<2 x float> to !llvm.vec<2 x half> %0 = fptrunc %arg0: vector<2xf32> to vector<2xf16> // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x half> %1 = fptrunc %arg1: vector<2xf64> to vector<2xf16> // CHECK-NEXT: = llvm.fptrunc {{.*}} : !llvm.vec<2 x double> to !llvm.vec<2 x float> %2 = fptrunc %arg1: vector<2xf64> to vector<2xf32> return } // Check sign and zero extension and truncation of integers. // CHECK-LABEL: @integer_extension_and_truncation func @integer_extension_and_truncation() { // CHECK-NEXT: %0 = llvm.mlir.constant(-3 : i3) : !llvm.i3 %0 = constant 5 : i3 // CHECK-NEXT: = llvm.sext %0 : !llvm.i3 to !llvm.i6 %1 = sexti %0 : i3 to i6 // CHECK-NEXT: = llvm.zext %0 : !llvm.i3 to !llvm.i6 %2 = zexti %0 : i3 to i6 // CHECK-NEXT: = llvm.trunc %0 : !llvm.i3 to !llvm.i2 %3 = trunci %0 : i3 to i2 return } // CHECK-LABEL: @dfs_block_order func @dfs_block_order(%arg0: i32) -> (i32) { // CHECK-NEXT: %[[CST:.*]] = llvm.mlir.constant(42 : i32) : !llvm.i32 %0 = constant 42 : i32 // CHECK-NEXT: llvm.br ^bb2 br ^bb2 // CHECK-NEXT: ^bb1: // CHECK-NEXT: %[[ADD:.*]] = llvm.add %arg0, %[[CST]] : !llvm.i32 // CHECK-NEXT: llvm.return %[[ADD]] : !llvm.i32 ^bb1: %2 = addi %arg0, %0 : i32 return %2 : i32 // CHECK-NEXT: ^bb2: ^bb2: // CHECK-NEXT: llvm.br ^bb1 br ^bb1 } // CHECK-LABEL: func @fcmp(%arg0: !llvm.float, %arg1: !llvm.float) { func @fcmp(f32, f32) -> () { ^bb0(%arg0: f32, %arg1: f32): // CHECK: llvm.fcmp "oeq" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ogt" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "oge" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "olt" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ole" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "one" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ord" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ueq" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ugt" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "uge" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ult" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "ule" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "une" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.fcmp "uno" %arg0, %arg1 : !llvm.float // CHECK-NEXT: llvm.return %1 = cmpf "oeq", %arg0, %arg1 : f32 %2 = cmpf "ogt", %arg0, %arg1 : f32 %3 = cmpf "oge", %arg0, %arg1 : f32 %4 = cmpf "olt", %arg0, %arg1 : f32 %5 = cmpf "ole", %arg0, %arg1 : f32 %6 = cmpf "one", %arg0, %arg1 : f32 %7 = cmpf "ord", %arg0, %arg1 : f32 %8 = cmpf "ueq", %arg0, %arg1 : f32 %9 = cmpf "ugt", %arg0, %arg1 : f32 %10 = cmpf "uge", %arg0, %arg1 : f32 %11 = cmpf "ult", %arg0, %arg1 : f32 %12 = cmpf "ule", %arg0, %arg1 : f32 %13 = cmpf "une", %arg0, %arg1 : f32 %14 = cmpf "uno", %arg0, %arg1 : f32 return } // CHECK-LABEL: @vec_bin func @vec_bin(%arg0: vector<2x2x2xf32>) -> vector<2x2x2xf32> { %0 = addf %arg0, %arg0 : vector<2x2x2xf32> return %0 : vector<2x2x2xf32> // CHECK-NEXT: llvm.mlir.undef : !llvm.array<2 x array<2 x vec<2 x float>>> // This block appears 2x2 times // CHECK-NEXT: llvm.extractvalue %{{.*}}[0, 0] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK-NEXT: llvm.extractvalue %{{.*}}[0, 0] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK-NEXT: llvm.fadd %{{.*}} : !llvm.vec<2 x float> // CHECK-NEXT: llvm.insertvalue %{{.*}}[0, 0] : !llvm.array<2 x array<2 x vec<2 x float>>> // We check the proper indexing of extract/insert in the remaining 3 positions. // CHECK: llvm.extractvalue %{{.*}}[0, 1] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK: llvm.insertvalue %{{.*}}[0, 1] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK: llvm.extractvalue %{{.*}}[1, 0] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK: llvm.insertvalue %{{.*}}[1, 0] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK: llvm.extractvalue %{{.*}}[1, 1] : !llvm.array<2 x array<2 x vec<2 x float>>> // CHECK: llvm.insertvalue %{{.*}}[1, 1] : !llvm.array<2 x array<2 x vec<2 x float>>> // And we're done // CHECK-NEXT: return } // CHECK-LABEL: @splat // CHECK-SAME: %[[A:arg[0-9]+]]: !llvm.vec<4 x float> // CHECK-SAME: %[[ELT:arg[0-9]+]]: !llvm.float func @splat(%a: vector<4xf32>, %b: f32) -> vector<4xf32> { %vb = splat %b : vector<4xf32> %r = mulf %a, %vb : vector<4xf32> return %r : vector<4xf32> } // CHECK-NEXT: %[[UNDEF:[0-9]+]] = llvm.mlir.undef : !llvm.vec<4 x float> // CHECK-NEXT: %[[ZERO:[0-9]+]] = llvm.mlir.constant(0 : i32) : !llvm.i32 // CHECK-NEXT: %[[V:[0-9]+]] = llvm.insertelement %[[ELT]], %[[UNDEF]][%[[ZERO]] : !llvm.i32] : !llvm.vec<4 x float> // CHECK-NEXT: %[[SPLAT:[0-9]+]] = llvm.shufflevector %[[V]], %[[UNDEF]] [0 : i32, 0 : i32, 0 : i32, 0 : i32] // CHECK-NEXT: %[[SCALE:[0-9]+]] = llvm.fmul %[[A]], %[[SPLAT]] : !llvm.vec<4 x float> // CHECK-NEXT: llvm.return %[[SCALE]] : !llvm.vec<4 x float> // CHECK-LABEL: func @view( // CHECK: %[[ARG0:.*]]: !llvm.i64, %[[ARG1:.*]]: !llvm.i64, %[[ARG2:.*]]: !llvm.i64 func @view(%arg0 : index, %arg1 : index, %arg2 : index) { // CHECK: llvm.mlir.constant(2048 : index) : !llvm.i64 // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> %0 = alloc() : memref<2048xi8> // Test two dynamic sizes. // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_PTR:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK: %[[SHIFTED_BASE_PTR:.*]] = llvm.getelementptr %[[BASE_PTR]][%[[ARG2]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK: %[[CAST_SHIFTED_BASE_PTR:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK: llvm.insertvalue %[[C0]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.insertvalue %[[ARG1]], %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.insertvalue %[[ARG0]], %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mul %{{.*}}, %[[ARG1]] // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> %1 = view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref // Test one dynamic size. // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_PTR_2:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK: %[[SHIFTED_BASE_PTR_2:.*]] = llvm.getelementptr %[[BASE_PTR_2]][%[[ARG2]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK: %[[CAST_SHIFTED_BASE_PTR_2:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR_2]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR_2]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[C0_2:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK: llvm.insertvalue %[[C0_2]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.insertvalue %[[ARG1]], %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(4 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mul %{{.*}}, %[[ARG1]] // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> %3 = view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32> // Test static sizes. // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_PTR_3:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK: %[[SHIFTED_BASE_PTR_3:.*]] = llvm.getelementptr %[[BASE_PTR_3]][%[[ARG2]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK: %[[CAST_SHIFTED_BASE_PTR_3:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR_3]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR_3]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[C0_3:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK: llvm.insertvalue %[[C0_3]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(4 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(64 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(4 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> %5 = view %0[%arg2][] : memref<2048xi8> to memref<64x4xf32> // Test view memory space. // CHECK: llvm.mlir.constant(2048 : index) : !llvm.i64 // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> %6 = alloc() : memref<2048xi8, 4> // CHECK: llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BASE_PTR_4:.*]] = llvm.extractvalue %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK: %[[SHIFTED_BASE_PTR_4:.*]] = llvm.getelementptr %[[BASE_PTR_4]][%[[ARG2]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK: %[[CAST_SHIFTED_BASE_PTR_4:.*]] = llvm.bitcast %[[SHIFTED_BASE_PTR_4]] : !llvm.ptr to !llvm.ptr // CHECK: llvm.insertvalue %[[CAST_SHIFTED_BASE_PTR_4]], %{{.*}}[1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[C0_4:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK: llvm.insertvalue %[[C0_4]], %{{.*}}[2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(4 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(64 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: llvm.mlir.constant(4 : index) : !llvm.i64 // CHECK: llvm.insertvalue %{{.*}}, %{{.*}}[4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> %7 = view %6[%arg2][] : memref<2048xi8, 4> to memref<64x4xf32, 4> return } // CHECK-LABEL: func @subview( // CHECK-COUNT-2: !llvm.ptr, // CHECK-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i64, // CHECK: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG2:.*]]: !llvm.i64) // CHECK32-LABEL: func @subview( // CHECK32-COUNT-2: !llvm.ptr, // CHECK32-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i32, // CHECK32: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG2:.*]]: !llvm.i32) func @subview(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFFINC:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i64 // CHECK: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i64 // CHECK: %[[OFFINC1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i64 // CHECK: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC3:.*]] = llvm.insertvalue %[[ARG1]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i64 // CHECK: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFFINC:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i32 // CHECK32: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i32 // CHECK32: %[[OFFINC1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i32 // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[ARG1]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i32 %1 = subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] : memref<64x4xf32, offset: 0, strides: [4, 1]> to memref return } // CHECK-LABEL: func @subview_non_zero_addrspace( // CHECK-COUNT-2: !llvm.ptr, // CHECK-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i64, // CHECK: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG2:.*]]: !llvm.i64) // CHECK32-LABEL: func @subview_non_zero_addrspace( // CHECK32-COUNT-2: !llvm.ptr, // CHECK32-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i32, // CHECK32: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG2:.*]]: !llvm.i32) func @subview_non_zero_addrspace(%0 : memref<64x4xf32, offset: 0, strides: [4, 1], 3>, %arg0 : index, %arg1 : index, %arg2 : index) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFFINC:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i64 // CHECK: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i64 // CHECK: %[[OFFINC1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i64 // CHECK: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC3:.*]] = llvm.insertvalue %[[ARG1]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i64 // CHECK: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFFINC:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i32 // CHECK32: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i32 // CHECK32: %[[OFFINC1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i32 // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[ARG1]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG0]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i32 %1 = subview %0[%arg0, %arg1][%arg0, %arg1][%arg0, %arg1] : memref<64x4xf32, offset: 0, strides: [4, 1], 3> to memref return } // CHECK-LABEL: func @subview_const_size( // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG7:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG8:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG9:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK32-LABEL: func @subview_const_size( // CHECK32-SAME: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK32-SAME: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK32-SAME: %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG7:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG8:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG9:[a-zA-Z0-9]*]]: !llvm.i32 func @subview_const_size(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFFINC:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i64 // CHECK: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i64 // CHECK: %[[OFFINC1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i64 // CHECK: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[CST2:.*]] = llvm.mlir.constant(2 : i64) // CHECK: %[[DESC3:.*]] = llvm.insertvalue %[[CST2]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[CST4:.*]] = llvm.mlir.constant(4 : i64) // CHECK: %[[DESC5:.*]] = llvm.insertvalue %[[CST4]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i64 // CHECK: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFFINC:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i32 // CHECK32: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i32 // CHECK32: %[[OFFINC1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i32 // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST2:.*]] = llvm.mlir.constant(2 : i64) // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[CST2]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[DESCSTRIDE1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST4:.*]] = llvm.mlir.constant(4 : i64) // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST4]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i32 // CHECK32: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> %1 = subview %0[%arg0, %arg1][4, 2][%arg0, %arg1] : memref<64x4xf32, offset: 0, strides: [4, 1]> to memref<4x2xf32, offset: ?, strides: [?, ?]> return } // CHECK-LABEL: func @subview_const_stride( // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG7:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG8:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK-SAME: %[[ARG9:[a-zA-Z0-9]*]]: !llvm.i64 // CHECK32-LABEL: func @subview_const_stride( // CHECK32-SAME: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK32-SAME: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.ptr, // CHECK32-SAME: %[[ARG2:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG3:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG4:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG5:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG6:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG7:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG8:[a-zA-Z0-9]*]]: !llvm.i32 // CHECK32-SAME: %[[ARG9:[a-zA-Z0-9]*]]: !llvm.i32 func @subview_const_stride(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[OFFINC:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i64 // CHECK: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i64 // CHECK: %[[OFFINC1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i64 // CHECK: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i64 // CHECK: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC3:.*]] = llvm.insertvalue %[[ARG8]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[CST2:.*]] = llvm.mlir.constant(2 : i64) // CHECK: %[[DESC4:.*]] = llvm.insertvalue %[[CST2]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[DESC5:.*]] = llvm.insertvalue %[[ARG7]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK: %[[CST4:.*]] = llvm.mlir.constant(4 : i64) // CHECK: llvm.insertvalue %[[CST4]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFFINC:.*]] = llvm.mul %[[ARG7]], %[[STRIDE0]] : !llvm.i32 // CHECK32: %[[OFF1:.*]] = llvm.add %[[OFF]], %[[OFFINC]] : !llvm.i32 // CHECK32: %[[OFFINC1:.*]] = llvm.mul %[[ARG8]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[OFF2:.*]] = llvm.add %[[OFF1]], %[[OFFINC1]] : !llvm.i32 // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[OFF2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[ARG8]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST2:.*]] = llvm.mlir.constant(2 : i64) // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[CST2]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[ARG7]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST4:.*]] = llvm.mlir.constant(4 : i64) // CHECK32: llvm.insertvalue %[[CST4]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> %1 = subview %0[%arg0, %arg1][%arg0, %arg1][1, 2] : memref<64x4xf32, offset: 0, strides: [4, 1]> to memref return } // CHECK-LABEL: func @subview_const_stride_and_offset( // CHECK32-LABEL: func @subview_const_stride_and_offset( func @subview_const_stride_and_offset(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST8:.*]] = llvm.mlir.constant(8 : index) // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[CST8]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST3:.*]] = llvm.mlir.constant(3 : i64) // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[CST3]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST1:.*]] = llvm.mlir.constant(1 : i64) // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[CST1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST62:.*]] = llvm.mlir.constant(62 : i64) // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST62]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST4:.*]] = llvm.mlir.constant(4 : i64) // CHECK32: llvm.insertvalue %[[CST4]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> %1 = subview %0[0, 8][62, 3][1, 1] : memref<64x4xf32, offset: 0, strides: [4, 1]> to memref<62x3xf32, offset: 8, strides: [4, 1]> return } // CHECK-LABEL: func @subview_mixed_static_dynamic( // CHECK-COUNT-2: !llvm.ptr, // CHECK-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i64, // CHECK: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i64, // CHECK: %[[ARG2:.*]]: !llvm.i64) // CHECK32-LABEL: func @subview_mixed_static_dynamic( // CHECK32-COUNT-2: !llvm.ptr, // CHECK32-COUNT-5: {{%[a-zA-Z0-9]*}}: !llvm.i32, // CHECK32: %[[ARG0:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG1:[a-zA-Z0-9]*]]: !llvm.i32, // CHECK32: %[[ARG2:.*]]: !llvm.i32) func @subview_mixed_static_dynamic(%0 : memref<64x4xf32, offset: 0, strides: [4, 1]>, %arg0 : index, %arg1 : index, %arg2 : index) { // The last "insertvalue" that populates the memref descriptor from the function arguments. // CHECK: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[MEMREF:.*]] = llvm.insertvalue %{{.*}}, %{{.*}}[4, 1] // CHECK32: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST0:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC0:.*]] = llvm.insertvalue %[[BITCAST0]], %[[DESC]][0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[BITCAST1:.*]] = llvm.bitcast %{{.*}} : !llvm.ptr to !llvm.ptr // CHECK32: %[[DESC1:.*]] = llvm.insertvalue %[[BITCAST1]], %[[DESC0]][1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE0:.*]] = llvm.extractvalue %[[MEMREF]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[STRIDE1:.*]] = llvm.extractvalue %[[MEMREF]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFF:.*]] = llvm.extractvalue %[[MEMREF]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[OFFM1:.*]] = llvm.mul %[[ARG1]], %[[STRIDE0]] : !llvm.i32 // CHECK32: %[[OFFA1:.*]] = llvm.add %[[OFF]], %[[OFFM1]] : !llvm.i32 // CHECK32: %[[CST8:.*]] = llvm.mlir.constant(8 : i64) : !llvm.i32 // CHECK32: %[[OFFM2:.*]] = llvm.mul %[[CST8]], %[[STRIDE1]] : !llvm.i32 // CHECK32: %[[OFFA2:.*]] = llvm.add %[[OFFA1]], %[[OFFM2]] : !llvm.i32 // CHECK32: %[[DESC2:.*]] = llvm.insertvalue %[[OFFA2]], %[[DESC1]][2] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESC3:.*]] = llvm.insertvalue %[[ARG2]], %[[DESC2]][3, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST1:.*]] = llvm.mlir.constant(1 : i64) : !llvm.i32 // CHECK32: %[[DESC4:.*]] = llvm.insertvalue %[[CST1]], %[[DESC3]][4, 1] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[CST62:.*]] = llvm.mlir.constant(62 : i64) : !llvm.i32 // CHECK32: %[[DESC5:.*]] = llvm.insertvalue %[[CST62]], %[[DESC4]][3, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> // CHECK32: %[[DESCSTRIDE0:.*]] = llvm.mul %[[ARG0]], %[[STRIDE0]] : !llvm.i32 // CHECK32: llvm.insertvalue %[[DESCSTRIDE0]], %[[DESC5]][4, 0] : !llvm.struct<(ptr, ptr, i32, array<2 x i32>, array<2 x i32>)> %1 = subview %0[%arg1, 8][62, %arg2][%arg0, 1] : memref<64x4xf32, offset: 0, strides: [4, 1]> to memref<62x?xf32, offset: ?, strides: [?, 1]> return } // ----- // CHECK-LABEL: func @atomic_rmw func @atomic_rmw(%I : memref<10xi32>, %ival : i32, %F : memref<10xf32>, %fval : f32, %i : index) { atomic_rmw "assign" %fval, %F[%i] : (f32, memref<10xf32>) -> f32 // CHECK: llvm.atomicrmw xchg %{{.*}}, %{{.*}} acq_rel atomic_rmw "addi" %ival, %I[%i] : (i32, memref<10xi32>) -> i32 // CHECK: llvm.atomicrmw add %{{.*}}, %{{.*}} acq_rel atomic_rmw "maxs" %ival, %I[%i] : (i32, memref<10xi32>) -> i32 // CHECK: llvm.atomicrmw max %{{.*}}, %{{.*}} acq_rel atomic_rmw "mins" %ival, %I[%i] : (i32, memref<10xi32>) -> i32 // CHECK: llvm.atomicrmw min %{{.*}}, %{{.*}} acq_rel atomic_rmw "maxu" %ival, %I[%i] : (i32, memref<10xi32>) -> i32 // CHECK: llvm.atomicrmw umax %{{.*}}, %{{.*}} acq_rel atomic_rmw "minu" %ival, %I[%i] : (i32, memref<10xi32>) -> i32 // CHECK: llvm.atomicrmw umin %{{.*}}, %{{.*}} acq_rel atomic_rmw "addf" %fval, %F[%i] : (f32, memref<10xf32>) -> f32 // CHECK: llvm.atomicrmw fadd %{{.*}}, %{{.*}} acq_rel return } // ----- // CHECK-LABEL: func @generic_atomic_rmw func @generic_atomic_rmw(%I : memref<10xi32>, %i : index) -> i32 { %x = generic_atomic_rmw %I[%i] : memref<10xi32> { ^bb0(%old_value : i32): %c1 = constant 1 : i32 atomic_yield %c1 : i32 } // CHECK: [[init:%.*]] = llvm.load %{{.*}} : !llvm.ptr // CHECK-NEXT: llvm.br ^bb1([[init]] : !llvm.i32) // CHECK-NEXT: ^bb1([[loaded:%.*]]: !llvm.i32): // CHECK-NEXT: [[c1:%.*]] = llvm.mlir.constant(1 : i32) // CHECK-NEXT: [[pair:%.*]] = llvm.cmpxchg %{{.*}}, [[loaded]], [[c1]] // CHECK-SAME: acq_rel monotonic : !llvm.i32 // CHECK-NEXT: [[new:%.*]] = llvm.extractvalue [[pair]][0] // CHECK-NEXT: [[ok:%.*]] = llvm.extractvalue [[pair]][1] // CHECK-NEXT: llvm.cond_br [[ok]], ^bb2, ^bb1([[new]] : !llvm.i32) // CHECK-NEXT: ^bb2: %c2 = constant 2 : i32 %add = addi %c2, %x : i32 return %add : i32 // CHECK-NEXT: [[c2:%.*]] = llvm.mlir.constant(2 : i32) // CHECK-NEXT: [[add:%.*]] = llvm.add [[c2]], [[new]] : !llvm.i32 // CHECK-NEXT: llvm.return [[add]] } // ----- // CHECK-LABEL: func @assume_alignment func @assume_alignment(%0 : memref<4x4xf16>) { // CHECK: %[[PTR:.*]] = llvm.extractvalue %[[MEMREF:.*]][1] : !llvm.struct<(ptr, ptr, i64, array<2 x i64>, array<2 x i64>)> // CHECK-NEXT: %[[ZERO:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[MASK:.*]] = llvm.mlir.constant(15 : index) : !llvm.i64 // CHECK-NEXT: %[[INT:.*]] = llvm.ptrtoint %[[PTR]] : !llvm.ptr to !llvm.i64 // CHECK-NEXT: %[[MASKED_PTR:.*]] = llvm.and %[[INT]], %[[MASK:.*]] : !llvm.i64 // CHECK-NEXT: %[[CONDITION:.*]] = llvm.icmp "eq" %[[MASKED_PTR]], %[[ZERO]] : !llvm.i64 // CHECK-NEXT: "llvm.intr.assume"(%[[CONDITION]]) : (!llvm.i1) -> () assume_alignment %0, 16 : memref<4x4xf16> return } // ----- // CHECK-LABEL: func @mlir_cast_to_llvm // CHECK-SAME: %[[ARG:.*]]: func @mlir_cast_to_llvm(%0 : vector<2xf16>) -> !llvm.vec<2 x half> { %1 = llvm.mlir.cast %0 : vector<2xf16> to !llvm.vec<2 x half> // CHECK-NEXT: llvm.return %[[ARG]] return %1 : !llvm.vec<2 x half> } // CHECK-LABEL: func @mlir_cast_from_llvm // CHECK-SAME: %[[ARG:.*]]: func @mlir_cast_from_llvm(%0 : !llvm.vec<2 x half>) -> vector<2xf16> { %1 = llvm.mlir.cast %0 : !llvm.vec<2 x half> to vector<2xf16> // CHECK-NEXT: llvm.return %[[ARG]] return %1 : vector<2xf16> } // ----- // CHECK-LABEL: func @mlir_cast_to_llvm // CHECK-SAME: %[[ARG:.*]]: func @mlir_cast_to_llvm(%0 : f16) -> !llvm.half { %1 = llvm.mlir.cast %0 : f16 to !llvm.half // CHECK-NEXT: llvm.return %[[ARG]] return %1 : !llvm.half } // CHECK-LABEL: func @mlir_cast_from_llvm // CHECK-SAME: %[[ARG:.*]]: func @mlir_cast_from_llvm(%0 : !llvm.half) -> f16 { %1 = llvm.mlir.cast %0 : !llvm.half to f16 // CHECK-NEXT: llvm.return %[[ARG]] return %1 : f16 } // ----- // CHECK-LABEL: func @bfloat // CHECK-SAME: !llvm.bfloat) -> !llvm.bfloat func @bfloat(%arg0: bf16) -> bf16 { return %arg0 : bf16 } // CHECK-NEXT: return %{{.*}} : !llvm.bfloat // ----- // CHECK-LABEL: func @memref_index // CHECK-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, // CHECK-SAME: %arg2: !llvm.i64, %arg3: !llvm.i64, %arg4: !llvm.i64) // CHECK-SAME: -> !llvm.struct<(ptr, ptr, i64, array<1 x i64>, array<1 x i64>)> // CHECK32-LABEL: func @memref_index // CHECK32-SAME: %arg0: !llvm.ptr, %arg1: !llvm.ptr, // CHECK32-SAME: %arg2: !llvm.i32, %arg3: !llvm.i32, %arg4: !llvm.i32) // CHECK32-SAME: -> !llvm.struct<(ptr, ptr, i32, array<1 x i32>, array<1 x i32>)> func @memref_index(%arg0: memref<32xindex>) -> memref<32xindex> { return %arg0 : memref<32xindex> } // ----- // CHECK-LABEL: func @rank_of_unranked // CHECK32-LABEL: func @rank_of_unranked func @rank_of_unranked(%unranked: memref<*xi32>) { %rank = rank %unranked : memref<*xi32> return } // CHECK-NEXT: llvm.mlir.undef // CHECK-NEXT: llvm.insertvalue // CHECK-NEXT: llvm.insertvalue // CHECK-NEXT: llvm.extractvalue %{{.*}}[0] : !llvm.struct<(i64, ptr)> // CHECK32: llvm.extractvalue %{{.*}}[0] : !llvm.struct<(i32, ptr)> // CHECK-LABEL: func @rank_of_ranked // CHECK32-LABEL: func @rank_of_ranked func @rank_of_ranked(%ranked: memref) { %rank = rank %ranked : memref return } // CHECK: llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK32: llvm.mlir.constant(1 : index) : !llvm.i32 // ----- // CHECK-LABEL: func @dim_of_unranked // CHECK32-LABEL: func @dim_of_unranked func @dim_of_unranked(%unranked: memref<*xi32>) -> index { %c0 = constant 0 : index %dim = dim %unranked, %c0 : memref<*xi32> return %dim : index } // CHECK-NEXT: llvm.mlir.undef : !llvm.struct<(i64, ptr)> // CHECK-NEXT: llvm.insertvalue // CHECK-NEXT: %[[UNRANKED_DESC:.*]] = llvm.insertvalue // CHECK-NEXT: %[[C0:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[RANKED_DESC:.*]] = llvm.extractvalue %[[UNRANKED_DESC]][1] // CHECK-SAME: : !llvm.struct<(i64, ptr)> // CHECK-NEXT: %[[ZERO_D_DESC:.*]] = llvm.bitcast %[[RANKED_DESC]] // CHECK-SAME: : !llvm.ptr to !llvm.ptr, ptr, i64)>> // CHECK-NEXT: %[[C2_i32:.*]] = llvm.mlir.constant(2 : i32) : !llvm.i32 // CHECK-NEXT: %[[C0_:.*]] = llvm.mlir.constant(0 : index) : !llvm.i64 // CHECK-NEXT: %[[OFFSET_PTR:.*]] = llvm.getelementptr %[[ZERO_D_DESC]]{{\[}} // CHECK-SAME: %[[C0_]], %[[C2_i32]]] : (!llvm.ptr, ptr, // CHECK-SAME: i64)>>, !llvm.i64, !llvm.i32) -> !llvm.ptr // CHECK-NEXT: %[[C1:.*]] = llvm.mlir.constant(1 : index) : !llvm.i64 // CHECK-NEXT: %[[INDEX_INC:.*]] = llvm.add %[[C1]], %[[C0]] : !llvm.i64 // CHECK-NEXT: %[[SIZE_PTR:.*]] = llvm.getelementptr %[[OFFSET_PTR]]{{\[}} // CHECK-SAME: %[[INDEX_INC]]] : (!llvm.ptr, !llvm.i64) -> !llvm.ptr // CHECK-NEXT: %[[SIZE:.*]] = llvm.load %[[SIZE_PTR]] : !llvm.ptr // CHECK-NEXT: llvm.return %[[SIZE]] : !llvm.i64 // CHECK32: %[[SIZE:.*]] = llvm.load %{{.*}} : !llvm.ptr // CHECK32-NEXT: llvm.return %[[SIZE]] : !llvm.i32 diff --git a/mlir/test/Conversion/StandardToLLVM/invalid.mlir b/mlir/test/Conversion/StandardToLLVM/invalid.mlir index 40acf4bc9d49..a8513a805d9e 100644 --- a/mlir/test/Conversion/StandardToLLVM/invalid.mlir +++ b/mlir/test/Conversion/StandardToLLVM/invalid.mlir @@ -1,40 +1,40 @@ // RUN: mlir-opt %s -convert-std-to-llvm -verify-diagnostics -split-input-file func @mlir_cast_to_llvm(%0 : index) -> !llvm.i64 { // expected-error@+1 {{'llvm.mlir.cast' op type must be non-index integer types, float types, or vector of mentioned types}} %1 = llvm.mlir.cast %0 : index to !llvm.i64 return %1 : !llvm.i64 } // ----- func @mlir_cast_from_llvm(%0 : !llvm.i64) -> index { // expected-error@+1 {{'llvm.mlir.cast' op type must be non-index integer types, float types, or vector of mentioned types}} %1 = llvm.mlir.cast %0 : !llvm.i64 to index return %1 : index } // ----- func @mlir_cast_to_llvm_int(%0 : i32) -> !llvm.i64 { // expected-error@+1 {{failed to legalize operation 'llvm.mlir.cast' that was explicitly marked illegal}} %1 = llvm.mlir.cast %0 : i32 to !llvm.i64 return %1 : !llvm.i64 } // ----- func @mlir_cast_to_llvm_vec(%0 : vector<1x1xf32>) -> !llvm.vec<1 x float> { // expected-error@+1 {{'llvm.mlir.cast' op only 1-d vector is allowed}} %1 = llvm.mlir.cast %0 : vector<1x1xf32> to !llvm.vec<1 x float> return %1 : !llvm.vec<1 x float> } // ----- // Should not crash on unsupported types in function signatures. -func @unsupported_signature() -> tensor<10 x i32> +func private @unsupported_signature() -> tensor<10 x i32> // ----- -func @partially_supported_signature() -> (vector<10 x i32>, tensor<10 x i32>) +func private @partially_supported_signature() -> (vector<10 x i32>, tensor<10 x i32>) diff --git a/mlir/test/Dialect/Affine/loop-unswitch.mlir b/mlir/test/Dialect/Affine/loop-unswitch.mlir index 0080e379427f..bbeb90dc4602 100644 --- a/mlir/test/Dialect/Affine/loop-unswitch.mlir +++ b/mlir/test/Dialect/Affine/loop-unswitch.mlir @@ -1,258 +1,258 @@ // RUN: mlir-opt %s -split-input-file -test-affine-loop-unswitch | FileCheck %s // CHECK-DAG: #[[$SET:.*]] = affine_set<(d0) : (d0 - 2 >= 0)> // CHECK-LABEL: func @if_else_imperfect func @if_else_imperfect(%A : memref<100xi32>, %B : memref<100xi32>, %v : i32) { // CHECK: %[[A:.*]]: memref<100xi32>, %[[B:.*]]: memref affine.for %i = 0 to 100 { affine.store %v, %A[%i] : memref<100xi32> affine.for %j = 0 to 100 { affine.store %v, %A[%j] : memref<100xi32> affine.if affine_set<(d0) : (d0 - 2 >= 0)>(%i) { affine.store %v, %B[%j] : memref<100xi32> } call @external() : () -> () } affine.store %v, %A[%i] : memref<100xi32> } return } -func @external() +func private @external() // CHECK: affine.for %[[I:.*]] = 0 to 100 { // CHECK-NEXT: affine.store %{{.*}}, %[[A]][%[[I]]] // CHECK-NEXT: affine.if #[[$SET]](%[[I]]) { // CHECK-NEXT: affine.for %[[J:.*]] = 0 to 100 { // CHECK-NEXT: affine.store %{{.*}}, %[[A]][%[[J]]] // CHECK-NEXT: affine.store %{{.*}}, %[[B]][%[[J]]] // CHECK-NEXT: call // CHECK-NEXT: } // CHECK-NEXT: } else { // CHECK-NEXT: affine.for %[[JJ:.*]] = 0 to 100 { // CHECK-NEXT: affine.store %{{.*}}, %[[A]][%[[J]]] // CHECK-NEXT: call // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: affine.store %{{.*}}, %[[A]][%[[I]]] // CHECK-NEXT: } // CHECK-NEXT: return // ----- -func @foo() -func @bar() -func @abc() -func @xyz() +func private @foo() +func private @bar() +func private @abc() +func private @xyz() // CHECK-LABEL: func @if_then_perfect func @if_then_perfect(%A : memref<100xi32>, %v : i32) { affine.for %i = 0 to 100 { affine.for %j = 0 to 100 { affine.for %k = 0 to 100 { affine.if affine_set<(d0) : (d0 - 2 >= 0)>(%i) { affine.store %v, %A[%i] : memref<100xi32> } } } } return } // CHECK: affine.for // CHECK-NEXT: affine.if // CHECK-NEXT: affine.for // CHECK-NEXT: affine.for // CHECK-NOT: else // CHECK-LABEL: func @if_else_perfect func @if_else_perfect(%A : memref<100xi32>, %v : i32) { affine.for %i = 0 to 99 { affine.for %j = 0 to 100 { affine.for %k = 0 to 100 { call @foo() : () -> () affine.if affine_set<(d0, d1) : (d0 - 2 >= 0, -d1 + 80 >= 0)>(%i, %j) { affine.store %v, %A[%i] : memref<100xi32> call @abc() : () -> () } else { affine.store %v, %A[%i + 1] : memref<100xi32> call @xyz() : () -> () } call @bar() : () -> () } } } return } // CHECK: affine.for // CHECK-NEXT: affine.for // CHECK-NEXT: affine.if // CHECK-NEXT: affine.for // CHECK-NEXT: call @foo // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%{{.*}}] // CHECK-NEXT: call @abc // CHECK-NEXT: call @bar // CHECK-NEXT: } // CHECK-NEXT: else // CHECK-NEXT: affine.for // CHECK-NEXT: call @foo // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%{{.*}} + 1] // CHECK-NEXT: call @xyz // CHECK-NEXT: call @bar // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-LABEL: func @if_then_imperfect func @if_then_imperfect(%A : memref<100xi32>, %N : index, %v: i32) { affine.for %i = 0 to 100 { affine.store %v, %A[0] : memref<100xi32> affine.if affine_set<(d0) : (d0 - 2 >= 0)>(%N) { affine.store %v, %A[%i] : memref<100xi32> } } return } // CHECK: affine.if // CHECK-NEXT: affine.for // CHECK-NEXT: affine.store // CHECK-NEXT: affine.store // CHECK-NEXT: } // CHECK-NEXT: } else { // CHECK-NEXT: affine.for // CHECK-NEXT: affine.store // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return // Check if unused operands are dropped: hence, hoisting is possible. // CHECK-LABEL: func @hoist_after_canonicalize func @hoist_after_canonicalize() { affine.for %i = 0 to 100 { affine.for %j = 0 to 100 { affine.if affine_set<(d0) : (d0 - 2 >= 0)>(%j) { affine.if affine_set<(d0, d1) : (d0 - 1 >= 0, -d0 + 99 >= 0)>(%i, %j) { // The call to external is to avoid DCE on affine.if. call @foo() : () -> () } } } } return } // CHECK: affine.for // CHECK-NEXT: affine.if // CHECK-NEXT: affine.for // CHECK-NEXT: affine.if // CHECK-NEXT: call // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return // CHECK-LABEL: func @handle_dead_if func @handle_dead_if(%N : index) { affine.for %i = 0 to 100 { affine.if affine_set<(d0) : (d0 - 1 >= 0, -d0 + 99 >= 0)>(%N) { } } return } // CHECK-NEXT: affine.for // CHECK-NEXT: } // CHECK-NEXT: return // ----- // A test case with affine.parallel. #flb1 = affine_map<(d0) -> (d0 * 3)> #fub1 = affine_map<(d0) -> (d0 * 3 + 3)> #flb0 = affine_map<(d0) -> (d0 * 16)> #fub0 = affine_map<(d0) -> (d0 * 16 + 16)> #pub1 = affine_map<(d0)[s0] -> (s0, d0 * 3 + 3)> #pub0 = affine_map<(d0)[s0] -> (s0, d0 * 16 + 16)> #lb1 = affine_map<(d0) -> (d0 * 480)> #ub1 = affine_map<(d0)[s0] -> (s0, d0 * 480 + 480)> #lb0 = affine_map<(d0) -> (d0 * 110)> #ub0 = affine_map<(d0)[s0] -> (d0 * 110 + 110, s0 floordiv 3)> #set0 = affine_set<(d0, d1)[s0, s1] : (d0 * -16 + s0 - 16 >= 0, d1 * -3 + s1 - 3 >= 0)> // CHECK-LABEL: func @perfect_if_else func @perfect_if_else(%arg0 : memref, %arg1 : memref, %v : f64, %arg4 : index, %arg5 : index, %arg6 : index, %sym : index) { affine.for %arg7 = #lb0(%arg5) to min #ub0(%arg5)[%sym] { affine.parallel (%i0, %j0) = (0, 0) to (symbol(%sym), 100) step (10, 10) { affine.for %arg8 = #lb1(%arg4) to min #ub1(%arg4)[%sym] { affine.if #set0(%arg6, %arg7)[%sym, %sym] { affine.for %arg9 = #flb0(%arg6) to #fub0(%arg6) { affine.for %arg10 = #flb1(%arg7) to #fub1(%arg7) { affine.store %v, %arg0[0, 0] : memref } } } else { affine.for %arg9 = #lb0(%arg6) to min #pub0(%arg6)[%sym] { affine.for %arg10 = #lb1(%arg7) to min #pub1(%arg7)[%sym] { affine.store %v, %arg0[0, 0] : memref } } } } } } return } // CHECK: affine.for // CHECK-NEXT: affine.if // CHECK-NEXT: affine.parallel // CHECK-NEXT: affine.for // CHECK-NEXT: affine.for // CHECK-NEXT: affine.for // CHECK-NEXT: affine.store // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } else { // CHECK-NEXT: affine.parallel // CHECK-NEXT: affine.for // CHECK-NEXT: affine.for // CHECK-NEXT: affine.for // CHECK-NEXT: affine.store // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: } // With multiple if ops in a function, the test pass just looks for the first if // op that it is able to successfully hoist. // CHECK-LABEL: func @multiple_if func @multiple_if(%N : index) { affine.if affine_set<() : (0 == 0)>() { call @external() : () -> () } affine.for %i = 0 to 100 { affine.if affine_set<()[s0] : (s0 >= 0)>()[%N] { call @external() : () -> () } } return } // CHECK: affine.if // CHECK-NEXT: call // CHECK-NEXT: } // CHECK-NEXT: affine.if // CHECK-NEXT: affine.for // CHECK-NEXT: call // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: return -func @external() +func private @external() diff --git a/mlir/test/Dialect/Affine/simplify-affine-structures.mlir b/mlir/test/Dialect/Affine/simplify-affine-structures.mlir index 664c6c0e5284..dad930cef061 100644 --- a/mlir/test/Dialect/Affine/simplify-affine-structures.mlir +++ b/mlir/test/Dialect/Affine/simplify-affine-structures.mlir @@ -1,327 +1,327 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -simplify-affine-structures | FileCheck %s // CHECK-DAG: #[[$SET_EMPTY:.*]] = affine_set<() : (1 == 0)> // CHECK-DAG: #[[$SET_2D:.*]] = affine_set<(d0, d1) : (d0 - 100 == 0, d1 - 10 == 0, -d0 + 100 >= 0, d1 >= 0)> // CHECK-DAG: #[[$SET_7_11:.*]] = affine_set<(d0, d1) : (d0 * 7 + d1 * 5 + 88 == 0, d0 * 5 - d1 * 11 + 60 == 0, d0 * 11 + d1 * 7 - 24 == 0, d0 * 7 + d1 * 5 + 88 == 0)> // An external function that we will use in bodies to avoid DCE. -func @external() -> () +func private @external() -> () // CHECK-LABEL: func @test_gaussian_elimination_empty_set0() { func @test_gaussian_elimination_empty_set0() { affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (2 == 0)>(%arg0, %arg1) { call @external() : () -> () } } } return } // CHECK-LABEL: func @test_gaussian_elimination_empty_set1() { func @test_gaussian_elimination_empty_set1() { affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (1 >= 0, -1 >= 0)> (%arg0, %arg1) { call @external() : () -> () } } } return } // CHECK-LABEL: func @test_gaussian_elimination_non_empty_set2() { func @test_gaussian_elimination_non_empty_set2() { affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: #[[$SET_2D]](%arg0, %arg1) affine.if affine_set<(d0, d1) : (d0 - 100 == 0, d1 - 10 == 0, -d0 + 100 >= 0, d1 >= 0, d1 + 101 >= 0)>(%arg0, %arg1) { call @external() : () -> () } } } return } // CHECK-LABEL: func @test_gaussian_elimination_empty_set3() { func @test_gaussian_elimination_empty_set3() { %c7 = constant 7 : index %c11 = constant 11 : index affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1)[s0, s1] : (d0 - s0 == 0, d0 + s0 == 0, s0 - 1 == 0)>(%arg0, %arg1)[%c7, %c11] { call @external() : () -> () } } } return } // Set for test case: test_gaussian_elimination_non_empty_set4 #set_2d_non_empty = affine_set<(d0, d1)[s0, s1] : (d0 * 7 + d1 * 5 + s0 * 11 + s1 == 0, d0 * 5 - d1 * 11 + s0 * 7 + s1 == 0, d0 * 11 + d1 * 7 - s0 * 5 + s1 == 0, d0 * 7 + d1 * 5 + s0 * 11 + s1 == 0)> // CHECK-LABEL: func @test_gaussian_elimination_non_empty_set4() { func @test_gaussian_elimination_non_empty_set4() { %c7 = constant 7 : index %c11 = constant 11 : index affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: #[[$SET_7_11]](%arg0, %arg1) affine.if #set_2d_non_empty(%arg0, %arg1)[%c7, %c11] { call @external() : () -> () } } } return } // Add invalid constraints to previous non-empty set to make it empty. #set_2d_empty = affine_set<(d0, d1)[s0, s1] : (d0 * 7 + d1 * 5 + s0 * 11 + s1 == 0, d0 * 5 - d1 * 11 + s0 * 7 + s1 == 0, d0 * 11 + d1 * 7 - s0 * 5 + s1 == 0, d0 * 7 + d1 * 5 + s0 * 11 + s1 == 0, d0 - 1 == 0, d0 + 2 == 0)> // CHECK-LABEL: func @test_gaussian_elimination_empty_set5() { func @test_gaussian_elimination_empty_set5() { %c7 = constant 7 : index %c11 = constant 11 : index affine.for %arg0 = 1 to 10 { affine.for %arg1 = 1 to 100 { // CHECK: #[[$SET_EMPTY]]() affine.if #set_2d_empty(%arg0, %arg1)[%c7, %c11] { call @external() : () -> () } } } return } // This is an artificially created system to exercise the worst case behavior of // FM elimination - as a safeguard against improperly constructed constraint // systems or fuzz input. #set_fuzz_virus = affine_set<(d0, d1, d2, d3, d4, d5) : ( 1089234*d0 + 203472*d1 + 82342 >= 0, -55*d0 + 24*d1 + 238*d2 - 234*d3 - 9743 >= 0, -5445*d0 - 284*d1 + 23*d2 + 34*d3 - 5943 >= 0, -5445*d0 + 284*d1 + 238*d2 - 34*d3 >= 0, 445*d0 + 284*d1 + 238*d2 + 39*d3 >= 0, -545*d0 + 214*d1 + 218*d2 - 94*d3 >= 0, 44*d0 - 184*d1 - 231*d2 + 14*d3 >= 0, -45*d0 + 284*d1 + 138*d2 - 39*d3 >= 0, 154*d0 - 84*d1 + 238*d2 - 34*d3 >= 0, 54*d0 - 284*d1 - 223*d2 + 384*d3 >= 0, -55*d0 + 284*d1 + 23*d2 + 34*d3 >= 0, 54*d0 - 84*d1 + 28*d2 - 34*d3 >= 0, 54*d0 - 24*d1 - 23*d2 + 34*d3 >= 0, -55*d0 + 24*d1 + 23*d2 + 4*d3 >= 0, 15*d0 - 84*d1 + 238*d2 - 3*d3 >= 0, 5*d0 - 24*d1 - 223*d2 + 84*d3 >= 0, -5*d0 + 284*d1 + 23*d2 - 4*d3 >= 0, 14*d0 + 4*d2 + 7234 >= 0, -174*d0 - 534*d2 + 9834 >= 0, 194*d0 - 954*d2 + 9234 >= 0, 47*d0 - 534*d2 + 9734 >= 0, -194*d0 - 934*d2 + 984 >= 0, -947*d0 - 953*d2 + 234 >= 0, 184*d0 - 884*d2 + 884 >= 0, -174*d0 + 834*d2 + 234 >= 0, 844*d0 + 634*d2 + 9874 >= 0, -797*d2 - 79*d3 + 257 >= 0, 2039*d0 + 793*d2 - 99*d3 - 24*d4 + 234*d5 >= 0, 78*d2 - 788*d5 + 257 >= 0, d3 - (d5 + 97*d0) floordiv 423 >= 0, 234* (d0 + d3 mod 5 floordiv 2342) mod 2309 + (d0 + 2038*d3) floordiv 208 >= 0, 239* (d0 + 2300 * d3) floordiv 2342 mod 2309 mod 239423 == 0, d0 + d3 mod 2642 + (d3 + 2*d0) mod 1247 mod 2038 mod 2390 mod 2039 floordiv 55 >= 0 )> // CHECK-LABEL: func @test_fuzz_explosion func @test_fuzz_explosion(%arg0 : index, %arg1 : index, %arg2 : index, %arg3 : index) { affine.for %arg4 = 1 to 10 { affine.for %arg5 = 1 to 100 { affine.if #set_fuzz_virus(%arg4, %arg5, %arg0, %arg1, %arg2, %arg3) { call @external() : () -> () } } } return } // CHECK-LABEL: func @test_empty_set(%arg0: index) { func @test_empty_set(%N : index) { affine.for %i = 0 to 10 { affine.for %j = 0 to 10 { // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (d0 - d1 >= 0, d1 - d0 - 1 >= 0)>(%i, %j) { "foo"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0) : (d0 >= 0, -d0 - 1 >= 0)>(%i) { "bar"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0) : (d0 >= 0, -d0 - 1 >= 0)>(%i) { "foo"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0)[s0, s1] : (d0 >= 0, -d0 + s0 - 1 >= 0, -s0 >= 0)>(%i)[%N, %N] { "bar"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() // The set below implies d0 = d1; so d1 >= d0, but d0 >= d1 + 1. affine.if affine_set<(d0, d1, d2) : (d0 - d1 == 0, d2 - d0 >= 0, d0 - d1 - 1 >= 0)>(%i, %j, %N) { "foo"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() // The set below has rational solutions but no integer solutions; GCD test catches it. affine.if affine_set<(d0, d1) : (d0*2 -d1*2 - 1 == 0, d0 >= 0, -d0 + 100 >= 0, d1 >= 0, -d1 + 100 >= 0)>(%i, %j) { "foo"() : () -> () } // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (d1 == 0, d0 - 1 >= 0, - d0 - 1 >= 0)>(%i, %j) { "foo"() : () -> () } } } // The tests below test GCDTightenInequalities(). affine.for %k = 0 to 10 { affine.for %l = 0 to 10 { // Empty because no multiple of 8 lies between 4 and 7. // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0) : (8*d0 - 4 >= 0, -8*d0 + 7 >= 0)>(%k) { "foo"() : () -> () } // Same as above but with equalities and inequalities. // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (d0 - 4*d1 == 0, 4*d1 - 5 >= 0, -4*d1 + 7 >= 0)>(%k, %l) { "foo"() : () -> () } // Same as above but with a combination of multiple identifiers. 4*d0 + // 8*d1 here is a multiple of 4, and so can't lie between 9 and 11. GCD // tightening will tighten constraints to 4*d0 + 8*d1 >= 12 and 4*d0 + // 8*d1 <= 8; hence infeasible. // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1) : (4*d0 + 8*d1 - 9 >= 0, -4*d0 - 8*d1 + 11 >= 0)>(%k, %l) { "foo"() : () -> () } // Same as above but with equalities added into the mix. // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0, d1, d2) : (d0 - 4*d2 == 0, d0 + 8*d1 - 9 >= 0, -d0 - 8*d1 + 11 >= 0)>(%k, %k, %l) { "foo"() : () -> () } } } affine.for %m = 0 to 10 { // CHECK: affine.if #[[$SET_EMPTY]]() affine.if affine_set<(d0) : (d0 mod 2 - 3 == 0)> (%m) { "foo"() : () -> () } } return } // ----- // An external function that we will use in bodies to avoid DCE. -func @external() -> () +func private @external() -> () // CHECK-DAG: #[[$SET:.*]] = affine_set<()[s0] : (s0 >= 0, -s0 + 50 >= 0) // CHECK-DAG: #[[$EMPTY_SET:.*]] = affine_set<() : (1 == 0) // CHECK-DAG: #[[$UNIV_SET:.*]] = affine_set<() : (0 == 0) // CHECK-LABEL: func @simplify_set func @simplify_set(%a : index, %b : index) { // CHECK: affine.if #[[$SET]] affine.if affine_set<(d0, d1) : (d0 - d1 + d1 + d0 >= 0, 2 >= 0, d0 >= 0, -d0 + 50 >= 0, -d0 + 100 >= 0)>(%a, %b) { call @external() : () -> () } // CHECK: affine.if #[[$EMPTY_SET]] affine.if affine_set<(d0, d1) : (d0 mod 2 - 1 == 0, d0 - 2 * (d0 floordiv 2) == 0)>(%a, %b) { call @external() : () -> () } // CHECK: affine.if #[[$UNIV_SET]] affine.if affine_set<(d0, d1) : (1 >= 0, 3 >= 0)>(%a, %b) { call @external() : () -> () } return } // ----- // CHECK-DAG: -> (s0 * 2 + 1) // Test "op local" simplification on affine.apply. DCE on addi will not happen. func @affine.apply(%N : index) { %v = affine.apply affine_map<(d0, d1) -> (d0 + d1 + 1)>(%N, %N) addi %v, %v : index // CHECK: affine.apply #map{{.*}}()[%arg0] // CHECK-NEXT: addi return } // ----- // CHECK-LABEL: func @simplify_zero_dim_map func @simplify_zero_dim_map(%in : memref) -> f32 { %out = affine.load %in[] : memref return %out : f32 } // ----- // Tests the simplification of a semi-affine expression in various cases. // CHECK-DAG: #[[$map0:.*]] = affine_map<()[s0, s1] -> (-(s1 floordiv s0) + 2)> // CHECK-DAG: #[[$map1:.*]] = affine_map<()[s0, s1] -> (-(s1 floordiv s0) + 42)> // Tests the simplification of a semi-affine expression with a modulo operation on a floordiv and multiplication. // CHECK-LABEL: func @semiaffine_mod func @semiaffine_mod(%arg0: index, %arg1: index) -> index { %a = affine.apply affine_map<(d0)[s0] ->((-((d0 floordiv s0) * s0) + s0 * s0) mod s0)> (%arg0)[%arg1] // CHECK: %[[CST:.*]] = constant 0 return %a : index } // Tests the simplification of a semi-affine expression with a nested floordiv and a floordiv on modulo operation. // CHECK-LABEL: func @semiaffine_floordiv func @semiaffine_floordiv(%arg0: index, %arg1: index) -> index { %a = affine.apply affine_map<(d0)[s0] ->((-((d0 floordiv s0) * s0) + ((2 * s0) mod (3 * s0))) floordiv s0)> (%arg0)[%arg1] // CHECK: affine.apply #[[$map0]]()[%arg1, %arg0] return %a : index } // Tests the simplification of a semi-affine expression with a ceildiv operation and a division of constant 0 by a symbol. // CHECK-LABEL: func @semiaffine_ceildiv func @semiaffine_ceildiv(%arg0: index, %arg1: index) -> index { %a = affine.apply affine_map<(d0)[s0] ->((-((d0 floordiv s0) * s0) + s0 * 42 + ((5-5) floordiv s0)) ceildiv s0)> (%arg0)[%arg1] // CHECK: affine.apply #[[$map1]]()[%arg1, %arg0] return %a : index } // Tests the simplification of a semi-affine expression with a nested ceildiv operation and further simplifications after performing ceildiv. // CHECK-LABEL: func @semiaffine_composite_floor func @semiaffine_composite_floor(%arg0: index, %arg1: index) -> index { %a = affine.apply affine_map<(d0)[s0] ->(((((s0 * 2) ceildiv 4) * 5) + s0 * 42) ceildiv s0)> (%arg0)[%arg1] // CHECK: %[[CST:.*]] = constant 47 return %a : index } // Tests the simplification of a semi-affine expression with a modulo operation with a second operand that simplifies to symbol. // CHECK-LABEL: func @semiaffine_unsimplified_symbol func @semiaffine_unsimplified_symbol(%arg0: index, %arg1: index) -> index { %a = affine.apply affine_map<(d0)[s0] ->(s0 mod (2 * s0 - s0))> (%arg0)[%arg1] // CHECK: %[[CST:.*]] = constant 0 return %a : index } diff --git a/mlir/test/Dialect/GPU/async-region.mlir b/mlir/test/Dialect/GPU/async-region.mlir index 8e0b81f57e1f..32e613e773fe 100644 --- a/mlir/test/Dialect/GPU/async-region.mlir +++ b/mlir/test/Dialect/GPU/async-region.mlir @@ -1,27 +1,27 @@ // RUN: mlir-opt -gpu-async-region %s | FileCheck %s // CHECK: module attributes {gpu.container_module} module attributes {gpu.container_module} { gpu.module @kernels { gpu.func @kernel() kernel { gpu.return } } - func @foo() -> () + func private @foo() -> () // CHECK-LABEL:func @async(%{{.*}}: index) func @async(%sz : index) { // CHECK: %[[t0:.*]] = gpu.wait async // CHECK: %[[t1:.*]] = gpu.launch_func async [%[[t0]]] gpu.launch_func @kernels::@kernel blocks in (%sz, %sz, %sz) threads in (%sz, %sz, %sz) // CHECK: %[[t2:.*]] = gpu.launch_func async [%[[t1]]] gpu.launch_func @kernels::@kernel blocks in (%sz, %sz, %sz) threads in (%sz, %sz, %sz) // CHECK: gpu.wait [%[[t2]]] // CHECK: call @foo call @foo() : () -> () return } } diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir index f7d19bc66c8d..9117f6aee3f0 100644 --- a/mlir/test/Dialect/LLVMIR/invalid.mlir +++ b/mlir/test/Dialect/LLVMIR/invalid.mlir @@ -1,654 +1,654 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics // expected-error@+1{{llvm.noalias argument attribute of non boolean type}} func @invalid_noalias(%arg0: !llvm.i32 {llvm.noalias = 3}) { "llvm.return"() : () -> () } // ----- // expected-error@+1{{llvm.align argument attribute of non integer type}} func @invalid_align(%arg0: !llvm.i32 {llvm.align = "foo"}) { "llvm.return"() : () -> () } //////////////////////////////////////////////////////////////////////////////// // Check that parser errors are properly produced and do not crash the compiler. // ----- func @icmp_non_string(%arg0 : !llvm.i32, %arg1 : !llvm.i16) { // expected-error@+1 {{invalid kind of attribute specified}} llvm.icmp 42 %arg0, %arg0 : !llvm.i32 return } // ----- func @icmp_wrong_string(%arg0 : !llvm.i32, %arg1 : !llvm.i16) { // expected-error@+1 {{'foo' is an incorrect value of the 'predicate' attribute}} llvm.icmp "foo" %arg0, %arg0 : !llvm.i32 return } // ----- func @alloca_missing_input_result_type(%size : !llvm.i64) { // expected-error@+1 {{expected trailing function type with one argument and one result}} llvm.alloca %size x !llvm.i32 : () -> () } // ----- func @alloca_missing_input_type() { // expected-error@+1 {{expected trailing function type with one argument and one result}} llvm.alloca %size x !llvm.i32 : () -> (!llvm.ptr) } // ----- func @alloca_missing_result_type() { // expected-error@+1 {{expected trailing function type with one argument and one result}} llvm.alloca %size x !llvm.i32 : (!llvm.i64) -> () } // ----- func @alloca_non_function_type() { // expected-error@+1 {{expected trailing function type with one argument and one result}} llvm.alloca %size x !llvm.i32 : !llvm.ptr } // ----- func @alloca_non_integer_alignment() { // expected-error@+1 {{expected integer alignment}} llvm.alloca %size x !llvm.i32 {alignment = 3.0} : !llvm.ptr } // ----- func @gep_missing_input_result_type(%pos : !llvm.i64, %base : !llvm.ptr) { // expected-error@+1 {{2 operands present, but expected 0}} llvm.getelementptr %base[%pos] : () -> () } // ----- func @gep_missing_input_type(%pos : !llvm.i64, %base : !llvm.ptr) { // expected-error@+1 {{2 operands present, but expected 0}} llvm.getelementptr %base[%pos] : () -> (!llvm.ptr) } // ----- func @gep_missing_result_type(%pos : !llvm.i64, %base : !llvm.ptr) { // expected-error@+1 {{op requires one result}} llvm.getelementptr %base[%pos] : (!llvm.ptr, !llvm.i64) -> () } // ----- func @gep_non_function_type(%pos : !llvm.i64, %base : !llvm.ptr) { // expected-error@+1 {{invalid kind of type specified}} llvm.getelementptr %base[%pos] : !llvm.ptr } // ----- func @load_non_llvm_type(%foo : memref) { // expected-error@+1 {{expected LLVM IR dialect type}} llvm.load %foo : memref } // ----- func @load_non_ptr_type(%foo : !llvm.float) { // expected-error@+1 {{expected LLVM pointer type}} llvm.load %foo : !llvm.float } // ----- func @store_non_llvm_type(%foo : memref, %bar : !llvm.float) { // expected-error@+1 {{expected LLVM IR dialect type}} llvm.store %bar, %foo : memref } // ----- func @store_non_ptr_type(%foo : !llvm.float, %bar : !llvm.float) { // expected-error@+1 {{expected LLVM pointer type}} llvm.store %bar, %foo : !llvm.float } // ----- func @call_non_function_type(%callee : !llvm.func, %arg : !llvm.i8) { // expected-error@+1 {{expected function type}} llvm.call %callee(%arg) : !llvm.func } // ----- func @invalid_call() { // expected-error@+1 {{'llvm.call' op must have either a `callee` attribute or at least an operand}} "llvm.call"() : () -> () } // ----- func @call_non_function_type(%callee : !llvm.func, %arg : !llvm.i8) { // expected-error@+1 {{expected function type}} llvm.call %callee(%arg) : !llvm.func } // ----- func @call_unknown_symbol() { // expected-error@+1 {{'llvm.call' op 'missing_callee' does not reference a symbol in the current scope}} llvm.call @missing_callee() : () -> () } // ----- -func @standard_func_callee() +func private @standard_func_callee() func @call_non_llvm() { // expected-error@+1 {{'llvm.call' op 'standard_func_callee' does not reference a valid LLVM function}} llvm.call @standard_func_callee() : () -> () } // ----- func @call_non_llvm_indirect(%arg0 : i32) { // expected-error@+1 {{'llvm.call' op operand #0 must be LLVM dialect type, but got 'i32'}} "llvm.call"(%arg0) : (i32) -> () } // ----- llvm.func @callee_func(!llvm.i8) -> () func @callee_arg_mismatch(%arg0 : !llvm.i32) { // expected-error@+1 {{'llvm.call' op operand type mismatch for operand 0: '!llvm.i32' != '!llvm.i8'}} llvm.call @callee_func(%arg0) : (!llvm.i32) -> () } // ----- func @indirect_callee_arg_mismatch(%arg0 : !llvm.i32, %callee : !llvm.ptr>) { // expected-error@+1 {{'llvm.call' op operand type mismatch for operand 0: '!llvm.i32' != '!llvm.i8'}} "llvm.call"(%callee, %arg0) : (!llvm.ptr>, !llvm.i32) -> () } // ----- llvm.func @callee_func() -> (!llvm.i8) func @callee_return_mismatch() { // expected-error@+1 {{'llvm.call' op result type mismatch: '!llvm.i32' != '!llvm.i8'}} %res = llvm.call @callee_func() : () -> (!llvm.i32) } // ----- func @indirect_callee_return_mismatch(%callee : !llvm.ptr>) { // expected-error@+1 {{'llvm.call' op result type mismatch: '!llvm.i32' != '!llvm.i8'}} "llvm.call"(%callee) : (!llvm.ptr>) -> (!llvm.i32) } // ----- func @call_too_many_results(%callee : () -> (i32,i32)) { // expected-error@+1 {{expected function with 0 or 1 result}} llvm.call %callee() : () -> (i32, i32) } // ----- func @call_non_llvm_result(%callee : () -> (i32)) { // expected-error@+1 {{expected result to have LLVM type}} llvm.call %callee() : () -> (i32) } // ----- func @call_non_llvm_input(%callee : (i32) -> (), %arg : i32) { // expected-error@+1 {{expected LLVM types as inputs}} llvm.call %callee(%arg) : (i32) -> () } // ----- func @constant_wrong_type() { // expected-error@+1 {{only supports integer, float, string or elements attributes}} llvm.mlir.constant(@constant_wrong_type) : !llvm.ptr> } // ----- func @insertvalue_non_llvm_type(%a : i32, %b : i32) { // expected-error@+1 {{expected LLVM IR Dialect type}} llvm.insertvalue %a, %b[0] : i32 } // ----- func @insertvalue_non_array_position() { // Note the double-type, otherwise attribute parsing consumes the trailing // type of the op as the (wrong) attribute type. // expected-error@+1 {{invalid kind of attribute specified}} llvm.insertvalue %a, %b 0 : i32 : !llvm.struct<(i32)> } // ----- func @insertvalue_non_integer_position() { // expected-error@+1 {{expected an array of integer literals}} llvm.insertvalue %a, %b[0.0] : !llvm.struct<(i32)> } // ----- func @insertvalue_struct_out_of_bounds() { // expected-error@+1 {{position out of bounds}} llvm.insertvalue %a, %b[1] : !llvm.struct<(i32)> } // ----- func @insertvalue_array_out_of_bounds() { // expected-error@+1 {{position out of bounds}} llvm.insertvalue %a, %b[1] : !llvm.array<1 x i32> } // ----- func @insertvalue_wrong_nesting() { // expected-error@+1 {{expected wrapped LLVM IR structure/array type}} llvm.insertvalue %a, %b[0,0] : !llvm.struct<(i32)> } // ----- func @extractvalue_non_llvm_type(%a : i32, %b : i32) { // expected-error@+1 {{expected LLVM IR Dialect type}} llvm.extractvalue %b[0] : i32 } // ----- func @extractvalue_non_array_position() { // Note the double-type, otherwise attribute parsing consumes the trailing // type of the op as the (wrong) attribute type. // expected-error@+1 {{invalid kind of attribute specified}} llvm.extractvalue %b 0 : i32 : !llvm.struct<(i32)> } // ----- func @extractvalue_non_integer_position() { // expected-error@+1 {{expected an array of integer literals}} llvm.extractvalue %b[0.0] : !llvm.struct<(i32)> } // ----- func @extractvalue_struct_out_of_bounds() { // expected-error@+1 {{position out of bounds}} llvm.extractvalue %b[1] : !llvm.struct<(i32)> } // ----- func @extractvalue_array_out_of_bounds() { // expected-error@+1 {{position out of bounds}} llvm.extractvalue %b[1] : !llvm.array<1 x i32> } // ----- func @extractvalue_wrong_nesting() { // expected-error@+1 {{expected wrapped LLVM IR structure/array type}} llvm.extractvalue %b[0,0] : !llvm.struct<(i32)> } // ----- func @invalid_vector_type_1(%arg0: !llvm.vec<4 x float>, %arg1: !llvm.i32, %arg2: !llvm.float) { // expected-error@+1 {{expected LLVM IR dialect vector type for operand #1}} %0 = llvm.extractelement %arg2[%arg1 : !llvm.i32] : !llvm.float } // ----- func @invalid_vector_type_2(%arg0: !llvm.vec<4 x float>, %arg1: !llvm.i32, %arg2: !llvm.float) { // expected-error@+1 {{expected LLVM IR dialect vector type for operand #1}} %0 = llvm.insertelement %arg2, %arg2[%arg1 : !llvm.i32] : !llvm.float } // ----- func @invalid_vector_type_3(%arg0: !llvm.vec<4 x float>, %arg1: !llvm.i32, %arg2: !llvm.float) { // expected-error@+1 {{expected LLVM IR dialect vector type for operand #1}} %0 = llvm.shufflevector %arg2, %arg2 [0 : i32, 0 : i32, 0 : i32, 0 : i32, 7 : i32] : !llvm.float, !llvm.float } // ----- func @null_non_llvm_type() { // expected-error@+1 {{expected LLVM IR pointer type}} llvm.mlir.null : !llvm.i32 } // ----- func @nvvm_invalid_shfl_pred_1(%arg0 : !llvm.i32, %arg1 : !llvm.i32, %arg2 : !llvm.i32, %arg3 : !llvm.i32) { // expected-error@+1 {{expected return type to be a two-element struct with i1 as the second element}} %0 = nvvm.shfl.sync.bfly %arg0, %arg3, %arg1, %arg2 {return_value_and_is_valid} : !llvm.i32 } // ----- func @nvvm_invalid_shfl_pred_2(%arg0 : !llvm.i32, %arg1 : !llvm.i32, %arg2 : !llvm.i32, %arg3 : !llvm.i32) { // expected-error@+1 {{expected return type to be a two-element struct with i1 as the second element}} %0 = nvvm.shfl.sync.bfly %arg0, %arg3, %arg1, %arg2 {return_value_and_is_valid} : !llvm.struct<(i32)> } // ----- func @nvvm_invalid_shfl_pred_3(%arg0 : !llvm.i32, %arg1 : !llvm.i32, %arg2 : !llvm.i32, %arg3 : !llvm.i32) { // expected-error@+1 {{expected return type to be a two-element struct with i1 as the second element}} %0 = nvvm.shfl.sync.bfly %arg0, %arg3, %arg1, %arg2 {return_value_and_is_valid} : !llvm.struct<(i32, i32)> } // ----- func @nvvm_invalid_mma_0(%a0 : !llvm.half, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{expected operands to be 4 s followed by either 4 s or 8 floats}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="row", blayout="col"} : (!llvm.half, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(float, float, float, float, float, float, float, float)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @nvvm_invalid_mma_1(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{expected result type to be a struct of either 4 s or 8 floats}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="row", blayout="col"} : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(float, float, float, float, float, float, float, half)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, half)> } // ----- func @nvvm_invalid_mma_2(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{alayout and blayout attributes must be set to either "row" or "col"}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(float, float, float, float, float, float, float, float)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @nvvm_invalid_mma_3(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.vec<2 x half>, %c1 : !llvm.vec<2 x half>, %c2 : !llvm.vec<2 x half>, %c3 : !llvm.vec<2 x half>) { // expected-error@+1 {{unimplemented mma.sync variant}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3 {alayout="row", blayout="col"} : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>) -> !llvm.struct<(float, float, float, float, float, float, float, float)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @nvvm_invalid_mma_4(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{unimplemented mma.sync variant}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="row", blayout="col"} : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(vec<2 x half>, vec<2 x half>, vec<2 x half>, vec<2 x half>)> llvm.return %0 : !llvm.struct<(vec<2 x half>, vec<2 x half>, vec<2 x half>, vec<2 x half>)> } // ----- func @nvvm_invalid_mma_5(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{unimplemented mma.sync variant}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="col", blayout="row"} : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(float, float, float, float, float, float, float, float)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @nvvm_invalid_mma_6(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{invalid kind of type specified}} %0 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="col", blayout="row"} : !llvm.struct<(float, float, float, float, float, float, float, float)> llvm.return %0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @nvvm_invalid_mma_7(%a0 : !llvm.vec<2 x half>, %a1 : !llvm.vec<2 x half>, %b0 : !llvm.vec<2 x half>, %b1 : !llvm.vec<2 x half>, %c0 : !llvm.float, %c1 : !llvm.float, %c2 : !llvm.float, %c3 : !llvm.float, %c4 : !llvm.float, %c5 : !llvm.float, %c6 : !llvm.float, %c7 : !llvm.float) { // expected-error@+1 {{op requires one result}} %0:2 = nvvm.mma.sync %a0, %a1, %b0, %b1, %c0, %c1, %c2, %c3, %c4, %c5, %c6, %c7 {alayout="col", blayout="row"} : (!llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.vec<2 x half>, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float, !llvm.float) -> (!llvm.struct<(float, float, float, float, float, float, float, float)>, !llvm.i32) llvm.return %0#0 : !llvm.struct<(float, float, float, float, float, float, float, float)> } // ----- func @atomicrmw_expected_ptr(%f32 : !llvm.float) { // expected-error@+1 {{operand #0 must be LLVM pointer to floating point LLVM type or LLVM integer type}} %0 = "llvm.atomicrmw"(%f32, %f32) {bin_op=11, ordering=1} : (!llvm.float, !llvm.float) -> !llvm.float llvm.return } // ----- func @atomicrmw_mismatched_operands(%f32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{expected LLVM IR element type for operand #0 to match type for operand #1}} %0 = "llvm.atomicrmw"(%f32_ptr, %i32) {bin_op=11, ordering=1} : (!llvm.ptr, !llvm.i32) -> !llvm.float llvm.return } // ----- func @atomicrmw_mismatched_operands(%f32_ptr : !llvm.ptr, %f32 : !llvm.float) { // expected-error@+1 {{expected LLVM IR result type to match type for operand #1}} %0 = "llvm.atomicrmw"(%f32_ptr, %f32) {bin_op=11, ordering=1} : (!llvm.ptr, !llvm.float) -> !llvm.i32 llvm.return } // ----- func @atomicrmw_expected_float(%i32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{expected LLVM IR floating point type}} %0 = llvm.atomicrmw fadd %i32_ptr, %i32 unordered : !llvm.i32 llvm.return } // ----- func @atomicrmw_unexpected_xchg_type(%i1_ptr : !llvm.ptr, %i1 : !llvm.i1) { // expected-error@+1 {{unexpected LLVM IR type for 'xchg' bin_op}} %0 = llvm.atomicrmw xchg %i1_ptr, %i1 unordered : !llvm.i1 llvm.return } // ----- func @atomicrmw_expected_int(%f32_ptr : !llvm.ptr, %f32 : !llvm.float) { // expected-error@+1 {{expected LLVM IR integer type}} %0 = llvm.atomicrmw max %f32_ptr, %f32 unordered : !llvm.float llvm.return } // ----- func @cmpxchg_expected_ptr(%f32_ptr : !llvm.ptr, %f32 : !llvm.float) { // expected-error@+1 {{op operand #0 must be LLVM pointer to LLVM integer type or LLVM pointer type}} %0 = "llvm.cmpxchg"(%f32, %f32, %f32) {success_ordering=2,failure_ordering=2} : (!llvm.float, !llvm.float, !llvm.float) -> !llvm.struct<(float, i1)> llvm.return } // ----- func @cmpxchg_mismatched_operands(%i64_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{expected LLVM IR element type for operand #0 to match type for all other operands}} %0 = "llvm.cmpxchg"(%i64_ptr, %i32, %i32) {success_ordering=2,failure_ordering=2} : (!llvm.ptr, !llvm.i32, !llvm.i32) -> !llvm.struct<(i32, i1)> llvm.return } // ----- func @cmpxchg_unexpected_type(%i1_ptr : !llvm.ptr, %i1 : !llvm.i1) { // expected-error@+1 {{unexpected LLVM IR type}} %0 = llvm.cmpxchg %i1_ptr, %i1, %i1 monotonic monotonic : !llvm.i1 llvm.return } // ----- func @cmpxchg_at_least_monotonic_success(%i32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{ordering must be at least 'monotonic'}} %0 = llvm.cmpxchg %i32_ptr, %i32, %i32 unordered monotonic : !llvm.i32 llvm.return } // ----- func @cmpxchg_at_least_monotonic_failure(%i32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{ordering must be at least 'monotonic'}} %0 = llvm.cmpxchg %i32_ptr, %i32, %i32 monotonic unordered : !llvm.i32 llvm.return } // ----- func @cmpxchg_failure_release(%i32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{failure ordering cannot be 'release' or 'acq_rel'}} %0 = llvm.cmpxchg %i32_ptr, %i32, %i32 acq_rel release : !llvm.i32 llvm.return } // ----- func @cmpxchg_failure_acq_rel(%i32_ptr : !llvm.ptr, %i32 : !llvm.i32) { // expected-error@+1 {{failure ordering cannot be 'release' or 'acq_rel'}} %0 = llvm.cmpxchg %i32_ptr, %i32, %i32 acq_rel acq_rel : !llvm.i32 llvm.return } // ----- llvm.func @foo(!llvm.i32) -> !llvm.i32 llvm.func @__gxx_personality_v0(...) -> !llvm.i32 llvm.func @bad_landingpad(%arg0: !llvm.ptr>) attributes { personality = @__gxx_personality_v0} { %0 = llvm.mlir.constant(3 : i32) : !llvm.i32 %1 = llvm.mlir.constant(2 : i32) : !llvm.i32 %2 = llvm.invoke @foo(%1) to ^bb1 unwind ^bb2 : (!llvm.i32) -> !llvm.i32 ^bb1: // pred: ^bb0 llvm.return %1 : !llvm.i32 ^bb2: // pred: ^bb0 // expected-error@+1 {{clause #0 is not a known constant - null, addressof, bitcast}} %3 = llvm.landingpad cleanup (catch %1 : !llvm.i32) (catch %arg0 : !llvm.ptr>) : !llvm.struct<(ptr, i32)> llvm.return %0 : !llvm.i32 } // ----- llvm.func @foo(!llvm.i32) -> !llvm.i32 llvm.func @__gxx_personality_v0(...) -> !llvm.i32 llvm.func @caller(%arg0: !llvm.i32) -> !llvm.i32 attributes { personality = @__gxx_personality_v0} { %0 = llvm.mlir.constant(1 : i32) : !llvm.i32 %1 = llvm.alloca %0 x !llvm.ptr : (!llvm.i32) -> !llvm.ptr> // expected-note@+1 {{global addresses expected as operand to bitcast used in clauses for landingpad}} %2 = llvm.bitcast %1 : !llvm.ptr> to !llvm.ptr %3 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (!llvm.i32) -> !llvm.i32 ^bb1: // pred: ^bb0 llvm.return %0 : !llvm.i32 ^bb2: // pred: ^bb0 // expected-error@+1 {{constant clauses expected}} %5 = llvm.landingpad (catch %2 : !llvm.ptr) : !llvm.struct<(ptr, i32)> llvm.return %0 : !llvm.i32 } // ----- llvm.func @foo(!llvm.i32) -> !llvm.i32 llvm.func @__gxx_personality_v0(...) -> !llvm.i32 llvm.func @caller(%arg0: !llvm.i32) -> !llvm.i32 attributes { personality = @__gxx_personality_v0} { %0 = llvm.mlir.constant(1 : i32) : !llvm.i32 %1 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (!llvm.i32) -> !llvm.i32 ^bb1: // pred: ^bb0 llvm.return %0 : !llvm.i32 ^bb2: // pred: ^bb0 // expected-error@+1 {{landingpad instruction expects at least one clause or cleanup attribute}} %2 = llvm.landingpad : !llvm.struct<(ptr, i32)> llvm.return %0 : !llvm.i32 } // ----- llvm.func @foo(!llvm.i32) -> !llvm.i32 llvm.func @__gxx_personality_v0(...) -> !llvm.i32 llvm.func @caller(%arg0: !llvm.i32) -> !llvm.i32 attributes { personality = @__gxx_personality_v0 } { %0 = llvm.mlir.constant(1 : i32) : !llvm.i32 %1 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (!llvm.i32) -> !llvm.i32 ^bb1: // pred: ^bb0 llvm.return %0 : !llvm.i32 ^bb2: // pred: ^bb0 %2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> // expected-error@+1 {{'llvm.resume' op expects landingpad value as operand}} llvm.resume %0 : !llvm.i32 } // ----- llvm.func @foo(!llvm.i32) -> !llvm.i32 llvm.func @caller(%arg0: !llvm.i32) -> !llvm.i32 { %0 = llvm.mlir.constant(1 : i32) : !llvm.i32 %1 = llvm.invoke @foo(%0) to ^bb1 unwind ^bb2 : (!llvm.i32) -> !llvm.i32 ^bb1: // pred: ^bb0 llvm.return %0 : !llvm.i32 ^bb2: // pred: ^bb0 // expected-error@+1 {{llvm.landingpad needs to be in a function with a personality}} %2 = llvm.landingpad cleanup : !llvm.struct<(ptr, i32)> llvm.resume %2 : !llvm.struct<(ptr, i32)> } // ----- func @invalid_ordering_in_fence() { // expected-error @+1 {{can be given only acquire, release, acq_rel, and seq_cst orderings}} llvm.fence syncscope("agent") monotonic } // ----- // expected-error @+1 {{invalid data layout descriptor}} module attributes {llvm.data_layout = "#vjkr32"} { func @invalid_data_layout() } diff --git a/mlir/test/Dialect/Linalg/bufferize.mlir b/mlir/test/Dialect/Linalg/bufferize.mlir index 866ded2fbe0e..5a0e4e86eaa3 100644 --- a/mlir/test/Dialect/Linalg/bufferize.mlir +++ b/mlir/test/Dialect/Linalg/bufferize.mlir @@ -1,215 +1,215 @@ // RUN: mlir-opt -linalg-bufferize -split-input-file %s | FileCheck %s #map0 = affine_map<(d0) -> (d0)> // In-depth checking of a basic case, this is testing // - tensor_to_memref / tensor_load materializations are properly inserted // - payload is correctly carried over // - affine maps are correctly carried over // Later tests will not check all these details. // CHECK: #map = affine_map<(d0) -> (d0)> // CHECK-LABEL: func @basic( // CHECK-SAME: %[[TENSOR:.*]]: tensor<4xf32>) -> tensor<4xf32> { // CHECK: %[[MEMREF:.*]] = tensor_to_memref %[[TENSOR]] : memref<4xf32> // CHECK: %[[RESULT_MEMREF:.*]] = alloc() : memref<4xf32> // CHECK: linalg.generic {indexing_maps = [#map, #map], iterator_types = ["parallel"]} // CHECK-SAME: ins(%[[MEMREF]] : memref<4xf32>) // CHECK-SAME: outs(%[[RESULT_MEMREF]] : memref<4xf32>) { // CHECK: ^bb0(%[[RESULT1:.*]]: f32, %[[UNUSED:.*]]: f32): // CHECK: %[[DIM1:.*]] = exp %[[RESULT1]] : f32 // CHECK: linalg.yield %[[DIM1]] : f32 // CHECK: } // CHECK: %[[RESULT:.*]] = tensor_load %[[RESULT_MEMREF]] : memref<4xf32> // CHECK: return %[[RESULT]] : tensor<4xf32> func @basic(%arg0: tensor<4xf32>) -> tensor<4xf32> { %0 = linalg.generic { indexing_maps = [#map0, #map0], iterator_types = ["parallel"] } ins(%arg0 : tensor<4xf32>) { ^bb0(%gen_arg1: f32): %tmp1 = exp %gen_arg1 : f32 linalg.yield %tmp1 : f32 } -> tensor<4xf32> return %0 : tensor<4xf32> } // ----- #map0 = affine_map<(d0) -> (d0)> // CHECK-LABEL: func @multiple_results // CHECK: %[[RESULT0:.*]] = alloc() : memref<4xf32> // CHECK: %[[RESULT1:.*]] = alloc() : memref<4xf32> // CHECK: linalg.generic // CHECK-SAME: ins(%{{.*}} : memref<4xf32>) // CHECK-SAME: outs(%[[RESULT0]], %[[RESULT1]] : memref<4xf32>, memref<4xf32>) func @multiple_results(%arg0: tensor<4xf32>) -> (tensor<4xf32>, tensor<4xf32>) { %0, %1 = linalg.generic { indexing_maps = [#map0, #map0, #map0], iterator_types = ["parallel"] } ins(%arg0 : tensor<4xf32>) { ^bb0(%gen_arg1: f32): %tmp1 = exp %gen_arg1 : f32 linalg.yield %tmp1, %tmp1 : f32, f32 } -> tensor<4xf32>, tensor<4xf32> return %0, %1 : tensor<4xf32>, tensor<4xf32> } // ----- #map_2d = affine_map<(d0, d1) -> (d0, d1)> #map_2d_inv = affine_map<(d0, d1) -> (d1, d0)> // Check that the allocs properly consider the different shapes of the output // operands. The permuted indexing maps translate to different output shapes. // CHECK: #map0 = affine_map<(d0, d1) -> (d0, d1)> // CHECK: #map1 = affine_map<(d0, d1) -> (d1, d0)> // CHECK-LABEL: func @dynamic_results( // CHECK-SAME: %[[ARG:.*]]: tensor // CHECK: %[[MEMREF_ARG:.*]] = tensor_to_memref %[[ARG]] : memref // CHECK: %[[C0:.*]] = constant 0 : index // CHECK: %[[DIM0:.*]] = dim %[[ARG]], %[[C0]] : tensor // CHECK: %[[C1:.*]] = constant 1 : index // CHECK: %[[DIM1:.*]] = dim %[[ARG]], %[[C1]] : tensor // CHECK: %[[RESULT0:.*]] = alloc(%[[DIM0]], %[[DIM1]]) : memref // CHECK: %[[RESULT1:.*]] = alloc(%[[DIM1]], %[[DIM0]]) : memref // CHECK: linalg.generic {indexing_maps = [#map0, #map0, #map1] // CHECK-SAME: ins(%[[MEMREF_ARG]] : memref) // CHECK-SAME: outs(%[[RESULT0]], %[[RESULT1]] : memref, memref) func @dynamic_results(%arg0: tensor) -> (tensor, tensor) { %0, %1 = linalg.generic { indexing_maps = [#map_2d, #map_2d, #map_2d_inv], iterator_types = ["parallel", "parallel"] } ins(%arg0 : tensor) { ^bb0(%gen_arg1: f32): %tmp1 = exp %gen_arg1 : f32 linalg.yield %tmp1, %tmp1 : f32, f32 } -> tensor, tensor return %0, %1 : tensor, tensor } // ----- #accesses = [ affine_map<(i, j, k) -> (j, i, k)>, affine_map<(i, j, k) -> (i, j)> ] #trait = { indexing_maps = #accesses, iterator_types = ["parallel", "parallel", "reduction"] } // Check the bufferization of init tensors. // CHECK-LABEL: func @generic_with_init_tensor( // CHECK-SAME: %[[ARG0_TENSOR:.*]]: tensor<2x3x4xvector<3x4xi4>>, // CHECK-SAME: %[[ARG1_TENSOR:.*]]: tensor<3x2xf32>) -> tensor<3x2xf32> { // CHECK: %[[ARG0_MEMREF:.*]] = tensor_to_memref %[[ARG0_TENSOR]] : memref<2x3x4xvector<3x4xi4>> // CHECK: %[[ARG1_MEMREF:.*]] = tensor_to_memref %[[ARG1_TENSOR]] : memref<3x2xf32> // CHECK: %[[INIT_BUFFER:.*]] = alloc() : memref<3x2xf32> // CHECK: linalg.copy(%[[ARG1_MEMREF]], %[[INIT_BUFFER]]) : memref<3x2xf32>, memref<3x2xf32> // CHECK: linalg.generic // CHECK-SAME: ins(%[[ARG0_MEMREF]] : memref<2x3x4xvector<3x4xi4>>) // CHECK-SAME: outs(%[[INIT_BUFFER]] : memref<3x2xf32>) { func @generic_with_init_tensor(%arg0: tensor<2x3x4xvector<3x4xi4>>, %arg1: tensor<3x2xf32>) -> (tensor<3x2xf32>) { %0 = linalg.generic #trait ins(%arg0 : tensor<2x3x4xvector<3x4xi4>>) init(%arg1 : tensor<3x2xf32>) { ^bb(%v0: vector<3x4xi4>, %v1: f32) : %f0 = constant 0.0 : f32 linalg.yield %f0 : f32 } -> tensor<3x2xf32> return %0 : tensor<3x2xf32> } // ----- // CHECK-DAG: #[[$MAP0:[0-9a-z]*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)> // CHECK-DAG: #[[$MAP1:[0-9a-z]*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1 * 2)> -func @make_index() -> index +func private @make_index() -> index // CHECK-LABEL: func @bufferize_subtensor( // CHECK-SAME: %[[T:[0-9a-z]*]]: tensor func @bufferize_subtensor(%t : tensor) -> (tensor<2x3xf32>, tensor<2x?xf32>) { // CHECK: %[[IDX:.*]] = call @make_index() : () -> index %i0 = call @make_index() : () -> index // CHECK: %[[M0:.*]] = tensor_to_memref %[[T]] : memref // CHECK-NEXT: %[[A0:.*]] = alloc() : memref<2x3xf32> // CHECK-NEXT: %[[SM0:.*]] = subview %[[M0]][0, 0] [2, 3] [1, 1] // CHECK-SAME: memref to memref<2x3xf32, #[[$MAP0]]> // CHECK-NEXT: linalg.copy(%[[SM0]], %[[A0]]) : memref<2x3xf32, #[[$MAP0]]>, memref<2x3xf32> // CHECK-NEXT: %[[RT0:.*]] = tensor_load %[[A0]] : memref<2x3xf32> %st0 = subtensor %t[0, 0][2, 3][1, 1] : tensor to tensor<2x3xf32> // CHECK: %[[M1:.*]] = tensor_to_memref %[[T]] : memref // CHECK-NEXT: %[[A1:.*]] = alloc(%[[IDX]]) : memref<2x?xf32> // CHECK-NEXT: %[[SM1:.*]] = subview %[[M1]][0, %[[IDX]]] [2, %[[IDX]]] [1, 2] // CHECK-SAME: memref to memref<2x?xf32, #[[$MAP1]]> // CHECK-NEXT: linalg.copy(%[[SM1]], %[[A1]]) : memref<2x?xf32, #[[$MAP1]]>, memref<2x?xf32> // CHECK-NEXT: %[[RT1:.*]] = tensor_load %[[A1]] : memref<2x?xf32> %st1 = subtensor %t[0, %i0][2, %i0][1, 2] : tensor to tensor<2x?xf32> // CHECK-NEXT: return %[[RT0]], %[[RT1]] return %st0, %st1 : tensor<2x3xf32>, tensor<2x?xf32> } // ----- // CHECK-DAG: #[[$MAP0:[0-9a-z]*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)> // CHECK-DAG: #[[$MAP1:[0-9a-z]*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1 * 2)> -func @make_index() -> index +func private @make_index() -> index // CHECK-LABEL: func @bufferize_subtensor_insert( // CHECK-SAME: %[[T:[0-9a-z]*]]: tensor // CHECK-SAME: %[[ST0:[0-9a-z]*]]: tensor<2x3xf32> // CHECK-SAME: %[[ST1:[0-9a-z]*]]: tensor<2x?xf32> func @bufferize_subtensor_insert(%t : tensor, %st0 : tensor<2x3xf32>, %st1 : tensor<2x?xf32>) -> (tensor, tensor) { %c0 = constant 0 : index %c1 = constant 1 : index // CHECK: %[[IDX:.*]] = call @make_index() : () -> index %i0 = call @make_index() : () -> index // CHECK-DAG: %[[M0:.*]] = tensor_to_memref %[[T]] : memref // CHECK-DAG: %[[SM0:.*]] = tensor_to_memref %[[ST0]] : memref<2x3xf32> // CHECK-NEXT: %[[C0:.*]] = constant 0 : index // CHECK-NEXT: %[[DIM0:.*]] = dim %[[M0]], %[[C0]] : memref // CHECK-NEXT: %[[C1:.*]] = constant 1 : index // CHECK-NEXT: %[[DIM1:.*]] = dim %[[M0]], %[[C1]] : memref // CHECK-NEXT: %[[M0_COPY:.*]] = alloc(%[[DIM0]], %[[DIM1]]) : memref // CHECK-NEXT: linalg.copy(%[[M0]], %[[M0_COPY]]) : memref, memref // CHECK-NEXT: %[[SUBVIEW0:.*]] = subview %[[M0_COPY]][0, 0] [2, 3] [1, 1] // CHECK-SAME: memref to memref<2x3xf32, #[[$MAP0]]> // CHECK-NEXT: linalg.copy(%[[SM0]], %[[SUBVIEW0]]) : memref<2x3xf32>, memref<2x3xf32, #[[$MAP0]]> // CHECK-NEXT: %[[RT0:.*]] = tensor_load %[[M0_COPY]] : memref %t0 = subtensor_insert %st0 into %t[0, 0][2, 3][1, 1] : tensor<2x3xf32> into tensor // CHECK-DAG: %[[M1:.*]] = tensor_to_memref %[[T]] : memref // CHECK-DAG: %[[SM1:.*]] = tensor_to_memref %[[ST1]] : memref<2x?xf32> // CHECK-NEXT: %[[C0:.*]] = constant 0 : index // CHECK-NEXT: %[[DIM0:.*]] = dim %[[M1]], %[[C0]] : memref // CHECK-NEXT: %[[C1:.*]] = constant 1 : index // CHECK-NEXT: %[[DIM1:.*]] = dim %[[M1]], %[[C1]] : memref // CHECK-NEXT: %[[M1_COPY:.*]] = alloc(%[[DIM0]], %[[DIM1]]) : memref // CHECK-NEXT: linalg.copy(%[[M1]], %[[M1_COPY]]) : memref, memref // CHECK-NEXT: %[[SUBVIEW1:.*]] = subview %[[M1_COPY]][0, %[[IDX]]] [2, %[[IDX]]] [1, 2] // CHECK-SAME: memref to memref<2x?xf32, #[[$MAP1]]> // CHECK-NEXT: linalg.copy(%[[SM1]], %[[SUBVIEW1]]) : memref<2x?xf32>, memref<2x?xf32, #[[$MAP1]]> // CHECK-NEXT: %[[RT1:.*]] = tensor_load %[[M1_COPY]] : memref %t1 = subtensor_insert %st1 into %t[0, %i0][2, %i0][1, 2] : tensor<2x?xf32> into tensor // CHECK: return %[[RT0]], %[[RT1]] return %t0, %t1: tensor, tensor } diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir index bd91f3bde403..dd44e3d2933a 100644 --- a/mlir/test/Dialect/SCF/canonicalize.mlir +++ b/mlir/test/Dialect/SCF/canonicalize.mlir @@ -1,174 +1,174 @@ // RUN: mlir-opt %s -pass-pipeline='func(canonicalize)' | FileCheck %s func @single_iteration(%A: memref) { %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c6 = constant 6 : index %c7 = constant 7 : index %c10 = constant 10 : index scf.parallel (%i0, %i1, %i2) = (%c0, %c3, %c7) to (%c1, %c6, %c10) step (%c1, %c2, %c3) { %c42 = constant 42 : i32 store %c42, %A[%i0, %i1, %i2] : memref scf.yield } return } // CHECK-LABEL: func @single_iteration( // CHECK-SAME: [[ARG0:%.*]]: memref) { // CHECK: [[C0:%.*]] = constant 0 : index // CHECK: [[C2:%.*]] = constant 2 : index // CHECK: [[C3:%.*]] = constant 3 : index // CHECK: [[C6:%.*]] = constant 6 : index // CHECK: [[C7:%.*]] = constant 7 : index // CHECK: [[C42:%.*]] = constant 42 : i32 // CHECK: scf.parallel ([[V0:%.*]]) = ([[C3]]) to ([[C6]]) step ([[C2]]) { // CHECK: store [[C42]], [[ARG0]]{{\[}}[[C0]], [[V0]], [[C7]]] : memref // CHECK: scf.yield // CHECK: } // CHECK: return // ----- func @no_iteration(%A: memref) { %c0 = constant 0 : index %c1 = constant 1 : index scf.parallel (%i0, %i1) = (%c0, %c0) to (%c1, %c0) step (%c1, %c1) { %c42 = constant 42 : i32 store %c42, %A[%i0, %i1] : memref scf.yield } return } // CHECK-LABEL: func @no_iteration( // CHECK-SAME: [[ARG0:%.*]]: memref) { // CHECK: [[C0:%.*]] = constant 0 : index // CHECK: [[C1:%.*]] = constant 1 : index // CHECK: [[C42:%.*]] = constant 42 : i32 // CHECK: scf.parallel ([[V1:%.*]]) = ([[C0]]) to ([[C0]]) step ([[C1]]) { // CHECK: store [[C42]], [[ARG0]]{{\[}}[[C0]], [[V1]]] : memref // CHECK: scf.yield // CHECK: } // CHECK: return // ----- func @one_unused() -> (index) { %c0 = constant 0 : index %c1 = constant 1 : index %true = constant true %0, %1 = scf.if %true -> (index, index) { scf.yield %c0, %c1 : index, index } else { scf.yield %c0, %c1 : index, index } return %1 : index } // CHECK-LABEL: func @one_unused // CHECK: [[C0:%.*]] = constant 1 : index // CHECK: [[C1:%.*]] = constant true // CHECK: [[V0:%.*]] = scf.if [[C1]] -> (index) { // CHECK: scf.yield [[C0]] : index // CHECK: } else // CHECK: scf.yield [[C0]] : index // CHECK: } // CHECK: return [[V0]] : index // ----- func @nested_unused() -> (index) { %c0 = constant 0 : index %c1 = constant 1 : index %true = constant true %0, %1 = scf.if %true -> (index, index) { %2, %3 = scf.if %true -> (index, index) { scf.yield %c0, %c1 : index, index } else { scf.yield %c0, %c1 : index, index } scf.yield %2, %3 : index, index } else { scf.yield %c0, %c1 : index, index } return %1 : index } // CHECK-LABEL: func @nested_unused // CHECK: [[C0:%.*]] = constant 1 : index // CHECK: [[C1:%.*]] = constant true // CHECK: [[V0:%.*]] = scf.if [[C1]] -> (index) { // CHECK: [[V1:%.*]] = scf.if [[C1]] -> (index) { // CHECK: scf.yield [[C0]] : index // CHECK: } else // CHECK: scf.yield [[C0]] : index // CHECK: } // CHECK: scf.yield [[V1]] : index // CHECK: } else // CHECK: scf.yield [[C0]] : index // CHECK: } // CHECK: return [[V0]] : index // ----- -func @side_effect() {} +func private @side_effect() {} func @all_unused() { %c0 = constant 0 : index %c1 = constant 1 : index %true = constant true %0, %1 = scf.if %true -> (index, index) { call @side_effect() : () -> () scf.yield %c0, %c1 : index, index } else { call @side_effect() : () -> () scf.yield %c0, %c1 : index, index } return } // CHECK-LABEL: func @all_unused // CHECK: [[C1:%.*]] = constant true // CHECK: scf.if [[C1]] { // CHECK: call @side_effect() : () -> () // CHECK: } else // CHECK: call @side_effect() : () -> () // CHECK: } // CHECK: return // ----- -func @make_i32() -> i32 +func private @make_i32() -> i32 func @for_yields_2(%lb : index, %ub : index, %step : index) -> i32 { %a = call @make_i32() : () -> (i32) %b = scf.for %i = %lb to %ub step %step iter_args(%0 = %a) -> i32 { scf.yield %0 : i32 } return %b : i32 } // CHECK-LABEL: func @for_yields_2 // CHECK-NEXT: %[[R:.*]] = call @make_i32() : () -> i32 // CHECK-NEXT: return %[[R]] : i32 func @for_yields_3(%lb : index, %ub : index, %step : index) -> (i32, i32, i32) { %a = call @make_i32() : () -> (i32) %b = call @make_i32() : () -> (i32) %r:3 = scf.for %i = %lb to %ub step %step iter_args(%0 = %a, %1 = %a, %2 = %b) -> (i32, i32, i32) { %c = call @make_i32() : () -> (i32) scf.yield %0, %c, %2 : i32, i32, i32 } return %r#0, %r#1, %r#2 : i32, i32, i32 } // CHECK-LABEL: func @for_yields_3 // CHECK-NEXT: %[[a:.*]] = call @make_i32() : () -> i32 // CHECK-NEXT: %[[b:.*]] = call @make_i32() : () -> i32 // CHECK-NEXT: %[[r1:.*]] = scf.for {{.*}} iter_args(%arg4 = %[[a]]) -> (i32) { // CHECK-NEXT: %[[c:.*]] = call @make_i32() : () -> i32 // CHECK-NEXT: scf.yield %[[c]] : i32 // CHECK-NEXT: } // CHECK-NEXT: return %[[a]], %[[r1]], %[[b]] : i32, i32, i32 diff --git a/mlir/test/Dialect/SPIRV/types.mlir b/mlir/test/Dialect/SPIRV/types.mlir index ebd120a10bf9..7b96f3dd2232 100644 --- a/mlir/test/Dialect/SPIRV/types.mlir +++ b/mlir/test/Dialect/SPIRV/types.mlir @@ -1,524 +1,524 @@ // RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s // TODO: Add more tests after switching to the generic parser. //===----------------------------------------------------------------------===// // ArrayType //===----------------------------------------------------------------------===// -// CHECK: func @scalar_array_type(!spv.array<16 x f32>, !spv.array<8 x i32>) -func @scalar_array_type(!spv.array<16xf32>, !spv.array<8 x i32>) -> () +// CHECK: func private @scalar_array_type(!spv.array<16 x f32>, !spv.array<8 x i32>) +func private @scalar_array_type(!spv.array<16xf32>, !spv.array<8 x i32>) -> () -// CHECK: func @vector_array_type(!spv.array<32 x vector<4xf32>>) -func @vector_array_type(!spv.array< 32 x vector<4xf32> >) -> () +// CHECK: func private @vector_array_type(!spv.array<32 x vector<4xf32>>) +func private @vector_array_type(!spv.array< 32 x vector<4xf32> >) -> () -// CHECK: func @array_type_stride(!spv.array<4 x !spv.array<4 x f32, stride=4>, stride=128>) -func @array_type_stride(!spv.array< 4 x !spv.array<4 x f32, stride=4>, stride = 128>) -> () +// CHECK: func private @array_type_stride(!spv.array<4 x !spv.array<4 x f32, stride=4>, stride=128>) +func private @array_type_stride(!spv.array< 4 x !spv.array<4 x f32, stride=4>, stride = 128>) -> () // ----- // expected-error @+1 {{expected '<'}} -func @missing_left_angle_bracket(!spv.array 4xf32>) -> () +func private @missing_left_angle_bracket(!spv.array 4xf32>) -> () // ----- // expected-error @+1 {{expected single integer for array element count}} -func @missing_count(!spv.array) -> () +func private @missing_count(!spv.array) -> () // ----- // expected-error @+1 {{expected 'x' in dimension list}} -func @missing_x(!spv.array<4 f32>) -> () +func private @missing_x(!spv.array<4 f32>) -> () // ----- // expected-error @+1 {{expected non-function type}} -func @missing_element_type(!spv.array<4x>) -> () +func private @missing_element_type(!spv.array<4x>) -> () // ----- // expected-error @+1 {{expected non-function type}} -func @cannot_parse_type(!spv.array<4xblabla>) -> () +func private @cannot_parse_type(!spv.array<4xblabla>) -> () // ----- // expected-error @+1 {{expected single integer for array element count}} -func @more_than_one_dim(!spv.array<4x3xf32>) -> () +func private @more_than_one_dim(!spv.array<4x3xf32>) -> () // ----- // expected-error @+1 {{only 1-D vector allowed but found 'vector<4x3xf32>'}} -func @non_1D_vector(!spv.array<4xvector<4x3xf32>>) -> () +func private @non_1D_vector(!spv.array<4xvector<4x3xf32>>) -> () // ----- // expected-error @+1 {{cannot use 'tensor<4xf32>' to compose SPIR-V types}} -func @tensor_type(!spv.array<4xtensor<4xf32>>) -> () +func private @tensor_type(!spv.array<4xtensor<4xf32>>) -> () // ----- // expected-error @+1 {{cannot use 'bf16' to compose SPIR-V types}} -func @bf16_type(!spv.array<4xbf16>) -> () +func private @bf16_type(!spv.array<4xbf16>) -> () // ----- // expected-error @+1 {{only 1/8/16/32/64-bit integer type allowed but found 'i256'}} -func @i256_type(!spv.array<4xi256>) -> () +func private @i256_type(!spv.array<4xi256>) -> () // ----- // expected-error @+1 {{cannot use 'index' to compose SPIR-V types}} -func @index_type(!spv.array<4xindex>) -> () +func private @index_type(!spv.array<4xindex>) -> () // ----- // expected-error @+1 {{cannot use '!llvm.i32' to compose SPIR-V types}} -func @llvm_type(!spv.array<4x!llvm.i32>) -> () +func private @llvm_type(!spv.array<4x!llvm.i32>) -> () // ----- // expected-error @+1 {{ArrayStride must be greater than zero}} -func @array_type_zero_stride(!spv.array<4xi32, stride=0>) -> () +func private @array_type_zero_stride(!spv.array<4xi32, stride=0>) -> () // ----- // expected-error @+1 {{expected array length greater than 0}} -func @array_type_zero_length(!spv.array<0xf32>) -> () +func private @array_type_zero_length(!spv.array<0xf32>) -> () // ----- //===----------------------------------------------------------------------===// // PointerType //===----------------------------------------------------------------------===// // CHECK: @bool_ptr_type(!spv.ptr) -func @bool_ptr_type(!spv.ptr) -> () +func private @bool_ptr_type(!spv.ptr) -> () // CHECK: @scalar_ptr_type(!spv.ptr) -func @scalar_ptr_type(!spv.ptr) -> () +func private @scalar_ptr_type(!spv.ptr) -> () // CHECK: @vector_ptr_type(!spv.ptr, PushConstant>) -func @vector_ptr_type(!spv.ptr,PushConstant>) -> () +func private @vector_ptr_type(!spv.ptr,PushConstant>) -> () // ----- // expected-error @+1 {{expected '<'}} -func @missing_left_angle_bracket(!spv.ptr f32, Uniform>) -> () +func private @missing_left_angle_bracket(!spv.ptr f32, Uniform>) -> () // ----- // expected-error @+1 {{expected ','}} -func @missing_comma(!spv.ptr) -> () +func private @missing_comma(!spv.ptr) -> () // ----- // expected-error @+1 {{expected non-function type}} -func @missing_pointee_type(!spv.ptr<, Uniform>) -> () +func private @missing_pointee_type(!spv.ptr<, Uniform>) -> () // ----- // expected-error @+1 {{unknown storage class: SomeStorageClass}} -func @unknown_storage_class(!spv.ptr) -> () +func private @unknown_storage_class(!spv.ptr) -> () // ----- //===----------------------------------------------------------------------===// // RuntimeArrayType //===----------------------------------------------------------------------===// -// CHECK: func @scalar_runtime_array_type(!spv.rtarray, !spv.rtarray) -func @scalar_runtime_array_type(!spv.rtarray, !spv.rtarray) -> () +// CHECK: func private @scalar_runtime_array_type(!spv.rtarray, !spv.rtarray) +func private @scalar_runtime_array_type(!spv.rtarray, !spv.rtarray) -> () -// CHECK: func @vector_runtime_array_type(!spv.rtarray>) -func @vector_runtime_array_type(!spv.rtarray< vector<4xf32> >) -> () +// CHECK: func private @vector_runtime_array_type(!spv.rtarray>) +func private @vector_runtime_array_type(!spv.rtarray< vector<4xf32> >) -> () -// CHECK: func @runtime_array_type_stride(!spv.rtarray) -func @runtime_array_type_stride(!spv.rtarray) -> () +// CHECK: func private @runtime_array_type_stride(!spv.rtarray) +func private @runtime_array_type_stride(!spv.rtarray) -> () // ----- // expected-error @+1 {{expected '<'}} -func @missing_left_angle_bracket(!spv.rtarray f32>) -> () +func private @missing_left_angle_bracket(!spv.rtarray f32>) -> () // ----- // expected-error @+1 {{expected non-function type}} -func @missing_element_type(!spv.rtarray<>) -> () +func private @missing_element_type(!spv.rtarray<>) -> () // ----- // expected-error @+1 {{expected non-function type}} -func @redundant_count(!spv.rtarray<4xf32>) -> () +func private @redundant_count(!spv.rtarray<4xf32>) -> () // ----- // expected-error @+1 {{ArrayStride must be greater than zero}} -func @runtime_array_type_zero_stride(!spv.rtarray) -> () +func private @runtime_array_type_zero_stride(!spv.rtarray) -> () // ----- //===----------------------------------------------------------------------===// // ImageType //===----------------------------------------------------------------------===// -// CHECK: func @image_parameters_1D(!spv.image) -func @image_parameters_1D(!spv.image) -> () +// CHECK: func private @image_parameters_1D(!spv.image) +func private @image_parameters_1D(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_one_element(!spv.image) -> () +func private @image_parameters_one_element(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_two_elements(!spv.image) -> () +func private @image_parameters_two_elements(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_three_elements(!spv.image) -> () +func private @image_parameters_three_elements(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_four_elements(!spv.image) -> () +func private @image_parameters_four_elements(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_five_elements(!spv.image) -> () +func private @image_parameters_five_elements(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_six_elements(!spv.image) -> () +func private @image_parameters_six_elements(!spv.image) -> () // ----- // expected-error @+1 {{expected '<'}} -func @image_parameters_delimiter(!spv.image f32, Dim1D, NoDepth, NonArrayed, SingleSampled, SamplerUnknown, Unknown>) -> () +func private @image_parameters_delimiter(!spv.image f32, Dim1D, NoDepth, NonArrayed, SingleSampled, SamplerUnknown, Unknown>) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_nocomma_1(!spv.image) -> () +func private @image_parameters_nocomma_1(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_nocomma_2(!spv.image) -> () +func private @image_parameters_nocomma_2(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_nocomma_3(!spv.image) -> () +func private @image_parameters_nocomma_3(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_nocomma_4(!spv.image) -> () +func private @image_parameters_nocomma_4(!spv.image) -> () // ----- // expected-error @+1 {{expected ','}} -func @image_parameters_nocomma_5(!spv.image) -> () +func private @image_parameters_nocomma_5(!spv.image) -> () // ----- //===----------------------------------------------------------------------===// // StructType //===----------------------------------------------------------------------===// -// CHECK: func @struct_type(!spv.struct<(f32)>) -func @struct_type(!spv.struct<(f32)>) -> () +// CHECK: func private @struct_type(!spv.struct<(f32)>) +func private @struct_type(!spv.struct<(f32)>) -> () -// CHECK: func @struct_type2(!spv.struct<(f32 [0])>) -func @struct_type2(!spv.struct<(f32 [0])>) -> () +// CHECK: func private @struct_type2(!spv.struct<(f32 [0])>) +func private @struct_type2(!spv.struct<(f32 [0])>) -> () -// CHECK: func @struct_type_simple(!spv.struct<(f32, !spv.image)>) -func @struct_type_simple(!spv.struct<(f32, !spv.image)>) -> () +// CHECK: func private @struct_type_simple(!spv.struct<(f32, !spv.image)>) +func private @struct_type_simple(!spv.struct<(f32, !spv.image)>) -> () -// CHECK: func @struct_type_with_offset(!spv.struct<(f32 [0], i32 [4])>) -func @struct_type_with_offset(!spv.struct<(f32 [0], i32 [4])>) -> () +// CHECK: func private @struct_type_with_offset(!spv.struct<(f32 [0], i32 [4])>) +func private @struct_type_with_offset(!spv.struct<(f32 [0], i32 [4])>) -> () -// CHECK: func @nested_struct(!spv.struct<(f32, !spv.struct<(f32, i32)>)>) -func @nested_struct(!spv.struct<(f32, !spv.struct<(f32, i32)>)>) +// CHECK: func private @nested_struct(!spv.struct<(f32, !spv.struct<(f32, i32)>)>) +func private @nested_struct(!spv.struct<(f32, !spv.struct<(f32, i32)>)>) -// CHECK: func @nested_struct_with_offset(!spv.struct<(f32 [0], !spv.struct<(f32 [0], i32 [4])> [4])>) -func @nested_struct_with_offset(!spv.struct<(f32 [0], !spv.struct<(f32 [0], i32 [4])> [4])>) +// CHECK: func private @nested_struct_with_offset(!spv.struct<(f32 [0], !spv.struct<(f32 [0], i32 [4])> [4])>) +func private @nested_struct_with_offset(!spv.struct<(f32 [0], !spv.struct<(f32 [0], i32 [4])> [4])>) -// CHECK: func @struct_type_with_decoration(!spv.struct<(f32 [NonWritable])>) -func @struct_type_with_decoration(!spv.struct<(f32 [NonWritable])>) +// CHECK: func private @struct_type_with_decoration(!spv.struct<(f32 [NonWritable])>) +func private @struct_type_with_decoration(!spv.struct<(f32 [NonWritable])>) -// CHECK: func @struct_type_with_decoration_and_offset(!spv.struct<(f32 [0, NonWritable])>) -func @struct_type_with_decoration_and_offset(!spv.struct<(f32 [0, NonWritable])>) +// CHECK: func private @struct_type_with_decoration_and_offset(!spv.struct<(f32 [0, NonWritable])>) +func private @struct_type_with_decoration_and_offset(!spv.struct<(f32 [0, NonWritable])>) -// CHECK: func @struct_type_with_decoration2(!spv.struct<(f32 [NonWritable], i32 [NonReadable])>) -func @struct_type_with_decoration2(!spv.struct<(f32 [NonWritable], i32 [NonReadable])>) +// CHECK: func private @struct_type_with_decoration2(!spv.struct<(f32 [NonWritable], i32 [NonReadable])>) +func private @struct_type_with_decoration2(!spv.struct<(f32 [NonWritable], i32 [NonReadable])>) -// CHECK: func @struct_type_with_decoration3(!spv.struct<(f32, i32 [NonReadable])>) -func @struct_type_with_decoration3(!spv.struct<(f32, i32 [NonReadable])>) +// CHECK: func private @struct_type_with_decoration3(!spv.struct<(f32, i32 [NonReadable])>) +func private @struct_type_with_decoration3(!spv.struct<(f32, i32 [NonReadable])>) -// CHECK: func @struct_type_with_decoration4(!spv.struct<(f32 [0], i32 [4, NonReadable])>) -func @struct_type_with_decoration4(!spv.struct<(f32 [0], i32 [4, NonReadable])>) +// CHECK: func private @struct_type_with_decoration4(!spv.struct<(f32 [0], i32 [4, NonReadable])>) +func private @struct_type_with_decoration4(!spv.struct<(f32 [0], i32 [4, NonReadable])>) -// CHECK: func @struct_type_with_decoration5(!spv.struct<(f32 [NonWritable, NonReadable])>) -func @struct_type_with_decoration5(!spv.struct<(f32 [NonWritable, NonReadable])>) +// CHECK: func private @struct_type_with_decoration5(!spv.struct<(f32 [NonWritable, NonReadable])>) +func private @struct_type_with_decoration5(!spv.struct<(f32 [NonWritable, NonReadable])>) -// CHECK: func @struct_type_with_decoration6(!spv.struct<(f32, !spv.struct<(i32 [NonWritable, NonReadable])>)>) -func @struct_type_with_decoration6(!spv.struct<(f32, !spv.struct<(i32 [NonWritable, NonReadable])>)>) +// CHECK: func private @struct_type_with_decoration6(!spv.struct<(f32, !spv.struct<(i32 [NonWritable, NonReadable])>)>) +func private @struct_type_with_decoration6(!spv.struct<(f32, !spv.struct<(i32 [NonWritable, NonReadable])>)>) -// CHECK: func @struct_type_with_decoration7(!spv.struct<(f32 [0], !spv.struct<(i32, f32 [NonReadable])> [4])>) -func @struct_type_with_decoration7(!spv.struct<(f32 [0], !spv.struct<(i32, f32 [NonReadable])> [4])>) +// CHECK: func private @struct_type_with_decoration7(!spv.struct<(f32 [0], !spv.struct<(i32, f32 [NonReadable])> [4])>) +func private @struct_type_with_decoration7(!spv.struct<(f32 [0], !spv.struct<(i32, f32 [NonReadable])> [4])>) -// CHECK: func @struct_type_with_decoration8(!spv.struct<(f32, !spv.struct<(i32 [0], f32 [4, NonReadable])>)>) -func @struct_type_with_decoration8(!spv.struct<(f32, !spv.struct<(i32 [0], f32 [4, NonReadable])>)>) +// CHECK: func private @struct_type_with_decoration8(!spv.struct<(f32, !spv.struct<(i32 [0], f32 [4, NonReadable])>)>) +func private @struct_type_with_decoration8(!spv.struct<(f32, !spv.struct<(i32 [0], f32 [4, NonReadable])>)>) -// CHECK: func @struct_type_with_matrix_1(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, ColMajor, MatrixStride=16])>) -func @struct_type_with_matrix_1(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, ColMajor, MatrixStride=16])>) +// CHECK: func private @struct_type_with_matrix_1(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, ColMajor, MatrixStride=16])>) +func private @struct_type_with_matrix_1(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, ColMajor, MatrixStride=16])>) -// CHECK: func @struct_type_with_matrix_2(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=16])>) -func @struct_type_with_matrix_2(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=16])>) +// CHECK: func private @struct_type_with_matrix_2(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=16])>) +func private @struct_type_with_matrix_2(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=16])>) -// CHECK: func @struct_empty(!spv.struct<()>) -func @struct_empty(!spv.struct<()>) +// CHECK: func private @struct_empty(!spv.struct<()>) +func private @struct_empty(!spv.struct<()>) // ----- // expected-error @+1 {{offset specification must be given for all members}} -func @struct_type_missing_offset1((!spv.struct<(f32, i32 [4])>) -> () +func private @struct_type_missing_offset1((!spv.struct<(f32, i32 [4])>) -> () // ----- // expected-error @+1 {{offset specification must be given for all members}} -func @struct_type_missing_offset2(!spv.struct<(f32 [3], i32)>) -> () +func private @struct_type_missing_offset2(!spv.struct<(f32 [3], i32)>) -> () // ----- // expected-error @+1 {{expected ')'}} -func @struct_type_missing_comma1(!spv.struct<(f32 i32)>) -> () +func private @struct_type_missing_comma1(!spv.struct<(f32 i32)>) -> () // ----- // expected-error @+1 {{expected ')'}} -func @struct_type_missing_comma2(!spv.struct<(f32 [0] i32)>) -> () +func private @struct_type_missing_comma2(!spv.struct<(f32 [0] i32)>) -> () // ----- // expected-error @+1 {{unbalanced ')' character in pretty dialect name}} -func @struct_type_neg_offset(!spv.struct<(f32 [0)>) -> () +func private @struct_type_neg_offset(!spv.struct<(f32 [0)>) -> () // ----- // expected-error @+1 {{unbalanced ']' character in pretty dialect name}} -func @struct_type_neg_offset(!spv.struct<(f32 0])>) -> () +func private @struct_type_neg_offset(!spv.struct<(f32 0])>) -> () // ----- // expected-error @+1 {{expected ']'}} -func @struct_type_neg_offset(!spv.struct<(f32 [NonWritable 0])>) -> () +func private @struct_type_neg_offset(!spv.struct<(f32 [NonWritable 0])>) -> () // ----- // expected-error @+1 {{expected valid keyword}} -func @struct_type_neg_offset(!spv.struct<(f32 [NonWritable, 0])>) -> () +func private @struct_type_neg_offset(!spv.struct<(f32 [NonWritable, 0])>) -> () // ----- // expected-error @+1 {{expected ','}} -func @struct_type_missing_comma(!spv.struct<(f32 [0 NonWritable], i32 [4])>) +func private @struct_type_missing_comma(!spv.struct<(f32 [0 NonWritable], i32 [4])>) // ----- // expected-error @+1 {{expected ']'}} -func @struct_type_missing_comma(!spv.struct<(f32 [0, NonWritable NonReadable], i32 [4])>) +func private @struct_type_missing_comma(!spv.struct<(f32 [0, NonWritable NonReadable], i32 [4])>) // ----- // expected-error @+1 {{expected ']'}} -func @struct_type_missing_comma(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor MatrixStride=16])>) +func private @struct_type_missing_comma(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor MatrixStride=16])>) // ----- // expected-error @+1 {{expected integer value}} -func @struct_missing_member_decorator_value(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=])>) +func private @struct_missing_member_decorator_value(!spv.struct<(!spv.matrix<3 x vector<3xf32>> [0, RowMajor, MatrixStride=])>) // ----- //===----------------------------------------------------------------------===// // StructType (identified) //===----------------------------------------------------------------------===// -// CHECK: func @id_struct_empty(!spv.struct) -func @id_struct_empty(!spv.struct) -> () +// CHECK: func private @id_struct_empty(!spv.struct) +func private @id_struct_empty(!spv.struct) -> () // ----- -// CHECK: func @id_struct_simple(!spv.struct) -func @id_struct_simple(!spv.struct) -> () +// CHECK: func private @id_struct_simple(!spv.struct) +func private @id_struct_simple(!spv.struct) -> () // ----- -// CHECK: func @id_struct_multiple_elements(!spv.struct) -func @id_struct_multiple_elements(!spv.struct) -> () +// CHECK: func private @id_struct_multiple_elements(!spv.struct) +func private @id_struct_multiple_elements(!spv.struct) -> () // ----- -// CHECK: func @id_struct_nested_literal(!spv.struct)>) -func @id_struct_nested_literal(!spv.struct)>) -> () +// CHECK: func private @id_struct_nested_literal(!spv.struct)>) +func private @id_struct_nested_literal(!spv.struct)>) -> () // ----- -// CHECK: func @id_struct_nested_id(!spv.struct)>) -func @id_struct_nested_id(!spv.struct)>) -> () +// CHECK: func private @id_struct_nested_id(!spv.struct)>) +func private @id_struct_nested_id(!spv.struct)>) -> () // ----- -// CHECK: func @literal_struct_nested_id(!spv.struct<(!spv.struct)>) -func @literal_struct_nested_id(!spv.struct<(!spv.struct)>) -> () +// CHECK: func private @literal_struct_nested_id(!spv.struct<(!spv.struct)>) +func private @literal_struct_nested_id(!spv.struct<(!spv.struct)>) -> () // ----- -// CHECK: func @id_struct_self_recursive(!spv.struct, Uniform>)>) -func @id_struct_self_recursive(!spv.struct, Uniform>)>) -> () +// CHECK: func private @id_struct_self_recursive(!spv.struct, Uniform>)>) +func private @id_struct_self_recursive(!spv.struct, Uniform>)>) -> () // ----- -// CHECK: func @id_struct_self_recursive2(!spv.struct, Uniform>)>) -func @id_struct_self_recursive2(!spv.struct, Uniform>)>) -> () +// CHECK: func private @id_struct_self_recursive2(!spv.struct, Uniform>)>) +func private @id_struct_self_recursive2(!spv.struct, Uniform>)>) -> () // ----- // expected-error @+1 {{recursive struct reference not nested in struct definition}} -func @id_wrong_recursive_reference(!spv.struct) -> () +func private @id_wrong_recursive_reference(!spv.struct) -> () // ----- // expected-error @+1 {{recursive struct reference not nested in struct definition}} -func @id_struct_recursive_invalid(!spv.struct, Uniform>)>) -> () +func private @id_struct_recursive_invalid(!spv.struct, Uniform>)>) -> () // ----- // expected-error @+1 {{identifier already used for an enclosing struct}} -func @id_struct_redefinition(!spv.struct, Uniform>)>, Uniform>)>) -> () +func private @id_struct_redefinition(!spv.struct, Uniform>)>, Uniform>)>) -> () // ----- // Equivalent to: // struct a { struct b *bPtr; }; // struct b { struct a *aPtr; }; -// CHECK: func @id_struct_recursive(!spv.struct, Uniform>)>, Uniform>)>) -func @id_struct_recursive(!spv.struct, Uniform>)>, Uniform>)>) -> () +// CHECK: func private @id_struct_recursive(!spv.struct, Uniform>)>, Uniform>)>) +func private @id_struct_recursive(!spv.struct, Uniform>)>, Uniform>)>) -> () // ----- // Equivalent to: // struct a { struct b *bPtr; }; // struct b { struct a *aPtr, struct b *bPtr; }; -// CHECK: func @id_struct_recursive(!spv.struct, Uniform>, !spv.ptr, Uniform>)>, Uniform>)>) -func @id_struct_recursive(!spv.struct, Uniform>, !spv.ptr, Uniform>)>, Uniform>)>) -> () +// CHECK: func private @id_struct_recursive(!spv.struct, Uniform>, !spv.ptr, Uniform>)>, Uniform>)>) +func private @id_struct_recursive(!spv.struct, Uniform>, !spv.ptr, Uniform>)>, Uniform>)>) -> () // ----- //===----------------------------------------------------------------------===// // CooperativeMatrix //===----------------------------------------------------------------------===// -// CHECK: func @coop_matrix_type(!spv.coopmatrix<8x16xi32, Subgroup>, !spv.coopmatrix<8x8xf32, Workgroup>) -func @coop_matrix_type(!spv.coopmatrix<8x16xi32, Subgroup>, !spv.coopmatrix<8x8xf32, Workgroup>) -> () +// CHECK: func private @coop_matrix_type(!spv.coopmatrix<8x16xi32, Subgroup>, !spv.coopmatrix<8x8xf32, Workgroup>) +func private @coop_matrix_type(!spv.coopmatrix<8x16xi32, Subgroup>, !spv.coopmatrix<8x8xf32, Workgroup>) -> () // ----- // expected-error @+1 {{expected ','}} -func @missing_scope(!spv.coopmatrix<8x16xi32>) -> () +func private @missing_scope(!spv.coopmatrix<8x16xi32>) -> () // ----- // expected-error @+1 {{expected rows and columns size}} -func @missing_count(!spv.coopmatrix<8xi32, Subgroup>) -> () +func private @missing_count(!spv.coopmatrix<8xi32, Subgroup>) -> () // ----- //===----------------------------------------------------------------------===// // Matrix //===----------------------------------------------------------------------===// -// CHECK: func @matrix_type(!spv.matrix<2 x vector<2xf16>>) -func @matrix_type(!spv.matrix<2 x vector<2xf16>>) -> () +// CHECK: func private @matrix_type(!spv.matrix<2 x vector<2xf16>>) +func private @matrix_type(!spv.matrix<2 x vector<2xf16>>) -> () // ----- -// CHECK: func @matrix_type(!spv.matrix<3 x vector<3xf32>>) -func @matrix_type(!spv.matrix<3 x vector<3xf32>>) -> () +// CHECK: func private @matrix_type(!spv.matrix<3 x vector<3xf32>>) +func private @matrix_type(!spv.matrix<3 x vector<3xf32>>) -> () // ----- -// CHECK: func @matrix_type(!spv.matrix<4 x vector<4xf16>>) -func @matrix_type(!spv.matrix<4 x vector<4xf16>>) -> () +// CHECK: func private @matrix_type(!spv.matrix<4 x vector<4xf16>>) +func private @matrix_type(!spv.matrix<4 x vector<4xf16>>) -> () // ----- // expected-error @+1 {{matrix is expected to have 2, 3, or 4 columns}} -func @matrix_invalid_size(!spv.matrix<5 x vector<3xf32>>) -> () +func private @matrix_invalid_size(!spv.matrix<5 x vector<3xf32>>) -> () // ----- // expected-error @+1 {{matrix is expected to have 2, 3, or 4 columns}} -func @matrix_invalid_size(!spv.matrix<1 x vector<3xf32>>) -> () +func private @matrix_invalid_size(!spv.matrix<1 x vector<3xf32>>) -> () // ----- // expected-error @+1 {{matrix columns size has to be less than or equal to 4 and greater than or equal 2, but found 5}} -func @matrix_invalid_columns_size(!spv.matrix<3 x vector<5xf32>>) -> () +func private @matrix_invalid_columns_size(!spv.matrix<3 x vector<5xf32>>) -> () // ----- // expected-error @+1 {{matrix columns size has to be less than or equal to 4 and greater than or equal 2, but found 1}} -func @matrix_invalid_columns_size(!spv.matrix<3 x vector<1xf32>>) -> () +func private @matrix_invalid_columns_size(!spv.matrix<3 x vector<1xf32>>) -> () // ----- // expected-error @+1 {{expected '<'}} -func @matrix_invalid_format(!spv.matrix 3 x vector<3xf32>>) -> () +func private @matrix_invalid_format(!spv.matrix 3 x vector<3xf32>>) -> () // ----- // expected-error @+1 {{unbalanced ')' character in pretty dialect name}} -func @matrix_invalid_format(!spv.matrix< 3 x vector<3xf32>) -> () +func private @matrix_invalid_format(!spv.matrix< 3 x vector<3xf32>) -> () // ----- // expected-error @+1 {{expected 'x' in dimension list}} -func @matrix_invalid_format(!spv.matrix<2 vector<3xi32>>) -> () +func private @matrix_invalid_format(!spv.matrix<2 vector<3xi32>>) -> () // ----- // expected-error @+1 {{matrix must be composed using vector type, got 'i32'}} -func @matrix_invalid_type(!spv.matrix< 3 x i32>) -> () +func private @matrix_invalid_type(!spv.matrix< 3 x i32>) -> () // ----- // expected-error @+1 {{matrix must be composed using vector type, got '!spv.array<16 x f32>'}} -func @matrix_invalid_type(!spv.matrix< 3 x !spv.array<16 x f32>>) -> () +func private @matrix_invalid_type(!spv.matrix< 3 x !spv.array<16 x f32>>) -> () // ----- // expected-error @+1 {{matrix must be composed using vector type, got '!spv.rtarray'}} -func @matrix_invalid_type(!spv.matrix< 3 x !spv.rtarray>) -> () +func private @matrix_invalid_type(!spv.matrix< 3 x !spv.rtarray>) -> () // ----- // expected-error @+1 {{matrix columns' elements must be of Float type, got 'i32'}} -func @matrix_invalid_type(!spv.matrix<2 x vector<3xi32>>) -> () +func private @matrix_invalid_type(!spv.matrix<2 x vector<3xi32>>) -> () // ----- // expected-error @+1 {{expected single unsigned integer for number of columns}} -func @matrix_size_type(!spv.matrix< x vector<3xi32>>) -> () +func private @matrix_size_type(!spv.matrix< x vector<3xi32>>) -> () // ----- // expected-error @+1 {{expected single unsigned integer for number of columns}} -func @matrix_size_type(!spv.matrix<2.0 x vector<3xi32>>) -> () +func private @matrix_size_type(!spv.matrix<2.0 x vector<3xi32>>) -> () // ----- diff --git a/mlir/test/Dialect/Standard/func-bufferize.mlir b/mlir/test/Dialect/Standard/func-bufferize.mlir index 20af66cdb880..61c5e184cd17 100644 --- a/mlir/test/Dialect/Standard/func-bufferize.mlir +++ b/mlir/test/Dialect/Standard/func-bufferize.mlir @@ -1,64 +1,64 @@ // RUN: mlir-opt %s -func-bufferize -split-input-file -verify-diagnostics | FileCheck %s // CHECK-LABEL: func @identity( // CHECK-SAME: %[[ARG:.*]]: memref) -> memref { // CHECK: return %[[ARG]] : memref func @identity(%arg0: tensor) -> tensor { return %arg0 : tensor } // CHECK-LABEL: func @block_arguments( // CHECK-SAME: %[[ARG:.*]]: memref) -> memref { // CHECK: br ^bb1(%[[ARG]] : memref) // CHECK: ^bb1(%[[BBARG:.*]]: memref): // CHECK: return %[[BBARG]] : memref func @block_arguments(%arg0: tensor) -> tensor { br ^bb1(%arg0: tensor) ^bb1(%bbarg: tensor): return %bbarg : tensor } // CHECK-LABEL: func @eliminate_target_materialization( // CHECK-SAME: %[[ARG:.*]]: memref) -> memref { // CHECK: return %[[ARG]] : memref func @eliminate_target_materialization(%arg0: tensor) -> memref { %0 = tensor_to_memref %arg0 : memref return %0 : memref } // CHECK-LABEL: func @eliminate_source_materialization( // CHECK-SAME: %[[ARG:.*]]: memref) -> memref { // CHECK: return %[[ARG]] : memref func @eliminate_source_materialization(%arg0: memref) -> tensor { %0 = tensor_load %arg0 : memref return %0 : tensor } -// CHECK-LABEL: func @source() -> memref +// CHECK-LABEL: func private @source() -> memref // CHECK-LABEL: func @call_source() -> memref { // CHECK: %[[RET:.*]] = call @source() : () -> memref // CHECK: return %[[RET]] : memref -func @source() -> tensor +func private @source() -> tensor func @call_source() -> tensor { %0 = call @source() : () -> tensor return %0 : tensor } -// CHECK-LABEL: func @sink(memref) +// CHECK-LABEL: func private @sink(memref) // CHECK-LABEL: func @call_sink( // CHECK-SAME: %[[ARG:.*]]: memref) { // CHECK: call @sink(%[[ARG]]) : (memref) -> () // CHECK: return -func @sink(tensor) +func private @sink(tensor) func @call_sink(%arg0: tensor) { call @sink(%arg0) : (tensor) -> () return } // ----- func @failed_to_legalize() -> tensor { // expected-error @+1 {{failed to legalize operation 'test.source'}} %0 = "test.source"() : () -> (tensor) return %0 : tensor } diff --git a/mlir/test/IR/affine-map.mlir b/mlir/test/IR/affine-map.mlir index f953c00e2043..3e3e2c3fe6f6 100644 --- a/mlir/test/IR/affine-map.mlir +++ b/mlir/test/IR/affine-map.mlir @@ -1,375 +1,375 @@ // RUN: mlir-opt -allow-unregistered-dialect %s | FileCheck %s // Identity maps used in trivial compositions in MemRefs are optimized away. // CHECK-NOT: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0, d1)> #map0 = affine_map<(i, j) -> (i, j)> // CHECK-NOT: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0, d1)> #map1 = affine_map<(i, j)[s0] -> (i, j)> // CHECK: #map{{[0-9]+}} = affine_map<() -> (0)> // A map may have 0 inputs. // However, an affine.apply always takes at least one input. #map2 = affine_map<() -> (0)> // All the maps in the following block are equivalent and are unique'd as one // map. Therefore there should be only one output and we explicitly CHECK-NOT // for the others. // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 + 1, d1 * 4 + 2)> #map3 = affine_map<(i, j) -> (i+1, 4*j + 2)> // CHECK-NOT: #map3{{[a-z]}} #map3a = affine_map<(i, j) -> (1+i, 4*j + 2)> #map3b = affine_map<(i, j) -> (2 + 3 - 2*2 + i, 4*j + 2)> #map3c = affine_map<(i, j) -> (i +1 + 0, 4*j + 2)> #map3d = affine_map<(i, j) -> (i + 3 + 2 - 4, 4*j + 2)> #map3e = affine_map<(i, j) -> (1*i+3*2-2*2-1, 4*j + 2)> #map3f = affine_map<(i, j) -> (i + 1, 4*j*1 + 2)> #map3g = affine_map<(i, j) -> (i + 1, 2*2*j + 2)> #map3h = affine_map<(i, j) -> (i + 1, 2*j*2 + 2)> #map3i = affine_map<(i, j) -> (i + 1, j*2*2 + 2)> #map3j = affine_map<(i, j) -> (i + 1, j*1*4 + 2)> #map3k = affine_map<(i, j) -> (i + 1, j*4*1 + 2)> // The following reduction should be unique'd out too but such expression // simplification is not performed for IR parsing, but only through analyses // and transforms. // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d1 - d0 + (d0 - d1 + 1) * 2 + d1 - 1, d1 * 4 + 2)> #map3l = affine_map<(i, j) -> ((j - i) + 2*(i - j + 1) + j - 1 + 0, j + j + 1 + j + j + 1)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 + 2, d1)> #map4 = affine_map<(i, j) -> (3+3-2*2+i, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + s0, d1)> #map5 = affine_map<(i, j)[s0] -> (i + s0, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + s0, d1 + 5)> #map6 = affine_map<(i, j)[s0] -> (i + s0, j + 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + s0, d1)> #map7 = affine_map<(i, j)[s0] -> (i + j + s0, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + s0 + 5, d1)> #map8 = affine_map<(i, j)[s0] -> (5 + i + j + s0, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + 5, d1)> #map9 = affine_map<(i, j)[s0] -> ((i + j) + 5, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + 5, d1)> #map10 = affine_map<(i, j)[s0] -> (i + (j + 5), j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 * 2, d1 * 3)> #map11 = affine_map<(i, j)[s0] -> (2*i, 3*j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + (d1 + s0 * 3) * 5 + 12, d1)> #map12 = affine_map<(i, j)[s0] -> (i + 2*6 + 5*(j+s0*3), j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 * 5 + d1, d1)> #map13 = affine_map<(i, j)[s0] -> (5*i + j, j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1, d1)> #map14 = affine_map<(i, j)[s0] -> ((i + j), (j))> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + 7, d1 + 3)> #map15 = affine_map<(i, j)[s0] -> ((i + j + 2) + 5, (j)+3)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0, 0)> #map16 = affine_map<(i, j)[s1] -> (i, 0)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0, d1 * s0)> #map17 = affine_map<(i, j)[s0] -> (i, s0*j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0, d0 * 3 + d1)> #map19 = affine_map<(i, j) -> (i, 3*i + j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0, d0 + d1 * 3)> #map20 = affine_map<(i, j) -> (i, i + 3*j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0, d0 * ((s0 * s0) * 9) + 3)> #map18 = affine_map<(i, j)[N] -> (i, 2 + N*N*9*i + 1)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (1, d0 + d1 * 3 + 5)> #map21 = affine_map<(i, j) -> (1, i + 3*j + 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (s0 * 5, d0 + d1 * 3 + d0 * 5)> #map22 = affine_map<(i, j)[s0] -> (5*s0, i + 3*j + 5*i)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0 * (s0 * s1), d1)> #map23 = affine_map<(i, j)[s0, s1] -> (i*(s0*s1), j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d1 mod 5)> #map24 = affine_map<(i, j)[s0, s1] -> (i, j mod 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d1 floordiv 5)> #map25 = affine_map<(i, j)[s0, s1] -> (i, j floordiv 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d1 ceildiv 5)> #map26 = affine_map<(i, j)[s0, s1] -> (i, j ceildiv 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d0 - d1 - 5)> #map29 = affine_map<(i, j)[s0, s1] -> (i, i - j - 5)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d0 - d1 * s1 + 2)> #map30 = affine_map<(i, j)[M, N] -> (i, i - N*j + 2)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0 * -5, d1 * -3, -2, -(d0 + d1), -s0)> #map32 = affine_map<(i, j)[s0, s1] -> (-5*i, -3*j, -2, -1*(i+j), -1*s0)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (-4, -d0)> #map33 = affine_map<(i, j) -> (-2+-5-(-3), -1*i)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0, d1 floordiv s0, d1 mod s0)> #map34 = affine_map<(i, j)[s0, s1] -> (i, j floordiv s0, j mod s0)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1, d2)[s0, s1, s2] -> ((d0 * s1) * s2 + d1 * s1 + d2)> #map35 = affine_map<(i, j, k)[s0, s1, s2] -> (i*s1*s2 + j*s1 + k)> // Constant folding. // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (8, 4, 1, 3, 2, 4)> #map36 = affine_map<(i, j) -> (5+3, 2*2, 8-7, 100 floordiv 32, 5 mod 3, 10 ceildiv 3)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (4, 11, 512, 15)> #map37 = affine_map<(i, j) -> (5 mod 3 + 2, 5*3 - 4, 128 * (500 ceildiv 128), 40 floordiv 7 * 3)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 * 2 + 1, d1 + 2)> #map38 = affine_map<(i, j) -> (1 + i*2, 2 + j)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0, s1] -> (d0 * s0, d0 + s0, d0 + 2, d1 * 2, s1 * 2, s0 + 2)> #map39 = affine_map<(i, j)[M, N] -> (i*M, M + i, 2+i, j*2, N*2, 2 + M)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> ((d0 * 5) floordiv 4, (d1 ceildiv 7) mod s0)> #map43 = affine_map<(i, j) [s0] -> ( i * 5 floordiv 4, j ceildiv 7 mod s0)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 - d1 * 2, (d1 * 6) floordiv 4)> #map44 = affine_map<(i, j) -> (i - 2*j, j * 6 floordiv 4)> // Simplifications // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1, d2)[s0] -> (d0 + d1 + d2 + 1, d2 + d1, (d0 * s0) * 8)> #map45 = affine_map<(i, j, k) [N] -> (1 + i + 3 + j - 3 + k, k + 5 + j - 5, 2*i*4*N)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (0, d1, d0 * 2, 0)> #map46 = affine_map<(i, j, k) -> (i*0, 1*j, i * 128 floordiv 64, j * 0 floordiv 64)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d0, d0 * 4, 0, 0, 0)> #map47 = affine_map<(i, j, k) -> (i * 64 ceildiv 64, i * 512 ceildiv 128, 4 * j mod 4, 4*j*4 mod 8, k mod 1)> // floordiv should resolve similarly to ceildiv and be unique'd out. // CHECK-NOT: #map48{{[a-z]}} #map48 = affine_map<(i, j, k) -> (i * 64 floordiv 64, i * 512 floordiv 128, 4 * j mod 4, 4*j*4 mod 8)> // Simplifications for mod using known GCD's of the LHS expr. // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (0, 0, 0, 1)> #map49 = affine_map<(i, j)[s0] -> ( (i * 4 + 8) mod 4, 32 * j * s0 * 8 mod 256, (4*i + (j * (s0 * 2))) mod 2, (4*i + 3) mod 2)> // Floordiv, ceildiv divide by one. // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 * 2 + 1, d1 + s0)> #map50 = affine_map<(i, j)[s0] -> ( (i * 2 + 1) ceildiv 1, (j + s0) floordiv 1)> // floordiv, ceildiv, and mod where LHS is negative. // CHECK: #map{{[0-9]+}} = affine_map<(d0) -> (-2, 1, -1)> #map51 = affine_map<(i) -> (-5 floordiv 3, -5 mod 3, -5 ceildiv 3)> // Parenthesis elision. // CHECK: #map{{[0-9]+}} = affine_map<(d0) -> (d0 * 16 - (d0 + 1) + 15)> #map52 = affine_map<(d0) -> (16*d0 + ((d0 + 1) * -1) + 15)> // CHECK: #map{{[0-9]+}} = affine_map<(d0) -> (d0 - (d0 + 1))> #map53 = affine_map<(d0) -> (d0 - (d0 + 1))> // CHECK: #map{{[0-9]+}} = affine_map<(d0)[s0] -> ((-s0) floordiv 4, d0 floordiv -1)> #map54 = affine_map<(d0)[s0] -> (-s0 floordiv 4, d0 floordiv -1)> // CHECK: #map{{[0-9]+}} = affine_map<() -> ()> #map55 = affine_map<() -> ()> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0, d0 * 2 + d1 * 4 + 2, 1, 2, (d0 * 4) mod 8)> #map56 = affine_map<(d0, d1) -> ((4*d0 + 2) floordiv 4, (4*d0 + 8*d1 + 5) floordiv 2, (2*d0 + 4*d1 + 3) mod 2, (3*d0 - 4) mod 3, (4*d0 + 8*d1) mod 8)> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d1, d0, 0)> #map57 = affine_map<(d0, d1) -> (d0 - d0 + d1, -d0 + d0 + d0, (1 + d0 + d1 floordiv 4) - (d0 + d1 floordiv 4 + 1))> // CHECK: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 * 3, (d0 + d1) * 2, d0 mod 2)> #map58 = affine_map<(d0, d1) -> (4*d0 - 2*d0 + d0, (d0 + d1) + (d0 + d1), 2 * (d0 mod 2) - d0 mod 2)> // Single identity maps are removed. -// CHECK: func @f0(memref<2x4xi8, 1>) -func @f0(memref<2x4xi8, #map0, 1>) +// CHECK: @f0(memref<2x4xi8, 1>) +func private @f0(memref<2x4xi8, #map0, 1>) // Single identity maps are removed. -// CHECK: func @f1(memref<2x4xi8, 1>) -func @f1(memref<2x4xi8, #map1, 1>) +// CHECK: @f1(memref<2x4xi8, 1>) +func private @f1(memref<2x4xi8, #map1, 1>) -// CHECK: func @f2(memref) -func @f2(memref) +// CHECK: @f2(memref) +func private @f2(memref) -// CHECK: func @f3(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3(memref<2x4xi8, #map3, 1>) -// CHECK: func @f3a(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3a(memref<2x4xi8, #map3a, 1>) -// CHECK: func @f3b(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3b(memref<2x4xi8, #map3b, 1>) -// CHECK: func @f3c(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3c(memref<2x4xi8, #map3c, 1>) -// CHECK: func @f3d(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3d(memref<2x4xi8, #map3d, 1>) -// CHECK: func @f3e(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3e(memref<2x4xi8, #map3e, 1>) -// CHECK: func @f3f(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3f(memref<2x4xi8, #map3f, 1>) -// CHECK: func @f3g(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3g(memref<2x4xi8, #map3g, 1>) -// CHECK: func @f3h(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3h(memref<2x4xi8, #map3h, 1>) -// CHECK: func @f3i(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3i(memref<2x4xi8, #map3i, 1>) -// CHECK: func @f3j(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3j(memref<2x4xi8, #map3j, 1>) -// CHECK: func @f3k(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3k(memref<2x4xi8, #map3k, 1>) -// CHECK: func @f3l(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f3l(memref<2x4xi8, #map3l, 1>) +// CHECK: @f3(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3(memref<2x4xi8, #map3, 1>) +// CHECK: @f3a(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3a(memref<2x4xi8, #map3a, 1>) +// CHECK: @f3b(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3b(memref<2x4xi8, #map3b, 1>) +// CHECK: @f3c(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3c(memref<2x4xi8, #map3c, 1>) +// CHECK: @f3d(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3d(memref<2x4xi8, #map3d, 1>) +// CHECK: @f3e(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3e(memref<2x4xi8, #map3e, 1>) +// CHECK: @f3f(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3f(memref<2x4xi8, #map3f, 1>) +// CHECK: @f3g(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3g(memref<2x4xi8, #map3g, 1>) +// CHECK: @f3h(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3h(memref<2x4xi8, #map3h, 1>) +// CHECK: @f3i(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3i(memref<2x4xi8, #map3i, 1>) +// CHECK: @f3j(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3j(memref<2x4xi8, #map3j, 1>) +// CHECK: @f3k(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3k(memref<2x4xi8, #map3k, 1>) +// CHECK: @f3l(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f3l(memref<2x4xi8, #map3l, 1>) -// CHECK: func @f4(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f4(memref<2x4xi8, #map4, 1>) +// CHECK: @f4(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f4(memref<2x4xi8, #map4, 1>) -// CHECK: func @f5(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f5(memref<2x4xi8, #map5, 1>) +// CHECK: @f5(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f5(memref<2x4xi8, #map5, 1>) -// CHECK: func @f6(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f6(memref<2x4xi8, #map6, 1>) +// CHECK: @f6(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f6(memref<2x4xi8, #map6, 1>) -// CHECK: func @f7(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f7(memref<2x4xi8, #map7, 1>) +// CHECK: @f7(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f7(memref<2x4xi8, #map7, 1>) -// CHECK: func @f8(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f8(memref<2x4xi8, #map8, 1>) +// CHECK: @f8(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f8(memref<2x4xi8, #map8, 1>) -// CHECK: func @f9(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f9(memref<2x4xi8, #map9, 1>) +// CHECK: @f9(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f9(memref<2x4xi8, #map9, 1>) -// CHECK: func @f10(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f10(memref<2x4xi8, #map10, 1>) +// CHECK: @f10(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f10(memref<2x4xi8, #map10, 1>) -// CHECK: func @f11(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f11(memref<2x4xi8, #map11, 1>) +// CHECK: @f11(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f11(memref<2x4xi8, #map11, 1>) -// CHECK: func @f12(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f12(memref<2x4xi8, #map12, 1>) +// CHECK: @f12(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f12(memref<2x4xi8, #map12, 1>) -// CHECK: func @f13(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f13(memref<2x4xi8, #map13, 1>) +// CHECK: @f13(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f13(memref<2x4xi8, #map13, 1>) -// CHECK: func @f14(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f14(memref<2x4xi8, #map14, 1>) +// CHECK: @f14(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f14(memref<2x4xi8, #map14, 1>) -// CHECK: func @f15(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f15(memref<2x4xi8, #map15, 1>) +// CHECK: @f15(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f15(memref<2x4xi8, #map15, 1>) -// CHECK: func @f16(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f16(memref<2x4xi8, #map16, 1>) +// CHECK: @f16(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f16(memref<2x4xi8, #map16, 1>) -// CHECK: func @f17(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f17(memref<2x4xi8, #map17, 1>) +// CHECK: @f17(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f17(memref<2x4xi8, #map17, 1>) -// CHECK: func @f19(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f19(memref<2x4xi8, #map19, 1>) +// CHECK: @f19(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f19(memref<2x4xi8, #map19, 1>) -// CHECK: func @f20(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f20(memref<2x4xi8, #map20, 1>) +// CHECK: @f20(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f20(memref<2x4xi8, #map20, 1>) -// CHECK: func @f18(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f18(memref<2x4xi8, #map18, 1>) +// CHECK: @f18(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f18(memref<2x4xi8, #map18, 1>) -// CHECK: func @f21(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f21(memref<2x4xi8, #map21, 1>) +// CHECK: @f21(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f21(memref<2x4xi8, #map21, 1>) -// CHECK: func @f22(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f22(memref<2x4xi8, #map22, 1>) +// CHECK: @f22(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f22(memref<2x4xi8, #map22, 1>) -// CHECK: func @f23(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f23(memref<2x4xi8, #map23, 1>) +// CHECK: @f23(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f23(memref<2x4xi8, #map23, 1>) -// CHECK: func @f24(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f24(memref<2x4xi8, #map24, 1>) +// CHECK: @f24(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f24(memref<2x4xi8, #map24, 1>) -// CHECK: func @f25(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f25(memref<2x4xi8, #map25, 1>) +// CHECK: @f25(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f25(memref<2x4xi8, #map25, 1>) -// CHECK: func @f26(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f26(memref<2x4xi8, #map26, 1>) +// CHECK: @f26(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f26(memref<2x4xi8, #map26, 1>) -// CHECK: func @f29(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f29(memref<2x4xi8, #map29, 1>) +// CHECK: @f29(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f29(memref<2x4xi8, #map29, 1>) -// CHECK: func @f30(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f30(memref<2x4xi8, #map30, 1>) +// CHECK: @f30(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f30(memref<2x4xi8, #map30, 1>) -// CHECK: func @f32(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f32(memref<2x4xi8, #map32, 1>) +// CHECK: @f32(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f32(memref<2x4xi8, #map32, 1>) -// CHECK: func @f33(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f33(memref<2x4xi8, #map33, 1>) +// CHECK: @f33(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f33(memref<2x4xi8, #map33, 1>) -// CHECK: func @f34(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f34(memref<2x4xi8, #map34, 1>) +// CHECK: @f34(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f34(memref<2x4xi8, #map34, 1>) -// CHECK: func @f35(memref<2x4x4xi8, #map{{[0-9]+}}, 1>) -func @f35(memref<2x4x4xi8, #map35, 1>) +// CHECK: @f35(memref<2x4x4xi8, #map{{[0-9]+}}, 1>) +func private @f35(memref<2x4x4xi8, #map35, 1>) -// CHECK: func @f36(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f36(memref<2x4xi8, #map36, 1>) +// CHECK: @f36(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f36(memref<2x4xi8, #map36, 1>) -// CHECK: func @f37(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f37(memref<2x4xi8, #map37, 1>) +// CHECK: @f37(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f37(memref<2x4xi8, #map37, 1>) -// CHECK: func @f38(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f38(memref<2x4xi8, #map38, 1>) +// CHECK: @f38(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f38(memref<2x4xi8, #map38, 1>) -// CHECK: func @f39(memref<2x4xi8, #map{{[0-9]+}}, 1>) -func @f39(memref<2x4xi8, #map39, 1>) +// CHECK: @f39(memref<2x4xi8, #map{{[0-9]+}}, 1>) +func private @f39(memref<2x4xi8, #map39, 1>) -// CHECK: func @f43(memref<2x4xi8, #map{{[0-9]+}}>) -func @f43(memref<2x4xi8, #map43>) +// CHECK: @f43(memref<2x4xi8, #map{{[0-9]+}}>) +func private @f43(memref<2x4xi8, #map43>) -// CHECK: func @f44(memref<2x4xi8, #map{{[0-9]+}}>) -func @f44(memref<2x4xi8, #map44>) +// CHECK: @f44(memref<2x4xi8, #map{{[0-9]+}}>) +func private @f44(memref<2x4xi8, #map44>) -// CHECK: func @f45(memref<100x100x100xi8, #map{{[0-9]+}}>) -func @f45(memref<100x100x100xi8, #map45>) +// CHECK: @f45(memref<100x100x100xi8, #map{{[0-9]+}}>) +func private @f45(memref<100x100x100xi8, #map45>) -// CHECK: func @f46(memref<100x100x100xi8, #map{{[0-9]+}}>) -func @f46(memref<100x100x100xi8, #map46>) +// CHECK: @f46(memref<100x100x100xi8, #map{{[0-9]+}}>) +func private @f46(memref<100x100x100xi8, #map46>) -// CHECK: func @f47(memref<100x100x100xi8, #map{{[0-9]+}}>) -func @f47(memref<100x100x100xi8, #map47>) +// CHECK: @f47(memref<100x100x100xi8, #map{{[0-9]+}}>) +func private @f47(memref<100x100x100xi8, #map47>) -// CHECK: func @f48(memref<100x100x100xi8, #map{{[0-9]+}}>) -func @f48(memref<100x100x100xi8, #map48>) +// CHECK: @f48(memref<100x100x100xi8, #map{{[0-9]+}}>) +func private @f48(memref<100x100x100xi8, #map48>) -// CHECK: func @f49(memref<100x100xi8, #map{{[0-9]+}}>) -func @f49(memref<100x100xi8, #map49>) +// CHECK: @f49(memref<100x100xi8, #map{{[0-9]+}}>) +func private @f49(memref<100x100xi8, #map49>) -// CHECK: func @f50(memref<100x100xi8, #map{{[0-9]+}}>) -func @f50(memref<100x100xi8, #map50>) +// CHECK: @f50(memref<100x100xi8, #map{{[0-9]+}}>) +func private @f50(memref<100x100xi8, #map50>) -// CHECK: func @f51(memref<1xi8, #map{{[0-9]+}}>) -func @f51(memref<1xi8, #map51>) +// CHECK: @f51(memref<1xi8, #map{{[0-9]+}}>) +func private @f51(memref<1xi8, #map51>) -// CHECK: func @f52(memref<1xi8, #map{{[0-9]+}}>) -func @f52(memref<1xi8, #map52>) +// CHECK: @f52(memref<1xi8, #map{{[0-9]+}}>) +func private @f52(memref<1xi8, #map52>) -// CHECK: func @f53(memref<1xi8, #map{{[0-9]+}}>) -func @f53(memref<1xi8, #map53>) +// CHECK: @f53(memref<1xi8, #map{{[0-9]+}}>) +func private @f53(memref<1xi8, #map53>) -// CHECK: func @f54(memref<10xi32, #map{{[0-9]+}}>) -func @f54(memref<10xi32, #map54>) +// CHECK: @f54(memref<10xi32, #map{{[0-9]+}}>) +func private @f54(memref<10xi32, #map54>) // CHECK: "foo.op"() {map = #map{{[0-9]+}}} : () -> () "foo.op"() {map = #map55} : () -> () -// CHECK: func @f56(memref<1x1xi8, #map{{[0-9]+}}>) -func @f56(memref<1x1xi8, #map56>) +// CHECK: @f56(memref<1x1xi8, #map{{[0-9]+}}>) +func private @f56(memref<1x1xi8, #map56>) // CHECK: "f57"() {map = #map{{[0-9]+}}} : () -> () "f57"() {map = #map57} : () -> () // CHECK: "f58"() {map = #map{{[0-9]+}}} : () -> () "f58"() {map = #map58} : () -> () diff --git a/mlir/test/IR/core-ops.mlir b/mlir/test/IR/core-ops.mlir index 838452619990..c894bf47c2a6 100644 --- a/mlir/test/IR/core-ops.mlir +++ b/mlir/test/IR/core-ops.mlir @@ -1,975 +1,975 @@ // RUN: mlir-opt -allow-unregistered-dialect %s | FileCheck %s // Verify the printed output can be parsed. // RUN: mlir-opt -allow-unregistered-dialect %s | mlir-opt -allow-unregistered-dialect | FileCheck %s // Verify the generic form can be parsed. // RUN: mlir-opt -allow-unregistered-dialect -mlir-print-op-generic %s | mlir-opt -allow-unregistered-dialect | FileCheck %s // CHECK: #map0 = affine_map<(d0) -> (d0 + 1)> // CHECK: #map1 = affine_map<()[s0] -> (s0 + 1)> // CHECK-DAG: #[[$BASE_MAP0:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)> // CHECK-DAG: #[[$BASE_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2)[s0, s1, s2, s3] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3)> // CHECK-DAG: #[[$BASE_MAP1:map[0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)> // CHECK-DAG: #[[$SUBVIEW_MAP1:map[0-9]+]] = affine_map<(d0)[s0, s1] -> (d0 * s1 + s0)> // CHECK-DAG: #[[$BASE_MAP2:map[0-9]+]] = affine_map<(d0, d1) -> (d0 * 22 + d1)> // CHECK-DAG: #[[$SUBVIEW_MAP2:map[0-9]+]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)> // CHECK-DAG: #[[$SUBVIEW_MAP3:map[0-9]+]] = affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2 + 8)> // CHECK-DAG: #[[$SUBVIEW_MAP4:map[0-9]+]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)> // CHECK-DAG: #[[$SUBVIEW_MAP5:map[0-9]+]] = affine_map<(d0, d1)[s0] -> (d0 * 8 + s0 + d1 * 2)> // CHECK-DAG: #[[$SUBVIEW_MAP6:map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4) -> (d0 * 36 + d1 * 36 + d2 * 4 + d3 * 4 + d4)> // CHECK-DAG: #[[$SUBVIEW_MAP7:map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4, d5)[s0, s1, s2, s3, s4, s5, s6] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4 + d4 * s5 + d5 * s6)> // CHECK-DAG: #[[$SUBVIEW_MAP8:map[0-9]+]] = affine_map<(d0, d1, d2, d3)[s0, s1, s2, s3, s4] -> (d0 * s1 + s0 + d1 * s2 + d2 * s3 + d3 * s4)> // CHECK-LABEL: func @func_with_ops // CHECK-SAME: %[[ARG:.*]]: f32 func @func_with_ops(f32) { ^bb0(%a : f32): // CHECK: %[[T:.*]] = "getTensor"() : () -> tensor<4x4x?xf32> %t = "getTensor"() : () -> tensor<4x4x?xf32> // CHECK: %[[C2:.*]] = constant 2 : index // CHECK-NEXT: %{{.*}} = dim %[[T]], %[[C2]] : tensor<4x4x?xf32> %c2 = constant 2 : index %t2 = "std.dim"(%t, %c2) : (tensor<4x4x?xf32>, index) -> index // CHECK: %{{.*}} = addf %[[ARG]], %[[ARG]] : f32 %x = "std.addf"(%a, %a) : (f32,f32) -> (f32) // CHECK: return return } // CHECK-LABEL: func @standard_instrs(%arg0: tensor<4x4x?xf32>, %arg1: f32, %arg2: i32, %arg3: index, %arg4: i64, %arg5: f16) { func @standard_instrs(tensor<4x4x?xf32>, f32, i32, index, i64, f16) { ^bb42(%t: tensor<4x4x?xf32>, %f: f32, %i: i32, %idx : index, %j: i64, %half: f16): // CHECK: %[[C2:.*]] = constant 2 : index // CHECK: %[[A2:.*]] = dim %arg0, %[[C2]] : tensor<4x4x?xf32> %c2 = constant 2 : index %a2 = dim %t, %c2 : tensor<4x4x?xf32> // CHECK: %[[F2:.*]] = addf %arg1, %arg1 : f32 %f2 = "std.addf"(%f, %f) : (f32,f32) -> f32 // CHECK: %[[F3:.*]] = addf %[[F2]], %[[F2]] : f32 %f3 = addf %f2, %f2 : f32 // CHECK: %[[I2:.*]] = addi %arg2, %arg2 : i32 %i2 = "std.addi"(%i, %i) : (i32,i32) -> i32 // CHECK: %[[I3:.*]] = addi %[[I2]], %[[I2]] : i32 %i3 = addi %i2, %i2 : i32 // CHECK: %[[IDX1:.*]] = addi %arg3, %arg3 : index %idx1 = addi %idx, %idx : index // CHECK: %[[IDX2:.*]] = addi %arg3, %[[IDX1]] : index %idx2 = "std.addi"(%idx, %idx1) : (index, index) -> index // CHECK: %[[F4:.*]] = subf %arg1, %arg1 : f32 %f4 = "std.subf"(%f, %f) : (f32,f32) -> f32 // CHECK: %[[F5:.*]] = subf %[[F4]], %[[F4]] : f32 %f5 = subf %f4, %f4 : f32 // CHECK: %[[I4:.*]] = subi %arg2, %arg2 : i32 %i4 = "std.subi"(%i, %i) : (i32,i32) -> i32 // CHECK: %[[I5:.*]] = subi %[[I4]], %[[I4]] : i32 %i5 = subi %i4, %i4 : i32 // CHECK: %[[F6:.*]] = mulf %[[F2]], %[[F2]] : f32 %f6 = mulf %f2, %f2 : f32 // CHECK: %[[I6:.*]] = muli %[[I2]], %[[I2]] : i32 %i6 = muli %i2, %i2 : i32 // CHECK: %[[C0:.*]] = create_complex %[[F2]], %[[F2]] : complex %c0 = "std.create_complex"(%f2, %f2) : (f32, f32) -> complex // CHECK: %[[C1:.*]] = create_complex %[[F2]], %[[F2]] : complex %c1 = create_complex %f2, %f2 : complex // CHECK: %[[REAL0:.*]] = re %[[CPLX0:.*]] : complex %real0 = "std.re"(%c0) : (complex) -> f32 // CHECK: %[[REAL1:.*]] = re %[[CPLX0]] : complex %real1 = re %c0 : complex // CHECK: %[[IMAG0:.*]] = im %[[CPLX0]] : complex %imag0 = "std.im"(%c0) : (complex) -> f32 // CHECK: %[[IMAG1:.*]] = im %[[CPLX0]] : complex %imag1 = im %c0 : complex // CHECK: %c42_i32 = constant 42 : i32 %x = "std.constant"(){value = 42 : i32} : () -> i32 // CHECK: %c42_i32_0 = constant 42 : i32 %7 = constant 42 : i32 // CHECK: %c43 = constant {crazy = "std.foo"} 43 : index %8 = constant {crazy = "std.foo"} 43: index // CHECK: %cst = constant 4.300000e+01 : bf16 %9 = constant 43.0 : bf16 // CHECK: %f = constant @func_with_ops : (f32) -> () %10 = constant @func_with_ops : (f32) -> () // CHECK: %f_1 = constant @affine_apply : () -> () %11 = constant @affine_apply : () -> () // CHECK: %f_2 = constant @affine_apply : () -> () %12 = constant @affine_apply : () -> () // CHECK: %cst_3 = constant dense<0> : vector<4xi32> %13 = constant dense<0> : vector<4 x i32> // CHECK: %cst_4 = constant dense<0> : tensor<42xi32> %tci32 = constant dense<0> : tensor<42 x i32> // CHECK: %cst_5 = constant dense<0> : vector<42xi32> %vci32 = constant dense<0> : vector<42 x i32> // CHECK: %{{[0-9]+}} = cmpi "eq", %{{[0-9]+}}, %{{[0-9]+}} : i32 %14 = cmpi "eq", %i3, %i4 : i32 // Predicate 1 means inequality comparison. // CHECK: %{{[0-9]+}} = cmpi "ne", %{{[0-9]+}}, %{{[0-9]+}} : i32 %15 = "std.cmpi"(%i3, %i4) {predicate = 1} : (i32, i32) -> i1 // CHECK: %{{[0-9]+}} = cmpi "slt", %cst_3, %cst_3 : vector<4xi32> %16 = cmpi "slt", %13, %13 : vector<4 x i32> // CHECK: %{{[0-9]+}} = cmpi "ne", %cst_3, %cst_3 : vector<4xi32> %17 = "std.cmpi"(%13, %13) {predicate = 1} : (vector<4 x i32>, vector<4 x i32>) -> vector<4 x i1> // CHECK: %{{[0-9]+}} = cmpi "slt", %arg3, %arg3 : index %18 = cmpi "slt", %idx, %idx : index // CHECK: %{{[0-9]+}} = cmpi "eq", %cst_4, %cst_4 : tensor<42xi32> %19 = cmpi "eq", %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = cmpi "eq", %cst_5, %cst_5 : vector<42xi32> %20 = cmpi "eq", %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = select %{{[0-9]+}}, %arg3, %arg3 : index %21 = select %18, %idx, %idx : index // CHECK: %{{[0-9]+}} = select %{{[0-9]+}}, %cst_4, %cst_4 : tensor<42xi1>, tensor<42xi32> %22 = select %19, %tci32, %tci32 : tensor<42 x i1>, tensor<42 x i32> // CHECK: %{{[0-9]+}} = select %{{[0-9]+}}, %cst_5, %cst_5 : vector<42xi1>, vector<42xi32> %23 = select %20, %vci32, %vci32 : vector<42 x i1>, vector<42 x i32> // CHECK: %{{[0-9]+}} = select %{{[0-9]+}}, %arg3, %arg3 : index %24 = "std.select"(%18, %idx, %idx) : (i1, index, index) -> index // CHECK: %{{[0-9]+}} = select %{{[0-9]+}}, %cst_4, %cst_4 : tensor<42xi32> %25 = std.select %18, %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = divi_signed %arg2, %arg2 : i32 %26 = divi_signed %i, %i : i32 // CHECK: %{{[0-9]+}} = divi_signed %arg3, %arg3 : index %27 = divi_signed %idx, %idx : index // CHECK: %{{[0-9]+}} = divi_signed %cst_5, %cst_5 : vector<42xi32> %28 = divi_signed %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = divi_signed %cst_4, %cst_4 : tensor<42xi32> %29 = divi_signed %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = divi_signed %arg2, %arg2 : i32 %30 = "std.divi_signed"(%i, %i) : (i32, i32) -> i32 // CHECK: %{{[0-9]+}} = divi_unsigned %arg2, %arg2 : i32 %31 = divi_unsigned %i, %i : i32 // CHECK: %{{[0-9]+}} = divi_unsigned %arg3, %arg3 : index %32 = divi_unsigned %idx, %idx : index // CHECK: %{{[0-9]+}} = divi_unsigned %cst_5, %cst_5 : vector<42xi32> %33 = divi_unsigned %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = divi_unsigned %cst_4, %cst_4 : tensor<42xi32> %34 = divi_unsigned %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = divi_unsigned %arg2, %arg2 : i32 %35 = "std.divi_unsigned"(%i, %i) : (i32, i32) -> i32 // CHECK: %{{[0-9]+}} = remi_signed %arg2, %arg2 : i32 %36 = remi_signed %i, %i : i32 // CHECK: %{{[0-9]+}} = remi_signed %arg3, %arg3 : index %37 = remi_signed %idx, %idx : index // CHECK: %{{[0-9]+}} = remi_signed %cst_5, %cst_5 : vector<42xi32> %38 = remi_signed %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = remi_signed %cst_4, %cst_4 : tensor<42xi32> %39 = remi_signed %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = remi_signed %arg2, %arg2 : i32 %40 = "std.remi_signed"(%i, %i) : (i32, i32) -> i32 // CHECK: %{{[0-9]+}} = remi_unsigned %arg2, %arg2 : i32 %41 = remi_unsigned %i, %i : i32 // CHECK: %{{[0-9]+}} = remi_unsigned %arg3, %arg3 : index %42 = remi_unsigned %idx, %idx : index // CHECK: %{{[0-9]+}} = remi_unsigned %cst_5, %cst_5 : vector<42xi32> %43 = remi_unsigned %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = remi_unsigned %cst_4, %cst_4 : tensor<42xi32> %44 = remi_unsigned %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = remi_unsigned %arg2, %arg2 : i32 %45 = "std.remi_unsigned"(%i, %i) : (i32, i32) -> i32 // CHECK: %{{[0-9]+}} = divf %arg1, %arg1 : f32 %46 = "std.divf"(%f, %f) : (f32,f32) -> f32 // CHECK: %{{[0-9]+}} = divf %arg1, %arg1 : f32 %47 = divf %f, %f : f32 // CHECK: %{{[0-9]+}} = divf %arg0, %arg0 : tensor<4x4x?xf32> %48 = divf %t, %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = remf %arg1, %arg1 : f32 %49 = "std.remf"(%f, %f) : (f32,f32) -> f32 // CHECK: %{{[0-9]+}} = remf %arg1, %arg1 : f32 %50 = remf %f, %f : f32 // CHECK: %{{[0-9]+}} = remf %arg0, %arg0 : tensor<4x4x?xf32> %51 = remf %t, %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = and %arg2, %arg2 : i32 %52 = "std.and"(%i, %i) : (i32,i32) -> i32 // CHECK: %{{[0-9]+}} = and %arg2, %arg2 : i32 %53 = and %i, %i : i32 // CHECK: %{{[0-9]+}} = and %cst_5, %cst_5 : vector<42xi32> %54 = std.and %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = and %cst_4, %cst_4 : tensor<42xi32> %55 = and %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = or %arg2, %arg2 : i32 %56 = "std.or"(%i, %i) : (i32,i32) -> i32 // CHECK: %{{[0-9]+}} = or %arg2, %arg2 : i32 %57 = or %i, %i : i32 // CHECK: %{{[0-9]+}} = or %cst_5, %cst_5 : vector<42xi32> %58 = std.or %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = or %cst_4, %cst_4 : tensor<42xi32> %59 = or %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = xor %arg2, %arg2 : i32 %60 = "std.xor"(%i, %i) : (i32,i32) -> i32 // CHECK: %{{[0-9]+}} = xor %arg2, %arg2 : i32 %61 = xor %i, %i : i32 // CHECK: %{{[0-9]+}} = xor %cst_5, %cst_5 : vector<42xi32> %62 = std.xor %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = xor %cst_4, %cst_4 : tensor<42xi32> %63 = xor %tci32, %tci32 : tensor<42 x i32> %64 = constant dense<0.> : vector<4 x f32> %tcf32 = constant dense<0.> : tensor<42 x f32> %vcf32 = constant dense<0.> : vector<4 x f32> // CHECK: %{{[0-9]+}} = cmpf "ogt", %{{[0-9]+}}, %{{[0-9]+}} : f32 %65 = cmpf "ogt", %f3, %f4 : f32 // Predicate 0 means ordered equality comparison. // CHECK: %{{[0-9]+}} = cmpf "oeq", %{{[0-9]+}}, %{{[0-9]+}} : f32 %66 = "std.cmpf"(%f3, %f4) {predicate = 1} : (f32, f32) -> i1 // CHECK: %{{[0-9]+}} = cmpf "olt", %cst_8, %cst_8 : vector<4xf32> %67 = cmpf "olt", %vcf32, %vcf32 : vector<4 x f32> // CHECK: %{{[0-9]+}} = cmpf "oeq", %cst_8, %cst_8 : vector<4xf32> %68 = "std.cmpf"(%vcf32, %vcf32) {predicate = 1} : (vector<4 x f32>, vector<4 x f32>) -> vector<4 x i1> // CHECK: %{{[0-9]+}} = cmpf "oeq", %cst_7, %cst_7 : tensor<42xf32> %69 = cmpf "oeq", %tcf32, %tcf32 : tensor<42 x f32> // CHECK: %{{[0-9]+}} = cmpf "oeq", %cst_8, %cst_8 : vector<4xf32> %70 = cmpf "oeq", %vcf32, %vcf32 : vector<4 x f32> // CHECK: %{{[0-9]+}} = rank %arg0 : tensor<4x4x?xf32> %71 = "std.rank"(%t) : (tensor<4x4x?xf32>) -> index // CHECK: %{{[0-9]+}} = rank %arg0 : tensor<4x4x?xf32> %72 = rank %t : tensor<4x4x?xf32> // CHECK: = constant unit %73 = constant unit // CHECK: constant true %74 = constant true // CHECK: constant false %75 = constant false // CHECK: = index_cast {{.*}} : index to i64 %76 = index_cast %idx : index to i64 // CHECK: = index_cast {{.*}} : i32 to index %77 = index_cast %i : i32 to index // CHECK: = sitofp {{.*}} : i32 to f32 %78 = sitofp %i : i32 to f32 // CHECK: = sitofp {{.*}} : i32 to f64 %79 = sitofp %i : i32 to f64 // CHECK: = sitofp {{.*}} : i64 to f32 %80 = sitofp %j : i64 to f32 // CHECK: = sitofp {{.*}} : i64 to f64 %81 = sitofp %j : i64 to f64 // CHECK: = sexti %arg2 : i32 to i64 %82 = "std.sexti"(%i) : (i32) -> i64 // CHECK: = sexti %arg2 : i32 to i64 %83 = sexti %i : i32 to i64 // CHECK: %{{[0-9]+}} = sexti %cst_5 : vector<42xi32> %84 = sexti %vci32 : vector<42 x i32> to vector<42 x i64> // CHECK: %{{[0-9]+}} = sexti %cst_4 : tensor<42xi32> %85 = sexti %tci32 : tensor<42 x i32> to tensor<42 x i64> // CHECK: = zexti %arg2 : i32 to i64 %86 = "std.zexti"(%i) : (i32) -> i64 // CHECK: = zexti %arg2 : i32 to i64 %87 = zexti %i : i32 to i64 // CHECK: %{{[0-9]+}} = zexti %cst_5 : vector<42xi32> %88 = zexti %vci32 : vector<42 x i32> to vector<42 x i64> // CHECK: %{{[0-9]+}} = zexti %cst_4 : tensor<42xi32> %89 = zexti %tci32 : tensor<42 x i32> to tensor<42 x i64> // CHECK: = trunci %arg2 : i32 to i16 %90 = "std.trunci"(%i) : (i32) -> i16 // CHECK: = trunci %arg2 : i32 to i16 %91 = trunci %i : i32 to i16 // CHECK: %{{[0-9]+}} = trunci %cst_5 : vector<42xi32> %92 = trunci %vci32 : vector<42 x i32> to vector<42 x i16> // CHECK: %{{[0-9]+}} = trunci %cst_4 : tensor<42xi32> %93 = trunci %tci32 : tensor<42 x i32> to tensor<42 x i16> // CHECK: = fpext {{.*}} : f16 to f32 %94 = fpext %half : f16 to f32 // CHECK: = fptrunc {{.*}} : f32 to f16 %95 = fptrunc %f : f32 to f16 // CHECK: %{{[0-9]+}} = exp %arg1 : f32 %96 = "std.exp"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = exp %arg1 : f32 %97 = exp %f : f32 // CHECK: %{{[0-9]+}} = exp %cst_8 : vector<4xf32> %98 = exp %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = exp %arg0 : tensor<4x4x?xf32> %99 = exp %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = absf %arg1 : f32 %100 = "std.absf"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = absf %arg1 : f32 %101 = absf %f : f32 // CHECK: %{{[0-9]+}} = absf %cst_8 : vector<4xf32> %102 = absf %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = absf %arg0 : tensor<4x4x?xf32> %103 = absf %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = ceilf %arg1 : f32 %104 = "std.ceilf"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = ceilf %arg1 : f32 %105 = ceilf %f : f32 // CHECK: %{{[0-9]+}} = ceilf %cst_8 : vector<4xf32> %106 = ceilf %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = ceilf %arg0 : tensor<4x4x?xf32> %107 = ceilf %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = cos %arg1 : f32 %108 = "std.cos"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = cos %arg1 : f32 %109 = cos %f : f32 // CHECK: %{{[0-9]+}} = cos %cst_8 : vector<4xf32> %110 = cos %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = cos %arg0 : tensor<4x4x?xf32> %111 = cos %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = negf %arg1 : f32 %112 = "std.negf"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = negf %arg1 : f32 %113 = negf %f : f32 // CHECK: %{{[0-9]+}} = negf %cst_8 : vector<4xf32> %114 = negf %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = negf %arg0 : tensor<4x4x?xf32> %115 = negf %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = copysign %arg1, %arg1 : f32 %116 = "std.copysign"(%f, %f) : (f32, f32) -> f32 // CHECK: %{{[0-9]+}} = copysign %arg1, %arg1 : f32 %117 = copysign %f, %f : f32 // CHECK: %{{[0-9]+}} = copysign %cst_8, %cst_8 : vector<4xf32> %118 = copysign %vcf32, %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = copysign %arg0, %arg0 : tensor<4x4x?xf32> %119 = copysign %t, %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = tanh %arg1 : f32 %120 = "std.tanh"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = tanh %arg1 : f32 %121 = tanh %f : f32 // CHECK: %{{[0-9]+}} = tanh %cst_8 : vector<4xf32> %122 = tanh %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = tanh %arg0 : tensor<4x4x?xf32> %123 = tanh %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = shift_left %arg2, %arg2 : i32 %124 = "std.shift_left"(%i, %i) : (i32, i32) -> i32 // CHECK:%{{[0-9]+}} = shift_left %[[I2]], %[[I2]] : i32 %125 = shift_left %i2, %i2 : i32 // CHECK: %{{[0-9]+}} = shift_left %arg3, %arg3 : index %126 = shift_left %idx, %idx : index // CHECK: %{{[0-9]+}} = shift_left %cst_5, %cst_5 : vector<42xi32> %127 = shift_left %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = shift_left %cst_4, %cst_4 : tensor<42xi32> %128 = shift_left %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = shift_right_signed %arg2, %arg2 : i32 %129 = "std.shift_right_signed"(%i, %i) : (i32, i32) -> i32 // CHECK:%{{[0-9]+}} = shift_right_signed %[[I2]], %[[I2]] : i32 %130 = shift_right_signed %i2, %i2 : i32 // CHECK: %{{[0-9]+}} = shift_right_signed %arg3, %arg3 : index %131 = shift_right_signed %idx, %idx : index // CHECK: %{{[0-9]+}} = shift_right_signed %cst_5, %cst_5 : vector<42xi32> %132 = shift_right_signed %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = shift_right_signed %cst_4, %cst_4 : tensor<42xi32> %133 = shift_right_signed %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = shift_right_unsigned %arg2, %arg2 : i32 %134 = "std.shift_right_unsigned"(%i, %i) : (i32, i32) -> i32 // CHECK:%{{[0-9]+}} = shift_right_unsigned %[[I2]], %[[I2]] : i32 %135 = shift_right_unsigned %i2, %i2 : i32 // CHECK: %{{[0-9]+}} = shift_right_unsigned %arg3, %arg3 : index %136 = shift_right_unsigned %idx, %idx : index // CHECK: %{{[0-9]+}} = shift_right_unsigned %cst_5, %cst_5 : vector<42xi32> %137 = shift_right_unsigned %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = shift_right_unsigned %cst_4, %cst_4 : tensor<42xi32> %138 = shift_right_unsigned %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = sqrt %arg1 : f32 %139 = "std.sqrt"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = sqrt %arg1 : f32 %140 = sqrt %f : f32 // CHECK: %{{[0-9]+}} = sqrt %cst_8 : vector<4xf32> %141 = sqrt %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = sqrt %arg0 : tensor<4x4x?xf32> %142 = sqrt %t : tensor<4x4x?xf32> // CHECK: = fpext {{.*}} : vector<4xf32> to vector<4xf64> %143 = fpext %vcf32 : vector<4xf32> to vector<4xf64> // CHECK: = fptrunc {{.*}} : vector<4xf32> to vector<4xf16> %144 = fptrunc %vcf32 : vector<4xf32> to vector<4xf16> // CHECK: %{{[0-9]+}} = rsqrt %arg1 : f32 %145 = rsqrt %f : f32 // CHECK: %{{[0-9]+}} = sin %arg1 : f32 %146 = "std.sin"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = sin %arg1 : f32 %147 = sin %f : f32 // CHECK: %{{[0-9]+}} = sin %cst_8 : vector<4xf32> %148 = sin %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = sin %arg0 : tensor<4x4x?xf32> %149 = sin %t : tensor<4x4x?xf32> // CHECK: = fptosi {{.*}} : f32 to i32 %159 = fptosi %f : f32 to i32 // CHECK: = fptosi {{.*}} : f32 to i64 %160 = fptosi %f : f32 to i64 // CHECK: = fptosi {{.*}} : f16 to i32 %161 = fptosi %half : f16 to i32 // CHECK: = fptosi {{.*}} : f16 to i64 %162 = fptosi %half : f16 to i64 // CHECK: floorf %arg1 : f32 %163 = "std.floorf"(%f) : (f32) -> f32 // CHECK: %{{[0-9]+}} = floorf %arg1 : f32 %164 = floorf %f : f32 // CHECK: %{{[0-9]+}} = floorf %cst_8 : vector<4xf32> %165 = floorf %vcf32 : vector<4xf32> // CHECK: %{{[0-9]+}} = floorf %arg0 : tensor<4x4x?xf32> %166 = floorf %t : tensor<4x4x?xf32> // CHECK: %{{[0-9]+}} = floordivi_signed %arg2, %arg2 : i32 %167 = floordivi_signed %i, %i : i32 // CHECK: %{{[0-9]+}} = floordivi_signed %arg3, %arg3 : index %168 = floordivi_signed %idx, %idx : index // CHECK: %{{[0-9]+}} = floordivi_signed %cst_5, %cst_5 : vector<42xi32> %169 = floordivi_signed %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = floordivi_signed %cst_4, %cst_4 : tensor<42xi32> %170 = floordivi_signed %tci32, %tci32 : tensor<42 x i32> // CHECK: %{{[0-9]+}} = ceildivi_signed %arg2, %arg2 : i32 %171 = ceildivi_signed %i, %i : i32 // CHECK: %{{[0-9]+}} = ceildivi_signed %arg3, %arg3 : index %172 = ceildivi_signed %idx, %idx : index // CHECK: %{{[0-9]+}} = ceildivi_signed %cst_5, %cst_5 : vector<42xi32> %173 = ceildivi_signed %vci32, %vci32 : vector<42 x i32> // CHECK: %{{[0-9]+}} = ceildivi_signed %cst_4, %cst_4 : tensor<42xi32> %174 = ceildivi_signed %tci32, %tci32 : tensor<42 x i32> return } // CHECK-LABEL: func @affine_apply() { func @affine_apply() { %i = "std.constant"() {value = 0: index} : () -> index %j = "std.constant"() {value = 1: index} : () -> index // CHECK: affine.apply #map0(%c0) %a = "affine.apply" (%i) { map = affine_map<(d0) -> (d0 + 1)> } : (index) -> (index) // CHECK: affine.apply #map1()[%c0] %b = affine.apply affine_map<()[x] -> (x+1)>()[%i] return } // CHECK-LABEL: func @load_store_prefetch func @load_store_prefetch(memref<4x4xi32>, index) { ^bb0(%0: memref<4x4xi32>, %1: index): // CHECK: %0 = load %arg0[%arg1, %arg1] : memref<4x4xi32> %2 = "std.load"(%0, %1, %1) : (memref<4x4xi32>, index, index)->i32 // CHECK: %{{.*}} = load %arg0[%arg1, %arg1] : memref<4x4xi32> %3 = load %0[%1, %1] : memref<4x4xi32> // CHECK: prefetch %arg0[%arg1, %arg1], write, locality<1>, data : memref<4x4xi32> prefetch %0[%1, %1], write, locality<1>, data : memref<4x4xi32> // CHECK: prefetch %arg0[%arg1, %arg1], read, locality<3>, instr : memref<4x4xi32> prefetch %0[%1, %1], read, locality<3>, instr : memref<4x4xi32> return } // Test with zero-dimensional operands using no index in load/store. // CHECK-LABEL: func @zero_dim_no_idx func @zero_dim_no_idx(%arg0 : memref, %arg1 : memref, %arg2 : memref) { %0 = std.load %arg0[] : memref std.store %0, %arg1[] : memref return // CHECK: %0 = load %{{.*}}[] : memref // CHECK: store %{{.*}}, %{{.*}}[] : memref } // CHECK-LABEL: func @return_op(%arg0: i32) -> i32 { func @return_op(%a : i32) -> i32 { // CHECK: return %arg0 : i32 "std.return" (%a) : (i32)->() } // CHECK-LABEL: func @calls(%arg0: i32) { func @calls(%arg0: i32) { // CHECK: %0 = call @return_op(%arg0) : (i32) -> i32 %x = call @return_op(%arg0) : (i32) -> i32 // CHECK: %1 = call @return_op(%0) : (i32) -> i32 %y = call @return_op(%x) : (i32) -> i32 // CHECK: %2 = call @return_op(%0) : (i32) -> i32 %z = "std.call"(%x) {callee = @return_op} : (i32) -> i32 // CHECK: %f = constant @affine_apply : () -> () %f = constant @affine_apply : () -> () // CHECK: call_indirect %f() : () -> () call_indirect %f() : () -> () // CHECK: %f_0 = constant @return_op : (i32) -> i32 %f_0 = constant @return_op : (i32) -> i32 // CHECK: %3 = call_indirect %f_0(%arg0) : (i32) -> i32 %2 = call_indirect %f_0(%arg0) : (i32) -> i32 // CHECK: %4 = call_indirect %f_0(%arg0) : (i32) -> i32 %3 = "std.call_indirect"(%f_0, %arg0) : ((i32) -> i32, i32) -> i32 return } // CHECK-LABEL: func @extract_element(%arg0: tensor<*xi32>, %arg1: tensor<4x4xf32>) -> i32 { func @extract_element(%arg0: tensor<*xi32>, %arg1 : tensor<4x4xf32>) -> i32 { %c0 = "std.constant"() {value = 0: index} : () -> index // CHECK: %0 = extract_element %arg0[%c0, %c0, %c0, %c0] : tensor<*xi32> %0 = extract_element %arg0[%c0, %c0, %c0, %c0] : tensor<*xi32> // CHECK: %1 = extract_element %arg1[%c0, %c0] : tensor<4x4xf32> %1 = extract_element %arg1[%c0, %c0] : tensor<4x4xf32> return %0 : i32 } // CHECK-LABEL: func @tensor_from_elements() { func @tensor_from_elements() { %c0 = "std.constant"() {value = 0: index} : () -> index // CHECK: %0 = tensor_from_elements %c0 : tensor<1xindex> %0 = tensor_from_elements %c0 : tensor<1xindex> %c1 = "std.constant"() {value = 1: index} : () -> index // CHECK: %1 = tensor_from_elements %c0, %c1 : tensor<2xindex> %1 = tensor_from_elements %c0, %c1 : tensor<2xindex> %c0_f32 = "std.constant"() {value = 0.0: f32} : () -> f32 // CHECK: [[C0_F32:%.*]] = constant // CHECK: %2 = tensor_from_elements [[C0_F32]] : tensor<1xf32> %2 = tensor_from_elements %c0_f32 : tensor<1xf32> // CHECK: tensor_from_elements : tensor<0xindex> %3 = tensor_from_elements : tensor<0xindex> return } // CHECK-LABEL: func @tensor_cast(%arg0 func @tensor_cast(%arg0: tensor<*xf32>, %arg1 : tensor<4x4xf32>, %arg2: tensor) { // CHECK: %0 = tensor_cast %arg0 : tensor<*xf32> to tensor %0 = tensor_cast %arg0 : tensor<*xf32> to tensor // CHECK: %1 = tensor_cast %arg1 : tensor<4x4xf32> to tensor<*xf32> %1 = tensor_cast %arg1 : tensor<4x4xf32> to tensor<*xf32> // CHECK: %2 = tensor_cast %arg2 : tensor to tensor<4x?xf32> %2 = tensor_cast %arg2 : tensor to tensor<4x?xf32> // CHECK: %3 = tensor_cast %2 : tensor<4x?xf32> to tensor %3 = tensor_cast %2 : tensor<4x?xf32> to tensor return } // CHECK-LABEL: func @memref_cast(%arg0 func @memref_cast(%arg0: memref<4xf32>, %arg1 : memref, %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]>) { // CHECK: %0 = memref_cast %arg0 : memref<4xf32> to memref %0 = memref_cast %arg0 : memref<4xf32> to memref // CHECK: %1 = memref_cast %arg1 : memref to memref<4xf32> %1 = memref_cast %arg1 : memref to memref<4xf32> // CHECK: {{%.*}} = memref_cast %arg2 : memref<64x16x4xf32, #[[$BASE_MAP0]]> to memref<64x16x4xf32, #[[$BASE_MAP3]]> %2 = memref_cast %arg2 : memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]> to memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]> // CHECK: {{%.*}} = memref_cast {{%.*}} : memref<64x16x4xf32, #[[$BASE_MAP3]]> to memref<64x16x4xf32, #[[$BASE_MAP0]]> %3 = memref_cast %2 : memref<64x16x4xf32, offset: ?, strides: [?, ?, ?]> to memref<64x16x4xf32, offset: 0, strides: [64, 4, 1]> // CHECK: memref_cast %{{.*}} : memref<4xf32> to memref<*xf32> %4 = memref_cast %1 : memref<4xf32> to memref<*xf32> // CHECK: memref_cast %{{.*}} : memref<*xf32> to memref<4xf32> %5 = memref_cast %4 : memref<*xf32> to memref<4xf32> return } // Check that unranked memrefs with non-default memory space roundtrip // properly. // CHECK-LABEL: @unranked_memref_roundtrip(memref<*xf32, 4>) -func @unranked_memref_roundtrip(memref<*xf32, 4>) +func private @unranked_memref_roundtrip(memref<*xf32, 4>) // CHECK-LABEL: func @memref_view(%arg0 func @memref_view(%arg0 : index, %arg1 : index, %arg2 : index) { %0 = alloc() : memref<2048xi8> // Test two dynamic sizes and dynamic offset. // CHECK: %{{.*}} = std.view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref %1 = view %0[%arg2][%arg0, %arg1] : memref<2048xi8> to memref // Test one dynamic size and dynamic offset. // CHECK: %{{.*}} = std.view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32> %3 = view %0[%arg2][%arg1] : memref<2048xi8> to memref<4x?xf32> // Test static sizes and static offset. // CHECK: %{{.*}} = std.view %0[{{.*}}][] : memref<2048xi8> to memref<64x4xf32> %c0 = constant 0: index %5 = view %0[%c0][] : memref<2048xi8> to memref<64x4xf32> return } // CHECK-LABEL: func @memref_subview(%arg0 func @memref_subview(%arg0 : index, %arg1 : index, %arg2 : index) { %c0 = constant 0 : index %c1 = constant 1 : index %0 = alloc() : memref<8x16x4xf32, affine_map<(d0, d1, d2) -> (d0 * 64 + d1 * 4 + d2)>> // CHECK: subview %0[%c0, %c0, %c0] [%arg0, %arg1, %arg2] [%c1, %c1, %c1] : // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> // CHECK-SAME: to memref %1 = subview %0[%c0, %c0, %c0][%arg0, %arg1, %arg2][%c1, %c1, %c1] : memref<8x16x4xf32, offset:0, strides: [64, 4, 1]> to memref %2 = alloc()[%arg2] : memref<64xf32, affine_map<(d0)[s0] -> (d0 + s0)>> // CHECK: subview %2[%c1] [%arg0] [%c1] : // CHECK-SAME: memref<64xf32, #[[$BASE_MAP1]]> // CHECK-SAME: to memref %3 = subview %2[%c1][%arg0][%c1] : memref<64xf32, affine_map<(d0)[s0] -> (d0 + s0)>> to memref (d0 * s1 + s0)>> %4 = alloc() : memref<64x22xf32, affine_map<(d0, d1) -> (d0 * 22 + d1)>> // CHECK: subview %4[%c0, %c1] [%arg0, %arg1] [%c1, %c0] : // CHECK-SAME: memref<64x22xf32, #[[$BASE_MAP2]]> // CHECK-SAME: to memref %5 = subview %4[%c0, %c1][%arg0, %arg1][%c1, %c0] : memref<64x22xf32, offset:0, strides: [22, 1]> to memref // CHECK: subview %0[0, 2, 0] [4, 4, 4] [1, 1, 1] : // CHECK-SAME: memref<8x16x4xf32, #[[$BASE_MAP0]]> // CHECK-SAME: to memref<4x4x4xf32, #[[$SUBVIEW_MAP3]]> %6 = subview %0[0, 2, 0][4, 4, 4][1, 1, 1] : memref<8x16x4xf32, offset:0, strides: [64, 4, 1]> to memref<4x4x4xf32, offset:8, strides: [64, 4, 1]> %7 = alloc(%arg1, %arg2) : memref // CHECK: subview {{%.*}}[0, 0] [4, 4] [1, 1] : // CHECK-SAME: memref // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP4]]> %8 = subview %7[0, 0][4, 4][1, 1] : memref to memref<4x4xf32, offset: ?, strides:[?, 1]> %9 = alloc() : memref<16x4xf32> // CHECK: subview {{%.*}}[{{%.*}}, {{%.*}}] [4, 4] [{{%.*}}, {{%.*}}] : // CHECK-SAME: memref<16x4xf32> // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP2]] %10 = subview %9[%arg1, %arg1][4, 4][%arg2, %arg2] : memref<16x4xf32> to memref<4x4xf32, offset: ?, strides:[?, ?]> // CHECK: subview {{%.*}}[{{%.*}}, {{%.*}}] [4, 4] [2, 2] : // CHECK-SAME: memref<16x4xf32> // CHECK-SAME: to memref<4x4xf32, #[[$SUBVIEW_MAP5]] %11 = subview %9[%arg1, %arg2][4, 4][2, 2] : memref<16x4xf32> to memref<4x4xf32, offset: ?, strides:[8, 2]> %12 = alloc() : memref<1x9x1x4x1xf32, affine_map<(d0, d1, d2, d3, d4) -> (36 * d0 + 36 * d1 + 4 * d2 + 4 * d3 + d4)>> // CHECK: subview %12[%arg1, %arg1, %arg1, %arg1, %arg1] // CHECK-SAME: [1, 9, 1, 4, 1] [%arg2, %arg2, %arg2, %arg2, %arg2] : // CHECK-SAME: memref<1x9x1x4x1xf32, #[[$SUBVIEW_MAP6]]> to memref<9x4xf32, #[[$SUBVIEW_MAP2]]> %13 = subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, offset: 0, strides: [36, 36, 4, 4, 1]> to memref<9x4xf32, offset: ?, strides: [?, ?]> // CHECK: subview %12[%arg1, %arg1, %arg1, %arg1, %arg1] // CHECK-SAME: [1, 9, 1, 4, 1] [%arg2, %arg2, %arg2, %arg2, %arg2] : // CHECK-SAME: memref<1x9x1x4x1xf32, #[[$SUBVIEW_MAP6]]> to memref<1x9x4xf32, #[[$BASE_MAP3]]> %14 = subview %12[%arg1, %arg1, %arg1, %arg1, %arg1][1, 9, 1, 4, 1][%arg2, %arg2, %arg2, %arg2, %arg2] : memref<1x9x1x4x1xf32, offset: 0, strides: [36, 36, 4, 4, 1]> to memref<1x9x4xf32, offset: ?, strides: [?, ?, ?]> %15 = alloc(%arg1, %arg2)[%c0, %c1, %arg1, %arg0, %arg0, %arg2, %arg2] : memref<1x?x5x1x?x1xf32, affine_map<(d0, d1, d2, d3, d4, d5)[s0, s1, s2, s3, s4, s5, s6] -> (s0 + s1 * d0 + s2 * d1 + s3 * d2 + s4 * d3 + s5 * d4 + s6 * d5)>> // CHECK: subview %15[0, 0, 0, 0, 0, 0] [1, %arg1, 5, 1, %arg2, 1] [1, 1, 1, 1, 1, 1] : // CHECK-SAME: memref<1x?x5x1x?x1xf32, #[[$SUBVIEW_MAP7]]> to memref %16 = subview %15[0, 0, 0, 0, 0, 0][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] : memref<1x?x5x1x?x1xf32, offset: ?, strides: [?, ?, ?, ?, ?, ?]> to memref // CHECK: subview %15[%arg1, %arg1, %arg1, %arg1, %arg1, %arg1] [1, %arg1, 5, 1, %arg2, 1] [1, 1, 1, 1, 1, 1] : // CHECK-SAME: memref<1x?x5x1x?x1xf32, #[[$SUBVIEW_MAP7]]> to memref %17 = subview %15[%arg1, %arg1, %arg1, %arg1, %arg1, %arg1][1, %arg1, 5, 1, %arg2, 1][1, 1, 1, 1, 1, 1] : memref<1x?x5x1x?x1xf32, offset: ?, strides: [?, ?, ?, ?, ?, ?]> to memref %18 = alloc() : memref<1x8xf32> // CHECK: subview %18[0, 0] [1, 8] [1, 1] : memref<1x8xf32> to memref<8xf32> %19 = subview %18[0, 0][1, 8][1, 1] : memref<1x8xf32> to memref<8xf32> %20 = alloc() : memref<8x16x4xf32> // CHECK: subview %20[0, 0, 0] [1, 16, 4] [1, 1, 1] : memref<8x16x4xf32> to memref<16x4xf32> %21 = subview %20[0, 0, 0][1, 16, 4][1, 1, 1] : memref<8x16x4xf32> to memref<16x4xf32> %22 = subview %20[3, 4, 2][1, 6, 3][1, 1, 1] : memref<8x16x4xf32> to memref<6x3xf32, offset: 210, strides: [4, 1]> %23 = alloc() : memref %78 = subview %23[] [] [] : memref to memref return } // CHECK-LABEL: func @test_dimop // CHECK-SAME: %[[ARG:.*]]: tensor<4x4x?xf32> func @test_dimop(%arg0: tensor<4x4x?xf32>) { // CHECK: %[[C2:.*]] = constant 2 : index // CHECK: %{{.*}} = dim %[[ARG]], %[[C2]] : tensor<4x4x?xf32> %c2 = constant 2 : index %0 = dim %arg0, %c2 : tensor<4x4x?xf32> // use dim as an index to ensure type correctness %1 = affine.apply affine_map<(d0) -> (d0)>(%0) return } // CHECK-LABEL: func @test_splat_op // CHECK-SAME: [[S:%arg[0-9]+]]: f32 func @test_splat_op(%s : f32) { %v = splat %s : vector<8xf32> // CHECK: splat [[S]] : vector<8xf32> %t = splat %s : tensor<8xf32> // CHECK: splat [[S]] : tensor<8xf32> %u = "std.splat"(%s) : (f32) -> vector<4xf32> // CHECK: splat [[S]] : vector<4xf32> return } // CHECK-LABEL: func @tensor_load_store func @tensor_load_store(%0 : memref<4x4xi32>) { // CHECK: %[[TENSOR:.*]] = tensor_load %[[MEMREF:.*]] : memref<4x4xi32> %1 = tensor_load %0 : memref<4x4xi32> // CHECK: tensor_store %[[TENSOR]], %[[MEMREF]] : memref<4x4xi32> tensor_store %1, %0 : memref<4x4xi32> return } // CHECK-LABEL: func @unranked_tensor_load_store func @unranked_tensor_load_store(%0 : memref<*xi32>) { // CHECK: %[[TENSOR:.*]] = tensor_load %[[MEMREF:.*]] : memref<*xi32> %1 = tensor_load %0 : memref<*xi32> // CHECK: tensor_store %[[TENSOR]], %[[MEMREF]] : memref<*xi32> tensor_store %1, %0 : memref<*xi32> return } // CHECK-LABEL: func @atomic_rmw // CHECK-SAME: ([[BUF:%.*]]: memref<10xf32>, [[VAL:%.*]]: f32, [[I:%.*]]: index) func @atomic_rmw(%I: memref<10xf32>, %val: f32, %i : index) { %x = atomic_rmw "addf" %val, %I[%i] : (f32, memref<10xf32>) -> f32 // CHECK: atomic_rmw "addf" [[VAL]], [[BUF]]{{\[}}[[I]]] return } // CHECK-LABEL: func @generic_atomic_rmw // CHECK-SAME: ([[BUF:%.*]]: memref<1x2xf32>, [[I:%.*]]: index, [[J:%.*]]: index) func @generic_atomic_rmw(%I: memref<1x2xf32>, %i : index, %j : index) { %x = generic_atomic_rmw %I[%i, %j] : memref<1x2xf32> { // CHECK-NEXT: generic_atomic_rmw [[BUF]]{{\[}}[[I]], [[J]]] : memref ^bb0(%old_value : f32): %c1 = constant 1.0 : f32 %out = addf %c1, %old_value : f32 atomic_yield %out : f32 // CHECK: index_attr = 8 : index } { index_attr = 8 : index } return } // CHECK-LABEL: func @assume_alignment // CHECK-SAME: %[[MEMREF:.*]]: memref<4x4xf16> func @assume_alignment(%0: memref<4x4xf16>) { // CHECK: assume_alignment %[[MEMREF]], 16 : memref<4x4xf16> assume_alignment %0, 16 : memref<4x4xf16> return } // CHECK-LABEL: func @subtensor({{.*}}) { func @subtensor(%t: tensor<8x16x4xf32>, %idx : index) { %c0 = constant 0 : index %c1 = constant 1 : index // CHECK: subtensor // CHECK-SAME: tensor<8x16x4xf32> to tensor %1 = subtensor %t[%c0, %c0, %c0][%idx, %idx, %idx][%c1, %c1, %c1] : tensor<8x16x4xf32> to tensor // CHECK: subtensor // CHECK-SAME: tensor<8x16x4xf32> to tensor<4x4x4xf32> %2 = subtensor %t[0, 2, 0][4, 4, 4][1, 1, 1] : tensor<8x16x4xf32> to tensor<4x4x4xf32> // CHECK: subtensor // CHECK-SAME: tensor<8x16x4xf32> to tensor<4x4xf32> %3 = subtensor %t[0, 2, 0][4, 1, 4][1, 1, 1] : tensor<8x16x4xf32> to tensor<4x4xf32> return } // CHECK-LABEL: func @subtensor_insert({{.*}}) { func @subtensor_insert(%t: tensor<8x16x4xf32>, %t2: tensor<16x32x8xf32>, %idx : index) { %c0 = constant 0 : index %c1 = constant 1 : index // CHECK: subtensor_insert // CHECK-SAME: tensor<8x16x4xf32> into tensor<16x32x8xf32> %1 = subtensor_insert %t into %t2[%c0, %c0, %c0][%idx, %idx, %idx][%c1, %c1, %c1] : tensor<8x16x4xf32> into tensor<16x32x8xf32> // CHECK: subtensor_insert // CHECK-SAME: tensor<8x16x4xf32> into tensor<16x32x8xf32> %2 = subtensor_insert %t into %t2[%c0, %idx, %c0][%idx, 4, %idx][%c1, 1, %c1] : tensor<8x16x4xf32> into tensor<16x32x8xf32> return } // CHECK-LABEL: func private @legacy_visibility_syntax func @legacy_visibility_syntax() attributes { sym_visibility = "private" } diff --git a/mlir/test/IR/invalid-func-op.mlir b/mlir/test/IR/invalid-func-op.mlir index 20af5ece6b11..afa736998076 100644 --- a/mlir/test/IR/invalid-func-op.mlir +++ b/mlir/test/IR/invalid-func-op.mlir @@ -1,75 +1,80 @@ // RUN: mlir-opt %s -split-input-file -verify-diagnostics // ----- func @func_op() { // expected-error@+1 {{expected valid '@'-identifier for symbol name}} func missingsigil() -> (i1, index, f32) return } // ----- func @func_op() { // expected-error@+1 {{expected type instead of SSA identifier}} func @mixed_named_arguments(f32, %a : i32) { return } return } // ----- func @func_op() { // expected-error@+1 {{expected SSA identifier}} func @mixed_named_arguments(%a : i32, f32) -> () { return } return } // ----- func @func_op() { // expected-error@+1 {{entry block must have 1 arguments to match function signature}} func @mixed_named_arguments(f32) { ^entry: return } return } // ----- func @func_op() { // expected-error@+1 {{type of entry block argument #0('i32') must match the type of the corresponding argument in function signature('f32')}} func @mixed_named_arguments(f32) { ^entry(%arg : i32): return } return } // ----- // expected-error@+1 {{expected non-function type}} func @f() -> (foo // ----- // expected-error@+1 {{expected attribute name}} func @f() -> (i1 {) // ----- // expected-error@+1 {{invalid to use 'test.invalid_attr'}} func @f(%arg0: i64 {test.invalid_attr}) { return } // ----- // expected-error@+1 {{invalid to use 'test.invalid_attr'}} func @f(%arg0: i64) -> (i64 {test.invalid_attr}) { return %arg0 : i64 } + +// ----- + +// expected-error@+1 {{symbol declaration cannot have public visibility}} +func @invalid_public_declaration() diff --git a/mlir/test/IR/locations.mlir b/mlir/test/IR/locations.mlir index f7c9636d2ba4..950b67827a0f 100644 --- a/mlir/test/IR/locations.mlir +++ b/mlir/test/IR/locations.mlir @@ -1,34 +1,34 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -mlir-print-debuginfo -mlir-print-local-scope | FileCheck %s // RUN: mlir-opt -allow-unregistered-dialect %s -mlir-print-debuginfo | FileCheck %s --check-prefix=CHECK-ALIAS // This test verifies that debug locations are round-trippable. #set0 = affine_set<(d0) : (1 == 0)> // CHECK-LABEL: func @inline_notation func @inline_notation() -> i32 { // CHECK: -> i32 loc("foo") %1 = "foo"() : () -> i32 loc("foo") // CHECK: constant 4 : index loc(callsite("foo" at "mysource.cc":10:8)) %2 = constant 4 : index loc(callsite("foo" at "mysource.cc":10:8)) // CHECK: } loc(fused["foo", "mysource.cc":10:8]) affine.for %i0 = 0 to 8 { } loc(fused["foo", "mysource.cc":10:8]) // CHECK: } loc(fused<"myPass">["foo", "foo2"]) affine.if #set0(%2) { } loc(fused<"myPass">["foo", "foo2"]) // CHECK: return %0 : i32 loc(unknown) return %1 : i32 loc(unknown) } -// CHECK-LABEL: func @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))}) -func @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))}) +// CHECK-LABEL: func private @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))}) +func private @loc_attr(i1 {foo.loc_attr = loc(callsite("foo" at "mysource.cc":10:8))}) // CHECK-ALIAS: "foo.op"() : () -> () loc(#[[LOC:.*]]) "foo.op"() : () -> () loc(#loc) // CHECK-ALIAS: #[[LOC]] = loc("out_of_line_location") #loc = loc("out_of_line_location") diff --git a/mlir/test/IR/parser.mlir b/mlir/test/IR/parser.mlir index ecb9ccc296ba..9098e9ace5fa 100644 --- a/mlir/test/IR/parser.mlir +++ b/mlir/test/IR/parser.mlir @@ -1,1380 +1,1380 @@ // RUN: mlir-opt -allow-unregistered-dialect %s | FileCheck %s // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2, d3, d4)[s0] -> (d0, d1, d2, d4, d3)> #map0 = affine_map<(d0, d1, d2, d3, d4)[s0] -> (d0, d1, d2, d4, d3)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0) -> (d0)> #map1 = affine_map<(d0) -> (d0)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d0, d1, d2)> #map2 = affine_map<(d0, d1, d2) -> (d0, d1, d2)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d1, d0, d2)> #map3 = affine_map<(d0, d1, d2) -> (d1, d0, d2)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d2, d1, d0)> #map4 = affine_map<(d0, d1, d2) -> (d2, d1, d0)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<()[s0] -> (0, s0 - 1)> #inline_map_minmax_loop1 = affine_map<()[s0] -> (0, s0 - 1)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<()[s0] -> (100, s0 + 1)> #inline_map_minmax_loop2 = affine_map<()[s0] -> (100, s0 + 1)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + s0)> #bound_map1 = affine_map<(i, j)[s] -> (i + j + s)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 + d1)> #inline_map_loop_bounds2 = affine_map<(d0, d1) -> (d0 + d1)> // CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0)[s0] -> (d0 + s0, d0 - s0)> #bound_map2 = affine_map<(i)[s] -> (i + s, i - s)> // All maps appear in arbitrary order before all sets, in arbitrary order. // CHECK-NOT: Placeholder // CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0)[s0, s1] : (d0 >= 0, -d0 + s0 >= 0, s0 - 5 == 0, -d0 + s1 + 1 >= 0)> #set0 = affine_set<(i)[N, M] : (i >= 0, -i + N >= 0, N - 5 == 0, -i + M + 1 >= 0)> // CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0, d1)[s0] : (d0 >= 0, d1 >= 0)> #set1 = affine_set<(d0, d1)[s0] : (d0 >= 0, d1 >= 0)> // CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0) : (d0 - 1 == 0)> #set2 = affine_set<(d0) : (d0 - 1 == 0)> // CHECK-DAG: [[$SET_TRUE:#set[0-9]+]] = affine_set<() : (0 == 0)> // CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0)[s0] : (d0 - 2 >= 0, -d0 + 4 >= 0)> -// CHECK: func @foo(i32, i64) -> f32 -func @foo(i32, i64) -> f32 +// CHECK: func private @foo(i32, i64) -> f32 +func private @foo(i32, i64) -> f32 -// CHECK: func @bar() -func @bar() -> () +// CHECK: func private @bar() +func private @bar() -> () -// CHECK: func @baz() -> (i1, index, f32) -func @baz() -> (i1, index, f32) +// CHECK: func private @baz() -> (i1, index, f32) +func private @baz() -> (i1, index, f32) -// CHECK: func @missingReturn() -func @missingReturn() +// CHECK: func private @missingReturn() +func private @missingReturn() -// CHECK: func @int_types(i1, i2, i4, i7, i87) -> (i1, index, i19) -func @int_types(i1, i2, i4, i7, i87) -> (i1, index, i19) +// CHECK: func private @int_types(i1, i2, i4, i7, i87) -> (i1, index, i19) +func private @int_types(i1, i2, i4, i7, i87) -> (i1, index, i19) -// CHECK: func @sint_types(si2, si4) -> (si7, si1023) -func @sint_types(si2, si4) -> (si7, si1023) +// CHECK: func private @sint_types(si2, si4) -> (si7, si1023) +func private @sint_types(si2, si4) -> (si7, si1023) -// CHECK: func @uint_types(ui2, ui4) -> (ui7, ui1023) -func @uint_types(ui2, ui4) -> (ui7, ui1023) +// CHECK: func private @uint_types(ui2, ui4) -> (ui7, ui1023) +func private @uint_types(ui2, ui4) -> (ui7, ui1023) -// CHECK: func @vectors(vector<1xf32>, vector<2x4xf32>) -func @vectors(vector<1 x f32>, vector<2x4xf32>) +// CHECK: func private @vectors(vector<1xf32>, vector<2x4xf32>) +func private @vectors(vector<1 x f32>, vector<2x4xf32>) -// CHECK: func @tensors(tensor<*xf32>, tensor<*xvector<2x4xf32>>, tensor<1x?x4x?x?xi32>, tensor) -func @tensors(tensor<* x f32>, tensor<* x vector<2x4xf32>>, +// CHECK: func private @tensors(tensor<*xf32>, tensor<*xvector<2x4xf32>>, tensor<1x?x4x?x?xi32>, tensor) +func private @tensors(tensor<* x f32>, tensor<* x vector<2x4xf32>>, tensor<1x?x4x?x?xi32>, tensor) -// CHECK: func @memrefs(memref<1x?x4x?x?xi32, #map{{[0-9]+}}>, memref<8xi8>) -func @memrefs(memref<1x?x4x?x?xi32, #map0>, memref<8xi8, #map1, #map1>) +// CHECK: func private @memrefs(memref<1x?x4x?x?xi32, #map{{[0-9]+}}>, memref<8xi8>) +func private @memrefs(memref<1x?x4x?x?xi32, #map0>, memref<8xi8, #map1, #map1>) // Test memref affine map compositions. -// CHECK: func @memrefs2(memref<2x4x8xi8, 1>) -func @memrefs2(memref<2x4x8xi8, #map2, 1>) +// CHECK: func private @memrefs2(memref<2x4x8xi8, 1>) +func private @memrefs2(memref<2x4x8xi8, #map2, 1>) -// CHECK: func @memrefs23(memref<2x4x8xi8, #map{{[0-9]+}}>) -func @memrefs23(memref<2x4x8xi8, #map2, #map3, 0>) +// CHECK: func private @memrefs23(memref<2x4x8xi8, #map{{[0-9]+}}>) +func private @memrefs23(memref<2x4x8xi8, #map2, #map3, 0>) -// CHECK: func @memrefs234(memref<2x4x8xi8, #map{{[0-9]+}}, #map{{[0-9]+}}, 3>) -func @memrefs234(memref<2x4x8xi8, #map2, #map3, #map4, 3>) +// CHECK: func private @memrefs234(memref<2x4x8xi8, #map{{[0-9]+}}, #map{{[0-9]+}}, 3>) +func private @memrefs234(memref<2x4x8xi8, #map2, #map3, #map4, 3>) // Test memref inline affine map compositions, minding that identity maps are removed. -// CHECK: func @memrefs3(memref<2x4x8xi8>) -func @memrefs3(memref<2x4x8xi8, affine_map<(d0, d1, d2) -> (d0, d1, d2)>>) +// CHECK: func private @memrefs3(memref<2x4x8xi8>) +func private @memrefs3(memref<2x4x8xi8, affine_map<(d0, d1, d2) -> (d0, d1, d2)>>) -// CHECK: func @memrefs33(memref<2x4x8xi8, #map{{[0-9]+}}, 1>) -func @memrefs33(memref<2x4x8xi8, affine_map<(d0, d1, d2) -> (d0, d1, d2)>, affine_map<(d0, d1, d2) -> (d1, d0, d2)>, 1>) +// CHECK: func private @memrefs33(memref<2x4x8xi8, #map{{[0-9]+}}, 1>) +func private @memrefs33(memref<2x4x8xi8, affine_map<(d0, d1, d2) -> (d0, d1, d2)>, affine_map<(d0, d1, d2) -> (d1, d0, d2)>, 1>) -// CHECK: func @memrefs_drop_triv_id_inline(memref<2xi8>) -func @memrefs_drop_triv_id_inline(memref<2xi8, affine_map<(d0) -> (d0)>>) +// CHECK: func private @memrefs_drop_triv_id_inline(memref<2xi8>) +func private @memrefs_drop_triv_id_inline(memref<2xi8, affine_map<(d0) -> (d0)>>) -// CHECK: func @memrefs_drop_triv_id_inline0(memref<2xi8>) -func @memrefs_drop_triv_id_inline0(memref<2xi8, affine_map<(d0) -> (d0)>, 0>) +// CHECK: func private @memrefs_drop_triv_id_inline0(memref<2xi8>) +func private @memrefs_drop_triv_id_inline0(memref<2xi8, affine_map<(d0) -> (d0)>, 0>) -// CHECK: func @memrefs_drop_triv_id_inline1(memref<2xi8, 1>) -func @memrefs_drop_triv_id_inline1(memref<2xi8, affine_map<(d0) -> (d0)>, 1>) +// CHECK: func private @memrefs_drop_triv_id_inline1(memref<2xi8, 1>) +func private @memrefs_drop_triv_id_inline1(memref<2xi8, affine_map<(d0) -> (d0)>, 1>) // Identity maps should be dropped from the composition, but not the pair of // "interchange" maps that, if composed, would be also an identity. -// CHECK: func @memrefs_drop_triv_id_composition(memref<2x2xi8, #map{{[0-9]+}}, #map{{[0-9]+}}>) -func @memrefs_drop_triv_id_composition(memref<2x2xi8, +// CHECK: func private @memrefs_drop_triv_id_composition(memref<2x2xi8, #map{{[0-9]+}}, #map{{[0-9]+}}>) +func private @memrefs_drop_triv_id_composition(memref<2x2xi8, affine_map<(d0, d1) -> (d1, d0)>, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d1, d0)>, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0, d1)>>) -// CHECK: func @memrefs_drop_triv_id_trailing(memref<2x2xi8, #map{{[0-9]+}}>) -func @memrefs_drop_triv_id_trailing(memref<2x2xi8, affine_map<(d0, d1) -> (d1, d0)>, +// CHECK: func private @memrefs_drop_triv_id_trailing(memref<2x2xi8, #map{{[0-9]+}}>) +func private @memrefs_drop_triv_id_trailing(memref<2x2xi8, affine_map<(d0, d1) -> (d1, d0)>, affine_map<(d0, d1) -> (d0, d1)>>) -// CHECK: func @memrefs_drop_triv_id_middle(memref<2x2xi8, #map{{[0-9]+}}, #map{{[0-9]+}}>) -func @memrefs_drop_triv_id_middle(memref<2x2xi8, +// CHECK: func private @memrefs_drop_triv_id_middle(memref<2x2xi8, #map{{[0-9]+}}, #map{{[0-9]+}}>) +func private @memrefs_drop_triv_id_middle(memref<2x2xi8, affine_map<(d0, d1) -> (d0, d1 + 1)>, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0 + 1, d1)>>) -// CHECK: func @memrefs_drop_triv_id_multiple(memref<2xi8>) -func @memrefs_drop_triv_id_multiple(memref<2xi8, affine_map<(d0) -> (d0)>, affine_map<(d0) -> (d0)>>) +// CHECK: func private @memrefs_drop_triv_id_multiple(memref<2xi8>) +func private @memrefs_drop_triv_id_multiple(memref<2xi8, affine_map<(d0) -> (d0)>, affine_map<(d0) -> (d0)>>) // These maps appeared before, so they must be uniqued and hoisted to the beginning. // Identity map should be removed. -// CHECK: func @memrefs_compose_with_id(memref<2x2xi8, #map{{[0-9]+}}>) -func @memrefs_compose_with_id(memref<2x2xi8, affine_map<(d0, d1) -> (d0, d1)>, +// CHECK: func private @memrefs_compose_with_id(memref<2x2xi8, #map{{[0-9]+}}>) +func private @memrefs_compose_with_id(memref<2x2xi8, affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d1, d0)>>) -// CHECK: func @complex_types(complex) -> complex -func @complex_types(complex) -> complex +// CHECK: func private @complex_types(complex) -> complex +func private @complex_types(complex) -> complex -// CHECK: func @memref_with_index_elems(memref<1x?xindex>) -func @memref_with_index_elems(memref<1x?xindex>) +// CHECK: func private @memref_with_index_elems(memref<1x?xindex>) +func private @memref_with_index_elems(memref<1x?xindex>) -// CHECK: func @memref_with_complex_elems(memref<1x?xcomplex>) -func @memref_with_complex_elems(memref<1x?xcomplex>) +// CHECK: func private @memref_with_complex_elems(memref<1x?xcomplex>) +func private @memref_with_complex_elems(memref<1x?xcomplex>) -// CHECK: func @memref_with_vector_elems(memref<1x?xvector<10xf32>>) -func @memref_with_vector_elems(memref<1x?xvector<10xf32>>) +// CHECK: func private @memref_with_vector_elems(memref<1x?xvector<10xf32>>) +func private @memref_with_vector_elems(memref<1x?xvector<10xf32>>) -// CHECK: func @unranked_memref_with_complex_elems(memref<*xcomplex>) -func @unranked_memref_with_complex_elems(memref<*xcomplex>) +// CHECK: func private @unranked_memref_with_complex_elems(memref<*xcomplex>) +func private @unranked_memref_with_complex_elems(memref<*xcomplex>) -// CHECK: func @unranked_memref_with_index_elems(memref<*xindex>) -func @unranked_memref_with_index_elems(memref<*xindex>) +// CHECK: func private @unranked_memref_with_index_elems(memref<*xindex>) +func private @unranked_memref_with_index_elems(memref<*xindex>) -// CHECK: func @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>) -func @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>) +// CHECK: func private @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>) +func private @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>) -// CHECK: func @functions((memref<1x?x4x?x?xi32, #map0>, memref<8xi8>) -> (), () -> ()) -func @functions((memref<1x?x4x?x?xi32, #map0, 0>, memref<8xi8, #map1, 0>) -> (), ()->()) +// CHECK: func private @functions((memref<1x?x4x?x?xi32, #map0>, memref<8xi8>) -> (), () -> ()) +func private @functions((memref<1x?x4x?x?xi32, #map0, 0>, memref<8xi8, #map1, 0>) -> (), ()->()) // CHECK-LABEL: func @simpleCFG(%{{.*}}: i32, %{{.*}}: f32) -> i1 { func @simpleCFG(%arg0: i32, %f: f32) -> i1 { // CHECK: %{{.*}} = "foo"() : () -> i64 %1 = "foo"() : ()->i64 // CHECK: "bar"(%{{.*}}) : (i64) -> (i1, i1, i1) %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) // CHECK: return %{{.*}}#1 return %2#1 : i1 // CHECK: } } // CHECK-LABEL: func @simpleCFGUsingBBArgs(%{{.*}}: i32, %{{.*}}: i64) { func @simpleCFGUsingBBArgs(i32, i64) { ^bb42 (%arg0: i32, %f: i64): // CHECK: "bar"(%{{.*}}) : (i64) -> (i1, i1, i1) %2:3 = "bar"(%f) : (i64) -> (i1,i1,i1) // CHECK: return{{$}} return // CHECK: } } // CHECK-LABEL: func @multiblock() { func @multiblock() { return // CHECK: return ^bb1: // CHECK: ^bb1: // no predecessors br ^bb4 // CHECK: br ^bb3 ^bb2: // CHECK: ^bb2: // pred: ^bb2 br ^bb2 // CHECK: br ^bb2 ^bb4: // CHECK: ^bb3: // pred: ^bb1 return // CHECK: return } // CHECK: } // CHECK-LABEL: func @emptyMLF() { func @emptyMLF() { return // CHECK: return } // CHECK: } // CHECK-LABEL: func @func_with_one_arg(%{{.*}}: i1) -> i2 { func @func_with_one_arg(%c : i1) -> i2 { // CHECK: %{{.*}} = "foo"(%{{.*}}) : (i1) -> i2 %b = "foo"(%c) : (i1) -> (i2) return %b : i2 // CHECK: return %{{.*}} : i2 } // CHECK: } // CHECK-LABEL: func @func_with_two_args(%{{.*}}: f16, %{{.*}}: i8) -> (i1, i32) { func @func_with_two_args(%a : f16, %b : i8) -> (i1, i32) { // CHECK: %{{.*}}:2 = "foo"(%{{.*}}, %{{.*}}) : (f16, i8) -> (i1, i32) %c:2 = "foo"(%a, %b) : (f16, i8)->(i1, i32) return %c#0, %c#1 : i1, i32 // CHECK: return %{{.*}}#0, %{{.*}}#1 : i1, i32 } // CHECK: } // CHECK-LABEL: func @second_order_func() -> (() -> ()) { func @second_order_func() -> (() -> ()) { // CHECK-NEXT: %{{.*}} = constant @emptyMLF : () -> () %c = constant @emptyMLF : () -> () // CHECK-NEXT: return %{{.*}} : () -> () return %c : () -> () } // CHECK-LABEL: func @third_order_func() -> (() -> (() -> ())) { func @third_order_func() -> (() -> (() -> ())) { // CHECK-NEXT: %{{.*}} = constant @second_order_func : () -> (() -> ()) %c = constant @second_order_func : () -> (() -> ()) // CHECK-NEXT: return %{{.*}} : () -> (() -> ()) return %c : () -> (() -> ()) } // CHECK-LABEL: func @identity_functor(%{{.*}}: () -> ()) -> (() -> ()) { func @identity_functor(%a : () -> ()) -> (() -> ()) { // CHECK-NEXT: return %{{.*}} : () -> () return %a : () -> () } // CHECK-LABEL: func @func_ops_in_loop() { func @func_ops_in_loop() { // CHECK: %{{.*}} = "foo"() : () -> i64 %a = "foo"() : ()->i64 // CHECK: affine.for %{{.*}} = 1 to 10 { affine.for %i = 1 to 10 { // CHECK: %{{.*}} = "doo"() : () -> f32 %b = "doo"() : ()->f32 // CHECK: "bar"(%{{.*}}, %{{.*}}) : (i64, f32) -> () "bar"(%a, %b) : (i64, f32) -> () // CHECK: } } // CHECK: return return // CHECK: } } // CHECK-LABEL: func @loops() { func @loops() { // CHECK: affine.for %{{.*}} = 1 to 100 step 2 { affine.for %i = 1 to 100 step 2 { // CHECK: affine.for %{{.*}} = 1 to 200 { affine.for %j = 1 to 200 { } // CHECK: } } // CHECK: } return // CHECK: return } // CHECK: } // CHECK-LABEL: func @complex_loops() { func @complex_loops() { affine.for %i1 = 1 to 100 { // CHECK: affine.for %{{.*}} = 1 to 100 { affine.for %j1 = 1 to 100 { // CHECK: affine.for %{{.*}} = 1 to 100 { // CHECK: "foo"(%{{.*}}, %{{.*}}) : (index, index) -> () "foo"(%i1, %j1) : (index,index) -> () } // CHECK: } "boo"() : () -> () // CHECK: "boo"() : () -> () affine.for %j2 = 1 to 10 { // CHECK: affine.for %{{.*}} = 1 to 10 { affine.for %k2 = 1 to 10 { // CHECK: affine.for %{{.*}} = 1 to 10 { "goo"() : () -> () // CHECK: "goo"() : () -> () } // CHECK: } } // CHECK: } } // CHECK: } return // CHECK: return } // CHECK: } // CHECK: func @triang_loop(%{{.*}}: index, %{{.*}}: memref) { func @triang_loop(%arg0: index, %arg1: memref) { %c = constant 0 : i32 // CHECK: %{{.*}} = constant 0 : i32 affine.for %i0 = 1 to %arg0 { // CHECK: affine.for %{{.*}} = 1 to %{{.*}} { affine.for %i1 = affine_map<(d0)[]->(d0)>(%i0)[] to %arg0 { // CHECK: affine.for %{{.*}} = #map{{[0-9]+}}(%{{.*}}) to %{{.*}} { store %c, %arg1[%i0, %i1] : memref // CHECK: store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] } // CHECK: } } // CHECK: } return // CHECK: return } // CHECK: } // CHECK: func @minmax_loop(%{{.*}}: index, %{{.*}}: index, %{{.*}}: memref<100xf32>) { func @minmax_loop(%arg0: index, %arg1: index, %arg2: memref<100xf32>) { // CHECK: affine.for %{{.*}} = max #map{{.*}}()[%{{.*}}] to min #map{{.*}}()[%{{.*}}] { affine.for %i0 = max affine_map<()[s]->(0,s-1)>()[%arg0] to min affine_map<()[s]->(100,s+1)>()[%arg1] { // CHECK: "foo"(%{{.*}}, %{{.*}}) : (memref<100xf32>, index) -> () "foo"(%arg2, %i0) : (memref<100xf32>, index) -> () } // CHECK: } return // CHECK: return } // CHECK: } // CHECK-LABEL: func @loop_bounds(%{{.*}}: index) { func @loop_bounds(%N : index) { // CHECK: %{{.*}} = "foo"(%{{.*}}) : (index) -> index %s = "foo"(%N) : (index) -> index // CHECK: affine.for %{{.*}} = %{{.*}} to %{{.*}} affine.for %i = %s to %N { // CHECK: affine.for %{{.*}} = #map{{[0-9]+}}(%{{.*}}) to 0 affine.for %j = affine_map<(d0)[]->(d0)>(%i)[] to 0 step 1 { // CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] %w1 = affine.apply affine_map<(d0, d1)[s0] -> (d0+d1)> (%i, %j) [%s] // CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] %w2 = affine.apply affine_map<(d0, d1)[s0] -> (s0+1)> (%i, %j) [%s] // CHECK: affine.for %{{.*}} = #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] to #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] { affine.for %k = #bound_map1 (%w1, %i)[%N] to affine_map<(i, j)[s] -> (i + j + s)> (%w2, %j)[%s] { // CHECK: "foo"(%{{.*}}, %{{.*}}, %{{.*}}) : (index, index, index) -> () "foo"(%i, %j, %k) : (index, index, index)->() // CHECK: %{{.*}} = constant 30 : index %c = constant 30 : index // CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}}) %u = affine.apply affine_map<(d0, d1)->(d0+d1)> (%N, %c) // CHECK: affine.for %{{.*}} = max #map{{.*}}(%{{.*}})[%{{.*}}] to min #map{{.*}}(%{{.*}})[%{{.*}}] { affine.for %l = max #bound_map2(%i)[%u] to min #bound_map2(%k)[%c] { // CHECK: "bar"(%{{.*}}) : (index) -> () "bar"(%l) : (index) -> () } // CHECK: } } // CHECK: } } // CHECK: } } // CHECK: } return // CHECK: return } // CHECK: } // CHECK-LABEL: func @ifinst(%{{.*}}: index) { func @ifinst(%N: index) { %c = constant 200 : index // CHECK %{{.*}} = constant 200 affine.for %i = 1 to 10 { // CHECK affine.for %{{.*}} = 1 to 10 { affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%{{.*}})[%{{.*}}, %{{.*}}] { %x = constant 1 : i32 // CHECK: %{{.*}} = constant 1 : i32 %y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %{{.*}} = "add"(%{{.*}}, %{{.*}}) : (i32, index) -> i32 %z = "mul"(%y, %y) : (i32, i32) -> i32 // CHECK: %{{.*}} = "mul"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32 } else { // CHECK } else { affine.if affine_set<(i)[N] : (i - 2 >= 0, 4 - i >= 0)>(%i)[%N] { // CHECK affine.if (#set1(%{{.*}})[%{{.*}}]) { // CHECK: %{{.*}} = constant 1 : index %u = constant 1 : index // CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] %w = affine.apply affine_map<(d0,d1)[s0] -> (d0+d1+s0)> (%i, %i) [%u] } else { // CHECK } else { %v = constant 3 : i32 // %c3_i32 = constant 3 : i32 } } // CHECK } } // CHECK } return // CHECK return } // CHECK } // CHECK-LABEL: func @simple_ifinst(%{{.*}}: index) { func @simple_ifinst(%N: index) { %c = constant 200 : index // CHECK %{{.*}} = constant 200 affine.for %i = 1 to 10 { // CHECK affine.for %{{.*}} = 1 to 10 { affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%{{.*}})[%{{.*}}, %{{.*}}] { %x = constant 1 : i32 // CHECK: %{{.*}} = constant 1 : i32 %y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %{{.*}} = "add"(%{{.*}}, %{{.*}}) : (i32, index) -> i32 %z = "mul"(%y, %y) : (i32, i32) -> i32 // CHECK: %{{.*}} = "mul"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32 } // CHECK } } // CHECK } return // CHECK return } // CHECK } // CHECK-LABEL: func @attributes() { func @attributes() { // CHECK: "foo"() "foo"(){} : ()->() // CHECK: "foo"() {a = 1 : i64, b = -423 : i64, c = [true, false], d = 1.600000e+01 : f64} : () -> () "foo"() {a = 1, b = -423, c = [true, false], d = 16.0 } : () -> () // CHECK: "foo"() {map1 = #map{{[0-9]+}}} "foo"() {map1 = #map1} : () -> () // CHECK: "foo"() {map2 = #map{{[0-9]+}}} "foo"() {map2 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>} : () -> () // CHECK: "foo"() {map12 = [#map{{[0-9]+}}, #map{{[0-9]+}}]} "foo"() {map12 = [#map1, #map2]} : () -> () // CHECK: "foo"() {set1 = #set{{[0-9]+}}} "foo"() {set1 = #set1} : () -> () // CHECK: "foo"() {set2 = #set{{[0-9]+}}} "foo"() {set2 = affine_set<(d0, d1, d2) : (d0 >= 0, d1 >= 0, d2 - d1 == 0)>} : () -> () // CHECK: "foo"() {set12 = [#set{{[0-9]+}}, #set{{[0-9]+}}]} "foo"() {set12 = [#set1, #set2]} : () -> () // CHECK: "foo"() {dictionary = {bool = true, fn = @ifinst}} "foo"() {dictionary = {bool = true, fn = @ifinst}} : () -> () // Check that the dictionary attribute elements are sorted. // CHECK: "foo"() {dictionary = {bar = false, bool = true, fn = @ifinst}} "foo"() {dictionary = {fn = @ifinst, bar = false, bool = true}} : () -> () // CHECK: "foo"() {d = 1.000000e-09 : f64, func = [], i123 = 7 : i64, if = "foo"} : () -> () "foo"() {if = "foo", func = [], i123 = 7, d = 1.e-9} : () -> () // CHECK: "foo"() {fn = @attributes, if = @ifinst} : () -> () "foo"() {fn = @attributes, if = @ifinst} : () -> () // CHECK: "foo"() {int = 0 : i42} : () -> () "foo"() {int = 0 : i42} : () -> () return } // CHECK-LABEL: func @ssa_values() -> (i16, i8) { func @ssa_values() -> (i16, i8) { // CHECK: %{{.*}}:2 = "foo"() : () -> (i1, i17) %0:2 = "foo"() : () -> (i1, i17) br ^bb2 ^bb1: // CHECK: ^bb1: // pred: ^bb2 // CHECK: %{{.*}}:2 = "baz"(%{{.*}}#1, %{{.*}}#0, %{{.*}}#1) : (f32, i11, i17) -> (i16, i8) %1:2 = "baz"(%2#1, %2#0, %0#1) : (f32, i11, i17) -> (i16, i8) // CHECK: return %{{.*}}#0, %{{.*}}#1 : i16, i8 return %1#0, %1#1 : i16, i8 ^bb2: // CHECK: ^bb2: // pred: ^bb0 // CHECK: %{{.*}}:2 = "bar"(%{{.*}}#0, %{{.*}}#1) : (i1, i17) -> (i11, f32) %2:2 = "bar"(%0#0, %0#1) : (i1, i17) -> (i11, f32) br ^bb1 } // CHECK-LABEL: func @bbargs() -> (i16, i8) { func @bbargs() -> (i16, i8) { // CHECK: %{{.*}}:2 = "foo"() : () -> (i1, i17) %0:2 = "foo"() : () -> (i1, i17) br ^bb1(%0#1, %0#0 : i17, i1) ^bb1(%x: i17, %y: i1): // CHECK: ^bb1(%{{.*}}: i17, %{{.*}}: i1): // CHECK: %{{.*}}:2 = "baz"(%{{.*}}, %{{.*}}, %{{.*}}#1) : (i17, i1, i17) -> (i16, i8) %1:2 = "baz"(%x, %y, %0#1) : (i17, i1, i17) -> (i16, i8) return %1#0, %1#1 : i16, i8 } // CHECK-LABEL: func @verbose_terminators() -> (i1, i17) func @verbose_terminators() -> (i1, i17) { %0:2 = "foo"() : () -> (i1, i17) // CHECK: br ^bb1(%{{.*}}#0, %{{.*}}#1 : i1, i17) "std.br"(%0#0, %0#1)[^bb1] : (i1, i17) -> () ^bb1(%x : i1, %y : i17): // CHECK: cond_br %{{.*}}, ^bb2(%{{.*}} : i17), ^bb3(%{{.*}}, %{{.*}} : i1, i17) "std.cond_br"(%x, %y, %x, %y) [^bb2, ^bb3] {operand_segment_sizes = dense<[1, 1, 2]>: vector<3xi32>} : (i1, i17, i1, i17) -> () ^bb2(%a : i17): %true = constant true // CHECK: return %{{.*}}, %{{.*}} : i1, i17 "std.return"(%true, %a) : (i1, i17) -> () ^bb3(%b : i1, %c : i17): // CHECK: return %{{.*}}, %{{.*}} : i1, i17 "std.return"(%b, %c) : (i1, i17) -> () } // CHECK-LABEL: func @condbr_simple func @condbr_simple() -> (i32) { %cond = "foo"() : () -> i1 %a = "bar"() : () -> i32 %b = "bar"() : () -> i64 // CHECK: cond_br %{{.*}}, ^bb1(%{{.*}} : i32), ^bb2(%{{.*}} : i64) cond_br %cond, ^bb1(%a : i32), ^bb2(%b : i64) // CHECK: ^bb1({{.*}}: i32): // pred: ^bb0 ^bb1(%x : i32): br ^bb2(%b: i64) // CHECK: ^bb2({{.*}}: i64): // 2 preds: ^bb0, ^bb1 ^bb2(%y : i64): %z = "foo"() : () -> i32 return %z : i32 } // CHECK-LABEL: func @condbr_moarargs func @condbr_moarargs() -> (i32) { %cond = "foo"() : () -> i1 %a = "bar"() : () -> i32 %b = "bar"() : () -> i64 // CHECK: cond_br %{{.*}}, ^bb1(%{{.*}}, %{{.*}} : i32, i64), ^bb2(%{{.*}}, %{{.*}}, %{{.*}} : i64, i32, i32) cond_br %cond, ^bb1(%a, %b : i32, i64), ^bb2(%b, %a, %a : i64, i32, i32) ^bb1(%x : i32, %y : i64): return %x : i32 ^bb2(%x2 : i64, %y2 : i32, %z2 : i32): %z = "foo"() : () -> i32 return %z : i32 } // Test pretty printing of constant names. // CHECK-LABEL: func @constants func @constants() -> (i32, i23, i23, i1, i1) { // CHECK: %{{.*}} = constant 42 : i32 %x = constant 42 : i32 // CHECK: %{{.*}} = constant 17 : i23 %y = constant 17 : i23 // This is a redundant definition of 17, the asmprinter gives it a unique name // CHECK: %{{.*}} = constant 17 : i23 %z = constant 17 : i23 // CHECK: %{{.*}} = constant true %t = constant true // CHECK: %{{.*}} = constant false %f = constant false // The trick to parse type declarations should not interfere with hex // literals. // CHECK: %{{.*}} = constant 3890 : i32 %h = constant 0xf32 : i32 // CHECK: return %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} return %x, %y, %z, %t, %f : i32, i23, i23, i1, i1 } // CHECK-LABEL: func @typeattr func @typeattr() -> () { ^bb0: // CHECK: "foo"() {bar = tensor<*xf32>} : () -> () "foo"(){bar = tensor<*xf32>} : () -> () return } // CHECK-LABEL: func @stringquote func @stringquote() -> () { ^bb0: // CHECK: "foo"() {bar = "a\22quoted\22string"} : () -> () "foo"(){bar = "a\"quoted\"string"} : () -> () // CHECK-NEXT: "typed_string" : !foo.string "foo"(){bar = "typed_string" : !foo.string} : () -> () return } // CHECK-LABEL: func @unitAttrs func @unitAttrs() -> () { // CHECK-NEXT: "foo"() {unitAttr} "foo"() {unitAttr = unit} : () -> () // CHECK-NEXT: "foo"() {unitAttr} "foo"() {unitAttr} : () -> () // CHECK-NEXT: "foo"() {nested = {unitAttr}} "foo"() {nested = {unitAttr}} : () -> () return } // CHECK-LABEL: func @floatAttrs func @floatAttrs() -> () { ^bb0: // CHECK: "foo"() {a = 4.000000e+00 : f64, b = 2.000000e+00 : f64, c = 7.100000e+00 : f64, d = -0.000000e+00 : f64} : () -> () "foo"(){a = 4.0, b = 2.0, c = 7.1, d = -0.0} : () -> () return } -// CHECK-LABEL: func @externalfuncattr -func @externalfuncattr() -> () +// CHECK-LABEL: func private @externalfuncattr +func private @externalfuncattr() -> () // CHECK: attributes {dialect.a = "a\22quoted\22string", dialect.b = 4.000000e+00 : f64, dialect.c = tensor<*xf32>} attributes {dialect.a = "a\"quoted\"string", dialect.b = 4.0, dialect.c = tensor<*xf32>} -// CHECK-LABEL: func @funcattrempty -func @funcattrempty() -> () +// CHECK-LABEL: func private @funcattrempty +func private @funcattrempty() -> () attributes {} -// CHECK-LABEL: func @funcattr -func @funcattr() -> () +// CHECK-LABEL: func private @funcattr +func private @funcattr() -> () // CHECK: attributes {dialect.a = "a\22quoted\22string", dialect.b = 4.000000e+00 : f64, dialect.c = tensor<*xf32>} attributes {dialect.a = "a\"quoted\"string", dialect.b = 4.0, dialect.c = tensor<*xf32>} { ^bb0: return } // CHECK-LABEL: func @funcattrwithblock func @funcattrwithblock() -> () attributes {} { ^bb0: return } // CHECK-label func @funcsimplemap #map_simple0 = affine_map<()[] -> (10)> #map_simple1 = affine_map<()[s0] -> (s0)> #map_non_simple0 = affine_map<(d0)[] -> (d0)> #map_non_simple1 = affine_map<(d0)[s0] -> (d0 + s0)> #map_non_simple2 = affine_map<()[s0, s1] -> (s0 + s1)> #map_non_simple3 = affine_map<()[s0] -> (s0 + 3)> func @funcsimplemap(%arg0: index, %arg1: index) -> () { affine.for %i0 = 0 to #map_simple0()[] { // CHECK: affine.for %{{.*}} = 0 to 10 { affine.for %i1 = 0 to #map_simple1()[%arg1] { // CHECK: affine.for %{{.*}} = 0 to %{{.*}} { affine.for %i2 = 0 to #map_non_simple0(%i0)[] { // CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}(%{{.*}}) { affine.for %i3 = 0 to #map_non_simple1(%i0)[%arg1] { // CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}(%{{.*}})[%{{.*}}] { affine.for %i4 = 0 to #map_non_simple2()[%arg1, %arg0] { // CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}()[%{{.*}}, %{{.*}}] { affine.for %i5 = 0 to #map_non_simple3()[%arg0] { // CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}()[%{{.*}}] { %c42_i32 = constant 42 : i32 } } } } } } return } // CHECK-LABEL: func @splattensorattr func @splattensorattr() -> () { ^bb0: // CHECK: "splatBoolTensor"() {bar = dense : tensor} : () -> () "splatBoolTensor"(){bar = dense : tensor} : () -> () // CHECK: "splatUIntTensor"() {bar = dense<222> : tensor<2x1x4xui8>} : () -> () "splatUIntTensor"(){bar = dense<222> : tensor<2x1x4xui8>} : () -> () // CHECK: "splatIntTensor"() {bar = dense<5> : tensor<2x1x4xi32>} : () -> () "splatIntTensor"(){bar = dense<5> : tensor<2x1x4xi32>} : () -> () // CHECK: "splatFloatTensor"() {bar = dense<-5.000000e+00> : tensor<2x1x4xf32>} : () -> () "splatFloatTensor"(){bar = dense<-5.0> : tensor<2x1x4xf32>} : () -> () // CHECK: "splatIntVector"() {bar = dense<5> : vector<2x1x4xi64>} : () -> () "splatIntVector"(){bar = dense<5> : vector<2x1x4xi64>} : () -> () // CHECK: "splatFloatVector"() {bar = dense<-5.000000e+00> : vector<2x1x4xf16>} : () -> () "splatFloatVector"(){bar = dense<-5.0> : vector<2x1x4xf16>} : () -> () // CHECK: "splatIntScalar"() {bar = dense<5> : tensor} : () -> () "splatIntScalar"() {bar = dense<5> : tensor} : () -> () // CHECK: "splatFloatScalar"() {bar = dense<-5.000000e+00> : tensor} : () -> () "splatFloatScalar"() {bar = dense<-5.0> : tensor} : () -> () return } // CHECK-LABEL: func @densetensorattr func @densetensorattr() -> () { ^bb0: // NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck. // CHECK: "fooi3"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi3>} : () -> () "fooi3"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi3>} : () -> () // CHECK: "fooi6"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : tensor<2x1x4xi6>} : () -> () "fooi6"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : tensor<2x1x4xi6>} : () -> () // CHECK: "fooi8"() {bar = dense<5> : tensor<1x1x1xi8>} : () -> () "fooi8"(){bar = dense<[[[5]]]> : tensor<1x1x1xi8>} : () -> () // CHECK: "fooi13"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi13>} : () -> () "fooi13"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi13>} : () -> () // CHECK: "fooi16"() {bar = dense<-5> : tensor<1x1x1xi16>} : () -> () "fooi16"(){bar = dense<[[[-5]]]> : tensor<1x1x1xi16>} : () -> () // CHECK: "fooi23"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi23>} : () -> () "fooi23"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi23>} : () -> () // CHECK: "fooi32"() {bar = dense<5> : tensor<1x1x1xi32>} : () -> () "fooi32"(){bar = dense<[[[5]]]> : tensor<1x1x1xi32>} : () -> () // CHECK: "fooi33"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi33>} : () -> () "fooi33"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi33>} : () -> () // CHECK: "fooi43"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi43>} : () -> () "fooi43"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi43>} : () -> () // CHECK: "fooi53"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi53>} : () -> () "fooi53"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi53>} : () -> () // CHECK: "fooi64"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 3, -1, 2]]]> : tensor<2x1x4xi64>} : () -> () "fooi64"(){bar = dense<[[[1, -2, 1, 2]], [[0, 3, -1, 2]]]> : tensor<2x1x4xi64>} : () -> () // CHECK: "fooi64"() {bar = dense<-5> : tensor<1x1x1xi64>} : () -> () "fooi64"(){bar = dense<[[[-5]]]> : tensor<1x1x1xi64>} : () -> () // CHECK: "fooi67"() {bar = dense<{{\[\[\[}}-5, 4, 6, 2]]]> : vector<1x1x4xi67>} : () -> () "fooi67"(){bar = dense<[[[-5, 4, 6, 2]]]> : vector<1x1x4xi67>} : () -> () // CHECK: "foo2"() {bar = dense<> : tensor<0xi32>} : () -> () "foo2"(){bar = dense<> : tensor<0xi32>} : () -> () // CHECK: "foo2"() {bar = dense<> : tensor<1x0xi32>} : () -> () "foo2"(){bar = dense<> : tensor<1x0xi32>} : () -> () // CHECK: dense<> : tensor<0x512x512xi32> "foo2"(){bar = dense<> : tensor<0x512x512xi32>} : () -> () // CHECK: "foo3"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : tensor<2x1x4xi32>} : () -> () "foo3"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : tensor<2x1x4xi32>} : () -> () // CHECK: "float1"() {bar = dense<5.000000e+00> : tensor<1x1x1xf32>} : () -> () "float1"(){bar = dense<[[[5.0]]]> : tensor<1x1x1xf32>} : () -> () // CHECK: "float2"() {bar = dense<> : tensor<0xf32>} : () -> () "float2"(){bar = dense<> : tensor<0xf32>} : () -> () // CHECK: "float2"() {bar = dense<> : tensor<1x0xf32>} : () -> () "float2"(){bar = dense<> : tensor<1x0xf32>} : () -> () // CHECK: "bfloat16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xbf16>} : () -> () "bfloat16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xbf16>} : () -> () // CHECK: "float16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf16>} : () -> () "float16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf16>} : () -> () // CHECK: "float32"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf32>} : () -> () "float32"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf32>} : () -> () // CHECK: "float64"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf64>} : () -> () "float64"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf64>} : () -> () // CHECK: "intscalar"() {bar = dense<1> : tensor} : () -> () "intscalar"(){bar = dense<1> : tensor} : () -> () // CHECK: "floatscalar"() {bar = dense<5.000000e+00> : tensor} : () -> () "floatscalar"(){bar = dense<5.0> : tensor} : () -> () // CHECK: "index"() {bar = dense<1> : tensor} : () -> () "index"(){bar = dense<1> : tensor} : () -> () // CHECK: "index"() {bar = dense<[1, 2]> : tensor<2xindex>} : () -> () "index"(){bar = dense<[1, 2]> : tensor<2xindex>} : () -> () // CHECK: dense<(1,1)> : tensor> "complex_attr"(){bar = dense<(1,1)> : tensor>} : () -> () // CHECK: dense<[(1,1), (2,2)]> : tensor<2xcomplex> "complex_attr"(){bar = dense<[(1,1), (2,2)]> : tensor<2xcomplex>} : () -> () // CHECK: dense<(1.000000e+00,0.000000e+00)> : tensor> "complex_attr"(){bar = dense<(1.000000e+00,0.000000e+00)> : tensor>} : () -> () // CHECK: dense<[(1.000000e+00,0.000000e+00), (2.000000e+00,2.000000e+00)]> : tensor<2xcomplex> "complex_attr"(){bar = dense<[(1.000000e+00,0.000000e+00), (2.000000e+00,2.000000e+00)]> : tensor<2xcomplex>} : () -> () return } // CHECK-LABEL: func @densevectorattr func @densevectorattr() -> () { ^bb0: // NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck. // CHECK: "fooi8"() {bar = dense<5> : vector<1x1x1xi8>} : () -> () "fooi8"(){bar = dense<[[[5]]]> : vector<1x1x1xi8>} : () -> () // CHECK: "fooi16"() {bar = dense<-5> : vector<1x1x1xi16>} : () -> () "fooi16"(){bar = dense<[[[-5]]]> : vector<1x1x1xi16>} : () -> () // CHECK: "foo32"() {bar = dense<5> : vector<1x1x1xi32>} : () -> () "foo32"(){bar = dense<[[[5]]]> : vector<1x1x1xi32>} : () -> () // CHECK: "fooi64"() {bar = dense<-5> : vector<1x1x1xi64>} : () -> () "fooi64"(){bar = dense<[[[-5]]]> : vector<1x1x1xi64>} : () -> () // CHECK: "foo3"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : vector<2x1x4xi32>} : () -> () "foo3"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : vector<2x1x4xi32>} : () -> () // CHECK: "float1"() {bar = dense<5.000000e+00> : vector<1x1x1xf32>} : () -> () "float1"(){bar = dense<[[[5.0]]]> : vector<1x1x1xf32>} : () -> () // CHECK: "bfloat16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xbf16>} : () -> () "bfloat16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xbf16>} : () -> () // CHECK: "float16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf16>} : () -> () "float16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf16>} : () -> () // CHECK: "float32"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf32>} : () -> () "float32"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf32>} : () -> () // CHECK: "float64"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf64>} : () -> () "float64"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf64>} : () -> () return } // CHECK-LABEL: func @sparsetensorattr func @sparsetensorattr() -> () { ^bb0: // NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck. // CHECK: "fooi8"() {bar = sparse<0, -2> : tensor<1x1x1xi8>} : () -> () "fooi8"(){bar = sparse<0, -2> : tensor<1x1x1xi8>} : () -> () // CHECK: "fooi16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2, -1, 5]> : tensor<2x2x2xi16>} : () -> () "fooi16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2, -1, 5]> : tensor<2x2x2xi16>} : () -> () // CHECK: "fooi32"() {bar = sparse<> : tensor<1x1xi32>} : () -> () "fooi32"(){bar = sparse<> : tensor<1x1xi32>} : () -> () // CHECK: "fooi64"() {bar = sparse<0, -1> : tensor<1xi64>} : () -> () "fooi64"(){bar = sparse<[[0]], [-1]> : tensor<1xi64>} : () -> () // CHECK: "foo2"() {bar = sparse<> : tensor<0xi32>} : () -> () "foo2"(){bar = sparse<> : tensor<0xi32>} : () -> () // CHECK: "foo3"() {bar = sparse<> : tensor} : () -> () "foo3"(){bar = sparse<> : tensor} : () -> () // CHECK: "foof16"() {bar = sparse<0, -2.000000e+00> : tensor<1x1x1xf16>} : () -> () "foof16"(){bar = sparse<0, -2.0> : tensor<1x1x1xf16>} : () -> () // CHECK: "foobf16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2.000000e+00, -1.000000e+00, 5.000000e+00]> : tensor<2x2x2xbf16>} : () -> () "foobf16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2.0, -1.0, 5.0]> : tensor<2x2x2xbf16>} : () -> () // CHECK: "foof32"() {bar = sparse<> : tensor<1x0x1xf32>} : () -> () "foof32"(){bar = sparse<> : tensor<1x0x1xf32>} : () -> () // CHECK: "foof64"() {bar = sparse<0, -1.000000e+00> : tensor<1xf64>} : () -> () "foof64"(){bar = sparse<[[0]], [-1.0]> : tensor<1xf64>} : () -> () // CHECK: "foof320"() {bar = sparse<> : tensor<0xf32>} : () -> () "foof320"(){bar = sparse<> : tensor<0xf32>} : () -> () // CHECK: "foof321"() {bar = sparse<> : tensor} : () -> () "foof321"(){bar = sparse<> : tensor} : () -> () // CHECK: "foostr"() {bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> () "foostr"(){bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> () // CHECK: "foostr"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}"a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> () "foostr"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], ["a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> () return } // CHECK-LABEL: func @sparsevectorattr func @sparsevectorattr() -> () { ^bb0: // NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck. // CHECK: "fooi8"() {bar = sparse<0, -2> : vector<1x1x1xi8>} : () -> () "fooi8"(){bar = sparse<0, -2> : vector<1x1x1xi8>} : () -> () // CHECK: "fooi16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2, -1, 5]> : vector<2x2x2xi16>} : () -> () "fooi16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2, -1, 5]> : vector<2x2x2xi16>} : () -> () // CHECK: "fooi32"() {bar = sparse<> : vector<1x1xi32>} : () -> () "fooi32"(){bar = sparse<> : vector<1x1xi32>} : () -> () // CHECK: "fooi64"() {bar = sparse<0, -1> : vector<1xi64>} : () -> () "fooi64"(){bar = sparse<[[0]], [-1]> : vector<1xi64>} : () -> () // CHECK: "foof16"() {bar = sparse<0, -2.000000e+00> : vector<1x1x1xf16>} : () -> () "foof16"(){bar = sparse<0, -2.0> : vector<1x1x1xf16>} : () -> () // CHECK: "foobf16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2.000000e+00, -1.000000e+00, 5.000000e+00]> : vector<2x2x2xbf16>} : () -> () "foobf16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2.0, -1.0, 5.0]> : vector<2x2x2xbf16>} : () -> () // CHECK: "foof64"() {bar = sparse<0, -1.000000e+00> : vector<1xf64>} : () -> () "foof64"(){bar = sparse<0, [-1.0]> : vector<1xf64>} : () -> () return } // CHECK-LABEL: func @unknown_dialect_type() -> !bar<""> { func @unknown_dialect_type() -> !bar<""> { // Unregistered dialect 'bar'. // CHECK: "foo"() : () -> !bar<""> %0 = "foo"() : () -> !bar<""> // CHECK: "foo"() : () -> !bar.baz %1 = "foo"() : () -> !bar<"baz"> return %0 : !bar<""> } // CHECK-LABEL: func @type_alias() -> i32 { !i32_type_alias = type i32 func @type_alias() -> !i32_type_alias { // Return a non-aliased i32 type. %0 = "foo"() : () -> i32 return %0 : i32 } // CHECK-LABEL: func @no_integer_set_constraints( func @no_integer_set_constraints() { // CHECK: affine.if [[$SET_TRUE]]() { affine.if affine_set<() : ()> () { } return } // CHECK-LABEL: func @verbose_if( func @verbose_if(%N: index) { %c = constant 200 : index // CHECK: affine.if #set{{.*}}(%{{.*}})[%{{.*}}, %{{.*}}] { "affine.if"(%c, %N, %c) ({ // CHECK-NEXT: "add" %y = "add"(%c, %N) : (index, index) -> index "affine.yield"() : () -> () // CHECK-NEXT: } else { }, { // The else region. // CHECK-NEXT: "add" %z = "add"(%c, %c) : (index, index) -> index "affine.yield"() : () -> () }) { condition = #set0 } : (index, index, index) -> () return } // CHECK-LABEL: func @terminator_with_regions func @terminator_with_regions() { // Combine successors and regions in the same operation. // CHECK: "region"()[^bb1] ( { // CHECK: }) : () -> () "region"()[^bb2] ({}) : () -> () ^bb2: return } // CHECK-LABEL: func @unregistered_term func @unregistered_term(%arg0 : i1) -> i1 { // CHECK-NEXT: "unregistered_br"(%{{.*}})[^bb1] : (i1) -> () "unregistered_br"(%arg0)[^bb1] : (i1) -> () ^bb1(%arg1 : i1): return %arg1 : i1 } // CHECK-LABEL: func @dialect_attrs func @dialect_attrs() // CHECK: attributes {dialect.attr = 10 attributes {dialect.attr = 10} { return } -// CHECK-LABEL: func @_valid.function$name -func @_valid.function$name() +// CHECK-LABEL: func private @_valid.function$name +func private @_valid.function$name() -// CHECK-LABEL: func @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32) -func @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32) +// CHECK-LABEL: func private @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32) +func private @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32) // CHECK-LABEL: func @func_arg_attrs(%{{.*}}: i1 {dialect.attr = 10 : i64}) func @func_arg_attrs(%arg0: i1 {dialect.attr = 10 : i64}) { return } // CHECK-LABEL: func @func_result_attrs({{.*}}) -> (f32 {dialect.attr = 1 : i64}) func @func_result_attrs(%arg0: f32) -> (f32 {dialect.attr = 1}) { return %arg0 : f32 } -// CHECK-LABEL: func @empty_tuple(tuple<>) -func @empty_tuple(tuple<>) +// CHECK-LABEL: func private @empty_tuple(tuple<>) +func private @empty_tuple(tuple<>) -// CHECK-LABEL: func @tuple_single_element(tuple) -func @tuple_single_element(tuple) +// CHECK-LABEL: func private @tuple_single_element(tuple) +func private @tuple_single_element(tuple) -// CHECK-LABEL: func @tuple_multi_element(tuple) -func @tuple_multi_element(tuple) +// CHECK-LABEL: func private @tuple_multi_element(tuple) +func private @tuple_multi_element(tuple) -// CHECK-LABEL: func @tuple_nested(tuple>>) -func @tuple_nested(tuple>>) +// CHECK-LABEL: func private @tuple_nested(tuple>>) +func private @tuple_nested(tuple>>) // CHECK-LABEL: func @pretty_form_multi_result func @pretty_form_multi_result() -> (i16, i16) { // CHECK: %{{.*}}:2 = "foo_div"() : () -> (i16, i16) %quot, %rem = "foo_div"() : () -> (i16, i16) return %quot, %rem : i16, i16 } // CHECK-LABEL: func @pretty_form_multi_result_groups func @pretty_form_multi_result_groups() -> (i16, i16, i16, i16, i16) { // CHECK: %[[RES:.*]]:5 = // CHECK: return %[[RES]]#0, %[[RES]]#1, %[[RES]]#2, %[[RES]]#3, %[[RES]]#4 %group_1:2, %group_2, %group_3:2 = "foo_test"() : () -> (i16, i16, i16, i16, i16) return %group_1#0, %group_1#1, %group_2, %group_3#0, %group_3#1 : i16, i16, i16, i16, i16 } // CHECK-LABEL: func @pretty_dialect_attribute() func @pretty_dialect_attribute() { // CHECK: "foo.unknown_op"() {foo = #foo.simple_attr} : () -> () "foo.unknown_op"() {foo = #foo.simple_attr} : () -> () // CHECK: "foo.unknown_op"() {foo = #foo.complexattr} : () -> () "foo.unknown_op"() {foo = #foo.complexattr} : () -> () // CHECK: "foo.unknown_op"() {foo = #foo.complexattr>} : () -> () "foo.unknown_op"() {foo = #foo.complexattr>} : () -> () // CHECK: "foo.unknown_op"() {foo = #foo.complexattr>} : () -> () "foo.unknown_op"() {foo = #foo.complexattr>} : () -> () // CHECK: "foo.unknown_op"() {foo = #foo.dialect} : () -> () "foo.unknown_op"() {foo = #foo.dialect} : () -> () // Extraneous extra > character can't use the pretty syntax. // CHECK: "foo.unknown_op"() {foo = #foo<"dialect>">} : () -> () "foo.unknown_op"() {foo = #foo<"dialect>">} : () -> () return } // CHECK-LABEL: func @pretty_dialect_type() func @pretty_dialect_type() { // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.simpletype %0 = "foo.unknown_op"() : () -> !foo.simpletype // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype %1 = "foo.unknown_op"() : () -> !foo.complextype // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype> %2 = "foo.unknown_op"() : () -> !foo.complextype> // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype> %3 = "foo.unknown_op"() : () -> !foo.complextype> // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.dialect %4 = "foo.unknown_op"() : () -> !foo.dialect // Extraneous extra > character can't use the pretty syntax. // CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo<"dialect>"> %5 = "foo.unknown_op"() : () -> !foo<"dialect>"> return } // CHECK-LABEL: func @none_type func @none_type() { // CHECK: "foo.unknown_op"() : () -> none %none_val = "foo.unknown_op"() : () -> none return } // CHECK-LABEL: func @scoped_names func @scoped_names() { // CHECK-NEXT: "foo.region_op" "foo.region_op"() ({ // CHECK-NEXT: "foo.unknown_op" %scoped_name = "foo.unknown_op"() : () -> none "foo.terminator"() : () -> () }, { // CHECK: "foo.unknown_op" %scoped_name = "foo.unknown_op"() : () -> none "foo.terminator"() : () -> () }) : () -> () return } // CHECK-LABEL: func @dialect_attribute_with_type func @dialect_attribute_with_type() { // CHECK-NEXT: foo = #foo.attr : i32 "foo.unknown_op"() {foo = #foo.attr : i32} : () -> () } // CHECK-LABEL: @f16_special_values func @f16_special_values() { // F16 NaNs. // CHECK: constant 0x7C01 : f16 %0 = constant 0x7C01 : f16 // CHECK: constant 0x7FFF : f16 %1 = constant 0x7FFF : f16 // CHECK: constant 0xFFFF : f16 %2 = constant 0xFFFF : f16 // F16 positive infinity. // CHECK: constant 0x7C00 : f16 %3 = constant 0x7C00 : f16 // F16 negative infinity. // CHECK: constant 0xFC00 : f16 %4 = constant 0xFC00 : f16 return } // CHECK-LABEL: @f32_special_values func @f32_special_values() { // F32 signaling NaNs. // CHECK: constant 0x7F800001 : f32 %0 = constant 0x7F800001 : f32 // CHECK: constant 0x7FBFFFFF : f32 %1 = constant 0x7FBFFFFF : f32 // F32 quiet NaNs. // CHECK: constant 0x7FC00000 : f32 %2 = constant 0x7FC00000 : f32 // CHECK: constant 0xFFFFFFFF : f32 %3 = constant 0xFFFFFFFF : f32 // F32 positive infinity. // CHECK: constant 0x7F800000 : f32 %4 = constant 0x7F800000 : f32 // F32 negative infinity. // CHECK: constant 0xFF800000 : f32 %5 = constant 0xFF800000 : f32 return } // CHECK-LABEL: @f64_special_values func @f64_special_values() { // F64 signaling NaNs. // CHECK: constant 0x7FF0000000000001 : f64 %0 = constant 0x7FF0000000000001 : f64 // CHECK: constant 0x7FF8000000000000 : f64 %1 = constant 0x7FF8000000000000 : f64 // F64 quiet NaNs. // CHECK: constant 0x7FF0000001000000 : f64 %2 = constant 0x7FF0000001000000 : f64 // CHECK: constant 0xFFF0000001000000 : f64 %3 = constant 0xFFF0000001000000 : f64 // F64 positive infinity. // CHECK: constant 0x7FF0000000000000 : f64 %4 = constant 0x7FF0000000000000 : f64 // F64 negative infinity. // CHECK: constant 0xFFF0000000000000 : f64 %5 = constant 0xFFF0000000000000 : f64 // Check that values that can't be represented with the default format, use // hex instead. // CHECK: constant 0xC1CDC00000000000 : f64 %6 = constant 0xC1CDC00000000000 : f64 return } // CHECK-LABEL: @bfloat16_special_values func @bfloat16_special_values() { // bfloat16 signaling NaNs. // CHECK: constant 0x7F81 : bf16 %0 = constant 0x7F81 : bf16 // CHECK: constant 0xFF81 : bf16 %1 = constant 0xFF81 : bf16 // bfloat16 quiet NaNs. // CHECK: constant 0x7FC0 : bf16 %2 = constant 0x7FC0 : bf16 // CHECK: constant 0xFFC0 : bf16 %3 = constant 0xFFC0 : bf16 // bfloat16 positive infinity. // CHECK: constant 0x7F80 : bf16 %4 = constant 0x7F80 : bf16 // bfloat16 negative infinity. // CHECK: constant 0xFF80 : bf16 %5 = constant 0xFF80 : bf16 return } // We want to print floats in exponential notation with 6 significant digits, // but it may lead to precision loss when parsing back, in which case we print // the decimal form instead. // CHECK-LABEL: @f32_potential_precision_loss() func @f32_potential_precision_loss() { // CHECK: constant -1.23697901 : f32 %0 = constant -1.23697901 : f32 return } // CHECK-LABEL: @special_float_values_in_tensors func @special_float_values_in_tensors() { // CHECK: dense<0xFFFFFFFF> : tensor<4x4xf32> "foo"(){bar = dense<0xFFFFFFFF> : tensor<4x4xf32>} : () -> () // CHECK: dense<[{{\[}}0xFFFFFFFF, 0x7F800000], [0x7FBFFFFF, 0x7F800001]]> : tensor<2x2xf32> "foo"(){bar = dense<[[0xFFFFFFFF, 0x7F800000], [0x7FBFFFFF, 0x7F800001]]> : tensor<2x2xf32>} : () -> () // CHECK: dense<[0xFFFFFFFF, 0.000000e+00]> : tensor<2xf32> "foo"(){bar = dense<[0xFFFFFFFF, 0.0]> : tensor<2xf32>} : () -> () // CHECK: sparse<[{{\[}}1, 1, 0], [0, 1, 1]], [0xFFFFFFFF, 0x7F800001]> "foo"(){bar = sparse<[[1,1,0],[0,1,1]], [0xFFFFFFFF, 0x7F800001]> : tensor<2x2x2xf32>} : () -> () } // Test parsing of an op with multiple region arguments, and without a // delimiter. // CHECK-LABEL: func @op_with_region_args func @op_with_region_args() { // CHECK: "test.polyfor"() ( { // CHECK-NEXT: ^bb{{.*}}(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index): test.polyfor %i, %j, %k { "foo"() : () -> () } return } // Test allowing different name scopes for regions isolated from above. // CHECK-LABEL: func @op_with_passthrough_region_args func @op_with_passthrough_region_args() { // CHECK: [[VAL:%.*]] = constant %0 = constant 10 : index // CHECK: test.isolated_region [[VAL]] { // CHECK-NEXT: "foo.consumer"([[VAL]]) : (index) // CHECK-NEXT: } test.isolated_region %0 { "foo.consumer"(%0) : (index) -> () } // CHECK: [[VAL:%.*]]:2 = "foo.op" %result:2 = "foo.op"() : () -> (index, index) // CHECK: test.isolated_region [[VAL]]#1 { // CHECK-NEXT: "foo.consumer"([[VAL]]#1) : (index) // CHECK-NEXT: } test.isolated_region %result#1 { "foo.consumer"(%result#1) : (index) -> () } return } -// CHECK-LABEL: func @ptr_to_function() -> !unreg.ptr<() -> ()> -func @ptr_to_function() -> !unreg.ptr<() -> ()> +// CHECK-LABEL: func private @ptr_to_function() -> !unreg.ptr<() -> ()> +func private @ptr_to_function() -> !unreg.ptr<() -> ()> -// CHECK-LABEL: func @escaped_string_char(i1 {foo.value = "\0A"}) -func @escaped_string_char(i1 {foo.value = "\n"}) +// CHECK-LABEL: func private @escaped_string_char(i1 {foo.value = "\0A"}) +func private @escaped_string_char(i1 {foo.value = "\n"}) // CHECK-LABEL: func @wrapped_keyword_test func @wrapped_keyword_test() { // CHECK: test.wrapped_keyword foo.keyword test.wrapped_keyword foo.keyword return } // CHECK-LABEL: func @"\22_string_symbol_reference\22" func @"\"_string_symbol_reference\""() { // CHECK: ref = @"\22_string_symbol_reference\22" "foo.symbol_reference"() {ref = @"\"_string_symbol_reference\""} : () -> () return } -// CHECK-LABEL: func @string_attr_name +// CHECK-LABEL: func private @string_attr_name // CHECK-SAME: {"0 . 0", nested = {"0 . 0"}} -func @string_attr_name() attributes {"0 . 0", nested = {"0 . 0"}} +func private @string_attr_name() attributes {"0 . 0", nested = {"0 . 0"}} -// CHECK-LABEL: func @nested_reference +// CHECK-LABEL: func private @nested_reference // CHECK: ref = @some_symbol::@some_nested_symbol -func @nested_reference() attributes {test.ref = @some_symbol::@some_nested_symbol } +func private @nested_reference() attributes {test.ref = @some_symbol::@some_nested_symbol } // CHECK-LABEL: func @custom_asm_names func @custom_asm_names() -> (i32, i32, i32, i32, i32, i32, i32) { // CHECK: %[[FIRST:first.*]], %[[MIDDLE:middle_results.*]]:2, %[[LAST:[0-9]+]] %0, %1:2, %2 = "test.asm_interface_op"() : () -> (i32, i32, i32, i32) // CHECK: %[[FIRST_2:first.*]], %[[LAST_2:[0-9]+]] %3, %4 = "test.asm_interface_op"() : () -> (i32, i32) // CHECK: %[[RESULT:result.*]] %5 = "test.asm_dialect_interface_op"() : () -> (i32) // CHECK: return %[[FIRST]], %[[MIDDLE]]#0, %[[MIDDLE]]#1, %[[LAST]], %[[FIRST_2]], %[[LAST_2]] return %0, %1#0, %1#1, %2, %3, %4, %5 : i32, i32, i32, i32, i32, i32, i32 } // CHECK-LABEL: func @pretty_names // This tests the behavior func @pretty_names() { // Simple case, should parse and print as %x being an implied 'name' // attribute. %x = test.string_attr_pretty_name // CHECK: %x = test.string_attr_pretty_name // CHECK-NOT: attributes // This specifies an explicit name, which should override the result. %YY = test.string_attr_pretty_name attributes { names = ["y"] } // CHECK: %y = test.string_attr_pretty_name // CHECK-NOT: attributes // Conflicts with the 'y' name, so need an explicit attribute. %0 = "test.string_attr_pretty_name"() { names = ["y"]} : () -> i32 // CHECK: %y_0 = test.string_attr_pretty_name attributes {names = ["y"]} // Name contains a space. %1 = "test.string_attr_pretty_name"() { names = ["space name"]} : () -> i32 // CHECK: %space_name = test.string_attr_pretty_name attributes {names = ["space name"]} "unknown.use"(%x, %YY, %0, %1) : (i32, i32, i32, i32) -> () // Multi-result support. %a, %b, %c = test.string_attr_pretty_name // CHECK: %a, %b, %c = test.string_attr_pretty_name // CHECK-NOT: attributes %q:3, %r = test.string_attr_pretty_name // CHECK: %q, %q_1, %q_2, %r = test.string_attr_pretty_name attributes {names = ["q", "q", "q", "r"]} // CHECK: return return } // CHECK-LABEL: func @unreachable_dominance_violation_ok func @unreachable_dominance_violation_ok() -> i1 { // CHECK: [[VAL:%.*]] = constant false // CHECK: return [[VAL]] : i1 // CHECK: ^bb1: // no predecessors // CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1) // CHECK: br ^bb3 // CHECK: ^bb2: // pred: ^bb2 // CHECK: br ^bb2 // CHECK: ^bb3: // pred: ^bb1 // CHECK: [[VAL3]] = "foo"() : () -> i64 // CHECK: return [[VAL2]]#1 : i1 // CHECK: } %c = constant false return %c : i1 ^bb1: // %1 is not dominated by it's definition, but block is not reachable. %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) br ^bb3 ^bb2: br ^bb2 ^bb3: %1 = "foo"() : ()->i64 return %2#1 : i1 } // CHECK-LABEL: func @graph_region_in_hierarchy_ok func @graph_region_in_hierarchy_ok() -> i64 { // CHECK: br ^bb2 // CHECK: ^bb1: // CHECK: test.graph_region { // CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1) // CHECK: } // CHECK: br ^bb3 // CHECK: ^bb2: // pred: ^bb0 // CHECK: [[VAL3]] = "foo"() : () -> i64 // CHECK: br ^bb1 // CHECK: ^bb3: // pred: ^bb1 // CHECK: return [[VAL3]] : i64 // CHECK: } br ^bb2 ^bb1: test.graph_region { // %1 is well-defined here, since bb2 dominates bb1. %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) } br ^bb4 ^bb2: %1 = "foo"() : ()->i64 br ^bb1 ^bb4: return %1 : i64 } // CHECK-LABEL: func @graph_region_kind func @graph_region_kind() -> () { // CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1) // CHECK: [[VAL3]] = "baz"([[VAL2]]#0) : (i1) -> i64 test.graph_region { // %1 OK here in in graph region. %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) %1 = "baz"(%2#0) : (i1) -> (i64) } return } // CHECK-LABEL: func @graph_region_inside_ssacfg_region func @graph_region_inside_ssacfg_region() -> () { // CHECK: "test.ssacfg_region" // CHECK: [[VAL3:%.*]] = "baz"() : () -> i64 // CHECK: test.graph_region { // CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3]]) : (i64) -> (i1, i1, i1) // CHECK: } // CHECK: [[VAL4:.*]] = "baz"() : () -> i64 "test.ssacfg_region"() ({ %1 = "baz"() : () -> (i64) test.graph_region { %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) } %3 = "baz"() : () -> (i64) }) : () -> () return } // CHECK-LABEL: func @graph_region_in_graph_region_ok func @graph_region_in_graph_region_ok() -> () { // CHECK: test.graph_region { // CHECK: test.graph_region { // CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1) // CHECK: } // CHECK: [[VAL3]] = "foo"() : () -> i64 // CHECK: } test.graph_region { test.graph_region { // %1 is well-defined here since defined in graph region %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) } %1 = "foo"() : ()->i64 "test.terminator"() : ()->() } return } // CHECK: test.graph_region { test.graph_region { // CHECK: [[VAL1:%.*]] = "op1"([[VAL3:%.*]]) : (i32) -> i32 // CHECK: [[VAL2:%.*]] = "test.ssacfg_region"([[VAL1]], [[VAL2]], [[VAL3]], [[VAL4:%.*]]) ( { // CHECK: [[VAL5:%.*]] = "op2"([[VAL1]], [[VAL2]], [[VAL3]], [[VAL4]]) : (i32, i32, i32, i32) -> i32 // CHECK: }) : (i32, i32, i32, i32) -> i32 // CHECK: [[VAL3]] = "op2"([[VAL1]], [[VAL4]]) : (i32, i32) -> i32 // CHECK: [[VAL4]] = "op3"([[VAL1]]) : (i32) -> i32 %1 = "op1"(%3) : (i32) -> (i32) %2 = "test.ssacfg_region"(%1, %2, %3, %4) ({ %5 = "op2"(%1, %2, %3, %4) : (i32, i32, i32, i32) -> (i32) }) : (i32, i32, i32, i32) -> (i32) %3 = "op2"(%1, %4) : (i32, i32) -> (i32) %4 = "op3"(%1) : (i32) -> (i32) } // CHECK: "unregistered_func_might_have_graph_region"() ( { // CHECK: [[VAL1:%.*]] = "foo"([[VAL1]], [[VAL2:%.*]]) : (i64, i64) -> i64 // CHECK: [[VAL2]] = "bar"([[VAL1]]) "unregistered_func_might_have_graph_region"() ( { %1 = "foo"(%1, %2) : (i64, i64) -> i64 %2 = "bar"(%1) : (i64) -> i64 "unregistered_terminator"() : () -> () }) {sym_name = "unregistered_op_dominance_violation_ok", type = () -> i1} : () -> () diff --git a/mlir/test/IR/test-func-erase-result.mlir b/mlir/test/IR/test-func-erase-result.mlir index bdd08475ef12..96ebffb9202b 100644 --- a/mlir/test/IR/test-func-erase-result.mlir +++ b/mlir/test/IR/test-func-erase-result.mlir @@ -1,68 +1,68 @@ // RUN: mlir-opt %s -test-func-erase-result -split-input-file | FileCheck %s -// CHECK: func @f(){{$}} +// CHECK: func private @f(){{$}} // CHECK-NOT: attributes{{.*}}result -func @f() -> (f32 {test.erase_this_result}) +func private @f() -> (f32 {test.erase_this_result}) // ----- -// CHECK: func @f() -> (f32 {test.A}) +// CHECK: func private @f() -> (f32 {test.A}) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( f32 {test.erase_this_result}, f32 {test.A} ) // ----- -// CHECK: func @f() -> (f32 {test.A}) +// CHECK: func private @f() -> (f32 {test.A}) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( f32 {test.A}, f32 {test.erase_this_result} ) // ----- -// CHECK: func @f() -> (f32 {test.A}, f32 {test.B}) +// CHECK: func private @f() -> (f32 {test.A}, f32 {test.B}) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( f32 {test.A}, f32 {test.erase_this_result}, f32 {test.B} ) // ----- -// CHECK: func @f() -> (f32 {test.A}, f32 {test.B}) +// CHECK: func private @f() -> (f32 {test.A}, f32 {test.B}) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( f32 {test.A}, f32 {test.erase_this_result}, f32 {test.erase_this_result}, f32 {test.B} ) // ----- -// CHECK: func @f() -> (f32 {test.A}, f32 {test.B}, f32 {test.C}) +// CHECK: func private @f() -> (f32 {test.A}, f32 {test.B}, f32 {test.C}) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( f32 {test.A}, f32 {test.erase_this_result}, f32 {test.B}, f32 {test.erase_this_result}, f32 {test.C} ) // ----- -// CHECK: func @f() -> (tensor<1xf32>, tensor<2xf32>, tensor<3xf32>) +// CHECK: func private @f() -> (tensor<1xf32>, tensor<2xf32>, tensor<3xf32>) // CHECK-NOT: attributes{{.*}}result -func @f() -> ( +func private @f() -> ( tensor<1xf32>, f32 {test.erase_this_result}, tensor<2xf32>, f32 {test.erase_this_result}, tensor<3xf32> ) diff --git a/mlir/test/IR/test-func-set-type.mlir b/mlir/test/IR/test-func-set-type.mlir index 032283ad705d..05a1393a8436 100644 --- a/mlir/test/IR/test-func-set-type.mlir +++ b/mlir/test/IR/test-func-set-type.mlir @@ -1,25 +1,25 @@ // RUN: mlir-opt %s -test-func-set-type -split-input-file | FileCheck %s // It's currently not possible to have an attribute with a function type due to // parser ambiguity. So instead we reference a function declaration to take the // type from. // ----- // Test case: The setType call needs to erase some arg attrs. -// CHECK: func @erase_arg(f32 {test.A}) +// CHECK: func private @erase_arg(f32 {test.A}) // CHECK-NOT: attributes{{.*arg[0-9]}} -func @t(f32) -func @erase_arg(%arg0: f32 {test.A}, %arg1: f32 {test.B}) +func private @t(f32) +func private @erase_arg(%arg0: f32 {test.A}, %arg1: f32 {test.B}) attributes {test.set_type_from = @t} // ----- // Test case: The setType call needs to erase some result attrs. -// CHECK: func @erase_result() -> (f32 {test.A}) +// CHECK: func private @erase_result() -> (f32 {test.A}) // CHECK-NOT: attributes{{.*result[0-9]}} -func @t() -> (f32) -func @erase_result() -> (f32 {test.A}, f32 {test.B}) +func private @t() -> (f32) +func private @erase_result() -> (f32 {test.A}, f32 {test.B}) attributes {test.set_type_from = @t} diff --git a/mlir/test/IR/test-symbol-rauw.mlir b/mlir/test/IR/test-symbol-rauw.mlir index 2924c20df732..5d50bc0483b9 100644 --- a/mlir/test/IR/test-symbol-rauw.mlir +++ b/mlir/test/IR/test-symbol-rauw.mlir @@ -1,75 +1,75 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -test-symbol-rauw -split-input-file | FileCheck %s // Symbol references to the module itself don't affect uses of symbols within // its table. // CHECK: module // CHECK-SAME: @symbol_foo module attributes {sym.outside_use = @symbol_foo } { - // CHECK: func @replaced_foo - func @symbol_foo() attributes {sym.new_name = "replaced_foo" } + // CHECK: func private @replaced_foo + func private @symbol_foo() attributes {sym.new_name = "replaced_foo" } // CHECK: func @symbol_bar // CHECK: @replaced_foo func @symbol_bar() attributes {sym.use = @symbol_foo} { // CHECK: foo.op // CHECK-SAME: non_symbol_attr, // CHECK-SAME: use = [{nested_symbol = [@replaced_foo], other_use = @symbol_bar, z_use = @replaced_foo}], // CHECK-SAME: z_non_symbol_attr_3 "foo.op"() { non_symbol_attr, use = [{nested_symbol = [@symbol_foo], other_use = @symbol_bar, z_use = @symbol_foo}], z_non_symbol_attr_3 } : () -> () } // CHECK: module attributes {test.reference = @replaced_foo} module attributes {test.reference = @symbol_foo} { // CHECK: foo.op // CHECK-SAME: @symbol_foo "foo.op"() {test.nested_reference = @symbol_foo} : () -> () } } // ----- // Check the support for nested references. // CHECK: module module { // CHECK: module @module_a module @module_a { - // CHECK: func @replaced_foo - func @foo() attributes {sym.new_name = "replaced_foo" } + // CHECK: func nested @replaced_foo + func nested @foo() attributes {sym.new_name = "replaced_foo" } } // CHECK: module @replaced_module_b module @module_b attributes {sym.new_name = "replaced_module_b"} { // CHECK: module @replaced_module_c module @module_c attributes {sym.new_name = "replaced_module_c"} { - // CHECK: func @replaced_foo - func @foo() attributes {sym.new_name = "replaced_foo" } + // CHECK: func nested @replaced_foo + func nested @foo() attributes {sym.new_name = "replaced_foo" } } } // CHECK: func @symbol_bar func @symbol_bar() { // CHECK: foo.op // CHECK-SAME: use_1 = @module_a::@replaced_foo // CHECK-SAME: use_2 = @replaced_module_b::@replaced_module_c::@replaced_foo "foo.op"() { use_1 = @module_a::@foo, use_2 = @module_b::@module_c::@foo } : () -> () } } // ----- // Check that the replacement fails for potentially unknown symbol tables. module { - // CHECK: func @failed_repl - func @failed_repl() attributes {sym.new_name = "replaced_name" } + // CHECK: func private @failed_repl + func private @failed_repl() attributes {sym.new_name = "replaced_name" } "foo.possibly_unknown_symbol_table"() ({ }) : () -> () } diff --git a/mlir/test/IR/test-symbol-uses.mlir b/mlir/test/IR/test-symbol-uses.mlir index 17f4a3054f9f..36c52c88756c 100644 --- a/mlir/test/IR/test-symbol-uses.mlir +++ b/mlir/test/IR/test-symbol-uses.mlir @@ -1,68 +1,68 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -test-symbol-uses -split-input-file -verify-diagnostics // Symbol references to the module itself don't affect uses of symbols within // its table. // expected-remark@below {{symbol_removable function successfully erased}} module attributes {sym.outside_use = @symbol_foo } { // expected-remark@+1 {{symbol has 2 uses}} - func @symbol_foo() + func private @symbol_foo() // expected-remark@below {{symbol has no uses}} // expected-remark@below {{found use of symbol : @symbol_foo}} // expected-remark@below {{symbol contains 2 nested references}} func @symbol_bar() attributes {sym.use = @symbol_foo} { // expected-remark@+1 {{found use of symbol : @symbol_foo}} "foo.op"() { non_symbol_attr, use = [{ nested_symbol = [@symbol_foo]}], z_other_non_symbol_attr } : () -> () } // expected-remark@below {{symbol has no uses}} - func @symbol_removable() + func private @symbol_removable() // expected-remark@+1 {{symbol has 1 use}} - func @symbol_baz() + func private @symbol_baz() // expected-remark@+1 {{found use of symbol : @symbol_baz}} module attributes {test.reference = @symbol_baz} { "foo.op"() {test.nested_reference = @symbol_baz} : () -> () } } // ----- // Test nested attribute support module { // expected-remark@+1 {{symbol has 2 uses}} module @module_b { // expected-remark@+1 {{symbol has 1 uses}} module @module_c { // expected-remark@+1 {{symbol has 1 uses}} - func @foo() + func nested @foo() } } // expected-remark@below {{symbol has no uses}} // expected-remark@below {{symbol contains 2 nested references}} func @symbol_bar() { // expected-remark@below {{found use of symbol : @module_b::@module_c::@foo : "foo"}} // expected-remark@below {{found use of symbol : @module_b::@module_c::@foo : "module_c"}} // expected-remark@below {{found use of symbol : @module_b::@module_c::@foo : "module_b"}} // expected-remark@below {{found use of symbol : @module_b : "module_b"}} "foo.op"() { use_1 = [{ nested_symbol = [@module_b::@module_c::@foo]}], use_2 = @module_b } : () -> () } } // ----- // expected-remark@+1 {{contains an unknown nested operation that 'may' define a new symbol table}} func @symbol_bar() { "foo.possibly_unknown_symbol_table"() ({ }) : () -> () } diff --git a/mlir/test/IR/traits.mlir b/mlir/test/IR/traits.mlir index 4dd6ef7dcf37..88762812e311 100644 --- a/mlir/test/IR/traits.mlir +++ b/mlir/test/IR/traits.mlir @@ -1,542 +1,542 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics | FileCheck %s // CHECK: succeededSameOperandsElementType func @succeededSameOperandsElementType(%t10x10 : tensor<10x10xf32>, %t1f: tensor<1xf32>, %v1: vector<1xf32>, %t1i: tensor<1xi32>, %sf: f32) { "test.same_operand_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xi32> "test.same_operand_element_type"(%t1f, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<1xi32> "test.same_operand_element_type"(%t10x10, %v1) : (tensor<10x10xf32>, vector<1xf32>) -> tensor<1xi32> "test.same_operand_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<1xi32> "test.same_operand_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<121xi32> "test.same_operand_element_type"(%sf, %sf) : (f32, f32) -> i32 "test.same_operand_element_type"(%sf, %t1f) : (f32, tensor<1xf32>) -> tensor<121xi32> "test.same_operand_element_type"(%sf, %v1) : (f32, vector<1xf32>) -> tensor<121xi32> "test.same_operand_element_type"(%sf, %t10x10) : (f32, tensor<10x10xf32>) -> tensor<121xi32> return } // ----- func @failedSameOperandElementType(%t1f: tensor<1xf32>, %t1i: tensor<1xi32>) { // expected-error@+1 {{requires the same element type for all operands}} "test.same_operand_element_type"(%t1f, %t1i) : (tensor<1xf32>, tensor<1xi32>) -> tensor<1xf32> } // ----- func @failedSameOperandAndResultElementType_no_operands() { // expected-error@+1 {{expected 2 operands, but found 0}} "test.same_operand_element_type"() : () -> tensor<1xf32> } // ----- func @failedSameOperandElementType_scalar_type_mismatch(%si: i32, %sf: f32) { // expected-error@+1 {{requires the same element type for all operands}} "test.same_operand_element_type"(%sf, %si) : (f32, i32) -> tensor<1xf32> } // ----- // CHECK: succeededSameOperandAndResultElementType func @succeededSameOperandAndResultElementType(%t10x10 : tensor<10x10xf32>, %t1f: tensor<1xf32>, %v1: vector<1xf32>, %t1i: tensor<1xi32>, %sf: f32) { "test.same_operand_and_result_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32> "test.same_operand_and_result_element_type"(%t1f, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<1xf32> "test.same_operand_and_result_element_type"(%t10x10, %v1) : (tensor<10x10xf32>, vector<1xf32>) -> tensor<1xf32> "test.same_operand_and_result_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<1xf32> "test.same_operand_and_result_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<121xf32> "test.same_operand_and_result_element_type"(%sf, %sf) : (f32, f32) -> f32 "test.same_operand_and_result_element_type"(%sf, %t1f) : (f32, tensor<1xf32>) -> tensor<121xf32> "test.same_operand_and_result_element_type"(%sf, %v1) : (f32, vector<1xf32>) -> tensor<121xf32> "test.same_operand_and_result_element_type"(%sf, %t10x10) : (f32, tensor<10x10xf32>) -> tensor<121xf32> return } // ----- func @failedSameOperandAndResultElementType_operand_result_mismatch(%t1f: tensor<1xf32>) { // expected-error@+1 {{requires the same element type for all operands and results}} "test.same_operand_and_result_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xi32> } // ----- func @failedSameOperandAndResultElementType_operand_mismatch(%t1f: tensor<1xf32>, %t1i: tensor<1xi32>) { // expected-error@+1 {{requires the same element type for all operands and results}} "test.same_operand_and_result_element_type"(%t1f, %t1i) : (tensor<1xf32>, tensor<1xi32>) -> tensor<1xf32> } // ----- func @failedSameOperandAndResultElementType_result_mismatch(%t1f: tensor<1xf32>) { // expected-error@+1 {{requires the same element type for all operands and results}} %0:2 = "test.same_operand_and_result_element_type"(%t1f) : (tensor<1xf32>) -> (tensor<1xf32>, tensor<1xi32>) } // ----- func @failedSameOperandAndResultElementType_no_operands() { // expected-error@+1 {{expected 1 or more operands}} "test.same_operand_and_result_element_type"() : () -> tensor<1xf32> } // ----- func @failedSameOperandAndResultElementType_no_results(%t1f: tensor<1xf32>) { // expected-error@+1 {{expected 1 or more results}} "test.same_operand_and_result_element_type"(%t1f) : (tensor<1xf32>) -> () } // ----- // CHECK: succeededSameOperandShape func @succeededSameOperandShape(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %m10x10 : memref<10x10xi32>, %tr: tensor<*xf32>) { "test.same_operand_shape"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> () "test.same_operand_shape"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> () "test.same_operand_shape"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> () "test.same_operand_shape"(%t10x10, %m10x10) : (tensor<10x10xf32>, memref<10x10xi32>) -> () return } // ----- func @failedSameOperandShape_operand_mismatch(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>) { // expected-error@+1 {{requires the same shape for all operands}} "test.same_operand_shape"(%t1, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> () } // ----- func @failedSameOperandShape_no_operands() { // expected-error@+1 {{expected 1 or more operands}} "test.same_operand_shape"() : () -> () } // ----- // CHECK: succeededSameOperandAndResultShape func @succeededSameOperandAndResultShape(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %tr: tensor<*xf32>, %t1d: tensor) { "test.same_operand_and_result_shape"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32> "test.same_operand_and_result_shape"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> tensor<10x10xf32> "test.same_operand_and_result_shape"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> tensor<1xf32> "test.same_operand_and_result_shape"(%t1, %t1d) : (tensor<1xf32>, tensor) -> tensor<1xf32> "test.same_operand_and_result_shape"(%t1, %t1d) : (tensor<1xf32>, tensor) -> memref<1xf32> return } // ----- func @failedSameOperandAndResultShape_operand_result_mismatch(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>) { // expected-error@+1 {{requires the same shape for all operands and results}} "test.same_operand_and_result_shape"(%t1, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<10x10xf32> } // ----- func @failedSameOperandAndResultShape_no_operands() { // expected-error@+1 {{expected 1 or more operands}} "test.same_operand_and_result_shape"() : () -> (tensor<1xf32>) } // ----- func @failedSameOperandAndResultShape_no_operands(%t1: tensor<1xf32>) { // expected-error@+1 {{expected 1 or more results}} "test.same_operand_and_result_shape"(%t1) : (tensor<1xf32>) -> () } // ----- // CHECK: succeededSameOperandAndResultType func @succeededSameOperandAndResultType(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %tr: tensor<*xf32>, %t1d: tensor, %i32 : i32) { "test.same_operand_and_result_type"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32> "test.same_operand_and_result_type"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> tensor<10x10xf32> "test.same_operand_and_result_type"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> tensor<1xf32> "test.same_operand_and_result_type"(%t1, %t1d) : (tensor<1xf32>, tensor) -> tensor<1xf32> "test.same_operand_and_result_type"(%i32, %i32) : (i32, i32) -> i32 return } // ----- func @failedSameOperandAndResultType_operand_result_mismatch(%t10 : tensor<10xf32>, %t20 : tensor<20xf32>) { // expected-error@+1 {{requires the same type for all operands and results}} "test.same_operand_and_result_type"(%t10, %t20) : (tensor<10xf32>, tensor<20xf32>) -> tensor<10xf32> } // ----- func @failedElementwiseMappable_different_rankedness(%arg0: tensor, %arg1: tensor<*xf32>) { // expected-error@+1 {{all non-scalar operands/results must have the same shape and base type: found 'tensor<*xf32>' and 'tensor'}} %0 = "test.elementwise_mappable"(%arg0, %arg1) : (tensor, tensor<*xf32>) -> tensor<*xf32> } // ----- func @failedElementwiseMappable_different_rank(%arg0: tensor, %arg1: tensor) { // expected-error@+1 {{all non-scalar operands/results must have the same shape and base type: found 'tensor' and 'tensor'}} %0 = "test.elementwise_mappable"(%arg0, %arg1) : (tensor, tensor) -> tensor } // ----- func @failedElementwiseMappable_different_shape(%arg0: tensor, %arg1: tensor<5xf32>) { // expected-error@+1 {{all non-scalar operands/results must have the same shape and base type: found 'tensor<5xf32>' and 'tensor'}} %0 = "test.elementwise_mappable"(%arg0, %arg1) : (tensor, tensor<5xf32>) -> tensor } // ----- func @failedElementwiseMappable_different_base_type(%arg0: vector<2xf32>, %arg1: tensor<2xf32>) { // expected-error@+1 {{all non-scalar operands/results must have the same shape and base type: found 'tensor<2xf32>' and 'vector<2xf32>'}} %0 = "test.elementwise_mappable"(%arg0, %arg1) : (vector<2xf32>, tensor<2xf32>) -> tensor<2xf32> return } // ----- func @failedElementwiseMappable_non_scalar_output(%arg0: vector<2xf32>) { // expected-error@+1 {{if an operand is non-scalar, then there must be at least one non-scalar result}} %0 = "test.elementwise_mappable"(%arg0) : (vector<2xf32>) -> f32 return } // ----- func @failedElementwiseMappable_non_scalar_result_all_scalar_input(%arg0: f32) { // expected-error@+1 {{if a result is non-scalar, then at least one operand must be non-scalar}} %0 = "test.elementwise_mappable"(%arg0) : (f32) -> tensor return } // ----- func @failedElementwiseMappable_mixed_scalar_non_scalar_results(%arg0: tensor<10xf32>) { // expected-error@+1 {{if an operand is non-scalar, then all results must be non-scalar}} %0, %1 = "test.elementwise_mappable"(%arg0) : (tensor<10xf32>) -> (f32, tensor<10xf32>) return } // ----- func @failedElementwiseMappable_zero_results(%arg0: tensor<10xf32>) { // expected-error@+1 {{if an operand is non-scalar, then there must be at least one non-scalar result}} "test.elementwise_mappable"(%arg0) : (tensor<10xf32>) -> () return } // ----- func @failedElementwiseMappable_zero_operands() { // expected-error@+1 {{if a result is non-scalar, then at least one operand must be non-scalar}} "test.elementwise_mappable"() : () -> (tensor<6xf32>) return } // ----- func @succeededElementwiseMappable(%arg0: vector<2xf32>) { // Check that varying element types are allowed. // CHECK: test.elementwise_mappable %0 = "test.elementwise_mappable"(%arg0) : (vector<2xf32>) -> vector<2xf16> return } // ----- func @failedHasParent_wrong_parent() { "some.op"() ({ // expected-error@+1 {{'test.child' op expects parent op 'test.parent'}} "test.child"() : () -> () }) : () -> () } // ----- // CHECK: succeededParentOneOf func @succeededParentOneOf() { "test.parent"() ({ "test.child_with_parent_one_of"() : () -> () "test.finish"() : () -> () }) : () -> () return } // ----- // CHECK: succeededParent1OneOf func @succeededParent1OneOf() { "test.parent1"() ({ "test.child_with_parent_one_of"() : () -> () "test.finish"() : () -> () }) : () -> () return } // ----- func @failedParentOneOf_wrong_parent1() { "some.otherop"() ({ // expected-error@+1 {{'test.child_with_parent_one_of' op expects parent op to be one of 'test.parent, test.parent1'}} "test.child_with_parent_one_of"() : () -> () "test.finish"() : () -> () }) : () -> () } // ----- func @failedSingleBlockImplicitTerminator_empty_block() { // expected-error@+1 {{'test.SingleBlockImplicitTerminator' op expects a non-empty block}} "test.SingleBlockImplicitTerminator"() ({ ^entry: }) : () -> () } // ----- func @failedSingleBlockImplicitTerminator_too_many_blocks() { // expected-error@+1 {{'test.SingleBlockImplicitTerminator' op expects region #0 to have 0 or 1 block}} "test.SingleBlockImplicitTerminator"() ({ ^entry: "test.finish" () : () -> () ^other: "test.finish" () : () -> () }) : () -> () } // ----- func @failedSingleBlockImplicitTerminator_missing_terminator() { // expected-error@+2 {{'test.SingleBlockImplicitTerminator' op expects regions to end with 'test.finish'}} // expected-note@+1 {{in custom textual format, the absence of terminator implies 'test.finish'}} "test.SingleBlockImplicitTerminator"() ({ ^entry: "test.non_existent_op"() : () -> () }) : () -> () } // ----- // Test the invariants of operations with the Symbol Trait. // expected-error@+1 {{requires string attribute 'sym_name'}} "test.symbol"() {} : () -> () // ----- // expected-error@+1 {{requires visibility attribute 'sym_visibility' to be a string attribute}} "test.symbol"() {sym_name = "foo_2", sym_visibility} : () -> () // ----- // expected-error@+1 {{visibility expected to be one of ["public", "private", "nested"]}} "test.symbol"() {sym_name = "foo_2", sym_visibility = "foo"} : () -> () // ----- "test.symbol"() {sym_name = "foo_3", sym_visibility = "nested"} : () -> () "test.symbol"() {sym_name = "foo_4", sym_visibility = "private"} : () -> () "test.symbol"() {sym_name = "foo_5", sym_visibility = "public"} : () -> () "test.symbol"() {sym_name = "foo_6"} : () -> () // ----- // Test that operation with the SymbolTable Trait define a new symbol scope. "test.symbol_scope"() ({ - func @foo() { + func private @foo() { } "test.finish" () : () -> () }) : () -> () -func @foo() { +func private @foo() { } // ----- // Test that operation with the SymbolTable Trait fails with too many blocks. // expected-error@+1 {{Operations with a 'SymbolTable' must have exactly one block}} "test.symbol_scope"() ({ ^entry: "test.finish" () : () -> () ^other: "test.finish" () : () -> () }) : () -> () // ----- func @failedMissingOperandSizeAttr(%arg: i32) { // expected-error @+1 {{requires 1D vector attribute 'operand_segment_sizes'}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) : (i32, i32, i32, i32) -> () } // ----- func @failedOperandSizeAttrWrongType(%arg: i32) { // expected-error @+1 {{requires 1D vector attribute 'operand_segment_sizes'}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[1, 1, 1, 1]>: tensor<4xi32>} : (i32, i32, i32, i32) -> () } // ----- func @failedOperandSizeAttrWrongRank(%arg: i32) { // expected-error @+1 {{requires 1D vector attribute 'operand_segment_sizes'}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[[1, 1], [1, 1]]>: vector<2x2xi32>} : (i32, i32, i32, i32) -> () } // ----- func @failedOperandSizeAttrNegativeValue(%arg: i32) { // expected-error @+1 {{'operand_segment_sizes' attribute cannot have negative elements}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[1, 1, -1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> () } // ----- func @failedOperandSizeAttrWrongTotalSize(%arg: i32) { // expected-error @+1 {{operand count (4) does not match with the total size (3) specified in attribute 'operand_segment_sizes'}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[0, 1, 1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> () } // ----- func @failedOperandSizeAttrWrongCount(%arg: i32) { // expected-error @+1 {{'operand_segment_sizes' attribute for specifying operand segments must have 4 elements}} "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[2, 1, 1]>: vector<3xi32>} : (i32, i32, i32, i32) -> () } // ----- func @succeededOperandSizeAttr(%arg: i32) { // CHECK: test.attr_sized_operands "test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[0, 2, 1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> () return } // ----- func @failedMissingResultSizeAttr() { // expected-error @+1 {{requires 1D vector attribute 'result_segment_sizes'}} %0:4 = "test.attr_sized_results"() : () -> (i32, i32, i32, i32) } // ----- func @failedResultSizeAttrWrongType() { // expected-error @+1 {{requires 1D vector attribute 'result_segment_sizes'}} %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[1, 1, 1, 1]>: tensor<4xi32>} : () -> (i32, i32, i32, i32) } // ----- func @failedResultSizeAttrWrongRank() { // expected-error @+1 {{requires 1D vector attribute 'result_segment_sizes'}} %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[[1, 1], [1, 1]]>: vector<2x2xi32>} : () -> (i32, i32, i32, i32) } // ----- func @failedResultSizeAttrNegativeValue() { // expected-error @+1 {{'result_segment_sizes' attribute cannot have negative elements}} %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[1, 1, -1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32) } // ----- func @failedResultSizeAttrWrongTotalSize() { // expected-error @+1 {{result count (4) does not match with the total size (3) specified in attribute 'result_segment_sizes'}} %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[0, 1, 1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32) } // ----- func @failedResultSizeAttrWrongCount() { // expected-error @+1 {{'result_segment_sizes' attribute for specifying result segments must have 4 elements}} %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[2, 1, 1]>: vector<3xi32>} : () -> (i32, i32, i32, i32) } // ----- func @succeededResultSizeAttr() { // CHECK: test.attr_sized_results %0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[0, 2, 1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32) return } // ----- func @failedHasDominanceScopeOutsideDominanceFreeScope() -> () { "test.ssacfg_region"() ({ test.graph_region { // expected-error @+1 {{operand #0 does not dominate this use}} %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) } // expected-note @+1 {{operand defined here}} %1 = "baz"() : () -> (i64) }) : () -> () return } // ----- // Ensure that SSACFG regions of operations in GRAPH regions are // checked for dominance func @illegalInsideDominanceFreeScope() -> () { test.graph_region { func @test() -> i1 { ^bb1: // expected-error @+1 {{operand #0 does not dominate this use}} %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) // expected-note @+1 {{operand defined here}} %1 = "baz"(%2#0) : (i1) -> (i64) return %2#1 : i1 } "terminator"() : () -> () } return } // ----- // Ensure that SSACFG regions of operations in GRAPH regions are // checked for dominance func @illegalCDFGInsideDominanceFreeScope() -> () { test.graph_region { func @test() -> i1 { ^bb1: // expected-error @+1 {{operand #0 does not dominate this use}} %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) br ^bb4 ^bb2: br ^bb2 ^bb4: %1 = "foo"() : ()->i64 // expected-note {{operand defined here}} return %2#1 : i1 } "terminator"() : () -> () } return } // ----- // Ensure that GRAPH regions still have all values defined somewhere. func @illegalCDFGInsideDominanceFreeScope() -> () { test.graph_region { // expected-error @+1 {{use of undeclared SSA value name}} %2:3 = "bar"(%1) : (i64) -> (i1,i1,i1) "terminator"() : () -> () } return } // ----- func @graph_region_cant_have_blocks() { test.graph_region { // expected-error@-1 {{'test.graph_region' op expects graph region #0 to have 0 or 1 blocks}} ^bb42: br ^bb43 ^bb43: "terminator"() : () -> () } } diff --git a/mlir/test/Pass/dynamic-pipeline-fail-on-parent.mlir b/mlir/test/Pass/dynamic-pipeline-fail-on-parent.mlir index 8885dab80538..57a1f31d84a9 100644 --- a/mlir/test/Pass/dynamic-pipeline-fail-on-parent.mlir +++ b/mlir/test/Pass/dynamic-pipeline-fail-on-parent.mlir @@ -1,11 +1,11 @@ // RUN: mlir-opt %s -pass-pipeline='module(test-dynamic-pipeline{op-name=inner_mod1 run-on-parent=1 dynamic-pipeline=test-patterns})' -split-input-file -verify-diagnostics // Verify that we fail to schedule a dynamic pipeline on the parent operation. // expected-error @+1 {{'module' op Trying to schedule a dynamic pipeline on an operation that isn't nested under the current operation}} module { module @inner_mod1 { "test.symbol"() {sym_name = "foo"} : () -> () - func @bar() + func private @bar() } } diff --git a/mlir/test/Pass/dynamic-pipeline-nested.mlir b/mlir/test/Pass/dynamic-pipeline-nested.mlir index 7651ff403348..9e0945b28e06 100644 --- a/mlir/test/Pass/dynamic-pipeline-nested.mlir +++ b/mlir/test/Pass/dynamic-pipeline-nested.mlir @@ -1,28 +1,28 @@ // RUN: mlir-opt %s -pass-pipeline='module(test-dynamic-pipeline{op-name=inner_mod1 dynamic-pipeline=cse})' --mlir-disable-threading -print-ir-before-all 2>&1 | FileCheck %s --check-prefix=NOTNESTED --check-prefix=CHECK // RUN: mlir-opt %s -pass-pipeline='module(test-dynamic-pipeline{op-name=inner_mod1 run-on-nested-operations=1 dynamic-pipeline=cse})' --mlir-disable-threading -print-ir-before-all 2>&1 | FileCheck %s --check-prefix=NESTED --check-prefix=CHECK // Verify that we can schedule a dynamic pipeline on a nested operation func @f() { return } // CHECK: IR Dump Before // CHECK-SAME: TestDynamicPipelinePass // CHECK-NEXT: module @inner_mod1 module @inner_mod1 { // We use the print-ir-after-all dumps to check the granularity of the // scheduling: if we are nesting we expect to see to individual "Dump Before // CSE" output: one for each of the function. If we don't nest, then we expect // the CSE pass to run on the `inner_mod1` module directly. // CHECK: Dump Before CSE // NOTNESTED-NEXT: @inner_mod1 // NESTED-NEXT: @foo - func @foo() + func private @foo() // Only in the nested case we have a second run of the pass here. // NESTED: Dump Before CSE // NESTED-NEXT: @baz - func @baz() + func private @baz() } diff --git a/mlir/test/Transforms/buffer-results-to-out-params.mlir b/mlir/test/Transforms/buffer-results-to-out-params.mlir index 9eb794abfa2f..cde929739475 100644 --- a/mlir/test/Transforms/buffer-results-to-out-params.mlir +++ b/mlir/test/Transforms/buffer-results-to-out-params.mlir @@ -1,113 +1,113 @@ // RUN: mlir-opt -buffer-results-to-out-params -split-input-file -verify-diagnostics %s | FileCheck %s // CHECK-LABEL: func @basic( // CHECK-SAME: %[[ARG:.*]]: memref) { // CHECK: %[[RESULT:.*]] = "test.source"() : () -> memref // CHECK: linalg.copy(%[[RESULT]], %[[ARG]]) : memref, memref // CHECK: return // CHECK: } func @basic() -> (memref) { %0 = "test.source"() : () -> (memref) return %0 : memref } // CHECK-LABEL: func @presence_of_existing_arguments( // CHECK-SAME: %[[ARG0:.*]]: memref<1xf32>, // CHECK-SAME: %[[ARG1:.*]]: memref<2xf32>) { // CHECK: %[[RESULT:.*]] = "test.source"() : () -> memref<2xf32> // CHECK: linalg.copy(%[[RESULT]], %[[ARG1]]) : memref<2xf32>, memref<2xf32> // CHECK: return // CHECK: } func @presence_of_existing_arguments(%arg0: memref<1xf32>) -> (memref<2xf32>) { %0 = "test.source"() : () -> (memref<2xf32>) return %0 : memref<2xf32> } // CHECK-LABEL: func @multiple_results( // CHECK-SAME: %[[ARG0:.*]]: memref<1xf32>, // CHECK-SAME: %[[ARG1:.*]]: memref<2xf32>) { // CHECK: %[[RESULTS:.*]]:2 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>) // CHECK: linalg.copy(%[[RESULTS]]#0, %[[ARG0]]) : memref<1xf32>, memref<1xf32> // CHECK: linalg.copy(%[[RESULTS]]#1, %[[ARG1]]) : memref<2xf32>, memref<2xf32> // CHECK: return // CHECK: } func @multiple_results() -> (memref<1xf32>, memref<2xf32>) { %0, %1 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>) return %0, %1 : memref<1xf32>, memref<2xf32> } // CHECK-LABEL: func @non_memref_types( // CHECK-SAME: %[[OUTPARAM:.*]]: memref) -> (i1, i32) { // CHECK: %[[RESULT1:.*]]:3 = "test.source"() : () -> (i1, memref, i32) // CHECK: linalg.copy(%[[RESULT1]]#1, %[[OUTPARAM]]) : memref, memref // CHECK: return %[[RESULT1]]#0, %[[RESULT1]]#2 : i1, i32 // CHECK: } func @non_memref_types() -> (i1, memref, i32) { %0, %1, %2 = "test.source"() : () -> (i1, memref, i32) return %0, %1, %2 : i1, memref, i32 } -// CHECK: func @external_function(memref) -func @external_function() -> (memref) -// CHECK: func @result_attrs(memref {test.some_attr}) -func @result_attrs() -> (memref {test.some_attr}) -// CHECK: func @mixed_result_attrs(memref<1xf32>, memref<2xf32> {test.some_attr}, memref<3xf32>) -func @mixed_result_attrs() -> (memref<1xf32>, memref<2xf32> {test.some_attr}, memref<3xf32>) +// CHECK: func private @external_function(memref) +func private @external_function() -> (memref) +// CHECK: func private @result_attrs(memref {test.some_attr}) +func private @result_attrs() -> (memref {test.some_attr}) +// CHECK: func private @mixed_result_attrs(memref<1xf32>, memref<2xf32> {test.some_attr}, memref<3xf32>) +func private @mixed_result_attrs() -> (memref<1xf32>, memref<2xf32> {test.some_attr}, memref<3xf32>) // ----- -// CHECK-LABEL: func @callee(memref<1xf32>) -func @callee() -> memref<1xf32> +// CHECK-LABEL: func private @callee(memref<1xf32>) +func private @callee() -> memref<1xf32> // CHECK-LABEL: func @call_basic() { // CHECK: %[[OUTPARAM:.*]] = alloc() : memref<1xf32> // CHECK: call @callee(%[[OUTPARAM]]) : (memref<1xf32>) -> () // CHECK: "test.sink"(%[[OUTPARAM]]) : (memref<1xf32>) -> () // CHECK: return // CHECK: } func @call_basic() { %0 = call @callee() : () -> memref<1xf32> "test.sink"(%0) : (memref<1xf32>) -> () return } // ----- -// CHECK-LABEL: func @callee(memref<1xf32>, memref<2xf32>) -func @callee() -> (memref<1xf32>, memref<2xf32>) +// CHECK-LABEL: func private @callee(memref<1xf32>, memref<2xf32>) +func private @callee() -> (memref<1xf32>, memref<2xf32>) // CHECK-LABEL: func @call_multiple_result() { // CHECK: %[[RESULT0:.*]] = alloc() : memref<1xf32> // CHECK: %[[RESULT1:.*]] = alloc() : memref<2xf32> // CHECK: call @callee(%[[RESULT0]], %[[RESULT1]]) : (memref<1xf32>, memref<2xf32>) -> () // CHECK: "test.sink"(%[[RESULT0]], %[[RESULT1]]) : (memref<1xf32>, memref<2xf32>) -> () // CHECK: } func @call_multiple_result() { %0, %1 = call @callee() : () -> (memref<1xf32>, memref<2xf32>) "test.sink"(%0, %1) : (memref<1xf32>, memref<2xf32>) -> () } // ----- -// CHECK-LABEL: func @callee(memref<1xf32>) -> (i1, i32) -func @callee() -> (i1, memref<1xf32>, i32) +// CHECK-LABEL: func private @callee(memref<1xf32>) -> (i1, i32) +func private @callee() -> (i1, memref<1xf32>, i32) // CHECK-LABEL: func @call_non_memref_result() { // CHECK: %[[RESULT0:.*]] = alloc() : memref<1xf32> // CHECK: %[[NON_MEMREF_RESULTS:.*]]:2 = call @callee(%[[RESULT0]]) : (memref<1xf32>) -> (i1, i32) // CHECK: "test.sink"(%[[NON_MEMREF_RESULTS]]#0, %[[RESULT0]], %[[NON_MEMREF_RESULTS]]#1) : (i1, memref<1xf32>, i32) -> () // CHECK: } func @call_non_memref_result() { %0, %1, %2 = call @callee() : () -> (i1, memref<1xf32>, i32) "test.sink"(%0, %1, %2) : (i1, memref<1xf32>, i32) -> () } // ----- -func @callee() -> (memref) +func private @callee() -> (memref) func @call_non_memref_result() { // expected-error @+1 {{cannot create out param for dynamically shaped result}} %0 = call @callee() : () -> (memref) "test.sink"(%0) : (memref) -> () } diff --git a/mlir/test/Transforms/decompose-call-graph-types.mlir b/mlir/test/Transforms/decompose-call-graph-types.mlir index c29bbdd2bd9e..850bf5e9ecfa 100644 --- a/mlir/test/Transforms/decompose-call-graph-types.mlir +++ b/mlir/test/Transforms/decompose-call-graph-types.mlir @@ -1,116 +1,116 @@ // RUN: mlir-opt %s -split-input-file -test-decompose-call-graph-types | FileCheck %s // Test case: Most basic case of a 1:N decomposition, an identity function. // CHECK-LABEL: func @identity( // CHECK-SAME: %[[ARG0:.*]]: i1, // CHECK-SAME: %[[ARG1:.*]]: i32) -> (i1, i32) { // CHECK: %[[ARG_MATERIALIZED:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) : (i1, i32) -> tuple // CHECK: %[[RET0:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) {index = 0 : i32} : (tuple) -> i1 // CHECK: %[[RET1:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) {index = 1 : i32} : (tuple) -> i32 // CHECK: return %[[RET0]], %[[RET1]] : i1, i32 func @identity(%arg0: tuple) -> tuple { return %arg0 : tuple } // ----- // Test case: Ensure no materializations in the case of 1:1 decomposition. // CHECK-LABEL: func @identity_1_to_1_no_materializations( // CHECK-SAME: %[[ARG0:.*]]: i1) -> i1 { // CHECK: return %[[ARG0]] : i1 func @identity_1_to_1_no_materializations(%arg0: tuple) -> tuple { return %arg0 : tuple } // ----- // Test case: Type that needs to be recursively decomposed. // CHECK-LABEL: func @recursive_decomposition( // CHECK-SAME: %[[ARG0:.*]]: i1) -> i1 { // CHECK: return %[[ARG0]] : i1 func @recursive_decomposition(%arg0: tuple>>) -> tuple>> { return %arg0 : tuple>> } // ----- // Test case: Check decomposition of calls. -// CHECK-LABEL: func @callee(i1, i32) -> (i1, i32) -func @callee(tuple) -> tuple +// CHECK-LABEL: func private @callee(i1, i32) -> (i1, i32) +func private @callee(tuple) -> tuple // CHECK-LABEL: func @caller( // CHECK-SAME: %[[ARG0:.*]]: i1, // CHECK-SAME: %[[ARG1:.*]]: i32) -> (i1, i32) { // CHECK: %[[ARG_MATERIALIZED:.*]] = "test.make_tuple"(%[[ARG0]], %[[ARG1]]) : (i1, i32) -> tuple // CHECK: %[[CALL_ARG0:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) {index = 0 : i32} : (tuple) -> i1 // CHECK: %[[CALL_ARG1:.*]] = "test.get_tuple_element"(%[[ARG_MATERIALIZED]]) {index = 1 : i32} : (tuple) -> i32 // CHECK: %[[DECOMPOSED:.*]]:2 = call @callee(%[[CALL_ARG0]], %[[CALL_ARG1]]) : (i1, i32) -> (i1, i32) // CHECK: %[[CALL_RESULT_RECOMPOSED:.*]] = "test.make_tuple"(%[[DECOMPOSED]]#0, %[[DECOMPOSED]]#1) : (i1, i32) -> tuple // CHECK: %[[RET0:.*]] = "test.get_tuple_element"(%[[CALL_RESULT_RECOMPOSED]]) {index = 0 : i32} : (tuple) -> i1 // CHECK: %[[RET1:.*]] = "test.get_tuple_element"(%[[CALL_RESULT_RECOMPOSED]]) {index = 1 : i32} : (tuple) -> i32 // CHECK: return %[[RET0]], %[[RET1]] : i1, i32 func @caller(%arg0: tuple) -> tuple { %0 = call @callee(%arg0) : (tuple) -> tuple return %0 : tuple } // ----- // Test case: Type that decomposes to nothing (that is, a 1:0 decomposition). -// CHECK-LABEL: func @callee() -func @callee(tuple<>) -> tuple<> +// CHECK-LABEL: func private @callee() +func private @callee(tuple<>) -> tuple<> // CHECK-LABEL: func @caller() { // CHECK: call @callee() : () -> () // CHECK: return func @caller(%arg0: tuple<>) -> tuple<> { %0 = call @callee(%arg0) : (tuple<>) -> (tuple<>) return %0 : tuple<> } // ----- // Test case: Ensure decompositions are inserted properly around results of // unconverted ops. // CHECK-LABEL: func @unconverted_op_result() -> (i1, i32) { // CHECK: %[[UNCONVERTED_VALUE:.*]] = "test.source"() : () -> tuple // CHECK: %[[RET0:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) {index = 0 : i32} : (tuple) -> i1 // CHECK: %[[RET1:.*]] = "test.get_tuple_element"(%[[UNCONVERTED_VALUE]]) {index = 1 : i32} : (tuple) -> i32 // CHECK: return %[[RET0]], %[[RET1]] : i1, i32 func @unconverted_op_result() -> tuple { %0 = "test.source"() : () -> (tuple) return %0 : tuple } // ----- // Test case: Check mixed decomposed and non-decomposed args. // This makes sure to test the cases if 1:0, 1:1, and 1:N decompositions. -// CHECK-LABEL: func @callee(i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6) -func @callee(tuple<>, i1, tuple, i3, tuple, i6) -> (tuple<>, i1, tuple, i3, tuple, i6) +// CHECK-LABEL: func private @callee(i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6) +func private @callee(tuple<>, i1, tuple, i3, tuple, i6) -> (tuple<>, i1, tuple, i3, tuple, i6) // CHECK-LABEL: func @caller( // CHECK-SAME: %[[I1:.*]]: i1, // CHECK-SAME: %[[I2:.*]]: i2, // CHECK-SAME: %[[I3:.*]]: i3, // CHECK-SAME: %[[I4:.*]]: i4, // CHECK-SAME: %[[I5:.*]]: i5, // CHECK-SAME: %[[I6:.*]]: i6) -> (i1, i2, i3, i4, i5, i6) { // CHECK: %[[ARG_TUPLE:.*]] = "test.make_tuple"(%[[I4]], %[[I5]]) : (i4, i5) -> tuple // CHECK: %[[ARG_TUPLE_0:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) {index = 0 : i32} : (tuple) -> i4 // CHECK: %[[ARG_TUPLE_1:.*]] = "test.get_tuple_element"(%[[ARG_TUPLE]]) {index = 1 : i32} : (tuple) -> i5 // CHECK: %[[CALL:.*]]:6 = call @callee(%[[I1]], %[[I2]], %[[I3]], %[[ARG_TUPLE_0]], %[[ARG_TUPLE_1]], %[[I6]]) : (i1, i2, i3, i4, i5, i6) -> (i1, i2, i3, i4, i5, i6) // CHECK: %[[RET_TUPLE:.*]] = "test.make_tuple"(%[[CALL]]#3, %[[CALL]]#4) : (i4, i5) -> tuple // CHECK: %[[RET_TUPLE_0:.*]] = "test.get_tuple_element"(%[[RET_TUPLE]]) {index = 0 : i32} : (tuple) -> i4 // CHECK: %[[RET_TUPLE_1:.*]] = "test.get_tuple_element"(%[[RET_TUPLE]]) {index = 1 : i32} : (tuple) -> i5 // CHECK: return %[[CALL]]#0, %[[CALL]]#1, %[[CALL]]#2, %[[RET_TUPLE_0]], %[[RET_TUPLE_1]], %[[CALL]]#5 : i1, i2, i3, i4, i5, i6 func @caller(%arg0: tuple<>, %arg1: i1, %arg2: tuple, %arg3: i3, %arg4: tuple, %arg5: i6) -> (tuple<>, i1, tuple, i3, tuple, i6) { %0, %1, %2, %3, %4, %5 = call @callee(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) : (tuple<>, i1, tuple, i3, tuple, i6) -> (tuple<>, i1, tuple, i3, tuple, i6) return %0, %1, %2, %3, %4, %5 : tuple<>, i1, tuple, i3, tuple, i6 } diff --git a/mlir/test/Transforms/inlining.mlir b/mlir/test/Transforms/inlining.mlir index e59d8094768b..be9aa9cfc55b 100644 --- a/mlir/test/Transforms/inlining.mlir +++ b/mlir/test/Transforms/inlining.mlir @@ -1,191 +1,191 @@ // RUN: mlir-opt %s -inline="disable-simplify" | FileCheck %s // RUN: mlir-opt %s -inline="disable-simplify" -mlir-print-debuginfo -mlir-print-local-scope | FileCheck %s --check-prefix INLINE-LOC // RUN: mlir-opt %s -inline | FileCheck %s --check-prefix INLINE_SIMPLIFY // Inline a function that takes an argument. func @func_with_arg(%c : i32) -> i32 { %b = addi %c, %c : i32 return %b : i32 } // CHECK-LABEL: func @inline_with_arg func @inline_with_arg(%arg0 : i32) -> i32 { // CHECK-NEXT: addi // CHECK-NEXT: return %0 = call @func_with_arg(%arg0) : (i32) -> i32 return %0 : i32 } // Inline a function that has multiple return operations. func @func_with_multi_return(%a : i1) -> (i32) { cond_br %a, ^bb1, ^bb2 ^bb1: %const_0 = constant 0 : i32 return %const_0 : i32 ^bb2: %const_55 = constant 55 : i32 return %const_55 : i32 } // CHECK-LABEL: func @inline_with_multi_return() -> i32 func @inline_with_multi_return() -> i32 { // CHECK-NEXT: [[VAL_7:%.*]] = constant false // CHECK-NEXT: cond_br [[VAL_7]], ^bb1, ^bb2 // CHECK: ^bb1: // CHECK-NEXT: [[VAL_8:%.*]] = constant 0 : i32 // CHECK-NEXT: br ^bb3([[VAL_8]] : i32) // CHECK: ^bb2: // CHECK-NEXT: [[VAL_9:%.*]] = constant 55 : i32 // CHECK-NEXT: br ^bb3([[VAL_9]] : i32) // CHECK: ^bb3([[VAL_10:%.*]]: i32): // CHECK-NEXT: return [[VAL_10]] : i32 %false = constant false %x = call @func_with_multi_return(%false) : (i1) -> i32 return %x : i32 } // Check that location information is updated for inlined instructions. func @func_with_locations(%c : i32) -> i32 { %b = addi %c, %c : i32 loc("mysource.cc":10:8) return %b : i32 loc("mysource.cc":11:2) } // INLINE-LOC-LABEL: func @inline_with_locations func @inline_with_locations(%arg0 : i32) -> i32 { // INLINE-LOC-NEXT: addi %{{.*}}, %{{.*}} : i32 loc(callsite("mysource.cc":10:8 at "mysource.cc":55:14)) // INLINE-LOC-NEXT: return %0 = call @func_with_locations(%arg0) : (i32) -> i32 loc("mysource.cc":55:14) return %0 : i32 } -// Check that external functions are not inlined. -func @func_external() +// Check that external function declarations are not inlined. +func private @func_external() // CHECK-LABEL: func @no_inline_external func @no_inline_external() { // CHECK-NEXT: call @func_external() call @func_external() : () -> () return } // Check that multiple levels of calls will be inlined. func @multilevel_func_a() { return } func @multilevel_func_b() { call @multilevel_func_a() : () -> () return } // CHECK-LABEL: func @inline_multilevel func @inline_multilevel() { // CHECK-NOT: call %fn = "test.functional_region_op"() ({ call @multilevel_func_b() : () -> () "test.return"() : () -> () }) : () -> (() -> ()) call_indirect %fn() : () -> () return } // Check that recursive calls are not inlined. // CHECK-LABEL: func @no_inline_recursive func @no_inline_recursive() { // CHECK: test.functional_region_op // CHECK-NOT: test.functional_region_op %fn = "test.functional_region_op"() ({ call @no_inline_recursive() : () -> () "test.return"() : () -> () }) : () -> (() -> ()) return } // Check that we can convert types for inputs and results as necessary. func @convert_callee_fn(%arg : i32) -> i32 { return %arg : i32 } func @convert_callee_fn_multi_arg(%a : i32, %b : i32) -> () { return } func @convert_callee_fn_multi_res() -> (i32, i32) { %res = constant 0 : i32 return %res, %res : i32, i32 } // CHECK-LABEL: func @inline_convert_call func @inline_convert_call() -> i16 { // CHECK: %[[INPUT:.*]] = constant %test_input = constant 0 : i16 // CHECK: %[[CAST_INPUT:.*]] = "test.cast"(%[[INPUT]]) : (i16) -> i32 // CHECK: %[[CAST_RESULT:.*]] = "test.cast"(%[[CAST_INPUT]]) : (i32) -> i16 // CHECK-NEXT: return %[[CAST_RESULT]] %res = "test.conversion_call_op"(%test_input) { callee=@convert_callee_fn } : (i16) -> (i16) return %res : i16 } func @convert_callee_fn_multiblock() -> i32 { br ^bb0 ^bb0: %0 = constant 0 : i32 return %0 : i32 } // CHECK-LABEL: func @inline_convert_result_multiblock func @inline_convert_result_multiblock() -> i16 { // CHECK: br ^bb1 // CHECK: ^bb1: // CHECK: %[[C:.+]] = constant 0 : i32 // CHECK: br ^bb2(%[[C]] : i32) // CHECK: ^bb2(%[[BBARG:.+]]: i32): // CHECK: %[[CAST_RESULT:.+]] = "test.cast"(%[[BBARG]]) : (i32) -> i16 // CHECK: return %[[CAST_RESULT]] : i16 %res = "test.conversion_call_op"() { callee=@convert_callee_fn_multiblock } : () -> (i16) return %res : i16 } // CHECK-LABEL: func @no_inline_convert_call func @no_inline_convert_call() { // CHECK: "test.conversion_call_op" %test_input_i16 = constant 0 : i16 %test_input_i64 = constant 0 : i64 "test.conversion_call_op"(%test_input_i16, %test_input_i64) { callee=@convert_callee_fn_multi_arg } : (i16, i64) -> () // CHECK: "test.conversion_call_op" %res_2:2 = "test.conversion_call_op"() { callee=@convert_callee_fn_multi_res } : () -> (i16, i64) return } // Check that we properly simplify when inlining. func @simplify_return_constant() -> i32 { %res = constant 0 : i32 return %res : i32 } func @simplify_return_reference() -> (() -> i32) { %res = constant @simplify_return_constant : () -> i32 return %res : () -> i32 } // INLINE_SIMPLIFY-LABEL: func @inline_simplify func @inline_simplify() -> i32 { // INLINE_SIMPLIFY-NEXT: %[[CST:.*]] = constant 0 : i32 // INLINE_SIMPLIFY-NEXT: return %[[CST]] %fn = call @simplify_return_reference() : () -> (() -> i32) %res = call_indirect %fn() : () -> i32 return %res : i32 } // CHECK-LABEL: func @no_inline_invalid_call func @no_inline_invalid_call() -> i32 { %res = "test.conversion_call_op"() { callee=@convert_callee_fn_multiblock, noinline } : () -> (i32) return %res : i32 } diff --git a/mlir/test/Transforms/normalize-memrefs.mlir b/mlir/test/Transforms/normalize-memrefs.mlir index 9c1e610c483a..7bdbfe6bfb35 100644 --- a/mlir/test/Transforms/normalize-memrefs.mlir +++ b/mlir/test/Transforms/normalize-memrefs.mlir @@ -1,321 +1,321 @@ // RUN: mlir-opt -normalize-memrefs -allow-unregistered-dialect %s | FileCheck %s // This file tests whether the memref type having non-trivial map layouts // are normalized to trivial (identity) layouts. // CHECK-LABEL: func @permute() func @permute() { %A = alloc() : memref<64x256xf32, affine_map<(d0, d1) -> (d1, d0)>> affine.for %i = 0 to 64 { affine.for %j = 0 to 256 { %1 = affine.load %A[%i, %j] : memref<64x256xf32, affine_map<(d0, d1) -> (d1, d0)>> "prevent.dce"(%1) : (f32) -> () } } dealloc %A : memref<64x256xf32, affine_map<(d0, d1) -> (d1, d0)>> return } // The old memref alloc should disappear. // CHECK-NOT: memref<64x256xf32> // CHECK: [[MEM:%[0-9]+]] = alloc() : memref<256x64xf32> // CHECK-NEXT: affine.for %[[I:arg[0-9]+]] = 0 to 64 { // CHECK-NEXT: affine.for %[[J:arg[0-9]+]] = 0 to 256 { // CHECK-NEXT: affine.load [[MEM]][%[[J]], %[[I]]] : memref<256x64xf32> // CHECK-NEXT: "prevent.dce" // CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: dealloc [[MEM]] // CHECK-NEXT: return // CHECK-LABEL: func @shift func @shift(%idx : index) { // CHECK-NEXT: alloc() : memref<65xf32> %A = alloc() : memref<64xf32, affine_map<(d0) -> (d0 + 1)>> // CHECK-NEXT: affine.load %{{.*}}[symbol(%arg0) + 1] : memref<65xf32> affine.load %A[%idx] : memref<64xf32, affine_map<(d0) -> (d0 + 1)>> affine.for %i = 0 to 64 { %1 = affine.load %A[%i] : memref<64xf32, affine_map<(d0) -> (d0 + 1)>> "prevent.dce"(%1) : (f32) -> () // CHECK: %{{.*}} = affine.load %{{.*}}[%arg{{.*}} + 1] : memref<65xf32> } return } // CHECK-LABEL: func @high_dim_permute() func @high_dim_permute() { // CHECK-NOT: memref<64x128x256xf32, %A = alloc() : memref<64x128x256xf32, affine_map<(d0, d1, d2) -> (d2, d0, d1)>> // CHECK: %[[I:arg[0-9]+]] affine.for %i = 0 to 64 { // CHECK: %[[J:arg[0-9]+]] affine.for %j = 0 to 128 { // CHECK: %[[K:arg[0-9]+]] affine.for %k = 0 to 256 { %1 = affine.load %A[%i, %j, %k] : memref<64x128x256xf32, affine_map<(d0, d1, d2) -> (d2, d0, d1)>> // CHECK: %{{.*}} = affine.load %{{.*}}[%[[K]], %[[I]], %[[J]]] : memref<256x64x128xf32> "prevent.dce"(%1) : (f32) -> () } } } return } // CHECK-LABEL: func @invalid_map func @invalid_map() { %A = alloc() : memref<64x128xf32, affine_map<(d0, d1) -> (d0, -d1 - 10)>> // CHECK: %{{.*}} = alloc() : memref<64x128xf32, return } // A tiled layout. // CHECK-LABEL: func @data_tiling func @data_tiling(%idx : index) { // CHECK: alloc() : memref<8x32x8x16xf32> %A = alloc() : memref<64x512xf32, affine_map<(d0, d1) -> (d0 floordiv 8, d1 floordiv 16, d0 mod 8, d1 mod 16)>> // CHECK: affine.load %{{.*}}[symbol(%arg0) floordiv 8, symbol(%arg0) floordiv 16, symbol(%arg0) mod 8, symbol(%arg0) mod 16] %1 = affine.load %A[%idx, %idx] : memref<64x512xf32, affine_map<(d0, d1) -> (d0 floordiv 8, d1 floordiv 16, d0 mod 8, d1 mod 16)>> "prevent.dce"(%1) : (f32) -> () return } // Strides 2 and 4 along respective dimensions. // CHECK-LABEL: func @strided func @strided() { %A = alloc() : memref<64x128xf32, affine_map<(d0, d1) -> (2*d0, 4*d1)>> // CHECK: affine.for %[[IV0:.*]] = affine.for %i = 0 to 64 { // CHECK: affine.for %[[IV1:.*]] = affine.for %j = 0 to 128 { // CHECK: affine.load %{{.*}}[%[[IV0]] * 2, %[[IV1]] * 4] : memref<127x509xf32> %1 = affine.load %A[%i, %j] : memref<64x128xf32, affine_map<(d0, d1) -> (2*d0, 4*d1)>> "prevent.dce"(%1) : (f32) -> () } } return } // Strided, but the strides are in the linearized space. // CHECK-LABEL: func @strided_cumulative func @strided_cumulative() { %A = alloc() : memref<2x5xf32, affine_map<(d0, d1) -> (3*d0 + 17*d1)>> // CHECK: affine.for %[[IV0:.*]] = affine.for %i = 0 to 2 { // CHECK: affine.for %[[IV1:.*]] = affine.for %j = 0 to 5 { // CHECK: affine.load %{{.*}}[%[[IV0]] * 3 + %[[IV1]] * 17] : memref<72xf32> %1 = affine.load %A[%i, %j] : memref<2x5xf32, affine_map<(d0, d1) -> (3*d0 + 17*d1)>> "prevent.dce"(%1) : (f32) -> () } } return } // Symbolic operand for alloc, although unused. Tests replaceAllMemRefUsesWith // when the index remap has symbols. // CHECK-LABEL: func @symbolic_operands func @symbolic_operands(%s : index) { // CHECK: alloc() : memref<100xf32> %A = alloc()[%s] : memref<10x10xf32, affine_map<(d0,d1)[s0] -> (10*d0 + d1)>> affine.for %i = 0 to 10 { affine.for %j = 0 to 10 { // CHECK: affine.load %{{.*}}[%{{.*}} * 10 + %{{.*}}] : memref<100xf32> %1 = affine.load %A[%i, %j] : memref<10x10xf32, affine_map<(d0,d1)[s0] -> (10*d0 + d1)>> "prevent.dce"(%1) : (f32) -> () } } return } // Semi-affine maps, normalization not implemented yet. // CHECK-LABEL: func @semi_affine_layout_map func @semi_affine_layout_map(%s0: index, %s1: index) { %A = alloc()[%s0, %s1] : memref<256x1024xf32, affine_map<(d0, d1)[s0, s1] -> (d0*s0 + d1*s1)>> affine.for %i = 0 to 256 { affine.for %j = 0 to 1024 { // CHECK: memref<256x1024xf32, #map{{[0-9]+}}> affine.load %A[%i, %j] : memref<256x1024xf32, affine_map<(d0, d1)[s0, s1] -> (d0*s0 + d1*s1)>> } } return } // CHECK-LABEL: func @alignment func @alignment() { %A = alloc() {alignment = 32 : i64}: memref<64x128x256xf32, affine_map<(d0, d1, d2) -> (d2, d0, d1)>> // CHECK-NEXT: alloc() {alignment = 32 : i64} : memref<256x64x128xf32> return } #tile = affine_map < (i)->(i floordiv 4, i mod 4) > // Following test cases check the inter-procedural memref normalization. // Test case 1: Check normalization for multiple memrefs in a function argument list. // CHECK-LABEL: func @multiple_argument_type // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<4x4xf64>, %[[B:arg[0-9]+]]: f64, %[[C:arg[0-9]+]]: memref<2x4xf64>, %[[D:arg[0-9]+]]: memref<24xf64>) -> f64 func @multiple_argument_type(%A: memref<16xf64, #tile>, %B: f64, %C: memref<8xf64, #tile>, %D: memref<24xf64>) -> f64 { %a = affine.load %A[0] : memref<16xf64, #tile> %p = mulf %a, %a : f64 affine.store %p, %A[10] : memref<16xf64, #tile> call @single_argument_type(%C): (memref<8xf64, #tile>) -> () return %B : f64 } // CHECK: %[[a:[0-9]+]] = affine.load %[[A]][0, 0] : memref<4x4xf64> // CHECK: %[[p:[0-9]+]] = mulf %[[a]], %[[a]] : f64 // CHECK: affine.store %[[p]], %[[A]][2, 2] : memref<4x4xf64> // CHECK: call @single_argument_type(%[[C]]) : (memref<2x4xf64>) -> () // CHECK: return %[[B]] : f64 // Test case 2: Check normalization for single memref argument in a function. // CHECK-LABEL: func @single_argument_type // CHECK-SAME: (%[[C:arg[0-9]+]]: memref<2x4xf64>) func @single_argument_type(%C : memref<8xf64, #tile>) { %a = alloc(): memref<8xf64, #tile> %b = alloc(): memref<16xf64, #tile> %d = constant 23.0 : f64 %e = alloc(): memref<24xf64> call @single_argument_type(%a): (memref<8xf64, #tile>) -> () call @single_argument_type(%C): (memref<8xf64, #tile>) -> () call @multiple_argument_type(%b, %d, %a, %e): (memref<16xf64, #tile>, f64, memref<8xf64, #tile>, memref<24xf64>) -> f64 return } // CHECK: %[[a:[0-9]+]] = alloc() : memref<2x4xf64> // CHECK: %[[b:[0-9]+]] = alloc() : memref<4x4xf64> // CHECK: %cst = constant 2.300000e+01 : f64 // CHECK: %[[e:[0-9]+]] = alloc() : memref<24xf64> // CHECK: call @single_argument_type(%[[a]]) : (memref<2x4xf64>) -> () // CHECK: call @single_argument_type(%[[C]]) : (memref<2x4xf64>) -> () // CHECK: call @multiple_argument_type(%[[b]], %cst, %[[a]], %[[e]]) : (memref<4x4xf64>, f64, memref<2x4xf64>, memref<24xf64>) -> f64 // Test case 3: Check function returning any other type except memref. // CHECK-LABEL: func @non_memref_ret // CHECK-SAME: (%[[C:arg[0-9]+]]: memref<2x4xf64>) -> i1 func @non_memref_ret(%A: memref<8xf64, #tile>) -> i1 { %d = constant 1 : i1 return %d : i1 } // Test cases here onwards deal with normalization of memref in function signature, caller site. // Test case 4: Check successful memref normalization in case of inter/intra-recursive calls. // CHECK-LABEL: func @ret_multiple_argument_type // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<4x4xf64>, %[[B:arg[0-9]+]]: f64, %[[C:arg[0-9]+]]: memref<2x4xf64>) -> (memref<2x4xf64>, f64) func @ret_multiple_argument_type(%A: memref<16xf64, #tile>, %B: f64, %C: memref<8xf64, #tile>) -> (memref<8xf64, #tile>, f64) { %a = affine.load %A[0] : memref<16xf64, #tile> %p = mulf %a, %a : f64 %cond = constant 1 : i1 cond_br %cond, ^bb1, ^bb2 ^bb1: %res1, %res2 = call @ret_single_argument_type(%C) : (memref<8xf64, #tile>) -> (memref<16xf64, #tile>, memref<8xf64, #tile>) return %res2, %p: memref<8xf64, #tile>, f64 ^bb2: return %C, %p: memref<8xf64, #tile>, f64 } // CHECK: %[[a:[0-9]+]] = affine.load %[[A]][0, 0] : memref<4x4xf64> // CHECK: %[[p:[0-9]+]] = mulf %[[a]], %[[a]] : f64 // CHECK: %true = constant true // CHECK: cond_br %true, ^bb1, ^bb2 // CHECK: ^bb1: // pred: ^bb0 // CHECK: %[[res:[0-9]+]]:2 = call @ret_single_argument_type(%[[C]]) : (memref<2x4xf64>) -> (memref<4x4xf64>, memref<2x4xf64>) // CHECK: return %[[res]]#1, %[[p]] : memref<2x4xf64>, f64 // CHECK: ^bb2: // pred: ^bb0 // CHECK: return %{{.*}}, %{{.*}} : memref<2x4xf64>, f64 // CHECK-LABEL: func @ret_single_argument_type // CHECK-SAME: (%[[C:arg[0-9]+]]: memref<2x4xf64>) -> (memref<4x4xf64>, memref<2x4xf64>) func @ret_single_argument_type(%C: memref<8xf64, #tile>) -> (memref<16xf64, #tile>, memref<8xf64, #tile>){ %a = alloc() : memref<8xf64, #tile> %b = alloc() : memref<16xf64, #tile> %d = constant 23.0 : f64 call @ret_single_argument_type(%a) : (memref<8xf64, #tile>) -> (memref<16xf64, #tile>, memref<8xf64, #tile>) call @ret_single_argument_type(%C) : (memref<8xf64, #tile>) -> (memref<16xf64, #tile>, memref<8xf64, #tile>) %res1, %res2 = call @ret_multiple_argument_type(%b, %d, %a) : (memref<16xf64, #tile>, f64, memref<8xf64, #tile>) -> (memref<8xf64, #tile>, f64) %res3, %res4 = call @ret_single_argument_type(%res1) : (memref<8xf64, #tile>) -> (memref<16xf64, #tile>, memref<8xf64, #tile>) return %b, %a: memref<16xf64, #tile>, memref<8xf64, #tile> } // CHECK: %[[a:[0-9]+]] = alloc() : memref<2x4xf64> // CHECK: %[[b:[0-9]+]] = alloc() : memref<4x4xf64> // CHECK: %cst = constant 2.300000e+01 : f64 // CHECK: %[[resA:[0-9]+]]:2 = call @ret_single_argument_type(%[[a]]) : (memref<2x4xf64>) -> (memref<4x4xf64>, memref<2x4xf64>) // CHECK: %[[resB:[0-9]+]]:2 = call @ret_single_argument_type(%[[C]]) : (memref<2x4xf64>) -> (memref<4x4xf64>, memref<2x4xf64>) // CHECK: %[[resC:[0-9]+]]:2 = call @ret_multiple_argument_type(%[[b]], %cst, %[[a]]) : (memref<4x4xf64>, f64, memref<2x4xf64>) -> (memref<2x4xf64>, f64) // CHECK: %[[resD:[0-9]+]]:2 = call @ret_single_argument_type(%[[resC]]#0) : (memref<2x4xf64>) -> (memref<4x4xf64>, memref<2x4xf64>) // CHECK: return %{{.*}}, %{{.*}} : memref<4x4xf64>, memref<2x4xf64> // Test case set #5: To check normalization in a chain of interconnected functions. // CHECK-LABEL: func @func_A // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<2x4xf64>) func @func_A(%A: memref<8xf64, #tile>) { call @func_B(%A) : (memref<8xf64, #tile>) -> () return } // CHECK: call @func_B(%[[A]]) : (memref<2x4xf64>) -> () // CHECK-LABEL: func @func_B // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<2x4xf64>) func @func_B(%A: memref<8xf64, #tile>) { call @func_C(%A) : (memref<8xf64, #tile>) -> () return } // CHECK: call @func_C(%[[A]]) : (memref<2x4xf64>) -> () // CHECK-LABEL: func @func_C // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<2x4xf64>) func @func_C(%A: memref<8xf64, #tile>) { return } // Test case set #6: Checking if no normalization takes place in a scenario: A -> B -> C and B has an unsupported type. // CHECK-LABEL: func @some_func_A // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<8xf64, #map{{[0-9]+}}>) func @some_func_A(%A: memref<8xf64, #tile>) { call @some_func_B(%A) : (memref<8xf64, #tile>) -> () return } // CHECK: call @some_func_B(%[[A]]) : (memref<8xf64, #map{{[0-9]+}}>) -> () // CHECK-LABEL: func @some_func_B // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<8xf64, #map{{[0-9]+}}>) func @some_func_B(%A: memref<8xf64, #tile>) { "test.test"(%A) : (memref<8xf64, #tile>) -> () call @some_func_C(%A) : (memref<8xf64, #tile>) -> () return } // CHECK: call @some_func_C(%[[A]]) : (memref<8xf64, #map{{[0-9]+}}>) -> () // CHECK-LABEL: func @some_func_C // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<8xf64, #map{{[0-9]+}}>) func @some_func_C(%A: memref<8xf64, #tile>) { return } // Test case set #7: Check normalization in case of external functions. -// CHECK-LABEL: func @external_func_A +// CHECK-LABEL: func private @external_func_A // CHECK-SAME: (memref<4x4xf64>) -func @external_func_A(memref<16xf64, #tile>) -> () +func private @external_func_A(memref<16xf64, #tile>) -> () -// CHECK-LABEL: func @external_func_B +// CHECK-LABEL: func private @external_func_B // CHECK-SAME: (memref<4x4xf64>, f64) -> memref<2x4xf64> -func @external_func_B(memref<16xf64, #tile>, f64) -> (memref<8xf64, #tile>) +func private @external_func_B(memref<16xf64, #tile>, f64) -> (memref<8xf64, #tile>) // CHECK-LABEL: func @simply_call_external() func @simply_call_external() { %a = alloc() : memref<16xf64, #tile> call @external_func_A(%a) : (memref<16xf64, #tile>) -> () return } // CHECK: %[[a:[0-9]+]] = alloc() : memref<4x4xf64> // CHECK: call @external_func_A(%[[a]]) : (memref<4x4xf64>) -> () // CHECK-LABEL: func @use_value_of_external // CHECK-SAME: (%[[A:arg[0-9]+]]: memref<4x4xf64>, %[[B:arg[0-9]+]]: f64) -> memref<2x4xf64> func @use_value_of_external(%A: memref<16xf64, #tile>, %B: f64) -> (memref<8xf64, #tile>) { %res = call @external_func_B(%A, %B) : (memref<16xf64, #tile>, f64) -> (memref<8xf64, #tile>) return %res : memref<8xf64, #tile> } // CHECK: %[[res:[0-9]+]] = call @external_func_B(%[[A]], %[[B]]) : (memref<4x4xf64>, f64) -> memref<2x4xf64> // CHECK: return %{{.*}} : memref<2x4xf64> diff --git a/mlir/test/Transforms/sccp-callgraph.mlir b/mlir/test/Transforms/sccp-callgraph.mlir index 4b81fad9b3c7..58279e7ba329 100644 --- a/mlir/test/Transforms/sccp-callgraph.mlir +++ b/mlir/test/Transforms/sccp-callgraph.mlir @@ -1,257 +1,257 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -sccp -split-input-file | FileCheck %s // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="module(sccp)" -split-input-file | FileCheck %s --check-prefix=NESTED /// Check that a constant is properly propagated through the arguments and /// results of a private function. // CHECK-LABEL: func private @private( func private @private(%arg0 : i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 return %arg0 : i32 } // CHECK-LABEL: func @simple_private( func @simple_private() -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 %1 = constant 1 : i32 %result = call @private(%1) : (i32) -> i32 return %result : i32 } // ----- /// Check that a constant is properly propagated through the arguments and /// results of a visible nested function. // CHECK: func nested @nested( func nested @nested(%arg0 : i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 return %arg0 : i32 } // CHECK-LABEL: func @simple_nested( func @simple_nested() -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 %1 = constant 1 : i32 %result = call @nested(%1) : (i32) -> i32 return %result : i32 } // ----- /// Check that non-visible nested functions do not track arguments. module { // NESTED-LABEL: module @nested_module module @nested_module attributes { sym_visibility = "public" } { // NESTED: func nested @nested( func nested @nested(%arg0 : i32) -> (i32, i32) { // NESTED: %[[CST:.*]] = constant 1 : i32 // NESTED: return %[[CST]], %arg0 : i32, i32 %1 = constant 1 : i32 return %1, %arg0 : i32, i32 } // NESTED: func @nested_not_all_uses_visible( func @nested_not_all_uses_visible() -> (i32, i32) { // NESTED: %[[CST:.*]] = constant 1 : i32 // NESTED: %[[CALL:.*]]:2 = call @nested // NESTED: return %[[CST]], %[[CALL]]#1 : i32, i32 %1 = constant 1 : i32 %result:2 = call @nested(%1) : (i32) -> (i32, i32) return %result#0, %result#1 : i32, i32 } } } // ----- /// Check that public functions do not track arguments. // CHECK-LABEL: func @public( func @public(%arg0 : i32) -> (i32, i32) { %1 = constant 1 : i32 return %1, %arg0 : i32, i32 } // CHECK-LABEL: func @simple_public( func @simple_public() -> (i32, i32) { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: %[[CALL:.*]]:2 = call @public // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32 %1 = constant 1 : i32 %result:2 = call @public(%1) : (i32) -> (i32, i32) return %result#0, %result#1 : i32, i32 } // ----- /// Check that functions with non-call users don't have arguments tracked. func private @callable(%arg0 : i32) -> (i32, i32) { %1 = constant 1 : i32 return %1, %arg0 : i32, i32 } // CHECK-LABEL: func @non_call_users( func @non_call_users() -> (i32, i32) { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: %[[CALL:.*]]:2 = call @callable // CHECK: return %[[CST]], %[[CALL]]#1 : i32, i32 %1 = constant 1 : i32 %result:2 = call @callable(%1) : (i32) -> (i32, i32) return %result#0, %result#1 : i32, i32 } "live.user"() {uses = [@callable]} : () -> () // ----- /// Check that return values are overdefined in the presence of an unknown terminator. func private @callable(%arg0 : i32) -> i32 { "unknown.return"(%arg0) : (i32) -> () } // CHECK-LABEL: func @unknown_terminator( func @unknown_terminator() -> i32 { // CHECK: %[[CALL:.*]] = call @callable // CHECK: return %[[CALL]] : i32 %1 = constant 1 : i32 %result = call @callable(%1) : (i32) -> i32 return %result : i32 } // ----- /// Check that return values are overdefined when the constant conflicts. func private @callable(%arg0 : i32) -> i32 { "unknown.return"(%arg0) : (i32) -> () } // CHECK-LABEL: func @conflicting_constant( func @conflicting_constant() -> (i32, i32) { // CHECK: %[[CALL1:.*]] = call @callable // CHECK: %[[CALL2:.*]] = call @callable // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32 %1 = constant 1 : i32 %2 = constant 2 : i32 %result = call @callable(%1) : (i32) -> i32 %result2 = call @callable(%2) : (i32) -> i32 return %result, %result2 : i32, i32 } // ----- /// Check that return values are overdefined when the constant conflicts with a /// non-constant. func private @callable(%arg0 : i32) -> i32 { "unknown.return"(%arg0) : (i32) -> () } // CHECK-LABEL: func @conflicting_constant( func @conflicting_constant(%arg0 : i32) -> (i32, i32) { // CHECK: %[[CALL1:.*]] = call @callable // CHECK: %[[CALL2:.*]] = call @callable // CHECK: return %[[CALL1]], %[[CALL2]] : i32, i32 %1 = constant 1 : i32 %result = call @callable(%1) : (i32) -> i32 %result2 = call @callable(%arg0) : (i32) -> i32 return %result, %result2 : i32, i32 } // ----- /// Check a more complex interaction with calls and control flow. // CHECK-LABEL: func private @complex_inner_if( func private @complex_inner_if(%arg0 : i32) -> i32 { // CHECK-DAG: %[[TRUE:.*]] = constant true // CHECK-DAG: %[[CST:.*]] = constant 1 : i32 // CHECK: cond_br %[[TRUE]], ^bb1 %cst_20 = constant 20 : i32 %cond = cmpi "ult", %arg0, %cst_20 : i32 cond_br %cond, ^bb1, ^bb2 ^bb1: // CHECK: ^bb1: // CHECK: return %[[CST]] : i32 %cst_1 = constant 1 : i32 return %cst_1 : i32 ^bb2: %cst_1_2 = constant 1 : i32 %arg_inc = addi %arg0, %cst_1_2 : i32 return %arg_inc : i32 } -func @complex_cond() -> i1 +func private @complex_cond() -> i1 // CHECK-LABEL: func private @complex_callee( func private @complex_callee(%arg0 : i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 %loop_cond = call @complex_cond() : () -> i1 cond_br %loop_cond, ^bb1, ^bb2 ^bb1: // CHECK: ^bb1: // CHECK-NEXT: return %[[CST]] : i32 return %arg0 : i32 ^bb2: // CHECK: ^bb2: // CHECK: call @complex_inner_if(%[[CST]]) : (i32) -> i32 // CHECK: call @complex_callee(%[[CST]]) : (i32) -> i32 // CHECK: return %[[CST]] : i32 %updated_arg = call @complex_inner_if(%arg0) : (i32) -> i32 %res = call @complex_callee(%updated_arg) : (i32) -> i32 return %res : i32 } // CHECK-LABEL: func @complex_caller( func @complex_caller(%arg0 : i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 %1 = constant 1 : i32 %result = call @complex_callee(%1) : (i32) -> i32 return %result : i32 } // ----- /// Check that non-symbol defining callables currently go to overdefined. // CHECK-LABEL: func @non_symbol_defining_callable func @non_symbol_defining_callable() -> i32 { // CHECK: %[[RES:.*]] = call_indirect // CHECK: return %[[RES]] : i32 %fn = "test.functional_region_op"() ({ %1 = constant 1 : i32 "test.return"(%1) : (i32) -> () }) : () -> (() -> i32) %res = call_indirect %fn() : () -> (i32) return %res : i32 } diff --git a/mlir/test/Transforms/sccp.mlir b/mlir/test/Transforms/sccp.mlir index 43a6ff5357cc..382ea5e39921 100644 --- a/mlir/test/Transforms/sccp.mlir +++ b/mlir/test/Transforms/sccp.mlir @@ -1,180 +1,180 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="func(sccp)" -split-input-file | FileCheck %s /// Check simple forward constant propagation without any control flow. // CHECK-LABEL: func @no_control_flow func @no_control_flow(%arg0: i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 // CHECK: return %[[CST]] : i32 %cond = constant true %cst_1 = constant 1 : i32 %select = select %cond, %cst_1, %arg0 : i32 return %select : i32 } /// Check that a constant is properly propagated when only one edge of a branch /// is taken. // CHECK-LABEL: func @simple_control_flow func @simple_control_flow(%arg0 : i32) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 %cond = constant true %1 = constant 1 : i32 cond_br %cond, ^bb1, ^bb2(%arg0 : i32) ^bb1: br ^bb2(%1 : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%{{.*}}: i32): // CHECK: return %[[CST]] : i32 return %arg : i32 } /// Check that the arguments go to overdefined if the branch cannot detect when /// a specific successor is taken. // CHECK-LABEL: func @simple_control_flow_overdefined func @simple_control_flow_overdefined(%arg0 : i32, %arg1 : i1) -> i32 { %1 = constant 1 : i32 cond_br %arg1, ^bb1, ^bb2(%arg0 : i32) ^bb1: br ^bb2(%1 : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%[[ARG:.*]]: i32): // CHECK: return %[[ARG]] : i32 return %arg : i32 } /// Check that the arguments go to overdefined if there are conflicting /// constants. // CHECK-LABEL: func @simple_control_flow_constant_overdefined func @simple_control_flow_constant_overdefined(%arg0 : i32, %arg1 : i1) -> i32 { %1 = constant 1 : i32 %2 = constant 2 : i32 cond_br %arg1, ^bb1, ^bb2(%arg0 : i32) ^bb1: br ^bb2(%2 : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%[[ARG:.*]]: i32): // CHECK: return %[[ARG]] : i32 return %arg : i32 } /// Check that the arguments go to overdefined if the branch is unknown. // CHECK-LABEL: func @unknown_terminator func @unknown_terminator(%arg0 : i32, %arg1 : i1) -> i32 { %1 = constant 1 : i32 "foo.cond_br"() [^bb1, ^bb2] : () -> () ^bb1: br ^bb2(%1 : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%[[ARG:.*]]: i32): // CHECK: return %[[ARG]] : i32 return %arg : i32 } /// Check that arguments are properly merged across loop-like control flow. -func @ext_cond_fn() -> i1 +func private @ext_cond_fn() -> i1 // CHECK-LABEL: func @simple_loop func @simple_loop(%arg0 : i32, %cond1 : i1) -> i32 { // CHECK: %[[CST:.*]] = constant 1 : i32 %cst_1 = constant 1 : i32 cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32) ^bb1(%iv: i32): // CHECK: ^bb1(%{{.*}}: i32): // CHECK-NEXT: %[[COND:.*]] = call @ext_cond_fn() // CHECK-NEXT: cond_br %[[COND]], ^bb1(%[[CST]] : i32), ^bb2(%[[CST]] : i32) %cst_0 = constant 0 : i32 %res = addi %iv, %cst_0 : i32 %cond2 = call @ext_cond_fn() : () -> i1 cond_br %cond2, ^bb1(%res : i32), ^bb2(%res : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%{{.*}}: i32): // CHECK: return %[[CST]] : i32 return %arg : i32 } /// Test that we can properly propagate within inner control, and in situations /// where the executable edges within the CFG are sensitive to the current state /// of the analysis. // CHECK-LABEL: func @simple_loop_inner_control_flow func @simple_loop_inner_control_flow(%arg0 : i32) -> i32 { // CHECK-DAG: %[[CST:.*]] = constant 1 : i32 // CHECK-DAG: %[[TRUE:.*]] = constant true %cst_1 = constant 1 : i32 br ^bb1(%cst_1 : i32) ^bb1(%iv: i32): %cond2 = call @ext_cond_fn() : () -> i1 cond_br %cond2, ^bb5(%iv : i32), ^bb2 ^bb2: // CHECK: ^bb2: // CHECK: cond_br %[[TRUE]], ^bb3, ^bb4 %cst_20 = constant 20 : i32 %cond = cmpi "ult", %iv, %cst_20 : i32 cond_br %cond, ^bb3, ^bb4 ^bb3: // CHECK: ^bb3: // CHECK: br ^bb1(%[[CST]] : i32) %cst_1_2 = constant 1 : i32 br ^bb1(%cst_1_2 : i32) ^bb4: %iv_inc = addi %iv, %cst_1 : i32 br ^bb1(%iv_inc : i32) ^bb5(%result: i32): // CHECK: ^bb5(%{{.*}}: i32): // CHECK: return %[[CST]] : i32 return %result : i32 } /// Check that arguments go to overdefined when loop backedges produce a /// conflicting value. -func @ext_cond_and_value_fn() -> (i1, i32) +func private @ext_cond_and_value_fn() -> (i1, i32) // CHECK-LABEL: func @simple_loop_overdefined func @simple_loop_overdefined(%arg0 : i32, %cond1 : i1) -> i32 { %cst_1 = constant 1 : i32 cond_br %cond1, ^bb1(%cst_1 : i32), ^bb2(%cst_1 : i32) ^bb1(%iv: i32): %cond2, %res = call @ext_cond_and_value_fn() : () -> (i1, i32) cond_br %cond2, ^bb1(%res : i32), ^bb2(%res : i32) ^bb2(%arg : i32): // CHECK: ^bb2(%[[ARG:.*]]: i32): // CHECK: return %[[ARG]] : i32 return %arg : i32 } diff --git a/mlir/test/Transforms/test-convert-call-op.mlir b/mlir/test/Transforms/test-convert-call-op.mlir index d1a1d5c35812..ea6b6a1d2469 100644 --- a/mlir/test/Transforms/test-convert-call-op.mlir +++ b/mlir/test/Transforms/test-convert-call-op.mlir @@ -1,14 +1,14 @@ // RUN: mlir-opt %s -test-convert-call-op | FileCheck %s // CHECK-LABEL: llvm.func @callee(!llvm.ptr) -> !llvm.i32 -func @callee(!test.test_type) -> i32 +func private @callee(!test.test_type) -> i32 // CHECK-NEXT: llvm.func @caller() -> !llvm.i32 func @caller() -> i32 { %arg = "test.type_producer"() : () -> !test.test_type %out = call @callee(%arg) : (!test.test_type) -> i32 return %out : i32 } // CHECK-NEXT: [[ARG:%.*]] = llvm.mlir.null : !llvm.ptr // CHECK-NEXT: [[OUT:%.*]] = llvm.call @callee([[ARG]]) // CHECK-SAME: : (!llvm.ptr) -> !llvm.i32 diff --git a/mlir/test/Transforms/test-legalizer.mlir b/mlir/test/Transforms/test-legalizer.mlir index 3a04ebfcea6d..878d903bfa18 100644 --- a/mlir/test/Transforms/test-legalizer.mlir +++ b/mlir/test/Transforms/test-legalizer.mlir @@ -1,271 +1,271 @@ // RUN: mlir-opt -allow-unregistered-dialect -split-input-file -test-legalize-patterns -verify-diagnostics %s | FileCheck %s // CHECK-LABEL: verifyDirectPattern func @verifyDirectPattern() -> i32 { // CHECK-NEXT: "test.legal_op_a"() {status = "Success"} %result = "test.illegal_op_a"() : () -> (i32) // expected-remark@+1 {{op 'std.return' is not legalizable}} return %result : i32 } // CHECK-LABEL: verifyLargerBenefit func @verifyLargerBenefit() -> i32 { // CHECK-NEXT: "test.legal_op_a"() {status = "Success"} %result = "test.illegal_op_c"() : () -> (i32) // expected-remark@+1 {{op 'std.return' is not legalizable}} return %result : i32 } -// CHECK-LABEL: func @remap_input_1_to_0() -func @remap_input_1_to_0(i16) +// CHECK-LABEL: func private @remap_input_1_to_0() +func private @remap_input_1_to_0(i16) // CHECK-LABEL: func @remap_input_1_to_1(%arg0: f64) func @remap_input_1_to_1(%arg0: i64) { // CHECK-NEXT: "test.valid"{{.*}} : (f64) "test.invalid"(%arg0) : (i64) -> () } // CHECK-LABEL: func @remap_call_1_to_1(%arg0: f64) func @remap_call_1_to_1(%arg0: i64) { // CHECK-NEXT: call @remap_input_1_to_1(%arg0) : (f64) -> () // expected-remark@+1 {{op 'std.call' is not legalizable}} call @remap_input_1_to_1(%arg0) : (i64) -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: func @remap_input_1_to_N({{.*}}f16, {{.*}}f16) func @remap_input_1_to_N(%arg0: f32) -> f32 { // CHECK-NEXT: "test.return"{{.*}} : (f16, f16) -> () "test.return"(%arg0) : (f32) -> () } // CHECK-LABEL: func @remap_input_1_to_N_remaining_use(%arg0: f16, %arg1: f16) func @remap_input_1_to_N_remaining_use(%arg0: f32) { // CHECK-NEXT: [[CAST:%.*]] = "test.cast"(%arg0, %arg1) : (f16, f16) -> f32 // CHECK-NEXT: "work"([[CAST]]) : (f32) -> () // expected-remark@+1 {{op 'work' is not legalizable}} "work"(%arg0) : (f32) -> () } // CHECK-LABEL: func @remap_materialize_1_to_1(%{{.*}}: i43) func @remap_materialize_1_to_1(%arg0: i42) { // CHECK: %[[V:.*]] = "test.cast"(%arg0) : (i43) -> i42 // CHECK: "test.return"(%[[V]]) "test.return"(%arg0) : (i42) -> () } // CHECK-LABEL: func @remap_input_to_self func @remap_input_to_self(%arg0: index) { // CHECK-NOT: test.cast // CHECK: "work" // expected-remark@+1 {{op 'work' is not legalizable}} "work"(%arg0) : (index) -> () } // CHECK-LABEL: func @remap_multi(%arg0: f64, %arg1: f64) -> (f64, f64) func @remap_multi(%arg0: i64, %unused: i16, %arg1: i64) -> (i64, i64) { // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64) "test.invalid"(%arg0, %arg1) : (i64, i64) -> () } // CHECK-LABEL: func @no_remap_nested func @no_remap_nested() { // CHECK-NEXT: "foo.region" // expected-remark@+1 {{op 'foo.region' is not legalizable}} "foo.region"() ({ // CHECK-NEXT: ^bb0(%{{.*}}: i64, %{{.*}}: i16, %{{.*}}: i64): ^bb0(%i0: i64, %unused: i16, %i1: i64): // CHECK-NEXT: "test.valid"{{.*}} : (i64, i64) "test.invalid"(%i0, %i1) : (i64, i64) -> () }) : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: func @remap_moved_region_args func @remap_moved_region_args() { // CHECK-NEXT: return // CHECK-NEXT: ^bb1(%{{.*}}: f64, %{{.*}}: f64, %{{.*}}: f16, %{{.*}}: f16): // CHECK-NEXT: "test.cast"{{.*}} : (f16, f16) -> f32 // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64, f32) "test.region"() ({ ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32): "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> () }) : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: func @remap_cloned_region_args func @remap_cloned_region_args() { // CHECK-NEXT: return // CHECK-NEXT: ^bb1(%{{.*}}: f64, %{{.*}}: f64, %{{.*}}: f16, %{{.*}}: f16): // CHECK-NEXT: "test.cast"{{.*}} : (f16, f16) -> f32 // CHECK-NEXT: "test.valid"{{.*}} : (f64, f64, f32) "test.region"() ({ ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32): "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> () }) {legalizer.should_clone} : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: func @remap_drop_region func @remap_drop_region() { // CHECK-NEXT: return // CHECK-NEXT: } "test.drop_region_op"() ({ ^bb1(%i0: i64, %unused: i16, %i1: i64, %2: f32): "test.invalid"(%i0, %i1, %2) : (i64, i64, f32) -> () }) : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: func @dropped_input_in_use func @dropped_input_in_use(%arg: i16, %arg2: i64) { // CHECK-NEXT: "test.cast"{{.*}} : () -> i16 // CHECK-NEXT: "work"{{.*}} : (i16) // expected-remark@+1 {{op 'work' is not legalizable}} "work"(%arg) : (i16) -> () } // CHECK-LABEL: func @up_to_date_replacement func @up_to_date_replacement(%arg: i8) -> i8 { // CHECK-NEXT: return %repl_1 = "test.rewrite"(%arg) : (i8) -> i8 %repl_2 = "test.rewrite"(%repl_1) : (i8) -> i8 // expected-remark@+1 {{op 'std.return' is not legalizable}} return %repl_2 : i8 } // CHECK-LABEL: func @remove_foldable_op // CHECK-SAME: (%[[ARG_0:[a-z0-9]*]]: i32) func @remove_foldable_op(%arg0 : i32) -> (i32) { // CHECK-NEXT: return %[[ARG_0]] %0 = "test.op_with_region_fold"(%arg0) ({ "foo.op_with_region_terminator"() : () -> () }) : (i32) -> (i32) // expected-remark@+1 {{op 'std.return' is not legalizable}} return %0 : i32 } // CHECK-LABEL: @create_block func @create_block() { // Check that we created a block with arguments. // CHECK-NOT: test.create_block // CHECK: ^{{.*}}(%{{.*}}: i32, %{{.*}}: i32): "test.create_block"() : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // CHECK-LABEL: @bounded_recursion func @bounded_recursion() { // CHECK: test.recursive_rewrite 0 test.recursive_rewrite 3 // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // ----- func @fail_to_convert_illegal_op() -> i32 { // expected-error@+1 {{failed to legalize operation 'test.illegal_op_f'}} %result = "test.illegal_op_f"() : () -> (i32) return %result : i32 } // ----- func @fail_to_convert_illegal_op_in_region() { // expected-error@+1 {{failed to legalize operation 'test.region_builder'}} "test.region_builder"() : () -> () return } // ----- // Check that the entry block arguments of a region are untouched in the case // of failure. // CHECK-LABEL: func @fail_to_convert_region func @fail_to_convert_region() { // CHECK-NEXT: "test.region" // CHECK-NEXT: ^bb{{.*}}(%{{.*}}: i64): "test.region"() ({ ^bb1(%i0: i64): // expected-error@+1 {{failed to legalize operation 'test.region_builder'}} "test.region_builder"() : () -> () "test.valid"() : () -> () }) : () -> () return } // ----- // CHECK-LABEL: @create_illegal_block func @create_illegal_block() { // Check that we can undo block creation, i.e. that the block was removed. // CHECK: test.create_illegal_block // CHECK-NOT: ^{{.*}}(%{{.*}}: i32, %{{.*}}: i32): // expected-remark@+1 {{op 'test.create_illegal_block' is not legalizable}} "test.create_illegal_block"() : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // ----- // CHECK-LABEL: @undo_block_arg_replace func @undo_block_arg_replace() { // expected-remark@+1 {{op 'test.undo_block_arg_replace' is not legalizable}} "test.undo_block_arg_replace"() ({ ^bb0(%arg0: i32): // CHECK: ^bb0(%[[ARG:.*]]: i32): // CHECK-NEXT: "test.return"(%[[ARG]]) : (i32) "test.return"(%arg0) : (i32) -> () }) : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } // ----- // The op in this function is rewritten to itself (and thus remains illegal) by // a pattern that removes its second block after adding an operation into it. // Check that we can undo block removal successfully. // CHECK-LABEL: @undo_block_erase func @undo_block_erase() { // CHECK: test.undo_block_erase "test.undo_block_erase"() ({ // expected-remark@-1 {{not legalizable}} // CHECK: "unregistered.return"()[^[[BB:.*]]] "unregistered.return"()[^bb1] : () -> () // expected-remark@-1 {{not legalizable}} // CHECK: ^[[BB]] ^bb1: // CHECK: unregistered.return "unregistered.return"() : () -> () // expected-remark@-1 {{not legalizable}} }) : () -> () } // ----- // The op in this function is attempted to be rewritten to another illegal op // with an attached region containing an invalid terminator. The terminator is // created before the parent op. The deletion should not crash when deleting // created ops in the inverse order, i.e. deleting the parent op and then the // child op. // CHECK-LABEL: @undo_child_created_before_parent func @undo_child_created_before_parent() { // expected-remark@+1 {{is not legalizable}} "test.illegal_op_with_region_anchor"() : () -> () // expected-remark@+1 {{op 'std.return' is not legalizable}} return } diff --git a/mlir/test/Transforms/test-symbol-dce.mlir b/mlir/test/Transforms/test-symbol-dce.mlir index 08b87ff4ae9f..e2d6ee124146 100644 --- a/mlir/test/Transforms/test-symbol-dce.mlir +++ b/mlir/test/Transforms/test-symbol-dce.mlir @@ -1,93 +1,90 @@ // RUN: mlir-opt -allow-unregistered-dialect %s -symbol-dce -split-input-file -verify-diagnostics | FileCheck %s // RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline="module(symbol-dce)" -split-input-file | FileCheck %s --check-prefix=NESTED // Check that trivially dead and trivially live non-nested cases are handled. // CHECK-LABEL: module attributes {test.simple} module attributes {test.simple} { // CHECK-NOT: func private @dead_private_function func private @dead_private_function() // CHECK-NOT: func nested @dead_nested_function func nested @dead_nested_function() // CHECK: func private @live_private_function func private @live_private_function() // CHECK: func nested @live_nested_function func nested @live_nested_function() // CHECK: func @public_function func @public_function() { "foo.return"() {uses = [@live_private_function, @live_nested_function]} : () -> () } - - // CHECK: func public @public_function_explicit - func public @public_function_explicit() } // ----- // Check that we don't DCE nested symbols if they are used. // CHECK-LABEL: module attributes {test.nested} module attributes {test.nested} { // CHECK: module @public_module module @public_module { // CHECK-NOT: func nested @dead_nested_function func nested @dead_nested_function() // CHECK: func private @private_function func private @private_function() // CHECK: func nested @nested_function func nested @nested_function() { "foo.return"() {uses = [@private_function]} : () -> () } } "live.user"() {uses = [@public_module::@nested_function]} : () -> () } // ----- // Check that we don't DCE symbols if we can't prove that the top-level symbol // table that we are running on is hidden from above. // NESTED-LABEL: module attributes {test.no_dce_non_hidden_parent} module attributes {test.no_dce_non_hidden_parent} { // NESTED: module @public_module module @public_module { // NESTED: func nested @nested_function func nested @nested_function() } // NESTED: module @nested_module module @nested_module attributes { sym_visibility = "nested" } { // NESTED: func nested @nested_function func nested @nested_function() } // Only private modules can be assumed to be hidden. // NESTED: module @private_module module @private_module attributes { sym_visibility = "private" } { // NESTED-NOT: func nested @nested_function func nested @nested_function() } "live.user"() {uses = [@nested_module, @private_module]} : () -> () } // ----- module { func private @private_symbol() // expected-error@+1 {{contains potentially unknown symbol table}} "foo.possibly_unknown_symbol_table"() ({ }) : () -> () } // ----- module { // expected-error@+1 {{unable to resolve reference to symbol}} "live.user"() {uses = [@unknown_symbol]} : () -> () } diff --git a/mlir/test/mlir-cpu-runner/async-group.mlir b/mlir/test/mlir-cpu-runner/async-group.mlir index 0ae378b45be1..87004ff7b381 100644 --- a/mlir/test/mlir-cpu-runner/async-group.mlir +++ b/mlir/test/mlir-cpu-runner/async-group.mlir @@ -1,40 +1,40 @@ // RUN: mlir-opt %s -convert-async-to-llvm \ // RUN: -convert-std-to-llvm \ // RUN: | mlir-cpu-runner \ // RUN: -e main -entry-point-result=void -O0 \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ // RUN: | FileCheck %s func @main() { %group = async.create_group %token0 = async.execute { async.yield } %token1 = async.execute { async.yield } %token2 = async.execute { async.yield } %token3 = async.execute { async.yield } %token4 = async.execute { async.yield } %0 = async.add_to_group %token0, %group : !async.token %1 = async.add_to_group %token1, %group : !async.token %2 = async.add_to_group %token2, %group : !async.token %3 = async.add_to_group %token3, %group : !async.token %4 = async.add_to_group %token4, %group : !async.token %token5 = async.execute { async.await_all %group async.yield } %group0 = async.create_group %5 = async.add_to_group %token5, %group0 : !async.token async.await_all %group0 // CHECK: Current thread id: [[THREAD:.*]] call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () return } -func @mlirAsyncRuntimePrintCurrentThreadId() -> () +func private @mlirAsyncRuntimePrintCurrentThreadId() -> () diff --git a/mlir/test/mlir-cpu-runner/async.mlir b/mlir/test/mlir-cpu-runner/async.mlir index 9ec4de98cc6b..fd0268e7ac56 100644 --- a/mlir/test/mlir-cpu-runner/async.mlir +++ b/mlir/test/mlir-cpu-runner/async.mlir @@ -1,84 +1,84 @@ // RUN: mlir-opt %s -convert-async-to-llvm \ // RUN: -convert-linalg-to-loops \ // RUN: -convert-linalg-to-llvm \ // RUN: -convert-std-to-llvm \ // RUN: | mlir-cpu-runner \ // RUN: -e main -entry-point-result=void -O0 \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext \ // RUN: -shared-libs=%linalg_test_lib_dir/libmlir_async_runtime%shlibext \ // RUN: | FileCheck %s func @main() { %i0 = constant 0 : index %i1 = constant 1 : index %i2 = constant 2 : index %i3 = constant 3 : index %c0 = constant 0.0 : f32 %c1 = constant 1.0 : f32 %c2 = constant 2.0 : f32 %c3 = constant 3.0 : f32 %c4 = constant 4.0 : f32 %A = alloc() : memref<4xf32> linalg.fill(%A, %c0) : memref<4xf32>, f32 // CHECK: [0, 0, 0, 0] %U = memref_cast %A : memref<4xf32> to memref<*xf32> call @print_memref_f32(%U): (memref<*xf32>) -> () // CHECK: Current thread id: [[MAIN:.*]] // CHECK: [1, 0, 0, 0] store %c1, %A[%i0]: memref<4xf32> call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () call @print_memref_f32(%U): (memref<*xf32>) -> () %outer = async.execute { // CHECK: Current thread id: [[THREAD0:.*]] // CHECK: [1, 2, 0, 0] store %c2, %A[%i1]: memref<4xf32> call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () call @print_memref_f32(%U): (memref<*xf32>) -> () // No op async region to create a token for testing async dependency. %noop = async.execute { // CHECK: Current thread id: [[THREAD1:.*]] call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () async.yield } %inner = async.execute [%noop] { // CHECK: Current thread id: [[THREAD2:.*]] // CHECK: [1, 2, 3, 0] store %c3, %A[%i2]: memref<4xf32> call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () call @print_memref_f32(%U): (memref<*xf32>) -> () async.yield } async.await %inner : !async.token // CHECK: Current thread id: [[THREAD3:.*]] // CHECK: [1, 2, 3, 4] store %c4, %A[%i3]: memref<4xf32> call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () call @print_memref_f32(%U): (memref<*xf32>) -> () async.yield } async.await %outer : !async.token // CHECK: Current thread id: [[MAIN]] // CHECK: [1, 2, 3, 4] call @mlirAsyncRuntimePrintCurrentThreadId(): () -> () call @print_memref_f32(%U): (memref<*xf32>) -> () dealloc %A : memref<4xf32> return } -func @mlirAsyncRuntimePrintCurrentThreadId() -> () +func private @mlirAsyncRuntimePrintCurrentThreadId() -> () -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } diff --git a/mlir/test/mlir-cpu-runner/bare_ptr_call_conv.mlir b/mlir/test/mlir-cpu-runner/bare_ptr_call_conv.mlir index 6dc8b5576251..9934083fb11a 100644 --- a/mlir/test/mlir-cpu-runner/bare_ptr_call_conv.mlir +++ b/mlir/test/mlir-cpu-runner/bare_ptr_call_conv.mlir @@ -1,68 +1,68 @@ // RUN: mlir-opt %s -convert-scf-to-std -convert-std-to-llvm='use-bare-ptr-memref-call-conv=1' | mlir-cpu-runner -shared-libs=%linalg_test_lib_dir/libmlir_c_runner_utils%shlibext -entry-point-result=void | FileCheck %s // Verify bare pointer memref calling convention. `simple_add1_add2_test` // gets two 2xf32 memrefs, adds 1.0f to the first one and 2.0f to the second // one. 'main' calls 'simple_add1_add2_test' with {1, 1} and {2, 2} so {2, 2} // and {4, 4} are the expected outputs. func @simple_add1_add2_test(%arg0: memref<2xf32>, %arg1: memref<2xf32>) { %c2 = constant 2 : index %c0 = constant 0 : index %c1 = constant 1 : index %cst = constant 1.000000e+00 : f32 %cst_0 = constant 2.000000e+00 : f32 scf.for %arg2 = %c0 to %c2 step %c1 { %0 = load %arg0[%arg2] : memref<2xf32> %1 = addf %0, %cst : f32 store %1, %arg0[%arg2] : memref<2xf32> // CHECK: 2, 2 %2 = load %arg1[%arg2] : memref<2xf32> %3 = addf %1, %cst_0 : f32 store %3, %arg1[%arg2] : memref<2xf32> // CHECK-NEXT: 4, 4 } return } // External declarations. llvm.func @malloc(!llvm.i64) -> !llvm.ptr llvm.func @free(!llvm.ptr) -func @printF32(%arg0: f32) -func @printComma() -func @printNewline() +func private @printF32(%arg0: f32) +func private @printComma() +func private @printNewline() func @main() { %c2 = constant 2 : index %c0 = constant 0 : index %c1 = constant 1 : index %cst = constant 1.000000e+00 : f32 %cst_0 = constant 2.000000e+00 : f32 %a = alloc() : memref<2xf32> %b = alloc() : memref<2xf32> scf.for %i = %c0 to %c2 step %c1 { store %cst, %a[%i] : memref<2xf32> store %cst, %b[%i] : memref<2xf32> } call @simple_add1_add2_test(%a, %b) : (memref<2xf32>, memref<2xf32>) -> () %l0 = load %a[%c0] : memref<2xf32> call @printF32(%l0) : (f32) -> () call @printComma() : () -> () %l1 = load %a[%c1] : memref<2xf32> call @printF32(%l1) : (f32) -> () call @printNewline() : () -> () %l2 = load %b[%c0] : memref<2xf32> call @printF32(%l2) : (f32) -> () call @printComma() : () -> () %l3 = load %b[%c1] : memref<2xf32> call @printF32(%l3) : (f32) -> () call @printNewline() : () -> () dealloc %a : memref<2xf32> dealloc %b : memref<2xf32> return } diff --git a/mlir/test/mlir-cpu-runner/global_memref.mlir b/mlir/test/mlir-cpu-runner/global_memref.mlir index 1c9cf4a33aeb..5dbd75a62a50 100644 --- a/mlir/test/mlir-cpu-runner/global_memref.mlir +++ b/mlir/test/mlir-cpu-runner/global_memref.mlir @@ -1,107 +1,107 @@ // RUN: mlir-opt %s -convert-std-to-llvm | mlir-cpu-runner -e main -entry-point-result=void -shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%mlir_runner_utils_dir/libmlir_c_runner_utils%shlibext | FileCheck %s -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } -func @print_memref_i32(memref<*xi32>) attributes { llvm.emit_c_interface } -func @printNewline() -> () +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_i32(memref<*xi32>) attributes { llvm.emit_c_interface } +func private @printNewline() -> () global_memref "private" @gv0 : memref<4xf32> = dense<[0.0, 1.0, 2.0, 3.0]> func @test1DMemref() { %0 = get_global_memref @gv0 : memref<4xf32> %U = memref_cast %0 : memref<4xf32> to memref<*xf32> // CHECK: rank = 1 // CHECK: offset = 0 // CHECK: sizes = [4] // CHECK: strides = [1] // CHECK: [0, 1, 2, 3] call @print_memref_f32(%U) : (memref<*xf32>) -> () call @printNewline() : () -> () // Overwrite some of the elements. %c0 = constant 0 : index %c2 = constant 2 : index %fp0 = constant 4.0 : f32 %fp1 = constant 5.0 : f32 store %fp0, %0[%c0] : memref<4xf32> store %fp1, %0[%c2] : memref<4xf32> // CHECK: rank = 1 // CHECK: offset = 0 // CHECK: sizes = [4] // CHECK: strides = [1] // CHECK: [4, 1, 5, 3] call @print_memref_f32(%U) : (memref<*xf32>) -> () call @printNewline() : () -> () return } global_memref constant @gv1 : memref<3x2xi32> = dense<[[0, 1],[2, 3],[4, 5]]> func @testConstantMemref() { %0 = get_global_memref @gv1 : memref<3x2xi32> %U = memref_cast %0 : memref<3x2xi32> to memref<*xi32> // CHECK: rank = 2 // CHECK: offset = 0 // CHECK: sizes = [3, 2] // CHECK: strides = [2, 1] // CHECK: [0, 1] // CHECK: [2, 3] // CHECK: [4, 5] call @print_memref_i32(%U) : (memref<*xi32>) -> () call @printNewline() : () -> () return } global_memref "private" @gv2 : memref<4x2xf32> = dense<[[0.0, 1.0], [2.0, 3.0], [4.0, 5.0], [6.0, 7.0]]> func @test2DMemref() { %0 = get_global_memref @gv2 : memref<4x2xf32> %U = memref_cast %0 : memref<4x2xf32> to memref<*xf32> // CHECK: rank = 2 // CHECK: offset = 0 // CHECK: sizes = [4, 2] // CHECK: strides = [2, 1] // CHECK: [0, 1] // CHECK: [2, 3] // CHECK: [4, 5] // CHECK: [6, 7] call @print_memref_f32(%U) : (memref<*xf32>) -> () call @printNewline() : () -> () // Overwrite the 1.0 (at index [0, 1]) with 10.0 %c0 = constant 0 : index %c1 = constant 1 : index %fp10 = constant 10.0 : f32 store %fp10, %0[%c0, %c1] : memref<4x2xf32> // CHECK: rank = 2 // CHECK: offset = 0 // CHECK: sizes = [4, 2] // CHECK: strides = [2, 1] // CHECK: [0, 10] // CHECK: [2, 3] // CHECK: [4, 5] // CHECK: [6, 7] call @print_memref_f32(%U) : (memref<*xf32>) -> () call @printNewline() : () -> () return } global_memref @gv3 : memref = dense<11> func @testScalarMemref() { %0 = get_global_memref @gv3 : memref %U = memref_cast %0 : memref to memref<*xi32> // CHECK: rank = 0 // CHECK: offset = 0 // CHECK: sizes = [] // CHECK: strides = [] // CHECK: [11] call @print_memref_i32(%U) : (memref<*xi32>) -> () call @printNewline() : () -> () return } func @main() -> () { call @test1DMemref() : () -> () call @testConstantMemref() : () -> () call @test2DMemref() : () -> () call @testScalarMemref() : () -> () return } diff --git a/mlir/test/mlir-cpu-runner/memref_reinterpret_cast.mlir b/mlir/test/mlir-cpu-runner/memref_reinterpret_cast.mlir index 4f933a7784cb..62a252988c96 100644 --- a/mlir/test/mlir-cpu-runner/memref_reinterpret_cast.mlir +++ b/mlir/test/mlir-cpu-runner/memref_reinterpret_cast.mlir @@ -1,105 +1,105 @@ // RUN: mlir-opt %s -convert-scf-to-std -convert-std-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%mlir_runner_utils_dir/libmlir_c_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } func @main() -> () { %c0 = constant 0 : index %c1 = constant 1 : index // Initialize input. %input = alloc() : memref<2x3xf32> %dim_x = dim %input, %c0 : memref<2x3xf32> %dim_y = dim %input, %c1 : memref<2x3xf32> scf.parallel (%i, %j) = (%c0, %c0) to (%dim_x, %dim_y) step (%c1, %c1) { %prod = muli %i, %dim_y : index %val = addi %prod, %j : index %val_i64 = index_cast %val : index to i64 %val_f32 = sitofp %val_i64 : i64 to f32 store %val_f32, %input[%i, %j] : memref<2x3xf32> } %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> call @print_memref_f32(%unranked_input) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [2, 3] strides = [3, 1] // CHECK-NEXT: [0, 1, 2] // CHECK-NEXT: [3, 4, 5] // Test cases. call @cast_ranked_memref_to_static_shape(%input) : (memref<2x3xf32>) -> () call @cast_ranked_memref_to_dynamic_shape(%input) : (memref<2x3xf32>) -> () call @cast_unranked_memref_to_static_shape(%input) : (memref<2x3xf32>) -> () call @cast_unranked_memref_to_dynamic_shape(%input) : (memref<2x3xf32>) -> () return } func @cast_ranked_memref_to_static_shape(%input : memref<2x3xf32>) { %output = memref_reinterpret_cast %input to offset: [0], sizes: [6, 1], strides: [1, 1] : memref<2x3xf32> to memref<6x1xf32> %unranked_output = memref_cast %output : memref<6x1xf32> to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [6, 1] strides = [1, 1] data = // CHECK-NEXT: [0], // CHECK-NEXT: [1], // CHECK-NEXT: [2], // CHECK-NEXT: [3], // CHECK-NEXT: [4], // CHECK-NEXT: [5] return } func @cast_ranked_memref_to_dynamic_shape(%input : memref<2x3xf32>) { %c0 = constant 0 : index %c1 = constant 1 : index %c6 = constant 6 : index %output = memref_reinterpret_cast %input to offset: [%c0], sizes: [%c1, %c6], strides: [%c6, %c1] : memref<2x3xf32> to memref %unranked_output = memref_cast %output : memref to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [1, 6] strides = [6, 1] data = // CHECK-NEXT: [0, 1, 2, 3, 4, 5] return } func @cast_unranked_memref_to_static_shape(%input : memref<2x3xf32>) { %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> %output = memref_reinterpret_cast %unranked_input to offset: [0], sizes: [6, 1], strides: [1, 1] : memref<*xf32> to memref<6x1xf32> %unranked_output = memref_cast %output : memref<6x1xf32> to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [6, 1] strides = [1, 1] data = // CHECK-NEXT: [0], // CHECK-NEXT: [1], // CHECK-NEXT: [2], // CHECK-NEXT: [3], // CHECK-NEXT: [4], // CHECK-NEXT: [5] return } func @cast_unranked_memref_to_dynamic_shape(%input : memref<2x3xf32>) { %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> %c0 = constant 0 : index %c1 = constant 1 : index %c6 = constant 6 : index %output = memref_reinterpret_cast %unranked_input to offset: [%c0], sizes: [%c1, %c6], strides: [%c6, %c1] : memref<*xf32> to memref %unranked_output = memref_cast %output : memref to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [1, 6] strides = [6, 1] data = // CHECK-NEXT: [0, 1, 2, 3, 4, 5] return } diff --git a/mlir/test/mlir-cpu-runner/memref_reshape.mlir b/mlir/test/mlir-cpu-runner/memref_reshape.mlir index 7832a82595e7..aa031802350c 100644 --- a/mlir/test/mlir-cpu-runner/memref_reshape.mlir +++ b/mlir/test/mlir-cpu-runner/memref_reshape.mlir @@ -1,105 +1,105 @@ // RUN: mlir-opt %s -convert-scf-to-std -std-expand -convert-std-to-llvm \ // RUN: | mlir-cpu-runner -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%mlir_runner_utils_dir/libmlir_c_runner_utils%shlibext \ // RUN: | FileCheck %s -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } func @main() -> () { %c0 = constant 0 : index %c1 = constant 1 : index // Initialize input. %input = alloc() : memref<2x3xf32> %dim_x = dim %input, %c0 : memref<2x3xf32> %dim_y = dim %input, %c1 : memref<2x3xf32> scf.parallel (%i, %j) = (%c0, %c0) to (%dim_x, %dim_y) step (%c1, %c1) { %prod = muli %i, %dim_y : index %val = addi %prod, %j : index %val_i64 = index_cast %val : index to i64 %val_f32 = sitofp %val_i64 : i64 to f32 store %val_f32, %input[%i, %j] : memref<2x3xf32> } %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> call @print_memref_f32(%unranked_input) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [2, 3] strides = [3, 1] // CHECK-NEXT: [0, 1, 2] // CHECK-NEXT: [3, 4, 5] // Initialize shape. %shape = alloc() : memref<2xindex> %c2 = constant 2 : index %c3 = constant 3 : index store %c3, %shape[%c0] : memref<2xindex> store %c2, %shape[%c1] : memref<2xindex> // Test cases. call @reshape_ranked_memref_to_ranked(%input, %shape) : (memref<2x3xf32>, memref<2xindex>) -> () call @reshape_unranked_memref_to_ranked(%input, %shape) : (memref<2x3xf32>, memref<2xindex>) -> () call @reshape_ranked_memref_to_unranked(%input, %shape) : (memref<2x3xf32>, memref<2xindex>) -> () call @reshape_unranked_memref_to_unranked(%input, %shape) : (memref<2x3xf32>, memref<2xindex>) -> () return } func @reshape_ranked_memref_to_ranked(%input : memref<2x3xf32>, %shape : memref<2xindex>) { %output = memref_reshape %input(%shape) : (memref<2x3xf32>, memref<2xindex>) -> memref %unranked_output = memref_cast %output : memref to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [3, 2] strides = [2, 1] data = // CHECK: [0, 1], // CHECK: [2, 3], // CHECK: [4, 5] return } func @reshape_unranked_memref_to_ranked(%input : memref<2x3xf32>, %shape : memref<2xindex>) { %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> %output = memref_reshape %input(%shape) : (memref<2x3xf32>, memref<2xindex>) -> memref %unranked_output = memref_cast %output : memref to memref<*xf32> call @print_memref_f32(%unranked_output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [3, 2] strides = [2, 1] data = // CHECK: [0, 1], // CHECK: [2, 3], // CHECK: [4, 5] return } func @reshape_ranked_memref_to_unranked(%input : memref<2x3xf32>, %shape : memref<2xindex>) { %dyn_size_shape = memref_cast %shape : memref<2xindex> to memref %output = memref_reshape %input(%dyn_size_shape) : (memref<2x3xf32>, memref) -> memref<*xf32> call @print_memref_f32(%output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [3, 2] strides = [2, 1] data = // CHECK: [0, 1], // CHECK: [2, 3], // CHECK: [4, 5] return } func @reshape_unranked_memref_to_unranked(%input : memref<2x3xf32>, %shape : memref<2xindex>) { %unranked_input = memref_cast %input : memref<2x3xf32> to memref<*xf32> %dyn_size_shape = memref_cast %shape : memref<2xindex> to memref %output = memref_reshape %input(%dyn_size_shape) : (memref<2x3xf32>, memref) -> memref<*xf32> call @print_memref_f32(%output) : (memref<*xf32>) -> () // CHECK: rank = 2 offset = 0 sizes = [3, 2] strides = [2, 1] data = // CHECK: [0, 1], // CHECK: [2, 3], // CHECK: [4, 5] return } diff --git a/mlir/test/mlir-cpu-runner/sgemm_naive_codegen.mlir b/mlir/test/mlir-cpu-runner/sgemm_naive_codegen.mlir index c6eab3d9b984..742a2385f002 100644 --- a/mlir/test/mlir-cpu-runner/sgemm_naive_codegen.mlir +++ b/mlir/test/mlir-cpu-runner/sgemm_naive_codegen.mlir @@ -1,74 +1,74 @@ // RUN: mlir-opt -convert-linalg-to-loops -lower-affine -convert-scf-to-std -convert-std-to-llvm %s | mlir-cpu-runner -O3 -e main -entry-point-result=void -shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext | FileCheck %s func @main() { %A = alloc() : memref<16x16xf32> %B = alloc() : memref<16x16xf32> %C = alloc() : memref<16x16xf32> %cf1 = constant 1.00000e+00 : f32 linalg.fill(%A, %cf1) : memref<16x16xf32>, f32 linalg.fill(%B, %cf1) : memref<16x16xf32>, f32 %reps = constant 1 : index %t_start = call @rtclock() : () -> f64 affine.for %arg0 = 0 to 5 { linalg.fill(%C, %cf1) : memref<16x16xf32>, f32 call @sgemm_naive(%A, %B, %C) : (memref<16x16xf32>, memref<16x16xf32>, memref<16x16xf32>) -> () } %t_end = call @rtclock() : () -> f64 %t = subf %t_end, %t_start : f64 %pC = memref_cast %C : memref<16x16xf32> to memref<*xf32> call @print_memref_f32(%pC) : (memref<*xf32>) -> () %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %M = dim %C, %c0 : memref<16x16xf32> %N = dim %C, %c1 : memref<16x16xf32> %K = dim %A, %c1 : memref<16x16xf32> %f1 = muli %M, %N : index %f2 = muli %f1, %K : index // 2*M*N*K. %f3 = muli %c2, %f2 : index %num_flops = muli %reps, %f3 : index %num_flops_i = index_cast %num_flops : index to i16 %num_flops_f = sitofp %num_flops_i : i16 to f64 %flops = divf %num_flops_f, %t : f64 call @print_flops(%flops) : (f64) -> () return } // CHECK: 17, 17, 17, func @sgemm_naive(%arg0: memref<16x16xf32>, %arg1: memref<16x16xf32>, %arg2: memref<16x16xf32>) { %c0 = constant 0 : index affine.for %arg3 = 0 to 16 { affine.for %arg4 = 0 to 16 { %m = alloc() : memref<1xf32> %v = affine.load %arg2[%arg3, %arg4] : memref<16x16xf32> affine.store %v, %m[%c0] : memref<1xf32> affine.for %arg5 = 0 to 16 { %3 = affine.load %arg0[%arg3, %arg5] : memref<16x16xf32> %4 = affine.load %arg1[%arg5, %arg4] : memref<16x16xf32> %5 = affine.load %m[0] : memref<1xf32> %6 = mulf %3, %4 : f32 %7 = addf %6, %5 : f32 affine.store %7, %m[0] : memref<1xf32> } %s = affine.load %m[%c0] : memref<1xf32> affine.store %s, %arg2[%arg3, %arg4] : memref<16x16xf32> dealloc %m : memref<1xf32> } } return } -func @print_flops(f64) -func @rtclock() -> f64 -func @print_memref_f32(memref<*xf32>) +func private @print_flops(f64) +func private @rtclock() -> f64 +func private @print_memref_f32(memref<*xf32>) diff --git a/mlir/test/mlir-cpu-runner/unranked_memref.mlir b/mlir/test/mlir-cpu-runner/unranked_memref.mlir index c950bfd3547c..eecce9d37603 100644 --- a/mlir/test/mlir-cpu-runner/unranked_memref.mlir +++ b/mlir/test/mlir-cpu-runner/unranked_memref.mlir @@ -1,125 +1,125 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | mlir-cpu-runner -e main -entry-point-result=void -shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%mlir_runner_utils_dir/libmlir_c_runner_utils%shlibext | FileCheck %s // CHECK: rank = 2 // CHECK-SAME: sizes = [10, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-10: [10, 10, 10] // // CHECK: rank = 2 // CHECK-SAME: sizes = [10, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-10: [5, 5, 5] // // CHECK: rank = 2 // CHECK-SAME: sizes = [10, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-10: [2, 2, 2] // // CHECK: rank = 0 // 122 is ASCII for 'z'. // CHECK: [z] // // CHECK: rank = 2 // CHECK-SAME: sizes = [4, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-4: [1, 1, 1] // // CHECK: rank = 2 // CHECK-SAME: sizes = [4, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-4: [1, 1, 1] // // CHECK: rank = 2 // CHECK-SAME: sizes = [4, 3] // CHECK-SAME: strides = [3, 1] // CHECK-COUNT-4: [1, 1, 1] func @main() -> () { %A = alloc() : memref<10x3xf32, 0> %f2 = constant 2.00000e+00 : f32 %f5 = constant 5.00000e+00 : f32 %f10 = constant 10.00000e+00 : f32 %V = memref_cast %A : memref<10x3xf32, 0> to memref linalg.fill(%V, %f10) : memref, f32 %U = memref_cast %A : memref<10x3xf32, 0> to memref<*xf32> call @print_memref_f32(%U) : (memref<*xf32>) -> () %V2 = memref_cast %U : memref<*xf32> to memref linalg.fill(%V2, %f5) : memref, f32 %U2 = memref_cast %V2 : memref to memref<*xf32> call @print_memref_f32(%U2) : (memref<*xf32>) -> () %V3 = memref_cast %V2 : memref to memref<*xf32> %V4 = memref_cast %V3 : memref<*xf32> to memref linalg.fill(%V4, %f2) : memref, f32 %U3 = memref_cast %V2 : memref to memref<*xf32> call @print_memref_f32(%U3) : (memref<*xf32>) -> () // 122 is ASCII for 'z'. %i8_z = constant 122 : i8 %I8 = alloc() : memref store %i8_z, %I8[]: memref %U4 = memref_cast %I8 : memref to memref<*xi8> call @print_memref_i8(%U4) : (memref<*xi8>) -> () dealloc %A : memref<10x3xf32, 0> call @return_var_memref_caller() : () -> () call @return_two_var_memref_caller() : () -> () call @dim_op_of_unranked() : () -> () return } -func @print_memref_i8(memref<*xi8>) attributes { llvm.emit_c_interface } -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_i8(memref<*xi8>) attributes { llvm.emit_c_interface } +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } func @return_two_var_memref_caller() { %0 = alloca() : memref<4x3xf32> %c0f32 = constant 1.0 : f32 linalg.fill(%0, %c0f32) : memref<4x3xf32>, f32 %1:2 = call @return_two_var_memref(%0) : (memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) call @print_memref_f32(%1#0) : (memref<*xf32>) -> () call @print_memref_f32(%1#1) : (memref<*xf32>) -> () return } func @return_two_var_memref(%arg0: memref<4x3xf32>) -> (memref<*xf32>, memref<*xf32>) { %0 = memref_cast %arg0 : memref<4x3xf32> to memref<*xf32> return %0, %0 : memref<*xf32>, memref<*xf32> } func @return_var_memref_caller() { %0 = alloca() : memref<4x3xf32> %c0f32 = constant 1.0 : f32 linalg.fill(%0, %c0f32) : memref<4x3xf32>, f32 %1 = call @return_var_memref(%0) : (memref<4x3xf32>) -> memref<*xf32> call @print_memref_f32(%1) : (memref<*xf32>) -> () return } func @return_var_memref(%arg0: memref<4x3xf32>) -> memref<*xf32> { %0 = memref_cast %arg0: memref<4x3xf32> to memref<*xf32> return %0 : memref<*xf32> } -func @printU64(index) -> () -func @printNewline() -> () +func private @printU64(index) -> () +func private @printNewline() -> () func @dim_op_of_unranked() { %ranked = alloc() : memref<4x3xf32> %unranked = memref_cast %ranked: memref<4x3xf32> to memref<*xf32> %c0 = constant 0 : index %dim_0 = dim %unranked, %c0 : memref<*xf32> call @printU64(%dim_0) : (index) -> () call @printNewline() : () -> () // CHECK: 4 %c1 = constant 1 : index %dim_1 = dim %unranked, %c1 : memref<*xf32> call @printU64(%dim_1) : (index) -> () call @printNewline() : () -> () // CHECK: 3 return } diff --git a/mlir/test/mlir-cpu-runner/utils.mlir b/mlir/test/mlir-cpu-runner/utils.mlir index 65957400bf7f..971d348ae48b 100644 --- a/mlir/test/mlir-cpu-runner/utils.mlir +++ b/mlir/test/mlir-cpu-runner/utils.mlir @@ -1,73 +1,73 @@ // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | mlir-cpu-runner -e print_0d -entry-point-result=void -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext | FileCheck %s --check-prefix=PRINT-0D // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | mlir-cpu-runner -e print_1d -entry-point-result=void -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext | FileCheck %s --check-prefix=PRINT-1D // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | mlir-cpu-runner -e print_3d -entry-point-result=void -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext | FileCheck %s --check-prefix=PRINT-3D // RUN: mlir-opt %s -convert-linalg-to-loops -convert-linalg-to-llvm -convert-std-to-llvm | mlir-cpu-runner -e vector_splat_2d -entry-point-result=void -shared-libs=%linalg_test_lib_dir/libmlir_runner_utils%shlibext | FileCheck %s --check-prefix=PRINT-VECTOR-SPLAT-2D func @print_0d() { %f = constant 2.00000e+00 : f32 %A = alloc() : memref store %f, %A[]: memref %U = memref_cast %A : memref to memref<*xf32> call @print_memref_f32(%U): (memref<*xf32>) -> () dealloc %A : memref return } // PRINT-0D: Unranked Memref base@ = {{.*}} rank = 0 offset = 0 sizes = [] strides = [] data = // PRINT-0D: [2] func @print_1d() { %f = constant 2.00000e+00 : f32 %A = alloc() : memref<16xf32> %B = memref_cast %A: memref<16xf32> to memref linalg.fill(%B, %f) : memref, f32 %U = memref_cast %B : memref to memref<*xf32> call @print_memref_f32(%U): (memref<*xf32>) -> () dealloc %A : memref<16xf32> return } // PRINT-1D: Unranked Memref base@ = {{.*}} rank = 1 offset = 0 sizes = [16] strides = [1] data = // PRINT-1D-NEXT: [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] func @print_3d() { %f = constant 2.00000e+00 : f32 %f4 = constant 4.00000e+00 : f32 %A = alloc() : memref<3x4x5xf32> %B = memref_cast %A: memref<3x4x5xf32> to memref linalg.fill(%B, %f) : memref, f32 %c2 = constant 2 : index store %f4, %B[%c2, %c2, %c2]: memref %U = memref_cast %B : memref to memref<*xf32> call @print_memref_f32(%U): (memref<*xf32>) -> () dealloc %A : memref<3x4x5xf32> return } // PRINT-3D: Unranked Memref base@ = {{.*}} rank = 3 offset = 0 sizes = [3, 4, 5] strides = [20, 5, 1] data = // PRINT-3D-COUNT-4: {{.*[[:space:]].*}}2, 2, 2, 2, 2 // PRINT-3D-COUNT-4: {{.*[[:space:]].*}}2, 2, 2, 2, 2 // PRINT-3D-COUNT-2: {{.*[[:space:]].*}}2, 2, 2, 2, 2 // PRINT-3D-NEXT: 2, 2, 4, 2, 2 // PRINT-3D-NEXT: 2, 2, 2, 2, 2 -func @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } +func private @print_memref_f32(memref<*xf32>) attributes { llvm.emit_c_interface } !vector_type_C = type vector<4x4xf32> !matrix_type_CC = type memref<1x1x!vector_type_C> func @vector_splat_2d() { %c0 = constant 0 : index %f10 = constant 10.0 : f32 %vf10 = splat %f10: !vector_type_C %C = alloc() : !matrix_type_CC store %vf10, %C[%c0, %c0]: !matrix_type_CC %CC = memref_cast %C: !matrix_type_CC to memref call @print_memref_vector_4x4xf32(%CC): (memref) -> () dealloc %C : !matrix_type_CC return } // PRINT-VECTOR-SPLAT-2D: Memref base@ = {{.*}} rank = 2 offset = 0 sizes = [1, 1] strides = [1, 1] data = // PRINT-VECTOR-SPLAT-2D-NEXT: [((10, 10, 10, 10), (10, 10, 10, 10), (10, 10, 10, 10), (10, 10, 10, 10))] -func @print_memref_vector_4x4xf32(memref) attributes { llvm.emit_c_interface } +func private @print_memref_vector_4x4xf32(memref) attributes { llvm.emit_c_interface } diff --git a/mlir/test/mlir-cuda-runner/all-reduce-and.mlir b/mlir/test/mlir-cuda-runner/all-reduce-and.mlir index ef8d50580d9e..9096cfeda563 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-and.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-and.mlir @@ -1,62 +1,62 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xi32> %sum = alloc() : memref<2xi32> %cst0 = constant 0 : i32 %cst1 = constant 1 : i32 %cst2 = constant 2 : i32 %cst4 = constant 4 : i32 %cst8 = constant 8 : i32 %cst16 = constant 16 : i32 %cst3 = constant 3 : i32 %cst6 = constant 6 : i32 %cst7 = constant 7 : i32 %cst10 = constant 10 : i32 %cst11 = constant 11 : i32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xi32> to memref<*xi32> gpu.host_register %cast_data : memref<*xi32> %cast_sum = memref_cast %sum : memref<2xi32> to memref<*xi32> gpu.host_register %cast_sum : memref<*xi32> store %cst0, %data[%c0, %c0] : memref<2x6xi32> store %cst1, %data[%c0, %c1] : memref<2x6xi32> store %cst2, %data[%c0, %c2] : memref<2x6xi32> store %cst4, %data[%c0, %c3] : memref<2x6xi32> store %cst8, %data[%c0, %c4] : memref<2x6xi32> store %cst16, %data[%c0, %c5] : memref<2x6xi32> store %cst2, %data[%c1, %c0] : memref<2x6xi32> store %cst3, %data[%c1, %c1] : memref<2x6xi32> store %cst6, %data[%c1, %c2] : memref<2x6xi32> store %cst7, %data[%c1, %c3] : memref<2x6xi32> store %cst10, %data[%c1, %c4] : memref<2x6xi32> store %cst11, %data[%c1, %c5] : memref<2x6xi32> // AND gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xi32> %reduced = "gpu.all_reduce"(%val) ({}) { op = "and" } : (i32) -> (i32) store %reduced, %sum[%bx] : memref<2xi32> gpu.terminator } call @print_memref_i32(%cast_sum) : (memref<*xi32>) -> () // CHECK: [0, 2] return } -func @print_memref_i32(memref<*xi32>) +func private @print_memref_i32(memref<*xi32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-max.mlir b/mlir/test/mlir-cuda-runner/all-reduce-max.mlir index be8087a55ea2..68dbf046ef4c 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-max.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-max.mlir @@ -1,62 +1,62 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xi32> %sum = alloc() : memref<2xi32> %cst0 = constant 0 : i32 %cst1 = constant 1 : i32 %cst2 = constant 2 : i32 %cst4 = constant 4 : i32 %cst8 = constant 8 : i32 %cst16 = constant 16 : i32 %cst3 = constant 3 : i32 %cst6 = constant 6 : i32 %cst7 = constant 7 : i32 %cst10 = constant 10 : i32 %cst11 = constant 11 : i32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xi32> to memref<*xi32> gpu.host_register %cast_data : memref<*xi32> %cast_sum = memref_cast %sum : memref<2xi32> to memref<*xi32> gpu.host_register %cast_sum : memref<*xi32> store %cst0, %data[%c0, %c0] : memref<2x6xi32> store %cst1, %data[%c0, %c1] : memref<2x6xi32> store %cst2, %data[%c0, %c2] : memref<2x6xi32> store %cst4, %data[%c0, %c3] : memref<2x6xi32> store %cst8, %data[%c0, %c4] : memref<2x6xi32> store %cst16, %data[%c0, %c5] : memref<2x6xi32> store %cst2, %data[%c1, %c0] : memref<2x6xi32> store %cst3, %data[%c1, %c1] : memref<2x6xi32> store %cst6, %data[%c1, %c2] : memref<2x6xi32> store %cst7, %data[%c1, %c3] : memref<2x6xi32> store %cst10, %data[%c1, %c4] : memref<2x6xi32> store %cst11, %data[%c1, %c5] : memref<2x6xi32> // MAX gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xi32> %reduced = "gpu.all_reduce"(%val) ({}) { op = "max" } : (i32) -> (i32) store %reduced, %sum[%bx] : memref<2xi32> gpu.terminator } call @print_memref_i32(%cast_sum) : (memref<*xi32>) -> () // CHECK: [16, 11] return } -func @print_memref_i32(memref<*xi32>) +func private @print_memref_i32(memref<*xi32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-min.mlir b/mlir/test/mlir-cuda-runner/all-reduce-min.mlir index ad03ed5497f0..d078d9231958 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-min.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-min.mlir @@ -1,62 +1,62 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xi32> %sum = alloc() : memref<2xi32> %cst0 = constant 0 : i32 %cst1 = constant 1 : i32 %cst2 = constant 2 : i32 %cst4 = constant 4 : i32 %cst8 = constant 8 : i32 %cst16 = constant 16 : i32 %cst3 = constant 3 : i32 %cst6 = constant 6 : i32 %cst7 = constant 7 : i32 %cst10 = constant 10 : i32 %cst11 = constant 11 : i32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xi32> to memref<*xi32> gpu.host_register %cast_data : memref<*xi32> %cast_sum = memref_cast %sum : memref<2xi32> to memref<*xi32> gpu.host_register %cast_sum : memref<*xi32> store %cst0, %data[%c0, %c0] : memref<2x6xi32> store %cst1, %data[%c0, %c1] : memref<2x6xi32> store %cst2, %data[%c0, %c2] : memref<2x6xi32> store %cst4, %data[%c0, %c3] : memref<2x6xi32> store %cst8, %data[%c0, %c4] : memref<2x6xi32> store %cst16, %data[%c0, %c5] : memref<2x6xi32> store %cst2, %data[%c1, %c0] : memref<2x6xi32> store %cst3, %data[%c1, %c1] : memref<2x6xi32> store %cst6, %data[%c1, %c2] : memref<2x6xi32> store %cst7, %data[%c1, %c3] : memref<2x6xi32> store %cst10, %data[%c1, %c4] : memref<2x6xi32> store %cst11, %data[%c1, %c5] : memref<2x6xi32> // MIN gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xi32> %reduced = "gpu.all_reduce"(%val) ({}) { op = "min" } : (i32) -> (i32) store %reduced, %sum[%bx] : memref<2xi32> gpu.terminator } call @print_memref_i32(%cast_sum) : (memref<*xi32>) -> () // CHECK: [0, 2] return } -func @print_memref_i32(memref<*xi32>) +func private @print_memref_i32(memref<*xi32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-op.mlir b/mlir/test/mlir-cuda-runner/all-reduce-op.mlir index a639c699027b..247d2c599db2 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-op.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-op.mlir @@ -1,31 +1,31 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK-COUNT-8: [{{(5356, ){12}5356}}] func @main() { %arg = alloc() : memref<2x4x13xf32> %dst = memref_cast %arg : memref<2x4x13xf32> to memref %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %sx = dim %dst, %c2 : memref %sy = dim %dst, %c1 : memref %sz = dim %dst, %c0 : memref %cast_dst = memref_cast %dst : memref to memref<*xf32> gpu.host_register %cast_dst : memref<*xf32> gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c1, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %sx, %block_y = %sy, %block_z = %sz) { %t0 = muli %tz, %block_y : index %t1 = addi %ty, %t0 : index %t2 = muli %t1, %block_x : index %idx = addi %tx, %t2 : index %t3 = index_cast %idx : index to i32 %val = sitofp %t3 : i32 to f32 %sum = "gpu.all_reduce"(%val) ({}) { op = "add" } : (f32) -> (f32) store %sum, %dst[%tz, %ty, %tx] : memref gpu.terminator } call @print_memref_f32(%cast_dst) : (memref<*xf32>) -> () return } -func @print_memref_f32(%ptr : memref<*xf32>) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-or.mlir b/mlir/test/mlir-cuda-runner/all-reduce-or.mlir index 1ed85e61ded5..c6a5ee5a1096 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-or.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-or.mlir @@ -1,62 +1,62 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xi32> %sum = alloc() : memref<2xi32> %cst0 = constant 0 : i32 %cst1 = constant 1 : i32 %cst2 = constant 2 : i32 %cst4 = constant 4 : i32 %cst8 = constant 8 : i32 %cst16 = constant 16 : i32 %cst3 = constant 3 : i32 %cst6 = constant 6 : i32 %cst7 = constant 7 : i32 %cst10 = constant 10 : i32 %cst11 = constant 11 : i32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xi32> to memref<*xi32> gpu.host_register %cast_data : memref<*xi32> %cast_sum = memref_cast %sum : memref<2xi32> to memref<*xi32> gpu.host_register %cast_sum : memref<*xi32> store %cst0, %data[%c0, %c0] : memref<2x6xi32> store %cst1, %data[%c0, %c1] : memref<2x6xi32> store %cst2, %data[%c0, %c2] : memref<2x6xi32> store %cst4, %data[%c0, %c3] : memref<2x6xi32> store %cst8, %data[%c0, %c4] : memref<2x6xi32> store %cst16, %data[%c0, %c5] : memref<2x6xi32> store %cst2, %data[%c1, %c0] : memref<2x6xi32> store %cst3, %data[%c1, %c1] : memref<2x6xi32> store %cst6, %data[%c1, %c2] : memref<2x6xi32> store %cst7, %data[%c1, %c3] : memref<2x6xi32> store %cst10, %data[%c1, %c4] : memref<2x6xi32> store %cst11, %data[%c1, %c5] : memref<2x6xi32> // OR gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xi32> %reduced = "gpu.all_reduce"(%val) ({}) { op = "or" } : (i32) -> (i32) store %reduced, %sum[%bx] : memref<2xi32> gpu.terminator } call @print_memref_i32(%cast_sum) : (memref<*xi32>) -> () // CHECK: [31, 15] return } -func @print_memref_i32(memref<*xi32>) +func private @print_memref_i32(memref<*xi32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-region.mlir b/mlir/test/mlir-cuda-runner/all-reduce-region.mlir index 49f24db131c7..dcff9d00e4cf 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-region.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-region.mlir @@ -1,28 +1,28 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK: [{{(35, ){34}35}}] func @main() { %arg = alloc() : memref<35xf32> %dst = memref_cast %arg : memref<35xf32> to memref %one = constant 1 : index %c0 = constant 0 : index %sx = dim %dst, %c0 : memref %cast_dst = memref_cast %dst : memref to memref<*xf32> gpu.host_register %cast_dst : memref<*xf32> gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %one, %grid_y = %one, %grid_z = %one) threads(%tx, %ty, %tz) in (%block_x = %sx, %block_y = %one, %block_z = %one) { %val = index_cast %tx : index to i32 %xor = "gpu.all_reduce"(%val) ({ ^bb(%lhs : i32, %rhs : i32): %xor = xor %lhs, %rhs : i32 "gpu.yield"(%xor) : (i32) -> () }) : (i32) -> (i32) %res = sitofp %xor : i32 to f32 store %res, %dst[%tx] : memref gpu.terminator } call @print_memref_f32(%cast_dst) : (memref<*xf32>) -> () return } -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) diff --git a/mlir/test/mlir-cuda-runner/all-reduce-xor.mlir b/mlir/test/mlir-cuda-runner/all-reduce-xor.mlir index 88cd9036998f..9ca81dff02f9 100644 --- a/mlir/test/mlir-cuda-runner/all-reduce-xor.mlir +++ b/mlir/test/mlir-cuda-runner/all-reduce-xor.mlir @@ -1,62 +1,62 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xi32> %sum = alloc() : memref<2xi32> %cst0 = constant 0 : i32 %cst1 = constant 1 : i32 %cst2 = constant 2 : i32 %cst4 = constant 4 : i32 %cst8 = constant 8 : i32 %cst16 = constant 16 : i32 %cst3 = constant 3 : i32 %cst6 = constant 6 : i32 %cst7 = constant 7 : i32 %cst10 = constant 10 : i32 %cst11 = constant 11 : i32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xi32> to memref<*xi32> gpu.host_register %cast_data : memref<*xi32> %cast_sum = memref_cast %sum : memref<2xi32> to memref<*xi32> gpu.host_register %cast_sum : memref<*xi32> store %cst0, %data[%c0, %c0] : memref<2x6xi32> store %cst1, %data[%c0, %c1] : memref<2x6xi32> store %cst2, %data[%c0, %c2] : memref<2x6xi32> store %cst4, %data[%c0, %c3] : memref<2x6xi32> store %cst8, %data[%c0, %c4] : memref<2x6xi32> store %cst16, %data[%c0, %c5] : memref<2x6xi32> store %cst2, %data[%c1, %c0] : memref<2x6xi32> store %cst3, %data[%c1, %c1] : memref<2x6xi32> store %cst6, %data[%c1, %c2] : memref<2x6xi32> store %cst7, %data[%c1, %c3] : memref<2x6xi32> store %cst10, %data[%c1, %c4] : memref<2x6xi32> store %cst11, %data[%c1, %c5] : memref<2x6xi32> // XOR gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xi32> %reduced = "gpu.all_reduce"(%val) ({}) { op = "xor" } : (i32) -> (i32) store %reduced, %sum[%bx] : memref<2xi32> gpu.terminator } call @print_memref_i32(%cast_sum) : (memref<*xi32>) -> () // CHECK: [31, 1] return } -func @print_memref_i32(memref<*xi32>) +func private @print_memref_i32(memref<*xi32>) diff --git a/mlir/test/mlir-cuda-runner/gpu-to-cubin.mlir b/mlir/test/mlir-cuda-runner/gpu-to-cubin.mlir index fb458eb375d0..e2340bd1f5fa 100644 --- a/mlir/test/mlir-cuda-runner/gpu-to-cubin.mlir +++ b/mlir/test/mlir-cuda-runner/gpu-to-cubin.mlir @@ -1,29 +1,29 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @other_func(%arg0 : f32, %arg1 : memref) { %cst = constant 1 : index %c0 = constant 0 : index %cst2 = dim %arg1, %c0 : memref gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %cst, %grid_y = %cst, %grid_z = %cst) threads(%tx, %ty, %tz) in (%block_x = %cst2, %block_y = %cst, %block_z = %cst) { store %arg0, %arg1[%tx] : memref gpu.terminator } return } // CHECK: [1, 1, 1, 1, 1] func @main() { %arg0 = alloc() : memref<5xf32> %21 = constant 5 : i32 %22 = memref_cast %arg0 : memref<5xf32> to memref %23 = memref_cast %22 : memref to memref<*xf32> gpu.host_register %23 : memref<*xf32> call @print_memref_f32(%23) : (memref<*xf32>) -> () %24 = constant 1.0 : f32 call @other_func(%24, %22) : (f32, memref) -> () call @print_memref_f32(%23) : (memref<*xf32>) -> () return } -func @print_memref_f32(%ptr : memref<*xf32>) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-cuda-runner/multiple-all-reduce.mlir b/mlir/test/mlir-cuda-runner/multiple-all-reduce.mlir index f3fb3b219ce0..44278791592a 100644 --- a/mlir/test/mlir-cuda-runner/multiple-all-reduce.mlir +++ b/mlir/test/mlir-cuda-runner/multiple-all-reduce.mlir @@ -1,69 +1,69 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @main() { %data = alloc() : memref<2x6xf32> %sum = alloc() : memref<2xf32> %mul = alloc() : memref<2xf32> %cst0 = constant 0.0 : f32 %cst1 = constant 1.0 : f32 %cst2 = constant 2.0 : f32 %cst4 = constant 4.0 : f32 %cst8 = constant 8.0 : f32 %cst16 = constant 16.0 : f32 %cst3 = constant 3.0 : f32 %cst6 = constant 6.0 : f32 %cst7 = constant 7.0 : f32 %cst10 = constant 10.0 : f32 %cst11 = constant 11.0 : f32 %c0 = constant 0 : index %c1 = constant 1 : index %c2 = constant 2 : index %c3 = constant 3 : index %c4 = constant 4 : index %c5 = constant 5 : index %c6 = constant 6 : index %cast_data = memref_cast %data : memref<2x6xf32> to memref<*xf32> gpu.host_register %cast_data : memref<*xf32> %cast_sum = memref_cast %sum : memref<2xf32> to memref<*xf32> gpu.host_register %cast_sum : memref<*xf32> %cast_mul = memref_cast %mul : memref<2xf32> to memref<*xf32> gpu.host_register %cast_mul : memref<*xf32> store %cst0, %data[%c0, %c0] : memref<2x6xf32> store %cst1, %data[%c0, %c1] : memref<2x6xf32> store %cst2, %data[%c0, %c2] : memref<2x6xf32> store %cst4, %data[%c0, %c3] : memref<2x6xf32> store %cst8, %data[%c0, %c4] : memref<2x6xf32> store %cst16, %data[%c0, %c5] : memref<2x6xf32> store %cst2, %data[%c1, %c0] : memref<2x6xf32> store %cst3, %data[%c1, %c1] : memref<2x6xf32> store %cst6, %data[%c1, %c2] : memref<2x6xf32> store %cst7, %data[%c1, %c3] : memref<2x6xf32> store %cst10, %data[%c1, %c4] : memref<2x6xf32> store %cst11, %data[%c1, %c5] : memref<2x6xf32> // ADD + MUL gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c2, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %c6, %block_y = %c1, %block_z = %c1) { %val = load %data[%bx, %tx] : memref<2x6xf32> %reduced0 = "gpu.all_reduce"(%val) ({}) { op = "add" } : (f32) -> (f32) store %reduced0, %sum[%bx] : memref<2xf32> %reduced1 = "gpu.all_reduce"(%val) ({}) { op = "mul" } : (f32) -> (f32) store %reduced1, %mul[%bx] : memref<2xf32> gpu.terminator } call @print_memref_f32(%cast_sum) : (memref<*xf32>) -> () // CHECK: [31, 39] call @print_memref_f32(%cast_mul) : (memref<*xf32>) -> () // CHECK: [0, 27720] return } -func @print_memref_f32(memref<*xf32>) +func private @print_memref_f32(memref<*xf32>) diff --git a/mlir/test/mlir-cuda-runner/shuffle.mlir b/mlir/test/mlir-cuda-runner/shuffle.mlir index 9846455142d6..b1fde24706ba 100644 --- a/mlir/test/mlir-cuda-runner/shuffle.mlir +++ b/mlir/test/mlir-cuda-runner/shuffle.mlir @@ -1,31 +1,31 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK: [4, 5, 6, 7, 0, 1, 2, 3, 12, -1, -1, -1, 8] func @main() { %arg = alloc() : memref<13xf32> %dst = memref_cast %arg : memref<13xf32> to memref %one = constant 1 : index %c0 = constant 0 : index %sx = dim %dst, %c0 : memref %cast_dst = memref_cast %dst : memref to memref<*xf32> gpu.host_register %cast_dst : memref<*xf32> gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %one, %grid_y = %one, %grid_z = %one) threads(%tx, %ty, %tz) in (%block_x = %sx, %block_y = %one, %block_z = %one) { %t0 = index_cast %tx : index to i32 %val = sitofp %t0 : i32 to f32 %width = index_cast %block_x : index to i32 %offset = constant 4 : i32 %shfl, %valid = gpu.shuffle %val, %offset, %width xor : f32 cond_br %valid, ^bb1(%shfl : f32), ^bb0 ^bb0: %m1 = constant -1.0 : f32 br ^bb1(%m1 : f32) ^bb1(%value : f32): store %value, %dst[%tx] : memref gpu.terminator } call @print_memref_f32(%cast_dst) : (memref<*xf32>) -> () return } -func @print_memref_f32(%ptr : memref<*xf32>) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-cuda-runner/two-modules.mlir b/mlir/test/mlir-cuda-runner/two-modules.mlir index 2ea58ae55b5e..982e8aa4f393 100644 --- a/mlir/test/mlir-cuda-runner/two-modules.mlir +++ b/mlir/test/mlir-cuda-runner/two-modules.mlir @@ -1,28 +1,28 @@ // RUN: mlir-cuda-runner %s --shared-libs=%cuda_wrapper_library_dir/libcuda-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] func @main() { %arg = alloc() : memref<13xi32> %dst = memref_cast %arg : memref<13xi32> to memref %one = constant 1 : index %c0 = constant 0 : index %sx = dim %dst, %c0 : memref %cast_dst = memref_cast %dst : memref to memref<*xi32> gpu.host_register %cast_dst : memref<*xi32> gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %one, %grid_y = %one, %grid_z = %one) threads(%tx, %ty, %tz) in (%block_x = %sx, %block_y = %one, %block_z = %one) { %t0 = index_cast %tx : index to i32 store %t0, %dst[%tx] : memref gpu.terminator } gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %one, %grid_y = %one, %grid_z = %one) threads(%tx, %ty, %tz) in (%block_x = %sx, %block_y = %one, %block_z = %one) { %t0 = index_cast %tx : index to i32 store %t0, %dst[%tx] : memref gpu.terminator } call @print_memref_i32(%cast_dst) : (memref<*xi32>) -> () return } -func @print_memref_i32(%memref : memref<*xi32>) +func private @print_memref_i32(%memref : memref<*xi32>) diff --git a/mlir/test/mlir-rocm-runner/gpu-to-hsaco.mlir b/mlir/test/mlir-rocm-runner/gpu-to-hsaco.mlir index 68e31fede8dc..14447743812d 100644 --- a/mlir/test/mlir-rocm-runner/gpu-to-hsaco.mlir +++ b/mlir/test/mlir-rocm-runner/gpu-to-hsaco.mlir @@ -1,32 +1,32 @@ // RUN: mlir-rocm-runner %s --shared-libs=%rocm_wrapper_library_dir/librocm-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @other_func(%arg0 : f32, %arg1 : memref) { %c0 = constant 0 : index %c1 = constant 1 : index %block_dim = dim %arg1, %c0 : memref gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c1, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %block_dim, %block_y = %c1, %block_z = %c1) { store %arg0, %arg1[%tx] : memref gpu.terminator } return } // CHECK: [1, 1, 1, 1, 1] func @main() { %arg0 = alloc() : memref<5xf32> %21 = constant 5 : i32 %22 = memref_cast %arg0 : memref<5xf32> to memref %cast = memref_cast %22 : memref to memref<*xf32> gpu.host_register %cast : memref<*xf32> %23 = memref_cast %22 : memref to memref<*xf32> call @print_memref_f32(%23) : (memref<*xf32>) -> () %24 = constant 1.0 : f32 %25 = call @mgpuMemGetDeviceMemRef1dFloat(%22) : (memref) -> (memref) call @other_func(%24, %25) : (f32, memref) -> () call @print_memref_f32(%23) : (memref<*xf32>) -> () return } -func @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) -func @print_memref_f32(%ptr : memref<*xf32>) +func private @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-rocm-runner/vecadd.mlir b/mlir/test/mlir-rocm-runner/vecadd.mlir index 9063974d5124..43c5e92cd597 100644 --- a/mlir/test/mlir-rocm-runner/vecadd.mlir +++ b/mlir/test/mlir-rocm-runner/vecadd.mlir @@ -1,50 +1,50 @@ // RUN: mlir-rocm-runner %s --shared-libs=%rocm_wrapper_library_dir/librocm-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @vecadd(%arg0 : memref, %arg1 : memref, %arg2 : memref) { %c0 = constant 0 : index %c1 = constant 1 : index %block_dim = dim %arg0, %c0 : memref gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %c1, %grid_y = %c1, %grid_z = %c1) threads(%tx, %ty, %tz) in (%block_x = %block_dim, %block_y = %c1, %block_z = %c1) { %a = load %arg0[%tx] : memref %b = load %arg1[%tx] : memref %c = addf %a, %b : f32 store %c, %arg2[%tx] : memref gpu.terminator } return } // CHECK: [2.46, 2.46, 2.46, 2.46, 2.46] func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c5 = constant 5 : index %cf1dot23 = constant 1.23 : f32 %0 = alloc() : memref<5xf32> %1 = alloc() : memref<5xf32> %2 = alloc() : memref<5xf32> %3 = memref_cast %0 : memref<5xf32> to memref %4 = memref_cast %1 : memref<5xf32> to memref %5 = memref_cast %2 : memref<5xf32> to memref scf.for %i = %c0 to %c5 step %c1 { store %cf1dot23, %3[%i] : memref store %cf1dot23, %4[%i] : memref } %6 = memref_cast %3 : memref to memref<*xf32> %7 = memref_cast %4 : memref to memref<*xf32> %8 = memref_cast %5 : memref to memref<*xf32> gpu.host_register %6 : memref<*xf32> gpu.host_register %7 : memref<*xf32> gpu.host_register %8 : memref<*xf32> %9 = call @mgpuMemGetDeviceMemRef1dFloat(%3) : (memref) -> (memref) %10 = call @mgpuMemGetDeviceMemRef1dFloat(%4) : (memref) -> (memref) %11 = call @mgpuMemGetDeviceMemRef1dFloat(%5) : (memref) -> (memref) call @vecadd(%9, %10, %11) : (memref, memref, memref) -> () call @print_memref_f32(%8) : (memref<*xf32>) -> () return } -func @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) -func @print_memref_f32(%ptr : memref<*xf32>) +func private @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-rocm-runner/vector-transferops.mlir b/mlir/test/mlir-rocm-runner/vector-transferops.mlir index 3d4424cc4281..87a05c564c5a 100644 --- a/mlir/test/mlir-rocm-runner/vector-transferops.mlir +++ b/mlir/test/mlir-rocm-runner/vector-transferops.mlir @@ -1,84 +1,84 @@ // RUN: mlir-rocm-runner %s --shared-libs=%rocm_wrapper_library_dir/librocm-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s func @vectransferx2(%arg0 : memref, %arg1 : memref) { %cst = constant 1 : index gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %cst, %grid_y = %cst, %grid_z = %cst) threads(%tx, %ty, %tz) in (%block_x = %cst, %block_y = %cst, %block_z = %cst) { %f0 = constant 0.0: f32 %base = constant 0 : index %f = vector.transfer_read %arg0[%base], %f0 {permutation_map = affine_map<(d0) -> (d0)>} : memref, vector<2xf32> %c = addf %f, %f : vector<2xf32> %base1 = constant 1 : index vector.transfer_write %c, %arg1[%base1] {permutation_map = affine_map<(d0) -> (d0)>} : vector<2xf32>, memref gpu.terminator } return } func @vectransferx4(%arg0 : memref, %arg1 : memref) { %cst = constant 1 : index gpu.launch blocks(%bx, %by, %bz) in (%grid_x = %cst, %grid_y = %cst, %grid_z = %cst) threads(%tx, %ty, %tz) in (%block_x = %cst, %block_y = %cst, %block_z = %cst) { %f0 = constant 0.0: f32 %base = constant 0 : index %f = vector.transfer_read %arg0[%base], %f0 {permutation_map = affine_map<(d0) -> (d0)>} : memref, vector<4xf32> %c = addf %f, %f : vector<4xf32> vector.transfer_write %c, %arg1[%base] {permutation_map = affine_map<(d0) -> (d0)>} : vector<4xf32>, memref gpu.terminator } return } func @main() { %c0 = constant 0 : index %c1 = constant 1 : index %c4 = constant 4 : index %cf1 = constant 1.0 : f32 %cf1dot23 = constant 1.23 : f32 %arg0 = alloc() : memref<4xf32> %arg1 = alloc() : memref<4xf32> %22 = memref_cast %arg0 : memref<4xf32> to memref %23 = memref_cast %arg1 : memref<4xf32> to memref scf.for %i = %c0 to %c4 step %c1 { store %cf1dot23, %22[%i] : memref store %cf1dot23, %23[%i] : memref } %cast0 = memref_cast %22 : memref to memref<*xf32> %cast1 = memref_cast %23 : memref to memref<*xf32> gpu.host_register %cast0 : memref<*xf32> gpu.host_register %cast1 : memref<*xf32> %24 = call @mgpuMemGetDeviceMemRef1dFloat(%22) : (memref) -> (memref) %26 = call @mgpuMemGetDeviceMemRef1dFloat(%23) : (memref) -> (memref) // CHECK: [1.23, 2.46, 2.46, 1.23] call @vectransferx2(%24, %26) : (memref, memref) -> () call @print_memref_f32(%cast1) : (memref<*xf32>) -> () // CHECK: [2.46, 2.46, 2.46, 2.46] call @vectransferx4(%24, %26) : (memref, memref) -> () call @print_memref_f32(%cast1) : (memref<*xf32>) -> () return } -func @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) -func @print_memref_f32(%ptr : memref<*xf32>) +func private @mgpuMemGetDeviceMemRef1dFloat(%ptr : memref) -> (memref) +func private @print_memref_f32(%ptr : memref<*xf32>) diff --git a/mlir/test/mlir-spirv-cpu-runner/double.mlir b/mlir/test/mlir-spirv-cpu-runner/double.mlir index 77a07b49292d..dd4a49c78d47 100644 --- a/mlir/test/mlir-spirv-cpu-runner/double.mlir +++ b/mlir/test/mlir-spirv-cpu-runner/double.mlir @@ -1,67 +1,67 @@ // RUN: mlir-spirv-cpu-runner %s -e main --entry-point-result=void --shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%spirv_wrapper_library_dir/libmlir_test_spirv_cpu_runner_c_wrappers%shlibext // CHECK: [8, 8, 8, 8, 8, 8] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {max_compute_workgroup_invocations = 128 : i32, max_compute_workgroup_size = dense<[128, 128, 64]> : vector<3xi32>}> } { gpu.module @kernels { gpu.func @double(%arg0 : memref<6xi32>, %arg1 : memref<6xi32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32>}} { %factor = constant 2 : i32 %i0 = constant 0 : index %i1 = constant 1 : index %i2 = constant 2 : index %i3 = constant 3 : index %i4 = constant 4 : index %i5 = constant 5 : index %x0 = load %arg0[%i0] : memref<6xi32> %x1 = load %arg0[%i1] : memref<6xi32> %x2 = load %arg0[%i2] : memref<6xi32> %x3 = load %arg0[%i3] : memref<6xi32> %x4 = load %arg0[%i4] : memref<6xi32> %x5 = load %arg0[%i5] : memref<6xi32> %y0 = muli %x0, %factor : i32 %y1 = muli %x1, %factor : i32 %y2 = muli %x2, %factor : i32 %y3 = muli %x3, %factor : i32 %y4 = muli %x4, %factor : i32 %y5 = muli %x5, %factor : i32 store %y0, %arg1[%i0] : memref<6xi32> store %y1, %arg1[%i1] : memref<6xi32> store %y2, %arg1[%i2] : memref<6xi32> store %y3, %arg1[%i3] : memref<6xi32> store %y4, %arg1[%i4] : memref<6xi32> store %y5, %arg1[%i5] : memref<6xi32> gpu.return } } func @main() { %input = alloc() : memref<6xi32> %output = alloc() : memref<6xi32> %four = constant 4 : i32 %zero = constant 0 : i32 %input_casted = memref_cast %input : memref<6xi32> to memref %output_casted = memref_cast %output : memref<6xi32> to memref call @fillI32Buffer(%input_casted, %four) : (memref, i32) -> () call @fillI32Buffer(%output_casted, %zero) : (memref, i32) -> () %one = constant 1 : index gpu.launch_func @kernels::@double blocks in (%one, %one, %one) threads in (%one, %one, %one) args(%input : memref<6xi32>, %output : memref<6xi32>) %result = memref_cast %output : memref<6xi32> to memref<*xi32> call @print_memref_i32(%result) : (memref<*xi32>) -> () return } - func @fillI32Buffer(%arg0 : memref, %arg1 : i32) - func @print_memref_i32(%ptr : memref<*xi32>) + func private @fillI32Buffer(%arg0 : memref, %arg1 : i32) + func private @print_memref_i32(%ptr : memref<*xi32>) } diff --git a/mlir/test/mlir-spirv-cpu-runner/simple_add.mlir b/mlir/test/mlir-spirv-cpu-runner/simple_add.mlir index 18b6390d6bb7..278ddcad113d 100644 --- a/mlir/test/mlir-spirv-cpu-runner/simple_add.mlir +++ b/mlir/test/mlir-spirv-cpu-runner/simple_add.mlir @@ -1,61 +1,61 @@ // RUN: mlir-spirv-cpu-runner %s -e main --entry-point-result=void --shared-libs=%mlir_runner_utils_dir/libmlir_runner_utils%shlibext,%spirv_wrapper_library_dir/libmlir_test_spirv_cpu_runner_c_wrappers%shlibext // CHECK: [[[7.7, 0, 0], [7.7, 0, 0], [7.7, 0, 0]], [[0, 7.7, 0], [0, 7.7, 0], [0, 7.7, 0]], [[0, 0, 7.7], [0, 0, 7.7], [0, 0, 7.7]]] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {max_compute_workgroup_invocations = 128 : i32, max_compute_workgroup_size = dense<[128, 128, 64]> : vector<3xi32>}> } { gpu.module @kernels { gpu.func @sum(%arg0 : memref<3xf32>, %arg1 : memref<3x3xf32>, %arg2 : memref<3x3x3xf32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32>}} { %i0 = constant 0 : index %i1 = constant 1 : index %i2 = constant 2 : index %x = load %arg0[%i0] : memref<3xf32> %y = load %arg1[%i0, %i0] : memref<3x3xf32> %sum = addf %x, %y : f32 store %sum, %arg2[%i0, %i0, %i0] : memref<3x3x3xf32> store %sum, %arg2[%i0, %i1, %i0] : memref<3x3x3xf32> store %sum, %arg2[%i0, %i2, %i0] : memref<3x3x3xf32> store %sum, %arg2[%i1, %i0, %i1] : memref<3x3x3xf32> store %sum, %arg2[%i1, %i1, %i1] : memref<3x3x3xf32> store %sum, %arg2[%i1, %i2, %i1] : memref<3x3x3xf32> store %sum, %arg2[%i2, %i0, %i2] : memref<3x3x3xf32> store %sum, %arg2[%i2, %i1, %i2] : memref<3x3x3xf32> store %sum, %arg2[%i2, %i2, %i2] : memref<3x3x3xf32> gpu.return } } func @main() { %input1 = alloc() : memref<3xf32> %input2 = alloc() : memref<3x3xf32> %output = alloc() : memref<3x3x3xf32> %0 = constant 0.0 : f32 %3 = constant 3.4 : f32 %4 = constant 4.3 : f32 %input1_casted = memref_cast %input1 : memref<3xf32> to memref %input2_casted = memref_cast %input2 : memref<3x3xf32> to memref %output_casted = memref_cast %output : memref<3x3x3xf32> to memref call @fillF32Buffer1D(%input1_casted, %3) : (memref, f32) -> () call @fillF32Buffer2D(%input2_casted, %4) : (memref, f32) -> () call @fillF32Buffer3D(%output_casted, %0) : (memref, f32) -> () %one = constant 1 : index gpu.launch_func @kernels::@sum blocks in (%one, %one, %one) threads in (%one, %one, %one) args(%input1 : memref<3xf32>, %input2 : memref<3x3xf32>, %output : memref<3x3x3xf32>) %result = memref_cast %output : memref<3x3x3xf32> to memref<*xf32> call @print_memref_f32(%result) : (memref<*xf32>) -> () return } - func @fillF32Buffer1D(%arg0 : memref, %arg1 : f32) - func @fillF32Buffer2D(%arg0 : memref, %arg1 : f32) - func @fillF32Buffer3D(%arg0 : memref, %arg1 : f32) - func @print_memref_f32(%arg0 : memref<*xf32>) + func private @fillF32Buffer1D(%arg0 : memref, %arg1 : f32) + func private @fillF32Buffer2D(%arg0 : memref, %arg1 : f32) + func private @fillF32Buffer3D(%arg0 : memref, %arg1 : f32) + func private @print_memref_f32(%arg0 : memref<*xf32>) } diff --git a/mlir/test/mlir-vulkan-runner/addf.mlir b/mlir/test/mlir-vulkan-runner/addf.mlir index 490ed2f20f25..e7ee7cb2e853 100644 --- a/mlir/test/mlir-vulkan-runner/addf.mlir +++ b/mlir/test/mlir-vulkan-runner/addf.mlir @@ -1,50 +1,50 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK: [3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3, 3.3] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_add(%arg0 : memref<8xf32>, %arg1 : memref<8xf32>, %arg2 : memref<8xf32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32> }} { %0 = "gpu.block_id"() {dimension = "x"} : () -> index %1 = load %arg0[%0] : memref<8xf32> %2 = load %arg1[%0] : memref<8xf32> %3 = addf %1, %2 : f32 store %3, %arg2[%0] : memref<8xf32> gpu.return } } func @main() { %arg0 = alloc() : memref<8xf32> %arg1 = alloc() : memref<8xf32> %arg2 = alloc() : memref<8xf32> %0 = constant 0 : i32 %1 = constant 1 : i32 %2 = constant 2 : i32 %value0 = constant 0.0 : f32 %value1 = constant 1.1 : f32 %value2 = constant 2.2 : f32 %arg3 = memref_cast %arg0 : memref<8xf32> to memref %arg4 = memref_cast %arg1 : memref<8xf32> to memref %arg5 = memref_cast %arg2 : memref<8xf32> to memref call @fillResource1DFloat(%arg3, %value1) : (memref, f32) -> () call @fillResource1DFloat(%arg4, %value2) : (memref, f32) -> () call @fillResource1DFloat(%arg5, %value0) : (memref, f32) -> () %cst1 = constant 1 : index %cst8 = constant 8 : index gpu.launch_func @kernels::@kernel_add blocks in (%cst8, %cst1, %cst1) threads in (%cst1, %cst1, %cst1) args(%arg0 : memref<8xf32>, %arg1 : memref<8xf32>, %arg2 : memref<8xf32>) %arg6 = memref_cast %arg5 : memref to memref<*xf32> call @print_memref_f32(%arg6) : (memref<*xf32>) -> () return } - func @fillResource1DFloat(%0 : memref, %1 : f32) - func @print_memref_f32(%ptr : memref<*xf32>) + func private @fillResource1DFloat(%0 : memref, %1 : f32) + func private @print_memref_f32(%ptr : memref<*xf32>) } diff --git a/mlir/test/mlir-vulkan-runner/addi.mlir b/mlir/test/mlir-vulkan-runner/addi.mlir index 6b289cdb7290..81ac4a98eaae 100644 --- a/mlir/test/mlir-vulkan-runner/addi.mlir +++ b/mlir/test/mlir-vulkan-runner/addi.mlir @@ -1,51 +1,51 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK-COUNT-64: [3, 3, 3, 3, 3, 3, 3, 3] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_addi(%arg0 : memref<8xi32>, %arg1 : memref<8x8xi32>, %arg2 : memref<8x8x8xi32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32>}} { %x = "gpu.block_id"() {dimension = "x"} : () -> index %y = "gpu.block_id"() {dimension = "y"} : () -> index %z = "gpu.block_id"() {dimension = "z"} : () -> index %0 = load %arg0[%x] : memref<8xi32> %1 = load %arg1[%y, %x] : memref<8x8xi32> %2 = addi %0, %1 : i32 store %2, %arg2[%z, %y, %x] : memref<8x8x8xi32> gpu.return } } func @main() { %arg0 = alloc() : memref<8xi32> %arg1 = alloc() : memref<8x8xi32> %arg2 = alloc() : memref<8x8x8xi32> %value0 = constant 0 : i32 %value1 = constant 1 : i32 %value2 = constant 2 : i32 %arg3 = memref_cast %arg0 : memref<8xi32> to memref %arg4 = memref_cast %arg1 : memref<8x8xi32> to memref %arg5 = memref_cast %arg2 : memref<8x8x8xi32> to memref call @fillResource1DInt(%arg3, %value1) : (memref, i32) -> () call @fillResource2DInt(%arg4, %value2) : (memref, i32) -> () call @fillResource3DInt(%arg5, %value0) : (memref, i32) -> () %cst1 = constant 1 : index %cst8 = constant 8 : index gpu.launch_func @kernels::@kernel_addi blocks in (%cst8, %cst8, %cst8) threads in (%cst1, %cst1, %cst1) args(%arg0 : memref<8xi32>, %arg1 : memref<8x8xi32>, %arg2 : memref<8x8x8xi32>) %arg6 = memref_cast %arg5 : memref to memref<*xi32> call @print_memref_i32(%arg6) : (memref<*xi32>) -> () return } - func @fillResource1DInt(%0 : memref, %1 : i32) - func @fillResource2DInt(%0 : memref, %1 : i32) - func @fillResource3DInt(%0 : memref, %1 : i32) - func @print_memref_i32(%ptr : memref<*xi32>) + func private @fillResource1DInt(%0 : memref, %1 : i32) + func private @fillResource2DInt(%0 : memref, %1 : i32) + func private @fillResource3DInt(%0 : memref, %1 : i32) + func private @print_memref_i32(%ptr : memref<*xi32>) } diff --git a/mlir/test/mlir-vulkan-runner/addi8.mlir b/mlir/test/mlir-vulkan-runner/addi8.mlir index 27bfa7d02396..920d6a9f6084 100644 --- a/mlir/test/mlir-vulkan-runner/addi8.mlir +++ b/mlir/test/mlir-vulkan-runner/addi8.mlir @@ -1,51 +1,51 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK-COUNT-64: [3, 3, 3, 3, 3, 3, 3, 3] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_addi(%arg0 : memref<8xi8>, %arg1 : memref<8x8xi8>, %arg2 : memref<8x8x8xi32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32>}} { %x = "gpu.block_id"() {dimension = "x"} : () -> index %y = "gpu.block_id"() {dimension = "y"} : () -> index %z = "gpu.block_id"() {dimension = "z"} : () -> index %0 = load %arg0[%x] : memref<8xi8> %1 = load %arg1[%y, %x] : memref<8x8xi8> %2 = addi %0, %1 : i8 %3 = zexti %2 : i8 to i32 store %3, %arg2[%z, %y, %x] : memref<8x8x8xi32> gpu.return } } func @main() { %arg0 = alloc() : memref<8xi8> %arg1 = alloc() : memref<8x8xi8> %arg2 = alloc() : memref<8x8x8xi32> %value0 = constant 0 : i32 %value1 = constant 1 : i8 %value2 = constant 2 : i8 %arg3 = memref_cast %arg0 : memref<8xi8> to memref %arg4 = memref_cast %arg1 : memref<8x8xi8> to memref %arg5 = memref_cast %arg2 : memref<8x8x8xi32> to memref call @fillResource1DInt8(%arg3, %value1) : (memref, i8) -> () call @fillResource2DInt8(%arg4, %value2) : (memref, i8) -> () call @fillResource3DInt(%arg5, %value0) : (memref, i32) -> () %cst1 = constant 1 : index %cst8 = constant 8 : index gpu.launch_func @kernels::@kernel_addi blocks in (%cst8, %cst8, %cst8) threads in (%cst1, %cst1, %cst1) args(%arg0 : memref<8xi8>, %arg1 : memref<8x8xi8>, %arg2 : memref<8x8x8xi32>) %arg6 = memref_cast %arg5 : memref to memref<*xi32> call @print_memref_i32(%arg6) : (memref<*xi32>) -> () return } - func @fillResource1DInt8(%0 : memref, %1 : i8) - func @fillResource2DInt8(%0 : memref, %1 : i8) - func @fillResource3DInt(%0 : memref, %1 : i32) - func @print_memref_i32(%ptr : memref<*xi32>) + func private @fillResource1DInt8(%0 : memref, %1 : i8) + func private @fillResource2DInt8(%0 : memref, %1 : i8) + func private @fillResource3DInt(%0 : memref, %1 : i32) + func private @print_memref_i32(%ptr : memref<*xi32>) } diff --git a/mlir/test/mlir-vulkan-runner/mulf.mlir b/mlir/test/mlir-vulkan-runner/mulf.mlir index a6b7b1b23e5d..e908d6672e03 100644 --- a/mlir/test/mlir-vulkan-runner/mulf.mlir +++ b/mlir/test/mlir-vulkan-runner/mulf.mlir @@ -1,51 +1,51 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK-COUNT-4: [6, 6, 6, 6] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_mul(%arg0 : memref<4x4xf32>, %arg1 : memref<4x4xf32>, %arg2 : memref<4x4xf32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32> }} { %x = "gpu.block_id"() {dimension = "x"} : () -> index %y = "gpu.block_id"() {dimension = "y"} : () -> index %1 = load %arg0[%x, %y] : memref<4x4xf32> %2 = load %arg1[%x, %y] : memref<4x4xf32> %3 = mulf %1, %2 : f32 store %3, %arg2[%x, %y] : memref<4x4xf32> gpu.return } } func @main() { %arg0 = alloc() : memref<4x4xf32> %arg1 = alloc() : memref<4x4xf32> %arg2 = alloc() : memref<4x4xf32> %0 = constant 0 : i32 %1 = constant 1 : i32 %2 = constant 2 : i32 %value0 = constant 0.0 : f32 %value1 = constant 2.0 : f32 %value2 = constant 3.0 : f32 %arg3 = memref_cast %arg0 : memref<4x4xf32> to memref %arg4 = memref_cast %arg1 : memref<4x4xf32> to memref %arg5 = memref_cast %arg2 : memref<4x4xf32> to memref call @fillResource2DFloat(%arg3, %value1) : (memref, f32) -> () call @fillResource2DFloat(%arg4, %value2) : (memref, f32) -> () call @fillResource2DFloat(%arg5, %value0) : (memref, f32) -> () %cst1 = constant 1 : index %cst4 = constant 4 : index gpu.launch_func @kernels::@kernel_mul blocks in (%cst4, %cst4, %cst1) threads in(%cst1, %cst1, %cst1) args(%arg0 : memref<4x4xf32>, %arg1 : memref<4x4xf32>, %arg2 : memref<4x4xf32>) %arg6 = memref_cast %arg5 : memref to memref<*xf32> call @print_memref_f32(%arg6) : (memref<*xf32>) -> () return } - func @fillResource2DFloat(%0 : memref, %1 : f32) - func @print_memref_f32(%ptr : memref<*xf32>) + func private @fillResource2DFloat(%0 : memref, %1 : f32) + func private @print_memref_f32(%ptr : memref<*xf32>) } diff --git a/mlir/test/mlir-vulkan-runner/subf.mlir b/mlir/test/mlir-vulkan-runner/subf.mlir index 00940688eb16..02ed80f91900 100644 --- a/mlir/test/mlir-vulkan-runner/subf.mlir +++ b/mlir/test/mlir-vulkan-runner/subf.mlir @@ -1,53 +1,53 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK-COUNT-32: [2.2, 2.2, 2.2, 2.2] module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_sub(%arg0 : memref<8x4x4xf32>, %arg1 : memref<4x4xf32>, %arg2 : memref<8x4x4xf32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[1, 1, 1]>: vector<3xi32> }} { %x = "gpu.block_id"() {dimension = "x"} : () -> index %y = "gpu.block_id"() {dimension = "y"} : () -> index %z = "gpu.block_id"() {dimension = "z"} : () -> index %1 = load %arg0[%x, %y, %z] : memref<8x4x4xf32> %2 = load %arg1[%y, %z] : memref<4x4xf32> %3 = subf %1, %2 : f32 store %3, %arg2[%x, %y, %z] : memref<8x4x4xf32> gpu.return } } func @main() { %arg0 = alloc() : memref<8x4x4xf32> %arg1 = alloc() : memref<4x4xf32> %arg2 = alloc() : memref<8x4x4xf32> %0 = constant 0 : i32 %1 = constant 1 : i32 %2 = constant 2 : i32 %value0 = constant 0.0 : f32 %value1 = constant 3.3 : f32 %value2 = constant 1.1 : f32 %arg3 = memref_cast %arg0 : memref<8x4x4xf32> to memref %arg4 = memref_cast %arg1 : memref<4x4xf32> to memref %arg5 = memref_cast %arg2 : memref<8x4x4xf32> to memref call @fillResource3DFloat(%arg3, %value1) : (memref, f32) -> () call @fillResource2DFloat(%arg4, %value2) : (memref, f32) -> () call @fillResource3DFloat(%arg5, %value0) : (memref, f32) -> () %cst1 = constant 1 : index %cst4 = constant 4 : index %cst8 = constant 8 : index gpu.launch_func @kernels::@kernel_sub blocks in (%cst8, %cst4, %cst4) threads in (%cst1, %cst1, %cst1) args(%arg0 : memref<8x4x4xf32>, %arg1 : memref<4x4xf32>, %arg2 : memref<8x4x4xf32>) %arg6 = memref_cast %arg5 : memref to memref<*xf32> call @print_memref_f32(%arg6) : (memref<*xf32>) -> () return } - func @fillResource2DFloat(%0 : memref, %1 : f32) - func @fillResource3DFloat(%0 : memref, %1 : f32) - func @print_memref_f32(%ptr : memref<*xf32>) + func private @fillResource2DFloat(%0 : memref, %1 : f32) + func private @fillResource3DFloat(%0 : memref, %1 : f32) + func private @print_memref_f32(%ptr : memref<*xf32>) } diff --git a/mlir/test/mlir-vulkan-runner/time.mlir b/mlir/test/mlir-vulkan-runner/time.mlir index 0bf92966cdec..be8ce0f54361 100644 --- a/mlir/test/mlir-vulkan-runner/time.mlir +++ b/mlir/test/mlir-vulkan-runner/time.mlir @@ -1,56 +1,56 @@ // RUN: mlir-vulkan-runner %s --shared-libs=%vulkan_wrapper_library_dir/libvulkan-runtime-wrappers%shlibext,%linalg_test_lib_dir/libmlir_runner_utils%shlibext --entry-point-result=void | FileCheck %s // CHECK: Compute shader execution time // CHECK: Command buffer submit time // CHECK: Wait idle time module attributes { gpu.container_module, spv.target_env = #spv.target_env< #spv.vce, {}> } { gpu.module @kernels { gpu.func @kernel_add(%arg0 : memref<16384xf32>, %arg1 : memref<16384xf32>, %arg2 : memref<16384xf32>) kernel attributes { spv.entry_point_abi = {local_size = dense<[128, 1, 1]>: vector<3xi32> }} { %bid = "gpu.block_id"() {dimension = "x"} : () -> index %tid = "gpu.thread_id"() {dimension = "x"} : () -> index %cst = constant 128 : index %b = muli %bid, %cst : index %0 = addi %b, %tid : index %1 = load %arg0[%0] : memref<16384xf32> %2 = load %arg1[%0] : memref<16384xf32> %3 = addf %1, %2 : f32 store %3, %arg2[%0] : memref<16384xf32> gpu.return } } func @main() { %arg0 = alloc() : memref<16384xf32> %arg1 = alloc() : memref<16384xf32> %arg2 = alloc() : memref<16384xf32> %0 = constant 0 : i32 %1 = constant 1 : i32 %2 = constant 2 : i32 %value0 = constant 0.0 : f32 %value1 = constant 1.1 : f32 %value2 = constant 2.2 : f32 %arg3 = memref_cast %arg0 : memref<16384xf32> to memref %arg4 = memref_cast %arg1 : memref<16384xf32> to memref %arg5 = memref_cast %arg2 : memref<16384xf32> to memref call @fillResource1DFloat(%arg3, %value1) : (memref, f32) -> () call @fillResource1DFloat(%arg4, %value2) : (memref, f32) -> () call @fillResource1DFloat(%arg5, %value0) : (memref, f32) -> () %cst1 = constant 1 : index %cst128 = constant 128 : index gpu.launch_func @kernels::@kernel_add blocks in (%cst128, %cst1, %cst1) threads in (%cst128, %cst1, %cst1) args(%arg0 : memref<16384xf32>, %arg1 : memref<16384xf32>, %arg2 : memref<16384xf32>) %arg6 = memref_cast %arg5 : memref to memref<*xf32> return } - func @fillResource1DFloat(%0 : memref, %1 : f32) - func @print_memref_f32(%ptr : memref<*xf32>) + func private @fillResource1DFloat(%0 : memref, %1 : f32) + func private @print_memref_f32(%ptr : memref<*xf32>) } diff --git a/mlir/unittests/Pass/AnalysisManagerTest.cpp b/mlir/unittests/Pass/AnalysisManagerTest.cpp index 55f953aacaff..3ea88b0f9843 100644 --- a/mlir/unittests/Pass/AnalysisManagerTest.cpp +++ b/mlir/unittests/Pass/AnalysisManagerTest.cpp @@ -1,160 +1,162 @@ //===- AnalysisManagerTest.cpp - AnalysisManager unit tests ---------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Pass/AnalysisManager.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Function.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "gtest/gtest.h" using namespace mlir; using namespace mlir::detail; namespace { /// Minimal class definitions for two analyses. struct MyAnalysis { MyAnalysis(Operation *) {} }; struct OtherAnalysis { OtherAnalysis(Operation *) {} }; struct OpSpecificAnalysis { OpSpecificAnalysis(ModuleOp) {} }; TEST(AnalysisManagerTest, FineGrainModuleAnalysisPreservation) { MLIRContext context; // Test fine grain invalidation of the module analysis manager. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Query two different analyses, but only preserve one before invalidating. am.getAnalysis(); am.getAnalysis(); detail::PreservedAnalyses pa; pa.preserve(); am.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(am.getCachedAnalysis().hasValue()); EXPECT_FALSE(am.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, FineGrainFunctionAnalysisPreservation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); FuncOp func1 = FuncOp::create(builder.getUnknownLoc(), "foo", builder.getFunctionType(llvm::None, llvm::None)); + func1.setPrivate(); module->push_back(func1); // Test fine grain invalidation of the function analysis manager. ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; AnalysisManager fam = am.nest(func1); // Query two different analyses, but only preserve one before invalidating. fam.getAnalysis(); fam.getAnalysis(); detail::PreservedAnalyses pa; pa.preserve(); fam.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(fam.getCachedAnalysis().hasValue()); EXPECT_FALSE(fam.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, FineGrainChildFunctionAnalysisPreservation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); FuncOp func1 = FuncOp::create(builder.getUnknownLoc(), "foo", builder.getFunctionType(llvm::None, llvm::None)); + func1.setPrivate(); module->push_back(func1); // Test fine grain invalidation of a function analysis from within a module // analysis manager. ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Check that the analysis cache is initially empty. EXPECT_FALSE(am.getCachedChildAnalysis(func1).hasValue()); // Query two different analyses, but only preserve one before invalidating. am.getChildAnalysis(func1); am.getChildAnalysis(func1); detail::PreservedAnalyses pa; pa.preserve(); am.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(am.getCachedChildAnalysis(func1).hasValue()); EXPECT_FALSE(am.getCachedChildAnalysis(func1).hasValue()); } /// Test analyses with custom invalidation logic. struct TestAnalysisSet {}; struct CustomInvalidatingAnalysis { CustomInvalidatingAnalysis(Operation *) {} bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) { return !pa.isPreserved(); } }; TEST(AnalysisManagerTest, CustomInvalidation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; detail::PreservedAnalyses pa; // Check that the analysis is invalidated properly. am.getAnalysis(); am.invalidate(pa); EXPECT_FALSE(am.getCachedAnalysis().hasValue()); // Check that the analysis is preserved properly. am.getAnalysis(); pa.preserve(); am.invalidate(pa); EXPECT_TRUE(am.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, OpSpecificAnalysis) { MLIRContext context; // Create a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Query the op specific analysis for the module and verify that its cached. am.getAnalysis(); EXPECT_TRUE(am.getCachedAnalysis().hasValue()); } } // end namespace diff --git a/mlir/unittests/Pass/PassManagerTest.cpp b/mlir/unittests/Pass/PassManagerTest.cpp index cf32fe9e424f..d47ba581e728 100644 --- a/mlir/unittests/Pass/PassManagerTest.cpp +++ b/mlir/unittests/Pass/PassManagerTest.cpp @@ -1,123 +1,124 @@ //===- PassManagerTest.cpp - PassManager unit tests -----------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Pass/PassManager.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Function.h" #include "mlir/Pass/Pass.h" #include "gtest/gtest.h" using namespace mlir; using namespace mlir::detail; namespace { /// Analysis that operates on any operation. struct GenericAnalysis { GenericAnalysis(Operation *op) : isFunc(isa(op)) {} const bool isFunc; }; /// Analysis that operates on a specific operation. struct OpSpecificAnalysis { OpSpecificAnalysis(FuncOp op) : isSecret(op.getName() == "secret") {} const bool isSecret; }; /// Simple pass to annotate a FuncOp with the results of analysis. /// Note: not using FunctionPass as it skip external functions. struct AnnotateFunctionPass : public PassWrapper> { void runOnOperation() override { FuncOp op = getOperation(); Builder builder(op.getParentOfType()); auto &ga = getAnalysis(); auto &sa = getAnalysis(); op.setAttr("isFunc", builder.getBoolAttr(ga.isFunc)); op.setAttr("isSecret", builder.getBoolAttr(sa.isSecret)); } }; TEST(PassManagerTest, OpSpecificAnalysis) { MLIRContext context; Builder builder(&context); // Create a module with 2 functions. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); for (StringRef name : {"secret", "not_secret"}) { FuncOp func = FuncOp::create(builder.getUnknownLoc(), name, builder.getFunctionType(llvm::None, llvm::None)); + func.setPrivate(); module->push_back(func); } // Instantiate and run our pass. PassManager pm(&context); pm.addNestedPass(std::make_unique()); LogicalResult result = pm.run(module.get()); EXPECT_TRUE(succeeded(result)); // Verify that each function got annotated with expected attributes. for (FuncOp func : module->getOps()) { ASSERT_TRUE(func.getAttr("isFunc").isa()); EXPECT_TRUE(func.getAttr("isFunc").cast().getValue()); bool isSecret = func.getName() == "secret"; ASSERT_TRUE(func.getAttr("isSecret").isa()); EXPECT_EQ(func.getAttr("isSecret").cast().getValue(), isSecret); } } namespace { struct InvalidPass : Pass { InvalidPass() : Pass(TypeID::get(), StringRef("invalid_op")) {} StringRef getName() const override { return "Invalid Pass"; } void runOnOperation() override {} /// A clone method to create a copy of this pass. std::unique_ptr clonePass() const override { return std::make_unique( *static_cast(this)); } }; } // anonymous namespace TEST(PassManagerTest, InvalidPass) { MLIRContext context; // Create a module OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); // Add a single "invalid_op" operation OpBuilder builder(&module->getBodyRegion()); OperationState state(UnknownLoc::get(&context), "invalid_op"); builder.insert(Operation::create(state)); // Register a diagnostic handler to capture the diagnostic so that we can // check it later. std::unique_ptr diagnostic; context.getDiagEngine().registerHandler([&](Diagnostic &diag) { diagnostic.reset(new Diagnostic(std::move(diag))); }); // Instantiate and run our pass. PassManager pm(&context); pm.nest("invalid_op").addPass(std::make_unique()); LogicalResult result = pm.run(module.get()); EXPECT_TRUE(failed(result)); ASSERT_TRUE(diagnostic.get() != nullptr); EXPECT_EQ( diagnostic->str(), "'invalid_op' op trying to schedule a pass on an unregistered operation"); // Check that adding the pass at the top-level triggers a fatal error. ASSERT_DEATH(pm.addPass(std::make_unique()), ""); } } // end namespace