Skip to content

WIP on some CIR → MLIR experiment #1334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 23 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f3c6945
[CIR][Lowering][NFC] Expose cir::prepareTypeConverter()
keryell Oct 9, 2024
1013314
[CIR] Add inline interface to CIR dialect
keryell Nov 20, 2024
e775742
[CIR] Add runAtStartOfConvertCIRToMLIRPass() to ConvertCIRToMLIRPass
keryell Dec 4, 2024
8bd9a8d
[CIR] Add runAtStartOfConvertCIRToLLVMPass() to ConvertCIRToLLVMPass
keryell Dec 18, 2024
e705fad
[CIR] Lower struct/union/class to tuple
keryell Jan 14, 2025
3793fc3
[CIR][MLIR] Allow memref of tuple
keryell Jan 22, 2025
ce2133d
[CIR][MLIR] Add minimal NamedTuple to core MLIR
keryell Jan 29, 2025
762695a
[CIR][MLIR] named_tuple.cast operation
keryell Feb 10, 2025
a09a2e8
[CIR][MLIR] Add some named_tuple type introspection functions
keryell Feb 11, 2025
12626d1
[CIR] Lower cir.get_member to named_tuple + memref casts
keryell Feb 11, 2025
64a0abd
[CIR] Lower to MLIR struct with array member
keryell Feb 14, 2025
a967bc7
[CIR][Lowering] Lower arrays in class/struct/union as tensor
keryell Feb 14, 2025
9ce66f2
[CIR][Lowering] Handle pointer of pointer of struct or array
keryell Feb 15, 2025
c1ddaff
[CIR][Lowering][MLIR] Export cir::lowerArrayType()
keryell Feb 18, 2025
1097f87
[CIR][Lowering][MLIR] Lower class/struct/union to memref by default
keryell Feb 19, 2025
6c35a8f
[CIR][Lowering][MLIR] Lower cir.cast(bitcast) between !cir.ptr
keryell Feb 21, 2025
a207932
[CIR][Lowering][MLIR] Rework the !cir.array lowering
keryell Feb 22, 2025
90b70f4
[CIR][Doc] Add some top-level documentation on CIR→MLIR WIP
keryell Feb 26, 2025
15abba4
[CIR][Lower][MLIR] Handle pointer decay of higher dimensions arrays
keryell Feb 28, 2025
429b8ae
[CIR][Lowering][MLIR] Generalize the lowering of cir.ptr_stride
keryell Feb 28, 2025
9338d3f
[CIR][Lowering][MLIR] Remove a layout API
keryell Mar 21, 2025
39b162f
[CIR][Lowering][NFC] Update code to upstream cir::RecordType
keryell Apr 17, 2025
7275515
[CIR][ThroughMLIR][NFC] Fix test syntax
keryell Apr 18, 2025
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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
# ClangIR (CIR)

## Work-in-progress on CIR→MLIR lowering

This is a huge work-in-progress version adding new features used by [`aie++` C++
programming model](https://github.com/keryell/mlir-aie/tree/clangir), such as
better support for lowering through MLIR standard dialects.

What is experimented here:
- adding new features to CIR→MLIR lowering;
- cleaner lowering C/C++arrays as `tensor` for value semantics (for example in
structs) and `memref` for reference semantics (all the other uses);
- fixing array support and allocation;
- allowing pointer to array or struct;
- adding support for class/struct/union by first experimenting with `tuple` and
then introducing a new `named_tuple` dialect;
- implementation of more type of C/C++ casts;
- support struct member access through some `memref` flattening and casting
casting;
- fixing a lot of verification bugs which are triggered when using ClangIR in a
broader framework;
- enabling in-lining interface to CIR dialect;
- exposing some API to use ClangIR from a broader framework.

The output of this new lowering flow has not been tested yet followed by the
MLIR std→LLVMIR.

An alternative design could be to rely on some MLIR std→LLVMIR→MLIR std
back-and-forth traveling in the same module to have some parts of the LLVMIR
dialect to implement some missing features like it is done in the
[Polygeist](https://github.com/llvm/Polygeist) project.

## Main documentation

Check https://clangir.org for general information, build instructions and documentation.
5 changes: 5 additions & 0 deletions clang/include/clang/CIR/LowerToLLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#define CLANG_CIR_LOWERTOLLVM_H

#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"

#include <functional>
#include <memory>

namespace llvm {
Expand All @@ -34,6 +36,9 @@ mlir::ModuleOp lowerDirectlyFromCIRToLLVMDialect(mlir::ModuleOp theModule,
bool disableCCLowering = false,
bool disableDebugInfo = false);

void runAtStartOfConvertCIRToLLVMPass(
std::function<void(mlir::ConversionTarget)>);

// Lower directly from pristine CIR to LLVMIR.
std::unique_ptr<llvm::Module> lowerDirectlyFromCIRToLLVMIR(
mlir::ModuleOp theModule, llvm::LLVMContext &llvmCtx,
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/CIR/LowerToMLIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,24 @@
#ifndef CLANG_CIR_LOWERTOMLIR_H
#define CLANG_CIR_LOWERTOMLIR_H

#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include <functional>

namespace cir {

void populateCIRLoopToSCFConversionPatterns(mlir::RewritePatternSet &patterns,
mlir::TypeConverter &converter);

mlir::Type lowerArrayType(cir::ArrayType type, bool hasValueSemantics,
mlir::TypeConverter &converter);

mlir::TypeConverter prepareTypeConverter(mlir::DataLayout &dataLayout);

void runAtStartOfConvertCIRToMLIRPass(
std::function<void(mlir::ConversionTarget)>);

mlir::ModuleOp
lowerFromCIRToMLIRToLLVMDialect(mlir::ModuleOp theModule,
mlir::MLIRContext *mlirCtx = nullptr);
Expand Down
37 changes: 36 additions & 1 deletion clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/InliningUtils.h"

using namespace mlir;

Expand Down Expand Up @@ -117,6 +118,40 @@ struct CIROpAsmDialectInterface : public OpAsmDialectInterface {
.Default([](Attribute) { return AliasResult::NoAlias; });
}
};

// Minimal interface to inline region with only one block for now (not handling
// the terminator remapping), assuming everything is inlinable.
struct CIRInlinerInterface : DialectInlinerInterface {
using DialectInlinerInterface::DialectInlinerInterface;
// Always allows inlining.
bool isLegalToInline(Operation *call, Operation *callable,
bool wouldBeCloned) const final override {
return true;
}

// Always allows inlining.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
IRMapping &valueMapping) const final override {
return true;
}

// Always allows inlining.
bool isLegalToInline(Operation *op, Region *, bool wouldBeCloned,
IRMapping &) const final override {
return true;
}

// Handle the terminator in the case of a single block
void handleTerminator(Operation *op,
ValueRange valuesToReplace) const final override {
// Only handle cir.return for now
if (auto returnOp = dyn_cast<cir::ReturnOp>(op))
for (auto &&[value, operand] :
llvm::zip(valuesToReplace, returnOp.getOperands()))
value.replaceAllUsesWith(operand);
}
};

} // namespace

/// Dialect initialization, the instance will be owned by the context. This is
Expand All @@ -128,7 +163,7 @@ void cir::CIRDialect::initialize() {
#define GET_OP_LIST
#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
>();
addInterfaces<CIROpAsmDialectInterface>();
addInterfaces<CIRInlinerInterface, CIROpAsmDialectInterface>();
}

Operation *cir::CIRDialect::materializeConstant(mlir::OpBuilder &builder,
Expand Down
14 changes: 13 additions & 1 deletion clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ mlir::Value CirAttrToValue::visitCirAttr(cir::ConstArrayAttr constArr) {
auto loc = parentOp->getLoc();
mlir::Value result;

if (auto zeros = constArr.getTrailingZerosNum()) {
if (constArr.getTrailingZerosNum()) {
auto arrayTy = constArr.getType();
result = rewriter.create<mlir::LLVM::ZeroOp>(
loc, converter->convertType(arrayTy));
Expand Down Expand Up @@ -1381,6 +1381,8 @@ struct ConvertCIRToLLVMPass

void processCIRAttrs(mlir::ModuleOp moduleOp);

inline static std::function<void(mlir::ConversionTarget)> runAtStartHook;

StringRef getDescription() const override {
return "Convert the prepared CIR dialect module to LLVM dialect";
}
Expand Down Expand Up @@ -4781,6 +4783,9 @@ void ConvertCIRToLLVMPass::runOnOperation() {
// ,YieldOp
>();
// clang-format on
if (runAtStartHook)
runAtStartHook(target);

target.addLegalDialect<mlir::LLVM::LLVMDialect>();
target.addIllegalDialect<mlir::BuiltinDialect, cir::CIRDialect,
mlir::func::FuncDialect>();
Expand Down Expand Up @@ -4818,6 +4823,13 @@ void ConvertCIRToLLVMPass::runOnOperation() {
processCIRAttrs(module);
}

/// Set a hook to be called just before applying the dialect conversion so other
/// dialects or patterns can be added
void runAtStartOfConvertCIRToLLVMPass(
std::function<void(mlir::ConversionTarget)> hook) {
ConvertCIRToLLVMPass::runAtStartHook = std::move(hook);
}

std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
return std::make_unique<ConvertCIRToLLVMPass>();
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_clang_library(clangCIRLoweringThroughMLIR
MLIRTransforms
MLIRSupport
MLIRMemRefDialect
MLIRNamedTupleDialect
MLIROpenMPDialect
MLIROpenMPToLLVMIRTranslation
)
Loading
Loading