brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 0786579 Raw
185 lines · cpp
1//====- LoweringHelpers.cpp - Lowering helper functions -------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains helper functions for lowering from CIR to LLVM or MLIR.10//11//===----------------------------------------------------------------------===//12 13#include "clang/CIR/LoweringHelpers.h"14#include "mlir/Dialect/LLVMIR/LLVMDialect.h"15#include "clang/CIR/MissingFeatures.h"16 17mlir::DenseElementsAttr18convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr,19                                     mlir::Type type) {20  auto values = llvm::SmallVector<mlir::APInt, 8>{};21  const auto stringAttr = mlir::cast<mlir::StringAttr>(attr.getElts());22 23  for (const char element : stringAttr)24    values.push_back({8, (uint64_t)element});25 26  const auto arrayTy = mlir::cast<cir::ArrayType>(attr.getType());27  if (arrayTy.getSize() != stringAttr.size())28    assert(!cir::MissingFeatures::stringTypeWithDifferentArraySize());29 30  return mlir::DenseElementsAttr::get(31      mlir::RankedTensorType::get({(int64_t)values.size()}, type),32      llvm::ArrayRef(values));33}34 35template <> mlir::APInt getZeroInitFromType(mlir::Type ty) {36  assert(mlir::isa<cir::IntType>(ty) && "expected int type");37  const auto intTy = mlir::cast<cir::IntType>(ty);38  return mlir::APInt::getZero(intTy.getWidth());39}40 41template <> mlir::APFloat getZeroInitFromType(mlir::Type ty) {42  assert((mlir::isa<cir::SingleType, cir::DoubleType>(ty)) &&43         "only float and double supported");44 45  if (ty.isF32() || mlir::isa<cir::SingleType>(ty))46    return mlir::APFloat(0.f);47 48  if (ty.isF64() || mlir::isa<cir::DoubleType>(ty))49    return mlir::APFloat(0.0);50 51  llvm_unreachable("NYI");52}53 54/// \param attr the ConstArrayAttr to convert55/// \param values the output parameter, the values array to fill56/// \param currentDims the shpae of tensor we're going to convert to57/// \param dimIndex the current dimension we're processing58/// \param currentIndex the current index in the values array59template <typename AttrTy, typename StorageTy>60void convertToDenseElementsAttrImpl(61    cir::ConstArrayAttr attr, llvm::SmallVectorImpl<StorageTy> &values,62    const llvm::SmallVectorImpl<int64_t> &currentDims, int64_t dimIndex,63    int64_t currentIndex) {64  if (auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {65    if (auto arrayType = mlir::dyn_cast<cir::ArrayType>(attr.getType())) {66      for (auto element : stringAttr) {67        auto intAttr = cir::IntAttr::get(arrayType.getElementType(), element);68        values[currentIndex++] = mlir::dyn_cast<AttrTy>(intAttr).getValue();69      }70      return;71    }72  }73 74  dimIndex++;75  std::size_t elementsSizeInCurrentDim = 1;76  for (std::size_t i = dimIndex; i < currentDims.size(); i++)77    elementsSizeInCurrentDim *= currentDims[i];78 79  auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());80  for (auto eltAttr : arrayAttr) {81    if (auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {82      values[currentIndex++] = valueAttr.getValue();83      continue;84    }85 86    if (auto subArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(eltAttr)) {87      convertToDenseElementsAttrImpl<AttrTy>(subArrayAttr, values, currentDims,88                                             dimIndex, currentIndex);89      currentIndex += elementsSizeInCurrentDim;90      continue;91    }92 93    if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(eltAttr)) {94      currentIndex += elementsSizeInCurrentDim;95      continue;96    }97 98    llvm_unreachable("unknown element in ConstArrayAttr");99  }100}101 102template <typename AttrTy, typename StorageTy>103mlir::DenseElementsAttr convertToDenseElementsAttr(104    cir::ConstArrayAttr attr, const llvm::SmallVectorImpl<int64_t> &dims,105    mlir::Type elementType, mlir::Type convertedElementType) {106  unsigned vectorSize = 1;107  for (auto dim : dims)108    vectorSize *= dim;109  auto values = llvm::SmallVector<StorageTy, 8>(110      vectorSize, getZeroInitFromType<StorageTy>(elementType));111  convertToDenseElementsAttrImpl<AttrTy>(attr, values, dims, /*currentDim=*/0,112                                         /*initialIndex=*/0);113  return mlir::DenseElementsAttr::get(114      mlir::RankedTensorType::get(dims, convertedElementType),115      llvm::ArrayRef(values));116}117 118std::optional<mlir::Attribute>119lowerConstArrayAttr(cir::ConstArrayAttr constArr,120                    const mlir::TypeConverter *converter) {121  // Ensure ConstArrayAttr has a type.122  const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr);123 124  // Ensure ConstArrayAttr type is a ArrayType.125  const auto cirArrayType = mlir::cast<cir::ArrayType>(typedConstArr.getType());126 127  // Is a ConstArrayAttr with an cir::ArrayType: fetch element type.128  mlir::Type type = cirArrayType;129  auto dims = llvm::SmallVector<int64_t, 2>{};130  while (auto arrayType = mlir::dyn_cast<cir::ArrayType>(type)) {131    dims.push_back(arrayType.getSize());132    type = arrayType.getElementType();133  }134 135  if (mlir::isa<mlir::StringAttr>(constArr.getElts()))136    return convertStringAttrToDenseElementsAttr(constArr,137                                                converter->convertType(type));138  if (mlir::isa<cir::IntType>(type))139    return convertToDenseElementsAttr<cir::IntAttr, mlir::APInt>(140        constArr, dims, type, converter->convertType(type));141 142  if (mlir::isa<cir::FPTypeInterface>(type))143    return convertToDenseElementsAttr<cir::FPAttr, mlir::APFloat>(144        constArr, dims, type, converter->convertType(type));145 146  return std::nullopt;147}148 149mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc,150                          mlir::Type typ, const llvm::APInt &val) {151  return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);152}153 154mlir::Value getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ,155                     unsigned val) {156  return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);157}158 159mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {160  if (!rhs)161    return lhs;162  mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);163  return mlir::LLVM::ShlOp::create(bld, lhs.getLoc(), lhs, rhsVal);164}165 166mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {167  if (!rhs)168    return lhs;169  mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);170  return mlir::LLVM::AShrOp::create(bld, lhs.getLoc(), lhs, rhsVal);171}172 173mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs,174                      const llvm::APInt &rhs) {175  mlir::Value rhsVal = getConstAPInt(bld, lhs.getLoc(), lhs.getType(), rhs);176  return mlir::LLVM::AndOp::create(bld, lhs.getLoc(), lhs, rhsVal);177}178 179mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs) {180  if (!rhs)181    return lhs;182  mlir::Value rhsVal = getConst(bld, lhs.getLoc(), lhs.getType(), rhs);183  return mlir::LLVM::LShrOp::create(bld, lhs.getLoc(), lhs, rhsVal);184}185