mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-14 06:29:38 +00:00
[MLIR] Change FuncOp assembly syntax to print visibility inline instead of in attrib dict.
- Change syntax for FuncOp to be `func <visibility>? @name` instead of printing the visibility in the attribute dictionary. - Since printFunctionLikeOp() and parseFunctionLikeOp() are also used by other operations, make the "inline visibility" an opt-in feature. - Updated unit test to use and check the new syntax. Differential Revision: https://reviews.llvm.org/D90859
This commit is contained in:
parent
d657f7cd30
commit
8b5a3e4632
@ -194,20 +194,21 @@ symbol has one of the following visibilities:
|
||||
table, but not outside of the visible IR, as long as each symbol table
|
||||
parent also defines a non-private symbol.
|
||||
|
||||
A few examples of what this looks like in the IR are shown below:
|
||||
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_function() attributes { sym_visibility = "nested" }
|
||||
func nested @nested_function()
|
||||
|
||||
// This function cannot be accessed outside of 'public_module'.
|
||||
func @private_function() attributes { sym_visibility = "private" }
|
||||
func private @private_function()
|
||||
}
|
||||
|
||||
// This function can only be accessed from within the top-level module.
|
||||
func @private_function() attributes { sym_visibility = "private" }
|
||||
func private @private_function()
|
||||
|
||||
// This function may be referenced externally.
|
||||
func @public_function()
|
||||
|
@ -78,15 +78,23 @@ parseFunctionSignature(OpAsmParser &parser, bool allowVariadic,
|
||||
/// whether the function is variadic. If the builder returns a null type,
|
||||
/// `result` will not contain the `type` attribute. The caller can then add a
|
||||
/// type, report the error or delegate the reporting to the op's verifier.
|
||||
/// If `allowInlineVisibility` is true, then the parser will allow visibility
|
||||
/// to be specified after the operation name. If the visibility is not specified
|
||||
/// there or `allowInlineVisibility` is false, visibility will be allowed in the
|
||||
/// attribute dict.
|
||||
ParseResult parseFunctionLikeOp(OpAsmParser &parser, OperationState &result,
|
||||
bool allowVariadic,
|
||||
FuncTypeBuilder funcTypeBuilder);
|
||||
FuncTypeBuilder funcTypeBuilder,
|
||||
bool allowInlineVisibility = false);
|
||||
|
||||
/// Printer implementation for function-like operations. Accepts lists of
|
||||
/// argument and result types to use while printing.
|
||||
/// argument and result types to use while printing. If `printVisibilityInline`
|
||||
/// is true, visibility is printed "inline" after the operation name and elided
|
||||
/// from the attributes dict. Otherwise, it is printed in the attribute dict.
|
||||
void printFunctionLikeOp(OpAsmPrinter &p, Operation *op,
|
||||
ArrayRef<Type> argTypes, bool isVariadic,
|
||||
ArrayRef<Type> resultTypes);
|
||||
ArrayRef<Type> resultTypes,
|
||||
bool printVisibilityInline = false);
|
||||
|
||||
/// Prints the signature of the function-like operation `op`. Assumes `op` has
|
||||
/// the FunctionLike trait and passed the verification.
|
||||
|
@ -351,6 +351,12 @@ public:
|
||||
/// Parse a keyword, if present, into 'keyword'.
|
||||
virtual ParseResult parseOptionalKeyword(StringRef *keyword) = 0;
|
||||
|
||||
/// Parse a keyword, if present, and if one of the 'allowedValues',
|
||||
/// into 'keyword'
|
||||
virtual ParseResult
|
||||
parseOptionalKeyword(StringRef *keyword,
|
||||
ArrayRef<StringRef> allowedValues) = 0;
|
||||
|
||||
/// Parse a `(` token.
|
||||
virtual ParseResult parseLParen() = 0;
|
||||
|
||||
|
@ -302,6 +302,18 @@ public:
|
||||
};
|
||||
|
||||
} // end namespace OpTrait
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Visibility parsing implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace impl {
|
||||
/// Parse an optional visibility attribute keyword (i.e., public, private, or
|
||||
/// nested) without quotes in a string attribute named 'attrName'.
|
||||
ParseResult parseOptionalVisibilityKeyword(OpAsmParser &parser,
|
||||
NamedAttrList &attrs);
|
||||
} // end namespace impl
|
||||
|
||||
} // end namespace mlir
|
||||
|
||||
/// Include the generated symbol interfaces.
|
||||
|
@ -570,11 +570,11 @@ def SymbolDCE : Pass<"symbol-dce"> {
|
||||
For example, consider the following input:
|
||||
|
||||
```mlir
|
||||
func @dead_private_function() attributes { sym_visibility = "private" }
|
||||
func @live_private_function() attributes { sym_visibility = "private" }
|
||||
func private @dead_private_function()
|
||||
func private @live_private_function()
|
||||
|
||||
// Note: The `public` isn't necessary here, as this is the default.
|
||||
func @public_function() attributes { sym_visibility = "public" } {
|
||||
func public @public_function() {
|
||||
"foo.return"() {uses = [@live_private_function]} : () -> ()
|
||||
}
|
||||
```
|
||||
@ -586,9 +586,9 @@ def SymbolDCE : Pass<"symbol-dce"> {
|
||||
are no links to known-live operations. After running, we get the expected:
|
||||
|
||||
```mlir
|
||||
func @live_private_function() attributes { sym_visibility = "private" }
|
||||
func private @live_private_function()
|
||||
|
||||
func @public_function() attributes { sym_visibility = "public" } {
|
||||
func public @public_function() {
|
||||
"foo.return"() {uses = [@live_private_function]} : () -> ()
|
||||
}
|
||||
```
|
||||
|
@ -69,13 +69,15 @@ ParseResult FuncOp::parse(OpAsmParser &parser, OperationState &result) {
|
||||
};
|
||||
|
||||
return impl::parseFunctionLikeOp(parser, result, /*allowVariadic=*/false,
|
||||
buildFuncType);
|
||||
buildFuncType,
|
||||
/*allowInlineVisibility=*/true);
|
||||
}
|
||||
|
||||
void FuncOp::print(OpAsmPrinter &p) {
|
||||
FunctionType fnType = getType();
|
||||
impl::printFunctionLikeOp(p, *this, fnType.getInputs(), /*isVariadic=*/false,
|
||||
fnType.getResults());
|
||||
fnType.getResults(),
|
||||
/*printVisibilityInline=*/true);
|
||||
}
|
||||
|
||||
LogicalResult FuncOp::verify() {
|
||||
|
@ -159,10 +159,9 @@ void mlir::impl::addArgAndResultAttrs(Builder &builder, OperationState &result,
|
||||
|
||||
/// Parser implementation for function-like operations. Uses `funcTypeBuilder`
|
||||
/// to construct the custom function type given lists of input and output types.
|
||||
ParseResult
|
||||
mlir::impl::parseFunctionLikeOp(OpAsmParser &parser, OperationState &result,
|
||||
bool allowVariadic,
|
||||
mlir::impl::FuncTypeBuilder funcTypeBuilder) {
|
||||
ParseResult mlir::impl::parseFunctionLikeOp(
|
||||
OpAsmParser &parser, OperationState &result, bool allowVariadic,
|
||||
mlir::impl::FuncTypeBuilder funcTypeBuilder, bool allowInlineVisibility) {
|
||||
SmallVector<OpAsmParser::OperandType, 4> entryArgs;
|
||||
SmallVector<NamedAttrList, 4> argAttrs;
|
||||
SmallVector<NamedAttrList, 4> resultAttrs;
|
||||
@ -170,9 +169,13 @@ mlir::impl::parseFunctionLikeOp(OpAsmParser &parser, OperationState &result,
|
||||
SmallVector<Type, 4> resultTypes;
|
||||
auto &builder = parser.getBuilder();
|
||||
|
||||
// Parse visibility if inline visibility is allowed.
|
||||
if (allowInlineVisibility)
|
||||
impl::parseOptionalVisibilityKeyword(parser, result.attributes);
|
||||
|
||||
// Parse the name as a symbol.
|
||||
StringAttr nameAttr;
|
||||
if (parser.parseSymbolName(nameAttr, ::mlir::SymbolTable::getSymbolAttrName(),
|
||||
if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
|
||||
result.attributes))
|
||||
return failure();
|
||||
|
||||
@ -303,17 +306,24 @@ void mlir::impl::printFunctionAttributes(OpAsmPrinter &p, Operation *op,
|
||||
/// argument and result types to use while printing.
|
||||
void mlir::impl::printFunctionLikeOp(OpAsmPrinter &p, Operation *op,
|
||||
ArrayRef<Type> argTypes, bool isVariadic,
|
||||
ArrayRef<Type> resultTypes) {
|
||||
ArrayRef<Type> resultTypes,
|
||||
bool printVisibilityInline) {
|
||||
// Print the operation and the function name.
|
||||
auto funcName =
|
||||
op->getAttrOfType<StringAttr>(::mlir::SymbolTable::getSymbolAttrName())
|
||||
op->getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName())
|
||||
.getValue();
|
||||
p << op->getName() << ' ';
|
||||
StringRef elidedAttr;
|
||||
if (printVisibilityInline) {
|
||||
elidedAttr = SymbolTable::getVisibilityAttrName();
|
||||
if (auto visibility = op->getAttrOfType<StringAttr>(elidedAttr))
|
||||
p << visibility.getValue() << ' ';
|
||||
}
|
||||
p.printSymbolName(funcName);
|
||||
|
||||
printFunctionSignature(p, op, argTypes, isVariadic, resultTypes);
|
||||
printFunctionAttributes(p, op, argTypes.size(), resultTypes.size());
|
||||
|
||||
printFunctionAttributes(p, op, argTypes.size(), resultTypes.size(),
|
||||
{elidedAttr});
|
||||
// Print the body if this is not an external function.
|
||||
Region &body = op->getRegion(0);
|
||||
if (!body.empty())
|
||||
|
@ -7,6 +7,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/IR/SymbolTable.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/OpImplementation.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
@ -986,6 +988,22 @@ SymbolTable &SymbolTableCollection::getSymbolTable(Operation *op) {
|
||||
return *it.first->second;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Visibility parsing implementation.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ParseResult impl::parseOptionalVisibilityKeyword(OpAsmParser &parser,
|
||||
NamedAttrList &attrs) {
|
||||
StringRef visibility;
|
||||
if (parser.parseOptionalKeyword(&visibility, {"public", "private", "nested"}))
|
||||
return failure();
|
||||
|
||||
StringAttr visibilityAttr = parser.getBuilder().getStringAttr(visibility);
|
||||
attrs.push_back(parser.getBuilder().getNamedAttr(
|
||||
SymbolTable::getVisibilityAttrName(), visibilityAttr));
|
||||
return success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Symbol Interfaces
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -1136,6 +1136,24 @@ public:
|
||||
return success();
|
||||
}
|
||||
|
||||
/// Parse a keyword if it is one of the 'allowedKeywords'.
|
||||
ParseResult
|
||||
parseOptionalKeyword(StringRef *keyword,
|
||||
ArrayRef<StringRef> allowedKeywords) override {
|
||||
// Check that the current token is a keyword.
|
||||
if (!isCurrentTokenAKeyword())
|
||||
return failure();
|
||||
|
||||
StringRef currentKeyword = parser.getTokenSpelling();
|
||||
if (llvm::is_contained(allowedKeywords, currentKeyword)) {
|
||||
*keyword = currentKeyword;
|
||||
parser.consumeToken();
|
||||
return success();
|
||||
}
|
||||
|
||||
return failure();
|
||||
}
|
||||
|
||||
/// Parse an optional @-identifier and store it (without the '@' symbol) in a
|
||||
/// string attribute named 'attrName'.
|
||||
ParseResult parseOptionalSymbolName(StringAttr &result, StringRef attrName,
|
||||
|
@ -15,8 +15,8 @@ func @execute_no_async_args(%arg0: f32, %arg1: memref<1xf32>) {
|
||||
}
|
||||
|
||||
// Function outlined from the async.execute operation.
|
||||
// CHECK-LABEL: func @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8> attributes {sym_visibility = "private"}
|
||||
// CHECK-LABEL: func private @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8>
|
||||
|
||||
// Create token for return op, and mark a function as a coroutine.
|
||||
// CHECK: %[[RET:.*]] = call @mlirAsyncRuntimeCreateToken()
|
||||
@ -79,8 +79,8 @@ func @nested_async_execute(%arg0: f32, %arg1: f32, %arg2: memref<1xf32>) {
|
||||
}
|
||||
|
||||
// Function outlined from the inner async.execute operation.
|
||||
// CHECK-LABEL: func @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>, %arg2: index)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8> attributes {sym_visibility = "private"}
|
||||
// CHECK-LABEL: func private @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>, %arg2: index)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8>
|
||||
// CHECK: %[[RET_0:.*]] = call @mlirAsyncRuntimeCreateToken()
|
||||
// CHECK: %[[HDL_0:.*]] = llvm.call @llvm.coro.begin
|
||||
// CHECK: call @mlirAsyncRuntimeExecute
|
||||
@ -89,8 +89,8 @@ func @nested_async_execute(%arg0: f32, %arg1: f32, %arg2: memref<1xf32>) {
|
||||
// CHECK: call @mlirAsyncRuntimeEmplaceToken(%[[RET_0]])
|
||||
|
||||
// Function outlined from the outer async.execute operation.
|
||||
// CHECK-LABEL: func @async_execute_fn_0(%arg0: f32, %arg1: memref<1xf32>, %arg2: f32)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8> attributes {sym_visibility = "private"}
|
||||
// CHECK-LABEL: func private @async_execute_fn_0(%arg0: f32, %arg1: memref<1xf32>, %arg2: f32)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8>
|
||||
// CHECK: %[[RET_1:.*]] = call @mlirAsyncRuntimeCreateToken()
|
||||
// CHECK: %[[HDL_1:.*]] = llvm.call @llvm.coro.begin
|
||||
|
||||
@ -128,8 +128,8 @@ func @async_execute_token_dependency(%arg0: f32, %arg1: memref<1xf32>) {
|
||||
}
|
||||
|
||||
// Function outlined from the first async.execute operation.
|
||||
// CHECK-LABEL: func @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8> attributes {sym_visibility = "private"}
|
||||
// CHECK-LABEL: func private @async_execute_fn(%arg0: f32, %arg1: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8>
|
||||
// CHECK: %[[RET_0:.*]] = call @mlirAsyncRuntimeCreateToken()
|
||||
// CHECK: %[[HDL_0:.*]] = llvm.call @llvm.coro.begin
|
||||
// CHECK: call @mlirAsyncRuntimeExecute
|
||||
@ -138,8 +138,8 @@ func @async_execute_token_dependency(%arg0: f32, %arg1: memref<1xf32>) {
|
||||
// CHECK: call @mlirAsyncRuntimeEmplaceToken(%[[RET_0]])
|
||||
|
||||
// Function outlined from the second async.execute operation with dependency.
|
||||
// CHECK-LABEL: func @async_execute_fn_0(%arg0: !llvm.ptr<i8>, %arg1: f32, %arg2: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8> attributes {sym_visibility = "private"}
|
||||
// CHECK-LABEL: func private @async_execute_fn_0(%arg0: !llvm.ptr<i8>, %arg1: f32, %arg2: memref<1xf32>)
|
||||
// CHECK-SAME: -> !llvm.ptr<i8>
|
||||
// CHECK: %[[RET_1:.*]] = call @mlirAsyncRuntimeCreateToken()
|
||||
// CHECK: %[[HDL_1:.*]] = llvm.call @llvm.coro.begin
|
||||
|
||||
|
@ -13,7 +13,7 @@ def main() {
|
||||
print(d);
|
||||
}
|
||||
|
||||
# CHECK-LABEL: func @multiply_transpose(
|
||||
# CHECK-LABEL: func private @multiply_transpose(
|
||||
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
|
||||
# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
// Check the result of inlining+shape inference on an input module.
|
||||
|
||||
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
|
||||
attributes { sym_visibility = "private" } {
|
||||
func private @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
|
||||
%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
|
||||
%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
|
||||
%2 = toy.mul %0, %1 : tensor<*xf64>
|
||||
@ -20,7 +19,7 @@ func @main() {
|
||||
toy.return
|
||||
}
|
||||
|
||||
// CHECK-NOT: func @multiply_transpose
|
||||
// CHECK-NOT: func private @multiply_transpose
|
||||
// CHECK-NOT: tensor<*xf64>
|
||||
|
||||
// CHECK-LABEL: func @main()
|
||||
|
@ -13,7 +13,7 @@ def main() {
|
||||
print(d);
|
||||
}
|
||||
|
||||
# CHECK-LABEL: func @multiply_transpose(
|
||||
# CHECK-LABEL: func private @multiply_transpose(
|
||||
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
|
||||
# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
// Check the result of inlining+shape inference on an input module.
|
||||
|
||||
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
|
||||
attributes { sym_visibility = "private" } {
|
||||
func private @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
|
||||
%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
|
||||
%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
|
||||
%2 = toy.mul %0, %1 : tensor<*xf64>
|
||||
|
@ -13,7 +13,7 @@ def main() {
|
||||
print(d);
|
||||
}
|
||||
|
||||
# CHECK-LABEL: func @multiply_transpose(
|
||||
# CHECK-LABEL: func private @multiply_transpose(
|
||||
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
|
||||
# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
// Check the result of inlining+shape inference on an input module.
|
||||
|
||||
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
|
||||
attributes { sym_visibility = "private" } {
|
||||
func private @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
|
||||
%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
|
||||
%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
|
||||
%2 = toy.mul %0, %1 : tensor<*xf64>
|
||||
|
@ -13,7 +13,7 @@ def main() {
|
||||
print(d);
|
||||
}
|
||||
|
||||
# CHECK-LABEL: func @multiply_transpose(
|
||||
# CHECK-LABEL: func private @multiply_transpose(
|
||||
# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>, [[VAL_1:%.*]]: tensor<*xf64>) -> tensor<*xf64>
|
||||
# CHECK: [[VAL_2:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_3:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
// Check the result of inlining+shape inference on an input module.
|
||||
|
||||
func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64>
|
||||
attributes { sym_visibility = "private" } {
|
||||
func private @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> {
|
||||
%0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64>
|
||||
%1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64>
|
||||
%2 = toy.mul %0, %1 : tensor<*xf64>
|
||||
|
@ -21,9 +21,8 @@ def main() {
|
||||
print(c);
|
||||
}
|
||||
|
||||
# CHECK-LABEL: func @multiply_transpose(
|
||||
# CHECK-LABEL: func private @multiply_transpose(
|
||||
# CHECK-SAME: [[VAL_0:%.*]]: !toy.struct<tensor<*xf64>, tensor<*xf64>>) -> tensor<*xf64>
|
||||
# CHECK-SAME: attributes {sym_visibility = "private"}
|
||||
# CHECK-NEXT: [[VAL_1:%.*]] = toy.struct_access [[VAL_0]][0] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64>
|
||||
# CHECK-NEXT: [[VAL_3:%.*]] = toy.struct_access [[VAL_0]][1] : !toy.struct<tensor<*xf64>, tensor<*xf64>> -> tensor<*xf64>
|
||||
|
@ -969,3 +969,7 @@ func @subtensor_insert(%t: tensor<8x16x4xf32>, %t2: tensor<16x32x8xf32>, %idx :
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func private @legacy_visibility_syntax
|
||||
func @legacy_visibility_syntax() attributes { sym_visibility = "private" }
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
// This file tests the callgraph dead code elimination performed by the inliner.
|
||||
|
||||
// Function is already dead.
|
||||
// CHECK-NOT: func @dead_function
|
||||
func @dead_function() attributes {sym_visibility = "private"} {
|
||||
// CHECK-NOT: func private @dead_function
|
||||
func private @dead_function() {
|
||||
return
|
||||
}
|
||||
|
||||
// Function becomes dead after inlining.
|
||||
// CHECK-NOT: func @dead_function_b
|
||||
func @dead_function_b() attributes {sym_visibility = "private"} {
|
||||
// CHECK-NOT: func private @dead_function_b
|
||||
func @dead_function_b() {
|
||||
return
|
||||
}
|
||||
|
||||
@ -26,13 +26,13 @@ func @live_function() {
|
||||
func @live_function_b() {
|
||||
return
|
||||
}
|
||||
// CHECK-NOT: func @dead_function_c
|
||||
func @dead_function_c() attributes {sym_visibility = "private"} {
|
||||
// CHECK-NOT: func private @dead_function_c
|
||||
func private @dead_function_c() {
|
||||
call @live_function_b() : () -> ()
|
||||
return
|
||||
}
|
||||
// CHECK-NOT: func @dead_function_d
|
||||
func @dead_function_d() attributes {sym_visibility = "private"} {
|
||||
// CHECK-NOT: func private @dead_function_d
|
||||
func private @dead_function_d() {
|
||||
call @dead_function_c() : () -> ()
|
||||
call @dead_function_c() : () -> ()
|
||||
return
|
||||
@ -45,8 +45,8 @@ func @live_function_c() {
|
||||
}
|
||||
|
||||
// Function is referenced by non-callable top-level user.
|
||||
// CHECK: func @live_function_d
|
||||
func @live_function_d() attributes {sym_visibility = "private"} {
|
||||
// CHECK: func private @live_function_d
|
||||
func private @live_function_d() {
|
||||
return
|
||||
}
|
||||
|
||||
@ -63,11 +63,11 @@ func @live_function_e() {
|
||||
return
|
||||
}
|
||||
// CHECK-NOT: func @dead_function_e
|
||||
func @dead_function_e() -> () attributes {sym_visibility = "private"} {
|
||||
func private @dead_function_e() -> () {
|
||||
"test.fold_to_call_op"() {callee=@dead_function_f} : () -> ()
|
||||
return
|
||||
}
|
||||
// CHECK-NOT: func @dead_function_f
|
||||
func @dead_function_f() attributes {sym_visibility = "private"} {
|
||||
// CHECK-NOT: func private @dead_function_f
|
||||
func private @dead_function_f() {
|
||||
return
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
/// Check that a constant is properly propagated through the arguments and
|
||||
/// results of a private function.
|
||||
|
||||
// CHECK-LABEL: func @private(
|
||||
func @private(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
// CHECK-LABEL: func private @private(
|
||||
func private @private(%arg0 : i32) -> i32 {
|
||||
// CHECK: %[[CST:.*]] = constant 1 : i32
|
||||
// CHECK: return %[[CST]] : i32
|
||||
|
||||
@ -27,8 +27,8 @@ func @simple_private() -> i32 {
|
||||
/// Check that a constant is properly propagated through the arguments and
|
||||
/// results of a visible nested function.
|
||||
|
||||
// CHECK: func @nested(
|
||||
func @nested(%arg0 : i32) -> i32 attributes { sym_visibility = "nested" } {
|
||||
// CHECK: func nested @nested(
|
||||
func nested @nested(%arg0 : i32) -> i32 {
|
||||
// CHECK: %[[CST:.*]] = constant 1 : i32
|
||||
// CHECK: return %[[CST]] : i32
|
||||
|
||||
@ -52,8 +52,8 @@ module {
|
||||
// NESTED-LABEL: module @nested_module
|
||||
module @nested_module attributes { sym_visibility = "public" } {
|
||||
|
||||
// NESTED: func @nested(
|
||||
func @nested(%arg0 : i32) -> (i32, i32) attributes { sym_visibility = "nested" } {
|
||||
// NESTED: func nested @nested(
|
||||
func nested @nested(%arg0 : i32) -> (i32, i32) {
|
||||
// NESTED: %[[CST:.*]] = constant 1 : i32
|
||||
// NESTED: return %[[CST]], %arg0 : i32, i32
|
||||
|
||||
@ -79,7 +79,7 @@ module {
|
||||
/// Check that public functions do not track arguments.
|
||||
|
||||
// CHECK-LABEL: func @public(
|
||||
func @public(%arg0 : i32) -> (i32, i32) attributes { sym_visibility = "public" } {
|
||||
func @public(%arg0 : i32) -> (i32, i32) {
|
||||
%1 = constant 1 : i32
|
||||
return %1, %arg0 : i32, i32
|
||||
}
|
||||
@ -99,7 +99,7 @@ func @simple_public() -> (i32, i32) {
|
||||
|
||||
/// Check that functions with non-call users don't have arguments tracked.
|
||||
|
||||
func @callable(%arg0 : i32) -> (i32, i32) attributes { sym_visibility = "private" } {
|
||||
func private @callable(%arg0 : i32) -> (i32, i32) {
|
||||
%1 = constant 1 : i32
|
||||
return %1, %arg0 : i32, i32
|
||||
}
|
||||
@ -121,7 +121,7 @@ func @non_call_users() -> (i32, i32) {
|
||||
|
||||
/// Check that return values are overdefined in the presence of an unknown terminator.
|
||||
|
||||
func @callable(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
func private @callable(%arg0 : i32) -> i32 {
|
||||
"unknown.return"(%arg0) : (i32) -> ()
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ func @unknown_terminator() -> i32 {
|
||||
|
||||
/// Check that return values are overdefined when the constant conflicts.
|
||||
|
||||
func @callable(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
func private @callable(%arg0 : i32) -> i32 {
|
||||
"unknown.return"(%arg0) : (i32) -> ()
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ func @conflicting_constant() -> (i32, i32) {
|
||||
/// Check that return values are overdefined when the constant conflicts with a
|
||||
/// non-constant.
|
||||
|
||||
func @callable(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
func private @callable(%arg0 : i32) -> i32 {
|
||||
"unknown.return"(%arg0) : (i32) -> ()
|
||||
}
|
||||
|
||||
@ -181,8 +181,8 @@ func @conflicting_constant(%arg0 : i32) -> (i32, i32) {
|
||||
|
||||
/// Check a more complex interaction with calls and control flow.
|
||||
|
||||
// CHECK-LABEL: func @complex_inner_if(
|
||||
func @complex_inner_if(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
// 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
|
||||
@ -206,8 +206,8 @@ func @complex_inner_if(%arg0 : i32) -> i32 attributes { sym_visibility = "privat
|
||||
|
||||
func @complex_cond() -> i1
|
||||
|
||||
// CHECK-LABEL: func @complex_callee(
|
||||
func @complex_callee(%arg0 : i32) -> i32 attributes { sym_visibility = "private" } {
|
||||
// CHECK-LABEL: func private @complex_callee(
|
||||
func private @complex_callee(%arg0 : i32) -> i32 {
|
||||
// CHECK: %[[CST:.*]] = constant 1 : i32
|
||||
|
||||
%loop_cond = call @complex_cond() : () -> i1
|
||||
|
@ -5,25 +5,25 @@
|
||||
|
||||
// CHECK-LABEL: module attributes {test.simple}
|
||||
module attributes {test.simple} {
|
||||
// CHECK-NOT: func @dead_private_function
|
||||
func @dead_private_function() attributes { sym_visibility = "private" }
|
||||
// CHECK-NOT: func private @dead_private_function
|
||||
func private @dead_private_function()
|
||||
|
||||
// CHECK-NOT: func @dead_nested_function
|
||||
func @dead_nested_function() attributes { sym_visibility = "nested" }
|
||||
// CHECK-NOT: func nested @dead_nested_function
|
||||
func nested @dead_nested_function()
|
||||
|
||||
// CHECK: func @live_private_function
|
||||
func @live_private_function() attributes { sym_visibility = "private" }
|
||||
// CHECK: func private @live_private_function
|
||||
func private @live_private_function()
|
||||
|
||||
// CHECK: func @live_nested_function
|
||||
func @live_nested_function() attributes { sym_visibility = "nested" }
|
||||
// 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_function_explicit
|
||||
func @public_function_explicit() attributes { sym_visibility = "public" }
|
||||
// CHECK: func public @public_function_explicit
|
||||
func public @public_function_explicit()
|
||||
}
|
||||
|
||||
// -----
|
||||
@ -33,14 +33,14 @@ module attributes {test.simple} {
|
||||
module attributes {test.nested} {
|
||||
// CHECK: module @public_module
|
||||
module @public_module {
|
||||
// CHECK-NOT: func @dead_nested_function
|
||||
func @dead_nested_function() attributes { sym_visibility = "nested" }
|
||||
// CHECK-NOT: func nested @dead_nested_function
|
||||
func nested @dead_nested_function()
|
||||
|
||||
// CHECK: func @private_function
|
||||
func @private_function() attributes { sym_visibility = "private" }
|
||||
// CHECK: func private @private_function
|
||||
func private @private_function()
|
||||
|
||||
// CHECK: func @nested_function
|
||||
func @nested_function() attributes { sym_visibility = "nested" } {
|
||||
// CHECK: func nested @nested_function
|
||||
func nested @nested_function() {
|
||||
"foo.return"() {uses = [@private_function]} : () -> ()
|
||||
}
|
||||
}
|
||||
@ -56,20 +56,20 @@ module attributes {test.nested} {
|
||||
module attributes {test.no_dce_non_hidden_parent} {
|
||||
// NESTED: module @public_module
|
||||
module @public_module {
|
||||
// NESTED: func @nested_function
|
||||
func @nested_function() attributes { sym_visibility = "nested" }
|
||||
// NESTED: func nested @nested_function
|
||||
func nested @nested_function()
|
||||
}
|
||||
// NESTED: module @nested_module
|
||||
module @nested_module attributes { sym_visibility = "nested" } {
|
||||
// NESTED: func @nested_function
|
||||
func @nested_function() 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_function
|
||||
func @nested_function() attributes { sym_visibility = "nested" }
|
||||
// NESTED-NOT: func nested @nested_function
|
||||
func nested @nested_function()
|
||||
}
|
||||
|
||||
"live.user"() {uses = [@nested_module, @private_module]} : () -> ()
|
||||
@ -78,7 +78,7 @@ module attributes {test.no_dce_non_hidden_parent} {
|
||||
// -----
|
||||
|
||||
module {
|
||||
func @private_symbol() attributes { sym_visibility = "private" }
|
||||
func private @private_symbol()
|
||||
|
||||
// expected-error@+1 {{contains potentially unknown symbol table}}
|
||||
"foo.possibly_unknown_symbol_table"() ({
|
||||
|
@ -6,10 +6,10 @@
|
||||
// CHECK-LABEL: func @simple1(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
|
||||
|
||||
// CHECK-NOT: func @dead_nested_function
|
||||
func @dead_private_function() attributes { sym_visibility = "private" }
|
||||
func private @dead_private_function()
|
||||
|
||||
// CHECK-NOT: func @dead_nested_function
|
||||
func @dead_nested_function() attributes { sym_visibility = "nested" }
|
||||
func nested @dead_nested_function()
|
||||
|
||||
func @simple1(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) {
|
||||
"test.crashOp" () : () -> ()
|
||||
|
Loading…
x
Reference in New Issue
Block a user