Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CIR/Lowering/LoweringHelpers.cpp
213799 views
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-exception
6
//
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
17
mlir::DenseElementsAttr
18
convertStringAttrToDenseElementsAttr(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
35
template <> 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
41
template <> 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 convert
55
/// \param values the output parameter, the values array to fill
56
/// \param currentDims the shpae of tensor we're going to convert to
57
/// \param dimIndex the current dimension we're processing
58
/// \param currentIndex the current index in the values array
59
template <typename AttrTy, typename StorageTy>
60
void 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
102
template <typename AttrTy, typename StorageTy>
103
mlir::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
118
std::optional<mlir::Attribute>
119
lowerConstArrayAttr(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
149
mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc,
150
mlir::Type typ, const llvm::APInt &val) {
151
return bld.create<mlir::LLVM::ConstantOp>(loc, typ, val);
152
}
153
154
mlir::Value getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ,
155
unsigned val) {
156
return bld.create<mlir::LLVM::ConstantOp>(loc, typ, val);
157
}
158
159
mlir::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 bld.create<mlir::LLVM::ShlOp>(lhs.getLoc(), lhs, rhsVal);
164
}
165
166
mlir::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 bld.create<mlir::LLVM::AShrOp>(lhs.getLoc(), lhs, rhsVal);
171
}
172
173
mlir::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 bld.create<mlir::LLVM::AndOp>(lhs.getLoc(), lhs, rhsVal);
177
}
178
179
mlir::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 bld.create<mlir::LLVM::LShrOp>(lhs.getLoc(), lhs, rhsVal);
184
}
185
186