Skip to content

Commit

Permalink
Add FIR
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanPerier committed Feb 27, 2020
1 parent d9871fa commit f53a6e9
Show file tree
Hide file tree
Showing 30 changed files with 6,782 additions and 14 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ add_definitions(${LLVM_DEFINITIONS})
set(LLVM_EXTERNAL_LIT ${LLVM_TOOLS_BINARY_DIR}/llvm-lit CACHE STRING "Command used to spawn lit")

if(LINK_WITH_FIR)
include(TableGen)
include(AddMLIR)
find_program(MLIR_TABLEGEN_EXE "mlir-tblgen" ${LLVM_TOOLS_BINARY_DIR}
NO_DEFAULT_PATH)
# tco/bbc tools output directory
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/lib)
message(STATUS "Linking driver with FIR and LLVM")
llvm_map_components_to_libnames(LLVM_COMMON_LIBS support)
message(STATUS "LLVM libraries: ${LLVM_COMMON_LIBS}")
Expand Down
2 changes: 0 additions & 2 deletions include/fir/.clang-format

This file was deleted.

11 changes: 3 additions & 8 deletions include/flang/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#===-- include/flang/CMakeLists.txt ----------------------------------------===#
#
# 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
#
#===------------------------------------------------------------------------===#

if(LINK_WITH_FIR)
add_subdirectory(Optimizer)
endif()
1 change: 1 addition & 0 deletions include/flang/Optimizer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(Dialect)
4 changes: 4 additions & 0 deletions include/flang/Optimizer/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(LLVM_TARGET_DEFINITIONS FIROps.td)
mlir_tablegen(FIROps.h.inc -gen-op-decls)
mlir_tablegen(FIROps.cpp.inc -gen-op-defs)
add_public_tablegen_target(FIROpsIncGen)
166 changes: 166 additions & 0 deletions include/flang/Optimizer/Dialect/FIRAttr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
//===-- optimizer/Dialect/FIRAttr.h -- FIR attributes -----------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef OPTIMIZER_DIALECT_FIRATTR_H
#define OPTIMIZER_DIALECT_FIRATTR_H

#include "mlir/IR/Attributes.h"

namespace mlir {
class DialectAsmParser;
class DialectAsmPrinter;
} // namespace mlir

namespace fir {

class FIROpsDialect;

namespace detail {
struct RealAttributeStorage;
struct TypeAttributeStorage;
} // namespace detail

enum AttributeKind {
FIR_ATTR = mlir::Attribute::FIRST_FIR_ATTR,
FIR_EXACTTYPE, // instance_of, precise type relation
FIR_SUBCLASS, // subsumed_by, is-a (subclass) relation
FIR_POINT,
FIR_CLOSEDCLOSED_INTERVAL,
FIR_OPENCLOSED_INTERVAL,
FIR_CLOSEDOPEN_INTERVAL,
FIR_REAL_ATTR,
};

class ExactTypeAttr
: public mlir::Attribute::AttrBase<ExactTypeAttr, mlir::Attribute,
detail::TypeAttributeStorage> {
public:
using Base::Base;
using ValueType = mlir::Type;

static constexpr llvm::StringRef getAttrName() { return "instance"; }
static ExactTypeAttr get(mlir::Type value);

mlir::Type getType() const;

static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() { return AttributeKind::FIR_EXACTTYPE; }
};

class SubclassAttr
: public mlir::Attribute::AttrBase<SubclassAttr, mlir::Attribute,
detail::TypeAttributeStorage> {
public:
using Base::Base;
using ValueType = mlir::Type;

static constexpr llvm::StringRef getAttrName() { return "subsumed"; }
static SubclassAttr get(mlir::Type value);

mlir::Type getType() const;

static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() { return AttributeKind::FIR_SUBCLASS; }
};

// Attributes for building SELECT CASE multiway branches

/// A closed interval (including the bound values) is an interval with both an
/// upper and lower bound as given as ssa-values.
/// A case selector of `CASE (n:m)` corresponds to any value from `n` to `m` and
/// is encoded as `#fir.interval, %n, %m`.
class ClosedIntervalAttr
: public mlir::Attribute::AttrBase<ClosedIntervalAttr> {
public:
using Base::Base;

static constexpr llvm::StringRef getAttrName() { return "interval"; }
static ClosedIntervalAttr get(mlir::MLIRContext *ctxt);
static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() {
return AttributeKind::FIR_CLOSEDCLOSED_INTERVAL;
}
};

/// An upper bound is an open interval (including the bound value) as given as
/// an ssa-value.
/// A case selector of `CASE (:m)` corresponds to any value up to and including
/// `m` and is encoded as `#fir.upper, %m`.
class UpperBoundAttr : public mlir::Attribute::AttrBase<UpperBoundAttr> {
public:
using Base::Base;

static constexpr llvm::StringRef getAttrName() { return "upper"; }
static UpperBoundAttr get(mlir::MLIRContext *ctxt);
static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() {
return AttributeKind::FIR_OPENCLOSED_INTERVAL;
}
};

/// A lower bound is an open interval (including the bound value) as given as
/// an ssa-value.
/// A case selector of `CASE (n:)` corresponds to any value down to and
/// including `n` and is encoded as `#fir.lower, %n`.
class LowerBoundAttr : public mlir::Attribute::AttrBase<LowerBoundAttr> {
public:
using Base::Base;

static constexpr llvm::StringRef getAttrName() { return "lower"; }
static LowerBoundAttr get(mlir::MLIRContext *ctxt);
static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() {
return AttributeKind::FIR_CLOSEDOPEN_INTERVAL;
}
};

/// A pointer interval is an closed interval as given as an ssa-value. The
/// interval contains exactly one value.
/// A case selector of `CASE (p)` corresponds to exactly the value `p` and is
/// encoded as `#fir.point, %p`.
class PointIntervalAttr : public mlir::Attribute::AttrBase<PointIntervalAttr> {
public:
using Base::Base;

static constexpr llvm::StringRef getAttrName() { return "point"; }
static PointIntervalAttr get(mlir::MLIRContext *ctxt);
static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() { return AttributeKind::FIR_POINT; }
};

/// A real attribute is used to workaround MLIR's default parsing of a real
/// constant.
/// `#fir.real<10, 3.14>` is used to introduce a real constant of value `3.14`
/// with a kind of `10`.
class RealAttr
: public mlir::Attribute::AttrBase<RealAttr, mlir::Attribute,
detail::RealAttributeStorage> {
public:
using Base::Base;
using ValueType = std::pair<int, llvm::APFloat>;

static constexpr llvm::StringRef getAttrName() { return "real"; }
static RealAttr get(mlir::MLIRContext *ctxt, const ValueType &key);

int getFKind() const;
llvm::APFloat getValue() const;

static constexpr bool kindof(unsigned kind) { return kind == getId(); }
static constexpr unsigned getId() { return AttributeKind::FIR_REAL_ATTR; }
};

mlir::Attribute parseFirAttribute(FIROpsDialect *dialect,
mlir::DialectAsmParser &parser,
mlir::Type type);

void printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,
mlir::DialectAsmPrinter &p);

} // namespace fir

#endif // OPTIMIZER_DIALECT_FIRATTR_H
86 changes: 86 additions & 0 deletions include/flang/Optimizer/Dialect/FIRDialect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//===-- optimizer/Dialect/FIRDialect.h -- FIR dialect -----------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef OPTIMIZER_DIALECT_FIRDIALECT_H
#define OPTIMIZER_DIALECT_FIRDIALECT_H

#include "mlir/IR/Dialect.h"
#include "mlir/InitAllPasses.h"

namespace llvm {
class raw_ostream;
class StringRef;
} // namespace llvm

namespace mlir {
class Attribute;
class DialectAsmParser;
class DialectAsmPrinter;
class Location;
class MLIRContext;
class Type;
} // namespace mlir

namespace fir {

/// FIR dialect
class FIROpsDialect final : public mlir::Dialect {
public:
explicit FIROpsDialect(mlir::MLIRContext *ctx);
virtual ~FIROpsDialect();

static llvm::StringRef getDialectNamespace() { return "fir"; }

mlir::Type parseType(mlir::DialectAsmParser &parser) const override;
void printType(mlir::Type ty, mlir::DialectAsmPrinter &p) const override;

mlir::Attribute parseAttribute(mlir::DialectAsmParser &parser,
mlir::Type type) const override;
void printAttribute(mlir::Attribute attr,
mlir::DialectAsmPrinter &p) const override;
};

/// Register the dialect with MLIR
inline void registerFIR() {
// we want to register exactly once
[[maybe_unused]] static bool init_once = [] {
mlir::registerDialect<FIROpsDialect>();
return true;
}();
}

/// Register the standard passes we use. This comes from registerAllPasses(),
/// but is a smaller set since we aren't using many of the passes found there.
inline void registerGeneralPasses() {
mlir::createCanonicalizerPass();
mlir::createCSEPass();
mlir::createVectorizePass({});
mlir::createLoopUnrollPass();
mlir::createLoopUnrollAndJamPass();
mlir::createSimplifyAffineStructuresPass();
mlir::createLoopFusionPass();
mlir::createLoopInvariantCodeMotionPass();
mlir::createAffineLoopInvariantCodeMotionPass();
mlir::createPipelineDataTransferPass();
mlir::createLowerAffinePass();
mlir::createLoopTilingPass(0);
mlir::createLoopCoalescingPass();
mlir::createAffineDataCopyGenerationPass(0, 0);
mlir::createMemRefDataFlowOptPass();
mlir::createStripDebugInfoPass();
mlir::createPrintOpStatsPass();
mlir::createInlinerPass();
mlir::createSymbolDCEPass();
mlir::createLocationSnapshotPass({});
}

inline void registerFIRPasses() { registerGeneralPasses(); }

} // namespace fir

#endif // OPTIMIZER_DIALECT_FIRDIALECT_H
74 changes: 74 additions & 0 deletions include/flang/Optimizer/Dialect/FIROps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//===-- optimizer/Dialect/FIROps.h - FIR operations -------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef OPTIMIZER_DIALECT_FIROPS_H
#define OPTIMIZER_DIALECT_FIROPS_H

#include "mlir/IR/Builders.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/SymbolTable.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"

using namespace mlir;

namespace fir {

class FirEndOp;

enum class CmpFPredicate {
FirstValidValue,
// Always false
AlwaysFalse = FirstValidValue,
// Ordered comparisons
OEQ,
OGT,
OGE,
OLT,
OLE,
ONE,
// Both ordered
ORD,
// Unordered comparisons
UEQ,
UGT,
UGE,
ULT,
ULE,
UNE,
// Any unordered
UNO,
// Always true
AlwaysTrue,
// Number of predicates.
NumPredicates
};

ParseResult isValidCaseAttr(Attribute attr);
unsigned getCaseArgumentOffset(ArrayRef<Attribute> cases, unsigned dest);
ParseResult parseSelector(OpAsmParser *parser, OperationState *result,
OpAsmParser::OperandType &selector, mlir::Type &type);

void buildCmpFOp(Builder *builder, OperationState &result,
CmpFPredicate predicate, Value lhs, Value rhs);
void buildCmpCOp(Builder *builder, OperationState &result,
CmpFPredicate predicate, Value lhs, Value rhs);
ParseResult parseCmpfOp(OpAsmParser &parser, OperationState &result);
ParseResult parseCmpcOp(OpAsmParser &parser, OperationState &result);

#define GET_OP_CLASSES
#include "flang/Optimizer/Dialect/FIROps.h.inc"

LoopOp getForInductionVarOwner(Value val);

bool isReferenceLike(mlir::Type type);

} // namespace fir

#endif // OPTIMIZER_DIALECT_FIROPS_H
Loading

0 comments on commit f53a6e9

Please sign in to comment.