Skip to content

[CIR][Lowering][NFC] Move helper functions to LoweringHelpers.cpp #754

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

Merged
merged 1 commit into from
Jul 25, 2024
Merged
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
43 changes: 43 additions & 0 deletions clang/include/clang/CIR/LoweringHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//====- LoweringHelpers.h - Lowering helper functions ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file declares helper functions for lowering from CIR to LLVM or MLIR.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CIR_LOWERINGHELPERS_H
#define LLVM_CLANG_CIR_LOWERINGHELPERS_H
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"

mlir::DenseElementsAttr
convertStringAttrToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
mlir::Type type);

template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type Ty);
template <> mlir::APInt getZeroInitFromType(mlir::Type Ty);
template <> mlir::APFloat getZeroInitFromType(mlir::Type Ty);

mlir::Type getNestedTypeAndElemQuantity(mlir::Type Ty, unsigned &elemQuantity);

template <typename AttrTy, typename StorageTy>
void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr,
llvm::SmallVectorImpl<StorageTy> &values);

template <typename AttrTy, typename StorageTy>
mlir::DenseElementsAttr
convertToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
const llvm::SmallVectorImpl<int64_t> &dims,
mlir::Type type);

std::optional<mlir::Attribute>
lowerConstArrayAttr(mlir::cir::ConstArrayAttr constArr,
const mlir::TypeConverter *converter);
#endif
40 changes: 40 additions & 0 deletions clang/lib/CIR/Lowering/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,42 @@
set(LLVM_LINK_COMPONENTS
Core
Support
)

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)

add_clang_library(clangCIRLoweringHelpers
LoweringHelpers.cpp

DEPENDS
MLIRCIROpsIncGen
MLIRCIREnumsGen
MLIRCIRASTAttrInterfacesIncGen
MLIRCIROpInterfacesIncGen
MLIRCIRLoopOpInterfaceIncGen
MLIRBuiltinLocationAttributesIncGen
MLIRBuiltinTypeInterfacesIncGen
MLIRFunctionInterfacesIncGen

LINK_LIBS
clangAST
clangBasic
clangCodeGen
clangLex
clangFrontend
clangCIR
${dialect_libs}
MLIRCIR
MLIRAnalysis
MLIRBuiltinToLLVMIRTranslation
MLIRLLVMToLLVMIRTranslation
MLIRIR
MLIRParser
MLIRSideEffectInterfaces
MLIRTransforms
MLIRSupport
MLIRMemRefDialect
)

add_subdirectory(DirectToLLVM)
add_subdirectory(ThroughMLIR)
1 change: 1 addition & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_clang_library(clangCIRLoweringDirectToLLVM
clangLex
clangFrontend
clangCIR
clangCIRLoweringHelpers
${dialect_libs}
MLIRCIR
MLIRAnalysis
Expand Down
129 changes: 1 addition & 128 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Export.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/LoweringHelpers.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
Expand Down Expand Up @@ -962,134 +963,6 @@ class CIRStoreLowering : public mlir::OpConversionPattern<mlir::cir::StoreOp> {
}
};

mlir::DenseElementsAttr
convertStringAttrToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
mlir::Type type) {
auto values = llvm::SmallVector<mlir::APInt, 8>{};
auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts());
assert(stringAttr && "expected string attribute here");
for (auto element : stringAttr)
values.push_back({8, (uint64_t)element});
return mlir::DenseElementsAttr::get(
mlir::RankedTensorType::get({(int64_t)values.size()}, type),
llvm::ArrayRef(values));
}

template <typename StorageTy> StorageTy getZeroInitFromType(mlir::Type Ty);

template <> mlir::APInt getZeroInitFromType(mlir::Type Ty) {
assert(mlir::isa<mlir::cir::IntType>(Ty) && "expected int type");
auto IntTy = mlir::cast<mlir::cir::IntType>(Ty);
return mlir::APInt::getZero(IntTy.getWidth());
}

template <> mlir::APFloat getZeroInitFromType(mlir::Type Ty) {
assert((mlir::isa<mlir::cir::SingleType, mlir::cir::DoubleType>(Ty)) &&
"only float and double supported");
if (Ty.isF32() || mlir::isa<mlir::cir::SingleType>(Ty))
return mlir::APFloat(0.f);
if (Ty.isF64() || mlir::isa<mlir::cir::DoubleType>(Ty))
return mlir::APFloat(0.0);
llvm_unreachable("NYI");
}

// return the nested type and quantity of elements for cir.array type.
// e.g: for !cir.array<!cir.array<!s32i x 3> x 1>
// it returns !s32i as return value and stores 3 to elemQuantity.
mlir::Type getNestedTypeAndElemQuantity(mlir::Type Ty, unsigned &elemQuantity) {
assert(mlir::isa<mlir::cir::ArrayType>(Ty) && "expected ArrayType");

elemQuantity = 1;
mlir::Type nestTy = Ty;
while (auto ArrTy = mlir::dyn_cast<mlir::cir::ArrayType>(nestTy)) {
nestTy = ArrTy.getEltType();
elemQuantity *= ArrTy.getSize();
}

return nestTy;
}

template <typename AttrTy, typename StorageTy>
void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr,
llvm::SmallVectorImpl<StorageTy> &values) {
auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());
for (auto eltAttr : arrayAttr) {
if (auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {
values.push_back(valueAttr.getValue());
} else if (auto subArrayAttr =
mlir::dyn_cast<mlir::cir::ConstArrayAttr>(eltAttr)) {
convertToDenseElementsAttrImpl<AttrTy>(subArrayAttr, values);
} else if (auto zeroAttr = mlir::dyn_cast<mlir::cir::ZeroAttr>(eltAttr)) {
unsigned numStoredZeros = 0;
auto nestTy =
getNestedTypeAndElemQuantity(zeroAttr.getType(), numStoredZeros);
values.insert(values.end(), numStoredZeros,
getZeroInitFromType<StorageTy>(nestTy));
} else {
llvm_unreachable("unknown element in ConstArrayAttr");
}
}

// Only fill in trailing zeros at the local cir.array level where the element
// type isn't another array (for the mult-dim case).
auto numTrailingZeros = attr.getTrailingZerosNum();
if (numTrailingZeros) {
auto localArrayTy = mlir::dyn_cast<mlir::cir::ArrayType>(attr.getType());
assert(localArrayTy && "expected !cir.array");

auto nestTy = localArrayTy.getEltType();
if (!mlir::isa<mlir::cir::ArrayType>(nestTy))
values.insert(values.end(), localArrayTy.getSize() - numTrailingZeros,
getZeroInitFromType<StorageTy>(nestTy));
}
}

template <typename AttrTy, typename StorageTy>
mlir::DenseElementsAttr
convertToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
const llvm::SmallVectorImpl<int64_t> &dims,
mlir::Type type) {
auto values = llvm::SmallVector<StorageTy, 8>{};
convertToDenseElementsAttrImpl<AttrTy>(attr, values);
return mlir::DenseElementsAttr::get(mlir::RankedTensorType::get(dims, type),
llvm::ArrayRef(values));
}

std::optional<mlir::Attribute>
lowerConstArrayAttr(mlir::cir::ConstArrayAttr constArr,
const mlir::TypeConverter *converter) {

// Ensure ConstArrayAttr has a type.
auto typedConstArr = mlir::dyn_cast<mlir::TypedAttr>(constArr);
assert(typedConstArr && "cir::ConstArrayAttr is not a mlir::TypedAttr");

// Ensure ConstArrayAttr type is a ArrayType.
auto cirArrayType =
mlir::dyn_cast<mlir::cir::ArrayType>(typedConstArr.getType());
assert(cirArrayType && "cir::ConstArrayAttr is not a cir::ArrayType");

// Is a ConstArrayAttr with an cir::ArrayType: fetch element type.
mlir::Type type = cirArrayType;
auto dims = llvm::SmallVector<int64_t, 2>{};
while (auto arrayType = mlir::dyn_cast<mlir::cir::ArrayType>(type)) {
dims.push_back(arrayType.getSize());
type = arrayType.getEltType();
}

// Convert array attr to LLVM compatible dense elements attr.
if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
return convertStringAttrToDenseElementsAttr(constArr,
converter->convertType(type));
if (mlir::isa<mlir::cir::IntType>(type))
return convertToDenseElementsAttr<mlir::cir::IntAttr, mlir::APInt>(
constArr, dims, converter->convertType(type));
if (mlir::isa<mlir::cir::CIRFPTypeInterface>(type))
return convertToDenseElementsAttr<mlir::cir::FPAttr, mlir::APFloat>(
constArr, dims, converter->convertType(type));

return std::nullopt;
}

bool hasTrailingZeros(mlir::cir::ConstArrayAttr attr) {
auto array = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts());
return attr.hasTrailingZeros() ||
Expand Down
137 changes: 137 additions & 0 deletions clang/lib/CIR/Lowering/LoweringHelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//====- LoweringHelpers.cpp - Lowering helper functions -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file contains helper functions for lowering from CIR to LLVM or MLIR.
//
//===----------------------------------------------------------------------===//
#include "clang/CIR/LoweringHelpers.h"

mlir::DenseElementsAttr
convertStringAttrToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
mlir::Type type) {
auto values = llvm::SmallVector<mlir::APInt, 8>{};
auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts());
assert(stringAttr && "expected string attribute here");
for (auto element : stringAttr)
values.push_back({8, (uint64_t)element});
return mlir::DenseElementsAttr::get(
mlir::RankedTensorType::get({(int64_t)values.size()}, type),
llvm::ArrayRef(values));
}

template <> mlir::APInt getZeroInitFromType(mlir::Type Ty) {
assert(mlir::isa<mlir::cir::IntType>(Ty) && "expected int type");
auto IntTy = mlir::cast<mlir::cir::IntType>(Ty);
return mlir::APInt::getZero(IntTy.getWidth());
}

template <> mlir::APFloat getZeroInitFromType(mlir::Type Ty) {
assert((mlir::isa<mlir::cir::SingleType, mlir::cir::DoubleType>(Ty)) &&
"only float and double supported");
if (Ty.isF32() || mlir::isa<mlir::cir::SingleType>(Ty))
return mlir::APFloat(0.f);
if (Ty.isF64() || mlir::isa<mlir::cir::DoubleType>(Ty))
return mlir::APFloat(0.0);
llvm_unreachable("NYI");
}

// return the nested type and quantity of elements for cir.array type.
// e.g: for !cir.array<!cir.array<!s32i x 3> x 1>
// it returns !s32i as return value and stores 3 to elemQuantity.
mlir::Type getNestedTypeAndElemQuantity(mlir::Type Ty, unsigned &elemQuantity) {
assert(mlir::isa<mlir::cir::ArrayType>(Ty) && "expected ArrayType");

elemQuantity = 1;
mlir::Type nestTy = Ty;
while (auto ArrTy = mlir::dyn_cast<mlir::cir::ArrayType>(nestTy)) {
nestTy = ArrTy.getEltType();
elemQuantity *= ArrTy.getSize();
}

return nestTy;
}

template <typename AttrTy, typename StorageTy>
void convertToDenseElementsAttrImpl(mlir::cir::ConstArrayAttr attr,
llvm::SmallVectorImpl<StorageTy> &values) {
auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());
for (auto eltAttr : arrayAttr) {
if (auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {
values.push_back(valueAttr.getValue());
} else if (auto subArrayAttr =
mlir::dyn_cast<mlir::cir::ConstArrayAttr>(eltAttr)) {
convertToDenseElementsAttrImpl<AttrTy>(subArrayAttr, values);
} else if (auto zeroAttr = mlir::dyn_cast<mlir::cir::ZeroAttr>(eltAttr)) {
unsigned numStoredZeros = 0;
auto nestTy =
getNestedTypeAndElemQuantity(zeroAttr.getType(), numStoredZeros);
values.insert(values.end(), numStoredZeros,
getZeroInitFromType<StorageTy>(nestTy));
} else {
llvm_unreachable("unknown element in ConstArrayAttr");
}
}

// Only fill in trailing zeros at the local cir.array level where the element
// type isn't another array (for the mult-dim case).
auto numTrailingZeros = attr.getTrailingZerosNum();
if (numTrailingZeros) {
auto localArrayTy = mlir::dyn_cast<mlir::cir::ArrayType>(attr.getType());
assert(localArrayTy && "expected !cir.array");

auto nestTy = localArrayTy.getEltType();
if (!mlir::isa<mlir::cir::ArrayType>(nestTy))
values.insert(values.end(), localArrayTy.getSize() - numTrailingZeros,
getZeroInitFromType<StorageTy>(nestTy));
}
}

template <typename AttrTy, typename StorageTy>
mlir::DenseElementsAttr
convertToDenseElementsAttr(mlir::cir::ConstArrayAttr attr,
const llvm::SmallVectorImpl<int64_t> &dims,
mlir::Type type) {
auto values = llvm::SmallVector<StorageTy, 8>{};
convertToDenseElementsAttrImpl<AttrTy>(attr, values);
return mlir::DenseElementsAttr::get(mlir::RankedTensorType::get(dims, type),
llvm::ArrayRef(values));
}

std::optional<mlir::Attribute>
lowerConstArrayAttr(mlir::cir::ConstArrayAttr constArr,
const mlir::TypeConverter *converter) {

// Ensure ConstArrayAttr has a type.
auto typedConstArr = mlir::dyn_cast<mlir::TypedAttr>(constArr);
assert(typedConstArr && "cir::ConstArrayAttr is not a mlir::TypedAttr");

// Ensure ConstArrayAttr type is a ArrayType.
auto cirArrayType =
mlir::dyn_cast<mlir::cir::ArrayType>(typedConstArr.getType());
assert(cirArrayType && "cir::ConstArrayAttr is not a cir::ArrayType");

// Is a ConstArrayAttr with an cir::ArrayType: fetch element type.
mlir::Type type = cirArrayType;
auto dims = llvm::SmallVector<int64_t, 2>{};
while (auto arrayType = mlir::dyn_cast<mlir::cir::ArrayType>(type)) {
dims.push_back(arrayType.getSize());
type = arrayType.getEltType();
}

if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
return convertStringAttrToDenseElementsAttr(constArr,
converter->convertType(type));
if (mlir::isa<mlir::cir::IntType>(type))
return convertToDenseElementsAttr<mlir::cir::IntAttr, mlir::APInt>(
constArr, dims, converter->convertType(type));
if (mlir::isa<mlir::cir::CIRFPTypeInterface>(type))
return convertToDenseElementsAttr<mlir::cir::FPAttr, mlir::APFloat>(
constArr, dims, converter->convertType(type));

return std::nullopt;
}
Loading