Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 tool and FIR lib output directories
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