Path: blob/main/contrib/llvm-project/clang/lib/CIR/Lowering/LoweringHelpers.cpp
213799 views
//====- LoweringHelpers.cpp - Lowering helper functions -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains helper functions for lowering from CIR to LLVM or MLIR.9//10//===----------------------------------------------------------------------===//1112#include "clang/CIR/LoweringHelpers.h"13#include "mlir/Dialect/LLVMIR/LLVMDialect.h"14#include "clang/CIR/MissingFeatures.h"1516mlir::DenseElementsAttr17convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr,18mlir::Type type) {19auto values = llvm::SmallVector<mlir::APInt, 8>{};20const auto stringAttr = mlir::cast<mlir::StringAttr>(attr.getElts());2122for (const char element : stringAttr)23values.push_back({8, (uint64_t)element});2425const auto arrayTy = mlir::cast<cir::ArrayType>(attr.getType());26if (arrayTy.getSize() != stringAttr.size())27assert(!cir::MissingFeatures::stringTypeWithDifferentArraySize());2829return mlir::DenseElementsAttr::get(30mlir::RankedTensorType::get({(int64_t)values.size()}, type),31llvm::ArrayRef(values));32}3334template <> mlir::APInt getZeroInitFromType(mlir::Type ty) {35assert(mlir::isa<cir::IntType>(ty) && "expected int type");36const auto intTy = mlir::cast<cir::IntType>(ty);37return mlir::APInt::getZero(intTy.getWidth());38}3940template <> mlir::APFloat getZeroInitFromType(mlir::Type ty) {41assert((mlir::isa<cir::SingleType, cir::DoubleType>(ty)) &&42"only float and double supported");4344if (ty.isF32() || mlir::isa<cir::SingleType>(ty))45return mlir::APFloat(0.f);4647if (ty.isF64() || mlir::isa<cir::DoubleType>(ty))48return mlir::APFloat(0.0);4950llvm_unreachable("NYI");51}5253/// \param attr the ConstArrayAttr to convert54/// \param values the output parameter, the values array to fill55/// \param currentDims the shpae of tensor we're going to convert to56/// \param dimIndex the current dimension we're processing57/// \param currentIndex the current index in the values array58template <typename AttrTy, typename StorageTy>59void convertToDenseElementsAttrImpl(60cir::ConstArrayAttr attr, llvm::SmallVectorImpl<StorageTy> &values,61const llvm::SmallVectorImpl<int64_t> ¤tDims, int64_t dimIndex,62int64_t currentIndex) {63if (auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {64if (auto arrayType = mlir::dyn_cast<cir::ArrayType>(attr.getType())) {65for (auto element : stringAttr) {66auto intAttr = cir::IntAttr::get(arrayType.getElementType(), element);67values[currentIndex++] = mlir::dyn_cast<AttrTy>(intAttr).getValue();68}69return;70}71}7273dimIndex++;74std::size_t elementsSizeInCurrentDim = 1;75for (std::size_t i = dimIndex; i < currentDims.size(); i++)76elementsSizeInCurrentDim *= currentDims[i];7778auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());79for (auto eltAttr : arrayAttr) {80if (auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {81values[currentIndex++] = valueAttr.getValue();82continue;83}8485if (auto subArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(eltAttr)) {86convertToDenseElementsAttrImpl<AttrTy>(subArrayAttr, values, currentDims,87dimIndex, currentIndex);88currentIndex += elementsSizeInCurrentDim;89continue;90}9192if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(eltAttr)) {93currentIndex += elementsSizeInCurrentDim;94continue;95}9697llvm_unreachable("unknown element in ConstArrayAttr");98}99}100101template <typename AttrTy, typename StorageTy>102mlir::DenseElementsAttr convertToDenseElementsAttr(103cir::ConstArrayAttr attr, const llvm::SmallVectorImpl<int64_t> &dims,104mlir::Type elementType, mlir::Type convertedElementType) {105unsigned vectorSize = 1;106for (auto dim : dims)107vectorSize *= dim;108auto values = llvm::SmallVector<StorageTy, 8>(109vectorSize, getZeroInitFromType<StorageTy>(elementType));110convertToDenseElementsAttrImpl<AttrTy>(attr, values, dims, /*currentDim=*/0,111/*initialIndex=*/0);112return mlir::DenseElementsAttr::get(113mlir::RankedTensorType::get(dims, convertedElementType),114llvm::ArrayRef(values));115}116117std::optional<mlir::Attribute>118lowerConstArrayAttr(cir::ConstArrayAttr constArr,119const mlir::TypeConverter *converter) {120// Ensure ConstArrayAttr has a type.121const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr);122123// Ensure ConstArrayAttr type is a ArrayType.124const auto cirArrayType = mlir::cast<cir::ArrayType>(typedConstArr.getType());125126// Is a ConstArrayAttr with an cir::ArrayType: fetch element type.127mlir::Type type = cirArrayType;128auto dims = llvm::SmallVector<int64_t, 2>{};129while (auto arrayType = mlir::dyn_cast<cir::ArrayType>(type)) {130dims.push_back(arrayType.getSize());131type = arrayType.getElementType();132}133134if (mlir::isa<mlir::StringAttr>(constArr.getElts()))135return convertStringAttrToDenseElementsAttr(constArr,136converter->convertType(type));137if (mlir::isa<cir::IntType>(type))138return convertToDenseElementsAttr<cir::IntAttr, mlir::APInt>(139constArr, dims, type, converter->convertType(type));140141if (mlir::isa<cir::FPTypeInterface>(type))142return convertToDenseElementsAttr<cir::FPAttr, mlir::APFloat>(143constArr, dims, type, converter->convertType(type));144145return std::nullopt;146}147148mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc,149mlir::Type typ, const llvm::APInt &val) {150return bld.create<mlir::LLVM::ConstantOp>(loc, typ, val);151}152153mlir::Value getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ,154unsigned val) {155return bld.create<mlir::LLVM::ConstantOp>(loc, typ, val);156}157158mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {159if (!rhs)160return lhs;161mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);162return bld.create<mlir::LLVM::ShlOp>(lhs.getLoc(), lhs, rhsVal);163}164165mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {166if (!rhs)167return lhs;168mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);169return bld.create<mlir::LLVM::AShrOp>(lhs.getLoc(), lhs, rhsVal);170}171172mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs,173const llvm::APInt &rhs) {174mlir::Value rhsVal = getConstAPInt(bld, lhs.getLoc(), lhs.getType(), rhs);175return bld.create<mlir::LLVM::AndOp>(lhs.getLoc(), lhs, rhsVal);176}177178mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {179if (!rhs)180return lhs;181mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);182return bld.create<mlir::LLVM::LShrOp>(lhs.getLoc(), lhs, rhsVal);183}184185186