2020-05-07 09:41:54 +08:00
|
|
|
//===-- Passes.td - Pass definition file -------------------*- 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2020-10-07 07:14:37 +08:00
|
|
|
#ifndef NPCOMP_REFBACKEND_PASSES
|
|
|
|
#define NPCOMP_REFBACKEND_PASSES
|
2020-05-07 09:41:54 +08:00
|
|
|
|
|
|
|
include "mlir/Pass/PassBase.td"
|
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
def BypassShapes : Pass<"bypass-shapes", "FuncOp"> {
|
|
|
|
let summary = "Bypass shape calculations around ops";
|
|
|
|
let constructor = "mlir::NPCOMP::createBypassShapesPass()";
|
2020-05-07 09:41:54 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
def LowerShapedResultsToMemref : Pass<"lower-shaped-results-to-memref", "FuncOp"> {
|
[RefBackend] Split out RefBackend (refback) dialect from TCP.
This is the first in a patch series that is refactoring the
constellation of things variously called or associated with "E2E",
"RefE2E", "npcomprt", and "TCP" into a more cleanly layered result.
Concretely, this first patch fixes the fact that TCP was basically
acting like a dumping ground needed by the reference backend. This
splits it out, which is fairly mechanical, but touches a lot of lines of
code (basically replacing `tcp` with `refback` and `TCP` with
`RefBackend).
Now, the RefBackend dialect is that dumping ground, which
is slighly better, as it starts allowing TCP to become a nice clean
middle layer that is not related per se to the reference backend.
The previous name RefE2E or "reference e2e flow" was super confusing.
Now that we are seeing more clearly where the "backend" distinction
lies, the [RefBackend] commit tag is born :)
2020-10-07 06:44:18 +08:00
|
|
|
let summary = "Lower refback.shaped_results regions";
|
2020-09-17 08:31:40 +08:00
|
|
|
let constructor = "mlir::NPCOMP::createLowerShapedResultsToMemrefPass()";
|
2020-07-11 08:31:24 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
def LowerStdToMemref : Pass<"lower-std-to-memref", "FuncOp"> {
|
|
|
|
let summary = "Lower std ops to memref";
|
|
|
|
let constructor = "mlir::NPCOMP::createLowerStdToMemrefPass()";
|
2020-05-07 09:41:54 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
def LowerConstantTensorsToMemref :
|
|
|
|
Pass<"lower-constant-tensors-to-memref", "ModuleOp"> {
|
|
|
|
let summary = "Lower std.constant of tensor type to memref";
|
|
|
|
let description = [{
|
[RefBackend] Split out RefBackend (refback) dialect from TCP.
This is the first in a patch series that is refactoring the
constellation of things variously called or associated with "E2E",
"RefE2E", "npcomprt", and "TCP" into a more cleanly layered result.
Concretely, this first patch fixes the fact that TCP was basically
acting like a dumping ground needed by the reference backend. This
splits it out, which is fairly mechanical, but touches a lot of lines of
code (basically replacing `tcp` with `refback` and `TCP` with
`RefBackend).
Now, the RefBackend dialect is that dumping ground, which
is slighly better, as it starts allowing TCP to become a nice clean
middle layer that is not related per se to the reference backend.
The previous name RefE2E or "reference e2e flow" was super confusing.
Now that we are seeing more clearly where the "backend" distinction
lies, the [RefBackend] commit tag is born :)
2020-10-07 06:44:18 +08:00
|
|
|
This must be a module pass since it involves creating refback.global ops.
|
2020-09-17 08:31:40 +08:00
|
|
|
}];
|
|
|
|
let constructor = "mlir::NPCOMP::createLowerConstantTensorsToMemrefPass()";
|
2020-05-12 05:24:57 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
def LowerStructuralToMemref :
|
|
|
|
Pass<"lower-structural-to-memref", "FuncOp"> {
|
|
|
|
let summary = "Lower structural IR constructs to memref";
|
|
|
|
let description = [{
|
|
|
|
Structural constructs include:
|
|
|
|
- control flow ops (both CFG and SCF)
|
|
|
|
- function signatures
|
|
|
|
- TODO: calls
|
|
|
|
An op is "structural" if it doesn't really care about the types it operates
|
|
|
|
on, but the types just have to converted to be consistent.
|
2020-05-12 09:50:51 +08:00
|
|
|
|
2020-09-17 08:31:40 +08:00
|
|
|
This pass also cleans up any previous memref<->tensor materializations,
|
|
|
|
finalizing the conversion from tensor to memref.
|
|
|
|
}];
|
|
|
|
let constructor = "mlir::NPCOMP::createLowerStructuralToMemrefPass()";
|
2020-05-12 12:22:40 +08:00
|
|
|
}
|
|
|
|
|
2020-10-08 08:12:52 +08:00
|
|
|
def LowerToRefbackrtABI : Pass<"lower-to-refbackrt-abi", "ModuleOp"> {
|
|
|
|
let summary = "Lower constructs requiring runtime support to `refbackrt`";
|
2020-09-17 08:31:40 +08:00
|
|
|
let description = [{
|
2020-10-08 08:12:52 +08:00
|
|
|
We have a specialized dialect `refbackrt` which models our runtime's data
|
2020-09-17 08:31:40 +08:00
|
|
|
structures, and function signatures (and presumably eventually, other
|
|
|
|
ABI boundaries like external calls if we ever support it) will be
|
|
|
|
converted.
|
|
|
|
|
|
|
|
The constructs requiring runtime support are:
|
|
|
|
- function signatures / module metadata
|
|
|
|
- globals
|
|
|
|
- error handling
|
|
|
|
}];
|
2020-10-08 08:12:52 +08:00
|
|
|
let constructor = "mlir::NPCOMP::createLowerToRefbackrtABIPass()";
|
2020-05-16 07:33:01 +08:00
|
|
|
}
|
|
|
|
|
2020-05-19 03:50:16 +08:00
|
|
|
def LowerAllocMemRefOps : Pass<"lower-alloc-memref-ops", "FuncOp"> {
|
|
|
|
let summary = "Lower AllocMemRefOp's";
|
|
|
|
let constructor = "mlir::NPCOMP::createLowerAllocMemRefOpsPass()";
|
|
|
|
}
|
|
|
|
|
2020-10-07 07:14:37 +08:00
|
|
|
def LowerToLLVM : Pass<"refback-lower-to-llvm", "ModuleOp"> {
|
2020-05-21 09:48:53 +08:00
|
|
|
let summary = "Lower everything to LLVM";
|
|
|
|
let constructor = "mlir::NPCOMP::createLowerToLLVMPass();";
|
|
|
|
}
|
|
|
|
|
2020-09-26 07:02:09 +08:00
|
|
|
// TODO: Move this pass to upstream.
|
|
|
|
// TODO: This pass will still do "folding" on all ops.
|
|
|
|
// The applyPatternsAndFoldGreedily driver will need to be changed to restrict
|
|
|
|
// folding to the specified dialects as well.
|
|
|
|
// Perhaps a better design is having a pass that uses the conversion framework.
|
|
|
|
// The the pass constructor would take a set of op names, and it would
|
|
|
|
// set up a conversion target that makes all those ops illegal, and uses
|
|
|
|
// the canonicalization patterns from those ops to legalize them.
|
|
|
|
def RestrictedCanonicalizer : Pass<"restricted-canonicalize"> {
|
|
|
|
let summary = "Canonicalize operations";
|
|
|
|
let description = [{
|
|
|
|
This pass is the same as the regular `canonicalize` pass, but it only
|
|
|
|
applies a restricted set of patterns.
|
|
|
|
|
|
|
|
This is useful when a particular canonicalization is actually needed for
|
|
|
|
correctness of a lowering flow. For such cases, running a restricted set of
|
|
|
|
canonicalizations makes it clearer which passes are needed for correctness
|
|
|
|
and which passes are "just optimizations". This helps when debugging
|
|
|
|
miscompiles and other situations where the compiler is not behaving as
|
|
|
|
expected.
|
|
|
|
}];
|
|
|
|
let constructor = "mlir::NPCOMP::createRestrictedCanonicalizerPass()";
|
|
|
|
let options = [
|
|
|
|
ListOption<"includedDialects", "included-dialects", "std::string",
|
|
|
|
"Which dialects should be canonicalized",
|
|
|
|
"llvm::cl::MiscFlags::CommaSeparated">
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-10-07 07:14:37 +08:00
|
|
|
#endif // NPCOMP_REFBACKEND_PASSES
|