diff options
Diffstat (limited to 'include/linalg1')
-rw-r--r-- | include/linalg1/Analysis.h | 49 | ||||
-rw-r--r-- | include/linalg1/Common.h | 120 | ||||
-rw-r--r-- | include/linalg1/ConvertToLLVMDialect.h | 66 | ||||
-rw-r--r-- | include/linalg1/Dialect.h | 42 | ||||
-rw-r--r-- | include/linalg1/Intrinsics.h | 32 | ||||
-rw-r--r-- | include/linalg1/LLVMIntrinsics.h | 41 | ||||
-rw-r--r-- | include/linalg1/Ops.h | 26 | ||||
-rw-r--r-- | include/linalg1/RangeOp.h | 56 | ||||
-rw-r--r-- | include/linalg1/RangeType.h | 49 | ||||
-rw-r--r-- | include/linalg1/SliceOp.h | 91 | ||||
-rw-r--r-- | include/linalg1/Types.h | 36 | ||||
-rw-r--r-- | include/linalg1/Utils.h | 37 | ||||
-rw-r--r-- | include/linalg1/ViewOp.h | 67 | ||||
-rw-r--r-- | include/linalg1/ViewType.h | 57 |
14 files changed, 769 insertions, 0 deletions
diff --git a/include/linalg1/Analysis.h b/include/linalg1/Analysis.h new file mode 100644 index 0000000..ef8fb98 --- /dev/null +++ b/include/linalg1/Analysis.h @@ -0,0 +1,49 @@ +//===- Analysis.h - Linalg dialect Analysis function definitions ----------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_ANALYSIS_H_ +#define LINALG1_ANALYSIS_H_ + +#include "mlir/Support/LLVM.h" + +namespace mlir { +class Value; +} // namespace mlir + +namespace linalg { +class ViewOp; + +/// Walks the chain of SliceOp until the unique base ViewOp. +ViewOp getViewBaseViewOp(mlir::Value *view); + +/// Walks the chain of SliceOp until the unique base ViewOp and returns the +/// MemRef upon which the ViewOp is laid. +mlir::Value *getViewSupportingMemRef(mlir::Value *view); + +/// Extract the indexing from the root ViewOp that this slice constrins along +/// `dim`. To achieve this, it walks back the chain of SliceOp and determine the +/// first slice that constrains `dim`. +/// Note that the dimension in the original ViewOp may shift due to +/// rank-reducing operations. +/// Returns a pair, with the indexing as the first element and the actual +/// dimension, in the root ViewOp, as the second element. +std::pair<mlir::Value *, unsigned> getViewRootIndexing(mlir::Value *view, + unsigned dim); + +} // namespace linalg + +#endif // LINALG1_ANALYSIS_H_ diff --git a/include/linalg1/Common.h b/include/linalg1/Common.h new file mode 100644 index 0000000..6573c72 --- /dev/null +++ b/include/linalg1/Common.h @@ -0,0 +1,120 @@ +//===- Common.h - Linalg dialect RangeOp operation -----------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_COMMON_H_ +#define LINALG1_COMMON_H_ + +#include "mlir/AffineOps/AffineOps.h" +#include "mlir/Analysis/SliceAnalysis.h" +#include "mlir/EDSC/Builders.h" +#include "mlir/EDSC/Helpers.h" +#include "mlir/EDSC/Intrinsics.h" +#include "mlir/IR/AffineExpr.h" +#include "mlir/IR/Attributes.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/Identifier.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/IR/Module.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/IR/StandardTypes.h" +#include "mlir/IR/Types.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/StandardOps/Ops.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/LoopUtils.h" +#include "mlir/Transforms/Passes.h" + +namespace linalg { +namespace common { + +//////////////////////////////////////////////////////////////////////////////// +// Define a few boilerplate objects used across all linalg examples. +//////////////////////////////////////////////////////////////////////////////// + +/// A 2-D abstraction over a flat contiguous memory region of f32 with symbolic +/// sizes. +template <int N> +inline mlir::MemRefType floatMemRefType(mlir::MLIRContext *context, + unsigned memorySpace = 0) { + llvm::SmallVector<int64_t, 4> shape(N, -1); + auto f32 = mlir::FloatType::getF32(context); + return mlir::MemRefType::get(shape, f32, {}, memorySpace); +} + +/// A basic function builder +inline mlir::Function *makeFunction(mlir::Module &module, llvm::StringRef name, + llvm::ArrayRef<mlir::Type> types, + llvm::ArrayRef<mlir::Type> resultTypes) { + auto *context = module.getContext(); + auto *function = new mlir::Function( + mlir::UnknownLoc::get(context), name, + mlir::FunctionType::get({types}, resultTypes, context)); + function->addEntryBlock(); + module.getFunctions().push_back(function); + return function; +} + +/// A basic pass manager pre-populated with cleanup passes. +inline std::unique_ptr<mlir::PassManager> cleanupPassManager() { + std::unique_ptr<mlir::PassManager> pm(new mlir::PassManager()); + pm->addPass(mlir::createCanonicalizerPass()); + pm->addPass(mlir::createSimplifyAffineStructuresPass()); + pm->addPass(mlir::createCSEPass()); + pm->addPass(mlir::createCanonicalizerPass()); + return pm; +} + +/// A simple function to verify and cleanup the IR before printing it to +/// llvm::outs() for FileCheck'ing. +/// If an error occurs, dump to llvm::errs() and do not print to llvm::outs() +/// which will make the associated FileCheck test fail. +inline void cleanupAndPrintFunction(mlir::Function *f) { + bool printToOuts = true; + auto check = [f, &printToOuts](mlir::LogicalResult result) { + if (failed(result)) { + f->getContext()->emitError(f->getLoc(), + "Verification and cleanup passes failed"); + printToOuts = false; + } + }; + auto pm = cleanupPassManager(); + check(f->getModule()->verify()); + check(pm->run(f->getModule())); + if (printToOuts) + f->print(llvm::outs()); +} + +/// Helper class to sugar building loop nests from indexings that appear in +/// ViewOp and SliceOp. +class LoopNestRangeBuilder { +public: + LoopNestRangeBuilder(llvm::ArrayRef<mlir::edsc::ValueHandle *> ivs, + llvm::ArrayRef<mlir::edsc::ValueHandle> indexings); + LoopNestRangeBuilder(llvm::ArrayRef<mlir::edsc::ValueHandle *> ivs, + llvm::ArrayRef<mlir::Value *> indexings); + mlir::edsc::ValueHandle + operator()(llvm::ArrayRef<mlir::edsc::CapturableHandle> stmts); + +private: + llvm::SmallVector<mlir::edsc::LoopBuilder, 4> loops; +}; + +} // namespace common +} // namespace linalg + +#endif // LINALG1_COMMON_H_ diff --git a/include/linalg1/ConvertToLLVMDialect.h b/include/linalg1/ConvertToLLVMDialect.h new file mode 100644 index 0000000..8e5a7ce --- /dev/null +++ b/include/linalg1/ConvertToLLVMDialect.h @@ -0,0 +1,66 @@ +//===- ConvertToLLVMDialect.h - conversion from Linalg to LLVM --*- C++ -*-===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_CONVERTTOLLVMDIALECT_H_ +#define LINALG1_CONVERTTOLLVMDIALECT_H_ + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/Allocator.h" + +#include <memory> + +namespace mlir { +class DialectConversion; +class DialectOpConversion; +class MLIRContext; +class Module; +class Type; +namespace LLVM { +class LLVMType; +} // end namespace LLVM +} // end namespace mlir + +namespace linalg { +/// Convert the given Linalg dialect type `t` into an LLVM IR dialect type. +/// Keep all other types unmodified. +mlir::Type convertLinalgType(mlir::Type t); + +/// Allocate the conversion patterns for RangeOp, ViewOp and SliceOp from the +/// Linalg dialect to the LLVM IR dialect. The converters are allocated in the +/// `allocator` using the provided `context`. The latter must have the LLVM IR +/// dialect registered. +/// This function can be used to apply multiple conversion patterns in the same +/// pass. It does not have to be called explicitly before the conversion. +llvm::DenseSet<mlir::DialectOpConversion *> +allocateDescriptorConverters(llvm::BumpPtrAllocator *allocator, + mlir::MLIRContext *context); + +/// Create a DialectConversion from the Linalg dialect to the LLVM IR dialect. +/// The conversion is set up to convert types and function signatures using +/// `convertLinalgType` and obtains operation converters by calling `initer`. +std::unique_ptr<mlir::DialectConversion> makeLinalgToLLVMLowering( + std::function<llvm::DenseSet<mlir::DialectOpConversion *>( + llvm::BumpPtrAllocator *, mlir::MLIRContext *context)> + initer); + +/// Convert the Linalg dialect types and RangeOp, ViewOp and SliceOp operations +/// to the LLVM IR dialect types and operations in the given `module`. This is +/// the main entry point to the conversion. +void convertToLLVM(mlir::Module &module); +} // end namespace linalg + +#endif // LINALG1_CONVERTTOLLVMDIALECT_H_ diff --git a/include/linalg1/Dialect.h b/include/linalg1/Dialect.h new file mode 100644 index 0000000..70023e1 --- /dev/null +++ b/include/linalg1/Dialect.h @@ -0,0 +1,42 @@ +//===- Dialect.h - Definition of the Linalg dialect -----------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_DIALECT_H_ +#define LINALG1_DIALECT_H_ + +#include "mlir/IR/Dialect.h" + +namespace linalg { + +/// The Linalg Dialect is not exposed to the outside world. It is registered by +/// linking and accessed via generic MLIR accessors. +class LinalgDialect : public mlir::Dialect { +public: + /// Create a new Dialect that is registered on construction and adds the + /// relevant types and operations. + explicit LinalgDialect(mlir::MLIRContext *context); + + /// Parse a type registered to this dialect. + mlir::Type parseType(llvm::StringRef spec, mlir::Location loc) const override; + + /// Print a type registered to this dialect. + void printType(mlir::Type type, llvm::raw_ostream &os) const override; +}; + +} // namespace linalg + +#endif // LINALG1_DIALECT_H_ diff --git a/include/linalg1/Intrinsics.h b/include/linalg1/Intrinsics.h new file mode 100644 index 0000000..305e3f3 --- /dev/null +++ b/include/linalg1/Intrinsics.h @@ -0,0 +1,32 @@ +//===- Intrinsics.h - Linalg intrinsics definitions -----------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_INTRINSICS_H_ +#define LINALG1_INTRINSICS_H_ + +#include "linalg1/Ops.h" +#include "mlir/EDSC/Intrinsics.h" + +namespace linalg { +namespace intrinsics { +using range = mlir::edsc::intrinsics::ValueBuilder<RangeOp>; +using slice = mlir::edsc::intrinsics::ValueBuilder<SliceOp>; +using view = mlir::edsc::intrinsics::ValueBuilder<ViewOp>; +} // namespace intrinsics +} // namespace linalg + +#endif // LINALG1_INTRINSICS_H_ diff --git a/include/linalg1/LLVMIntrinsics.h b/include/linalg1/LLVMIntrinsics.h new file mode 100644 index 0000000..577981b --- /dev/null +++ b/include/linalg1/LLVMIntrinsics.h @@ -0,0 +1,41 @@ +//===- LLVMIntrinsics.h - declarative builders for LLVM dialect -*- C++ -*-===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_LLVMINTRINSICS_H_ +#define LINALG1_LLVMINTRINSICS_H_ + +#include "mlir/EDSC/Builders.h" +#include "mlir/EDSC/Intrinsics.h" +#include "mlir/LLVMIR/LLVMDialect.h" + +// Expose some LLVM IR instructions to declarative builders. +namespace intrinsics { +using undef = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::UndefOp>; +using insertvalue = + mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::InsertValueOp>; +using extractvalue = + mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::ExtractValueOp>; +using constant = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::ConstantOp>; +using add = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::AddOp>; +using sub = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::SubOp>; +using mul = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::MulOp>; +using load = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::LoadOp>; +using store = mlir::edsc::intrinsics::OperationBuilder<mlir::LLVM::StoreOp>; +using gep = mlir::edsc::intrinsics::ValueBuilder<mlir::LLVM::GEPOp>; +} // end namespace intrinsics + +#endif // LINALG1_LLVMINTRINSICS_H_ diff --git a/include/linalg1/Ops.h b/include/linalg1/Ops.h new file mode 100644 index 0000000..2e662cf --- /dev/null +++ b/include/linalg1/Ops.h @@ -0,0 +1,26 @@ +//===- Ops.h - Linalg Ops single entry point ------------------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_OPS_H_ +#define LINALG1_OPS_H_ + +#include "linalg1/Types.h" +#include "linalg1/RangeOp.h" +#include "linalg1/SliceOp.h" +#include "linalg1/ViewOp.h" + +#endif // LINALG1_OPS_H_ diff --git a/include/linalg1/RangeOp.h b/include/linalg1/RangeOp.h new file mode 100644 index 0000000..9652f51 --- /dev/null +++ b/include/linalg1/RangeOp.h @@ -0,0 +1,56 @@ +//===- RangeOp.h - Linalg dialect RangeOp operation definition ------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_RANGEOP_H_ +#define LINALG1_RANGEOP_H_ + +#include "mlir/IR/OpDefinition.h" +#include "mlir/Support/LLVM.h" + +namespace linalg { + +/// A RangeOp is used to create a value of RangeType from 3 values of type index +/// that represent the min, max and step values of the range. +/// Note: step must be an mlir::ConstantIndexOp for now due to current +/// `affine.for` limitations. +class RangeOp : public mlir::Op<RangeOp, mlir::OpTrait::NOperands<3>::Impl, + mlir::OpTrait::OneResult, + mlir::OpTrait::HasNoSideEffect> { +public: + using Op::Op; + + ////////////////////////////////////////////////////////////////////////////// + // Hooks to customize the behavior of this op. + ////////////////////////////////////////////////////////////////////////////// + static llvm::StringRef getOperationName() { return "linalg.range"; } + static void build(mlir::Builder *b, mlir::OperationState *result, + mlir::Value *min, mlir::Value *max, mlir::Value *step); + mlir::LogicalResult verify(); + static bool parse(mlir::OpAsmParser *parser, mlir::OperationState *result); + void print(mlir::OpAsmPrinter *p); + + ////////////////////////////////////////////////////////////////////////////// + // Op-specific functionality. + ////////////////////////////////////////////////////////////////////////////// + mlir::Value *getMin() { return getOperand(0); } + mlir::Value *getMax() { return getOperand(1); } + mlir::Value *getStep() { return getOperand(2); } +}; + +} // namespace linalg + +#endif // LINALG1_RANGEOP_H_ diff --git a/include/linalg1/RangeType.h b/include/linalg1/RangeType.h new file mode 100644 index 0000000..d17c058 --- /dev/null +++ b/include/linalg1/RangeType.h @@ -0,0 +1,49 @@ +//===- RangeType.h - Linalg RangeType definition --------------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_RANGETYPE_H_ +#define LINALG1_RANGETYPE_H_ + +#include "linalg1/Types.h" +#include "mlir/IR/Types.h" + +namespace mlir { +class MLIRContext; +} + +namespace linalg { + +/// A RangeType is the simplest possible form of a type in MLIR. It represents +/// a minimal range abstraction (min, max, step). Since RangeType is constructed +/// without any additional argument, this example illustrates the minimal +/// amount of information required to implement a new custom MLIR type. +class RangeType : public mlir::Type::TypeBase<RangeType, mlir::Type> { +public: + // Used to implement llvm-style cast. + using Base::Base; + /// Construction hook. + static RangeType get(mlir::MLIRContext *context) { + /// Custom, uniqu'ed construction in the mlir::MLIRContext. + return Base::get(context, LinalgTypes::Range); + } + /// Used to implement llvm-style cast. + static bool kindof(unsigned kind) { return kind == LinalgTypes::Range; } +}; + +} // namespace linalg + +#endif // LINALG1_RANGETYPE_H_ diff --git a/include/linalg1/SliceOp.h b/include/linalg1/SliceOp.h new file mode 100644 index 0000000..1d79784 --- /dev/null +++ b/include/linalg1/SliceOp.h @@ -0,0 +1,91 @@ +//===- SliceOp.h - Linalg dialect SliceOp operation definition ------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_SLICEOP_H_ +#define LINALG1_SLICEOP_H_ + +#include "linalg1/Types.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/Support/LLVM.h" + +namespace linalg { + +/// A SliceOp is used to create a "sub-View" from a ViewType. It results in a +/// new ViewType which is contained within its parent ViewType. +class SliceOp : public mlir::Op<SliceOp, mlir::OpTrait::NOperands<2>::Impl, + mlir::OpTrait::OneResult, + mlir::OpTrait::HasNoSideEffect> { +public: + using Op::Op; + + ////////////////////////////////////////////////////////////////////////////// + // Hooks to customize the behavior of this op. + ////////////////////////////////////////////////////////////////////////////// + static llvm::StringRef getOperationName() { return "linalg.slice"; } + static void build(mlir::Builder *b, mlir::OperationState *result, + mlir::Value *view, mlir::Value *indexing, unsigned dim); + mlir::LogicalResult verify(); + static bool parse(mlir::OpAsmParser *parser, mlir::OperationState *result); + void print(mlir::OpAsmPrinter *p); + + ////////////////////////////////////////////////////////////////////////////// + // Op-specific functionality. + ////////////////////////////////////////////////////////////////////////////// + enum { FirstIndexingOperand = 1 }; + /// Returns the attribute name that describes which dimension of the input + /// view that this SliceOp slices. + static llvm::StringRef getSlicingDimAttrName() { return "dim"; } + /// Returns the unique result of the parent SliceOp of ViewOp instruction that + /// created the view on which this SliceOp operates. + mlir::Value *getParentView() { return getOperand(0); } + /// Returns the indexing operand of the current SliceOp. + /// This operands may either be: + /// 1. A range, in which case the operand comes from a RangeOp. This SliceOp + /// does not reduce the dimension of the input ViewType. + /// 2. An index, in which case the operand comes from any possible producer + /// of an index. This SliceOp reduces the dimension of the input ViewType + /// by 1. + mlir::Value *getIndexing() { return getOperand(1); } + /// Returns the dim of the parent ViewType that is sliced by this SliceOp. + unsigned getSlicingDim() { + return getAttrOfType<mlir::IntegerAttr>(getSlicingDimAttrName()).getInt(); + } + /// Returns the ViewType resulting from this SliceOp. + ViewType getViewType(); + /// Returns the rank of the current ViewType. + unsigned getRank(); + /// Return the element type of the current ViewType. + mlir::Type getElementType(); + + /// Returns the ViewType of `getParentView()`. + ViewType getParentViewType(); + /// Returns the rank of the ViewType of `getParentView()`. + unsigned getParentRank(); + /// Returns the element Type of the ViewType of `getParentView()`. + mlir::Type getParentElementType(); + + /// Returns true if the rank of the part view is greater than the rank of + /// the child view. + bool isRankDecreasing(); + + // Get all the indexings in this slice. + mlir::Operation::operand_range getIndexings(); +}; + +} // namespace linalg + +#endif // LINALG1_SLICEOP_H_ diff --git a/include/linalg1/Types.h b/include/linalg1/Types.h new file mode 100644 index 0000000..5032e96 --- /dev/null +++ b/include/linalg1/Types.h @@ -0,0 +1,36 @@ +//===- Types.h - Linalg Types forward declarations ------------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_TYPES_H_ +#define LINALG1_TYPES_H_ + +#include "mlir/IR/Types.h" + +namespace linalg { + +enum LinalgTypes { + Range = mlir::Type::FIRST_PRIVATE_EXPERIMENTAL_0_TYPE, + View, + FIRST_PRIVATE_EXPERIMENTAL_0_TYPE = View, +}; + +} // namespace linalg + +#include "linalg1/RangeType.h" +#include "linalg1/ViewType.h" + +#endif // LINALG1_TYPES_H_ diff --git a/include/linalg1/Utils.h b/include/linalg1/Utils.h new file mode 100644 index 0000000..3f7bb76 --- /dev/null +++ b/include/linalg1/Utils.h @@ -0,0 +1,37 @@ +//===- Utils.h - Linalg dialect utility functions definitions -------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_UTILS_H_ +#define LINALG1_UTILS_H_ + +namespace mlir { +class Value; +} // namespace mlir + +namespace linalg { +class ViewOp; + +/// Asserts `view` is of ViewType and returns its rank. +unsigned getViewRank(mlir::Value *view); + +/// Helper function to emit and return a new ViewOp from `memRef` that is +/// assumed to be of MemRefType. This needs to be called under a ScopedContext. +ViewOp emitAndReturnViewOpFromMemRef(mlir::Value *memRef); + +} // namespace linalg + +#endif // LINALG1_UTILS_H_ diff --git a/include/linalg1/ViewOp.h b/include/linalg1/ViewOp.h new file mode 100644 index 0000000..fcda553 --- /dev/null +++ b/include/linalg1/ViewOp.h @@ -0,0 +1,67 @@ +//===- ViewOp.h - Linalg dialect ViewOp operation definition ------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_VIEWOP_H_ +#define LINALG1_VIEWOP_H_ + +#include "mlir/IR/OpDefinition.h" +#include "mlir/Support/LLVM.h" + +namespace linalg { + +class ViewType; + +/// A `ViewOp` produces a `ViewType` which is a multi-dimensional range +/// abstraction on top of an underlying data type. For now we use the existing +/// mlir::MemRef for the underlying data type. +class ViewOp : public mlir::Op<ViewOp, mlir::OpTrait::VariadicOperands, + mlir::OpTrait::OneResult, + mlir::OpTrait::HasNoSideEffect> { +public: + using Op::Op; + + ////////////////////////////////////////////////////////////////////////////// + // Hooks to customize the behavior of this op. + ////////////////////////////////////////////////////////////////////////////// + static llvm::StringRef getOperationName() { return "linalg.view"; } + static void build(mlir::Builder *b, mlir::OperationState *result, + mlir::Value *memRef, + llvm::ArrayRef<mlir::Value *> indexings); + mlir::LogicalResult verify(); + static bool parse(mlir::OpAsmParser *parser, mlir::OperationState *result); + void print(mlir::OpAsmPrinter *p); + + ////////////////////////////////////////////////////////////////////////////// + // Op-specific functionality. + ////////////////////////////////////////////////////////////////////////////// + enum { FirstIndexingOperand = 1 }; + unsigned getRank(); + mlir::Type getElementType(); + ViewType getViewType(); + // May be something else than a MemRef in the future. + mlir::Value *getSupportingMemRef(); + // Get the underlying indexing at a given rank. + mlir::Value *getIndexing(unsigned rank); + // Get all the indexings of type RangeOp. + llvm::SmallVector<mlir::Value *, 8> getRanges(); + // Get all the indexings in this view. + mlir::Operation::operand_range getIndexings(); +}; + +} // namespace linalg + +#endif // LINALG1_VIEWOP_H_ diff --git a/include/linalg1/ViewType.h b/include/linalg1/ViewType.h new file mode 100644 index 0000000..c58e12c --- /dev/null +++ b/include/linalg1/ViewType.h @@ -0,0 +1,57 @@ +//===- ViewType.h - Linalg ViewType definition --------------------------===// +// +// Copyright 2019 The MLIR Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ============================================================================= + +#ifndef LINALG1_VIEWTYPE_H_ +#define LINALG1_VIEWTYPE_H_ + +#include "linalg1/Types.h" +#include "mlir/IR/Types.h" + +namespace linalg { + +class ViewTypeStorage; + +/// A ViewType represents a range abstraction on top of an underlying storage +/// type. It is parameterizable by the underlying element type and the rank of +/// the view. +class ViewType + : public mlir::Type::TypeBase<ViewType, mlir::Type, ViewTypeStorage> { +public: + ////////////////////////////////////////////////////////////////////////////// + // Hooks to customize the behavior of this type. + ////////////////////////////////////////////////////////////////////////////// + // Used to implement llvm-style cast. + using Base::Base; + // Used to implement llvm-style cast. + static bool kindof(unsigned kind) { return kind == LinalgTypes::View; } + /// Construction hook. + static ViewType get(mlir::MLIRContext *context, mlir::Type elementType, + unsigned rank); + + ////////////////////////////////////////////////////////////////////////////// + // Type-specific functionality. + ////////////////////////////////////////////////////////////////////////////// + /// Return the underlying elemental type. + mlir::Type getElementType(); + /// Return the rank of the view. + /// This is the number of indexings needed to reach an underlying element. + unsigned getRank(); +}; + +} // namespace linalg + +#endif // LINALG1_VIEWTYPE_H_ |