xref: /llvm-project/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp (revision 15e1e3b234884eb19b30e230ff783a13b499686f)
1e9639e9cSValentin Clement (バレンタイン クレメン) //===-- CodeGen.cpp -- bridge to lower to LLVM ----------------------------===//
2e9639e9cSValentin Clement (バレンタイン クレメン) //
3e9639e9cSValentin Clement (バレンタイン クレメン) // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e9639e9cSValentin Clement (バレンタイン クレメン) // See https://llvm.org/LICENSE.txt for license information.
5e9639e9cSValentin Clement (バレンタイン クレメン) // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e9639e9cSValentin Clement (バレンタイン クレメン) //
7e9639e9cSValentin Clement (バレンタイン クレメン) //===----------------------------------------------------------------------===//
8e9639e9cSValentin Clement (バレンタイン クレメン) //
9e9639e9cSValentin Clement (バレンタイン クレメン) // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10e9639e9cSValentin Clement (バレンタイン クレメン) //
11e9639e9cSValentin Clement (バレンタイン クレメン) //===----------------------------------------------------------------------===//
12e9639e9cSValentin Clement (バレンタイン クレメン) 
13e9639e9cSValentin Clement (バレンタイン クレメン) #include "flang/Optimizer/CodeGen/FIROpPatterns.h"
14e9639e9cSValentin Clement (バレンタイン クレメン) #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
15e9639e9cSValentin Clement (バレンタイン クレメン) #include "llvm/Support/Debug.h"
16e9639e9cSValentin Clement (バレンタイン クレメン) 
17e9639e9cSValentin Clement (バレンタイン クレメン) static inline mlir::Type getLlvmPtrType(mlir::MLIRContext *context,
18e9639e9cSValentin Clement (バレンタイン クレメン)                                         unsigned addressSpace = 0) {
19e9639e9cSValentin Clement (バレンタイン クレメン)   return mlir::LLVM::LLVMPointerType::get(context, addressSpace);
20e9639e9cSValentin Clement (バレンタイン クレメン) }
21e9639e9cSValentin Clement (バレンタイン クレメン) 
22e9639e9cSValentin Clement (バレンタイン クレメン) static unsigned getTypeDescFieldId(mlir::Type ty) {
23fac349a1SChristian Sigg   auto isArray = mlir::isa<fir::SequenceType>(fir::dyn_cast_ptrOrBoxEleTy(ty));
24e9639e9cSValentin Clement (バレンタイン クレメン)   return isArray ? kOptTypePtrPosInBox : kDimsPosInBox;
25e9639e9cSValentin Clement (バレンタイン クレメン) }
26e9639e9cSValentin Clement (バレンタイン クレメン) 
27e9639e9cSValentin Clement (バレンタイン クレメン) namespace fir {
28e9639e9cSValentin Clement (バレンタイン クレメン) 
29e9639e9cSValentin Clement (バレンタイン クレメン) ConvertFIRToLLVMPattern::ConvertFIRToLLVMPattern(
30e9639e9cSValentin Clement (バレンタイン クレメン)     llvm::StringRef rootOpName, mlir::MLIRContext *context,
31e9639e9cSValentin Clement (バレンタイン クレメン)     const fir::LLVMTypeConverter &typeConverter,
32e9639e9cSValentin Clement (バレンタイン クレメン)     const fir::FIRToLLVMPassOptions &options, mlir::PatternBenefit benefit)
33e9639e9cSValentin Clement (バレンタイン クレメン)     : ConvertToLLVMPattern(rootOpName, context, typeConverter, benefit),
34e9639e9cSValentin Clement (バレンタイン クレメン)       options(options) {}
35e9639e9cSValentin Clement (バレンタイン クレメン) 
36e9639e9cSValentin Clement (バレンタイン クレメン) // Convert FIR type to LLVM without turning fir.box<T> into memory
37e9639e9cSValentin Clement (バレンタイン クレメン) // reference.
38e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Type
39e9639e9cSValentin Clement (バレンタイン クレメン) ConvertFIRToLLVMPattern::convertObjectType(mlir::Type firType) const {
40fac349a1SChristian Sigg   if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(firType))
41e9639e9cSValentin Clement (バレンタイン クレメン)     return lowerTy().convertBoxTypeAsStruct(boxTy);
42e9639e9cSValentin Clement (バレンタイン クレメン)   return lowerTy().convertType(firType);
43e9639e9cSValentin Clement (バレンタイン クレメン) }
44e9639e9cSValentin Clement (バレンタイン クレメン) 
45e9639e9cSValentin Clement (バレンタイン クレメン) mlir::LLVM::ConstantOp ConvertFIRToLLVMPattern::genI32Constant(
46e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
47e9639e9cSValentin Clement (バレンタイン クレメン)     int value) const {
48e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type i32Ty = rewriter.getI32Type();
49e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::IntegerAttr attr = rewriter.getI32IntegerAttr(value);
50e9639e9cSValentin Clement (バレンタイン クレメン)   return rewriter.create<mlir::LLVM::ConstantOp>(loc, i32Ty, attr);
51e9639e9cSValentin Clement (バレンタイン クレメン) }
52e9639e9cSValentin Clement (バレンタイン クレメン) 
53e9639e9cSValentin Clement (バレンタイン クレメン) mlir::LLVM::ConstantOp ConvertFIRToLLVMPattern::genConstantOffset(
54e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
55e9639e9cSValentin Clement (バレンタイン クレメン)     int offset) const {
56e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type ity = lowerTy().offsetType();
57e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::IntegerAttr cattr = rewriter.getI32IntegerAttr(offset);
58e9639e9cSValentin Clement (バレンタイン クレメン)   return rewriter.create<mlir::LLVM::ConstantOp>(loc, ity, cattr);
59e9639e9cSValentin Clement (バレンタイン クレメン) }
60e9639e9cSValentin Clement (バレンタイン クレメン) 
61e9639e9cSValentin Clement (バレンタイン クレメン) /// Perform an extension or truncation as needed on an integer value. Lowering
62e9639e9cSValentin Clement (バレンタイン クレメン) /// to the specific target may involve some sign-extending or truncation of
63e9639e9cSValentin Clement (バレンタイン クレメン) /// values, particularly to fit them from abstract box types to the
64e9639e9cSValentin Clement (バレンタイン クレメン) /// appropriate reified structures.
65c0cba519SVijay Kandiah mlir::Value ConvertFIRToLLVMPattern::integerCast(
66c0cba519SVijay Kandiah     mlir::Location loc, mlir::ConversionPatternRewriter &rewriter,
67c0cba519SVijay Kandiah     mlir::Type ty, mlir::Value val, bool fold) const {
68e9639e9cSValentin Clement (バレンタイン クレメン)   auto valTy = val.getType();
69e9639e9cSValentin Clement (バレンタイン クレメン)   // If the value was not yet lowered, lower its type so that it can
70e9639e9cSValentin Clement (バレンタイン クレメン)   // be used in getPrimitiveTypeSizeInBits.
71fac349a1SChristian Sigg   if (!mlir::isa<mlir::IntegerType>(valTy))
72e9639e9cSValentin Clement (バレンタイン クレメン)     valTy = convertType(valTy);
73e9639e9cSValentin Clement (バレンタイン クレメン)   auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty);
74e9639e9cSValentin Clement (バレンタイン クレメン)   auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy);
75c0cba519SVijay Kandiah   if (fold) {
76c0cba519SVijay Kandiah     if (toSize < fromSize)
77c0cba519SVijay Kandiah       return rewriter.createOrFold<mlir::LLVM::TruncOp>(loc, ty, val);
78c0cba519SVijay Kandiah     if (toSize > fromSize)
79c0cba519SVijay Kandiah       return rewriter.createOrFold<mlir::LLVM::SExtOp>(loc, ty, val);
80c0cba519SVijay Kandiah   } else {
81e9639e9cSValentin Clement (バレンタイン クレメン)     if (toSize < fromSize)
82e9639e9cSValentin Clement (バレンタイン クレメン)       return rewriter.create<mlir::LLVM::TruncOp>(loc, ty, val);
83e9639e9cSValentin Clement (バレンタイン クレメン)     if (toSize > fromSize)
84e9639e9cSValentin Clement (バレンタイン クレメン)       return rewriter.create<mlir::LLVM::SExtOp>(loc, ty, val);
85c0cba519SVijay Kandiah   }
86e9639e9cSValentin Clement (バレンタイン クレメン)   return val;
87e9639e9cSValentin Clement (バレンタイン クレメン) }
88e9639e9cSValentin Clement (バレンタイン クレメン) 
89e9639e9cSValentin Clement (バレンタイン クレメン) fir::ConvertFIRToLLVMPattern::TypePair
90e9639e9cSValentin Clement (バレンタイン クレメン) ConvertFIRToLLVMPattern::getBoxTypePair(mlir::Type firBoxTy) const {
91e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type llvmBoxTy =
92e9639e9cSValentin Clement (バレンタイン クレメン)       lowerTy().convertBoxTypeAsStruct(mlir::cast<fir::BaseBoxType>(firBoxTy));
93e9639e9cSValentin Clement (バレンタイン クレメン)   return TypePair{firBoxTy, llvmBoxTy};
94e9639e9cSValentin Clement (バレンタイン クレメン) }
95e9639e9cSValentin Clement (バレンタイン クレメン) 
96e9639e9cSValentin Clement (バレンタイン クレメン) /// Construct code sequence to extract the specific value from a `fir.box`.
97e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getValueFromBox(
98e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box, mlir::Type resultTy,
99e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter, int boxValue) const {
100fac349a1SChristian Sigg   if (mlir::isa<mlir::LLVM::LLVMPointerType>(box.getType())) {
101e9639e9cSValentin Clement (バレンタイン クレメン)     auto pty = getLlvmPtrType(resultTy.getContext());
102e9639e9cSValentin Clement (バレンタイン クレメン)     auto p = rewriter.create<mlir::LLVM::GEPOp>(
103e9639e9cSValentin Clement (バレンタイン クレメン)         loc, pty, boxTy.llvm, box,
104e9639e9cSValentin Clement (バレンタイン クレメン)         llvm::ArrayRef<mlir::LLVM::GEPArg>{0, boxValue});
105ce2a3d90SKelvin Li     auto fldTy = getBoxEleTy(boxTy.llvm, {boxValue});
106ce2a3d90SKelvin Li     auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, fldTy, p);
107ce2a3d90SKelvin Li     auto castOp = integerCast(loc, rewriter, resultTy, loadOp);
108e9639e9cSValentin Clement (バレンタイン クレメン)     attachTBAATag(loadOp, boxTy.fir, nullptr, p);
109ce2a3d90SKelvin Li     return castOp;
110e9639e9cSValentin Clement (バレンタイン クレメン)   }
111e9639e9cSValentin Clement (バレンタイン クレメン)   return rewriter.create<mlir::LLVM::ExtractValueOp>(loc, box, boxValue);
112e9639e9cSValentin Clement (バレンタイン クレメン) }
113e9639e9cSValentin Clement (バレンタイン クレメン) 
114e9639e9cSValentin Clement (バレンタイン クレメン) /// Method to construct code sequence to get the triple for dimension `dim`
115e9639e9cSValentin Clement (バレンタイン クレメン) /// from a box.
116e9639e9cSValentin Clement (バレンタイン クレメン) llvm::SmallVector<mlir::Value, 3> ConvertFIRToLLVMPattern::getDimsFromBox(
117e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, TypePair boxTy,
118e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Value box, mlir::Value dim,
119e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
120e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l0 =
121e9639e9cSValentin Clement (バレンタイン クレメン)       loadDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter);
122e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l1 =
123e9639e9cSValentin Clement (バレンタイン クレメン)       loadDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter);
124e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l2 =
125e9639e9cSValentin Clement (バレンタイン クレメン)       loadDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter);
126e9639e9cSValentin Clement (バレンタイン クレメン)   return {l0, l1, l2};
127e9639e9cSValentin Clement (バレンタイン クレメン) }
128e9639e9cSValentin Clement (バレンタイン クレメン) 
129e9639e9cSValentin Clement (バレンタイン クレメン) llvm::SmallVector<mlir::Value, 3> ConvertFIRToLLVMPattern::getDimsFromBox(
130e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, TypePair boxTy,
131e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Value box, int dim, mlir::ConversionPatternRewriter &rewriter) const {
132e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l0 =
133e9639e9cSValentin Clement (バレンタイン クレメン)       getDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter);
134e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l1 =
135e9639e9cSValentin Clement (バレンタイン クレメン)       getDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter);
136e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value l2 =
137e9639e9cSValentin Clement (バレンタイン クレメン)       getDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter);
138e9639e9cSValentin Clement (バレンタイン クレメン)   return {l0, l1, l2};
139e9639e9cSValentin Clement (バレンタイン クレメン) }
140e9639e9cSValentin Clement (バレンタイン クレメン) 
141e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::loadDimFieldFromBox(
142e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box, mlir::Value dim,
143e9639e9cSValentin Clement (バレンタイン クレメン)     int off, mlir::Type ty, mlir::ConversionPatternRewriter &rewriter) const {
144fac349a1SChristian Sigg   assert(mlir::isa<mlir::LLVM::LLVMPointerType>(box.getType()) &&
145e9639e9cSValentin Clement (バレンタイン クレメン)          "descriptor inquiry with runtime dim can only be done on descriptor "
146e9639e9cSValentin Clement (バレンタイン クレメン)          "in memory");
147e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0,
148e9639e9cSValentin Clement (バレンタイン クレメン)                                static_cast<int>(kDimsPosInBox), dim, off);
149e9639e9cSValentin Clement (バレンタイン クレメン)   auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p);
150e9639e9cSValentin Clement (バレンタイン クレメン)   attachTBAATag(loadOp, boxTy.fir, nullptr, p);
151e9639e9cSValentin Clement (バレンタイン クレメン)   return loadOp;
152e9639e9cSValentin Clement (バレンタイン クレメン) }
153e9639e9cSValentin Clement (バレンタイン クレメン) 
154e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getDimFieldFromBox(
155e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box, int dim, int off,
156e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Type ty, mlir::ConversionPatternRewriter &rewriter) const {
157fac349a1SChristian Sigg   if (mlir::isa<mlir::LLVM::LLVMPointerType>(box.getType())) {
158e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0,
159e9639e9cSValentin Clement (バレンタイン クレメン)                                  static_cast<int>(kDimsPosInBox), dim, off);
160e9639e9cSValentin Clement (バレンタイン クレメン)     auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p);
161e9639e9cSValentin Clement (バレンタイン クレメン)     attachTBAATag(loadOp, boxTy.fir, nullptr, p);
162e9639e9cSValentin Clement (バレンタイン クレメン)     return loadOp;
163e9639e9cSValentin Clement (バレンタイン クレメン)   }
164e9639e9cSValentin Clement (バレンタイン クレメン)   return rewriter.create<mlir::LLVM::ExtractValueOp>(
165e9639e9cSValentin Clement (バレンタイン クレメン)       loc, box, llvm::ArrayRef<std::int64_t>{kDimsPosInBox, dim, off});
166e9639e9cSValentin Clement (バレンタイン クレメン) }
167e9639e9cSValentin Clement (バレンタイン クレメン) 
168e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getStrideFromBox(
169e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box, unsigned dim,
170e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
171e9639e9cSValentin Clement (バレンタイン クレメン)   auto idxTy = lowerTy().indexType();
172e9639e9cSValentin Clement (バレンタイン クレメン)   return getDimFieldFromBox(loc, boxTy, box, dim, kDimStridePos, idxTy,
173e9639e9cSValentin Clement (バレンタイン クレメン)                             rewriter);
174e9639e9cSValentin Clement (バレンタイン クレメン) }
175e9639e9cSValentin Clement (バレンタイン クレメン) 
176e9639e9cSValentin Clement (バレンタイン クレメン) /// Read base address from a fir.box. Returned address has type ty.
177e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getBaseAddrFromBox(
178e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box,
179e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
180e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type resultTy = ::getLlvmPtrType(boxTy.llvm.getContext());
181e9639e9cSValentin Clement (バレンタイン クレメン)   return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kAddrPosInBox);
182e9639e9cSValentin Clement (バレンタイン クレメン) }
183e9639e9cSValentin Clement (バレンタイン クレメン) 
184e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getElementSizeFromBox(
185e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, mlir::Type resultTy, TypePair boxTy, mlir::Value box,
186e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
187e9639e9cSValentin Clement (バレンタイン クレメン)   return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kElemLenPosInBox);
188e9639e9cSValentin Clement (バレンタイン クレメン) }
189e9639e9cSValentin Clement (バレンタイン クレメン) 
19026e0ce0bSjeanPerier /// Read base address from a fir.box. Returned address has type ty.
19126e0ce0bSjeanPerier mlir::Value ConvertFIRToLLVMPattern::getRankFromBox(
19226e0ce0bSjeanPerier     mlir::Location loc, TypePair boxTy, mlir::Value box,
19326e0ce0bSjeanPerier     mlir::ConversionPatternRewriter &rewriter) const {
19426e0ce0bSjeanPerier   mlir::Type resultTy = getBoxEleTy(boxTy.llvm, {kRankPosInBox});
19526e0ce0bSjeanPerier   return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kRankPosInBox);
19626e0ce0bSjeanPerier }
19726e0ce0bSjeanPerier 
198*15e1e3b2SValentin Clement (バレンタイン クレメン) /// Read the extra field from a fir.box.
199*15e1e3b2SValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::getExtraFromBox(
200*15e1e3b2SValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box,
201*15e1e3b2SValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
202*15e1e3b2SValentin Clement (バレンタイン クレメン)   mlir::Type resultTy = getBoxEleTy(boxTy.llvm, {kExtraPosInBox});
203*15e1e3b2SValentin Clement (バレンタイン クレメン)   return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kExtraPosInBox);
204*15e1e3b2SValentin Clement (バレンタイン クレメン) }
205*15e1e3b2SValentin Clement (バレンタイン クレメン) 
206e9639e9cSValentin Clement (バレンタイン クレメン) // Get the element type given an LLVM type that is of the form
207e9639e9cSValentin Clement (バレンタイン クレメン) // (array|struct|vector)+ and the provided indexes.
208e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Type ConvertFIRToLLVMPattern::getBoxEleTy(
209e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Type type, llvm::ArrayRef<std::int64_t> indexes) const {
210e9639e9cSValentin Clement (バレンタイン クレメン)   for (unsigned i : indexes) {
211fac349a1SChristian Sigg     if (auto t = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(type)) {
212e9639e9cSValentin Clement (バレンタイン クレメン)       assert(!t.isOpaque() && i < t.getBody().size());
213e9639e9cSValentin Clement (バレンタイン クレメン)       type = t.getBody()[i];
214fac349a1SChristian Sigg     } else if (auto t = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(type)) {
215e9639e9cSValentin Clement (バレンタイン クレメン)       type = t.getElementType();
216fac349a1SChristian Sigg     } else if (auto t = mlir::dyn_cast<mlir::VectorType>(type)) {
217e9639e9cSValentin Clement (バレンタイン クレメン)       type = t.getElementType();
218e9639e9cSValentin Clement (バレンタイン クレメン)     } else {
219e9639e9cSValentin Clement (バレンタイン クレメン)       fir::emitFatalError(mlir::UnknownLoc::get(type.getContext()),
220e9639e9cSValentin Clement (バレンタイン クレメン)                           "request for invalid box element type");
221e9639e9cSValentin Clement (バレンタイン クレメン)     }
222e9639e9cSValentin Clement (バレンタイン クレメン)   }
223e9639e9cSValentin Clement (バレンタイン クレメン)   return type;
224e9639e9cSValentin Clement (バレンタイン クレメン) }
225e9639e9cSValentin Clement (バレンタイン クレメン) 
226e9639e9cSValentin Clement (バレンタイン クレメン) // Return LLVM type of the object described by a fir.box of \p boxType.
227e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Type ConvertFIRToLLVMPattern::getLlvmObjectTypeFromBoxType(
228e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Type boxType) const {
229e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type objectType = fir::dyn_cast_ptrOrBoxEleTy(boxType);
230e9639e9cSValentin Clement (バレンタイン クレメン)   assert(objectType && "boxType must be a box type");
231e9639e9cSValentin Clement (バレンタイン クレメン)   return this->convertType(objectType);
232e9639e9cSValentin Clement (バレンタイン クレメン) }
233e9639e9cSValentin Clement (バレンタイン クレメン) 
234e9639e9cSValentin Clement (バレンタイン クレメン) /// Read the address of the type descriptor from a box.
235e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::loadTypeDescAddress(
236e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box,
237e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
238e9639e9cSValentin Clement (バレンタイン クレメン)   unsigned typeDescFieldId = getTypeDescFieldId(boxTy.fir);
239e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type tdescType = lowerTy().convertTypeDescType(rewriter.getContext());
240e9639e9cSValentin Clement (バレンタイン クレメン)   return getValueFromBox(loc, boxTy, box, tdescType, rewriter, typeDescFieldId);
241e9639e9cSValentin Clement (バレンタイン クレメン) }
242e9639e9cSValentin Clement (バレンタイン クレメン) 
243e9639e9cSValentin Clement (バレンタイン クレメン) // Load the attribute from the \p box and perform a check against \p maskValue
244e9639e9cSValentin Clement (バレンタイン クレメン) // The final comparison is implemented as `(attribute & maskValue) != 0`.
245e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::genBoxAttributeCheck(
246e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, TypePair boxTy, mlir::Value box,
247e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter, unsigned maskValue) const {
248e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Type attrTy = rewriter.getI32Type();
249e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value attribute =
250e9639e9cSValentin Clement (バレンタイン クレメン)       getValueFromBox(loc, boxTy, box, attrTy, rewriter, kAttributePosInBox);
251e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::LLVM::ConstantOp attrMask = genConstantOffset(loc, rewriter, maskValue);
252e9639e9cSValentin Clement (バレンタイン クレメン)   auto maskRes =
253e9639e9cSValentin Clement (バレンタイン クレメン)       rewriter.create<mlir::LLVM::AndOp>(loc, attrTy, attribute, attrMask);
254e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::LLVM::ConstantOp c0 = genConstantOffset(loc, rewriter, 0);
255e9639e9cSValentin Clement (バレンタイン クレメン)   return rewriter.create<mlir::LLVM::ICmpOp>(loc, mlir::LLVM::ICmpPredicate::ne,
256e9639e9cSValentin Clement (バレンタイン クレメン)                                              maskRes, c0);
257e9639e9cSValentin Clement (バレンタイン クレメン) }
258e9639e9cSValentin Clement (バレンタイン クレメン) 
259e398383fSjeanPerier mlir::Value ConvertFIRToLLVMPattern::computeBoxSize(
260e398383fSjeanPerier     mlir::Location loc, TypePair boxTy, mlir::Value box,
261e398383fSjeanPerier     mlir::ConversionPatternRewriter &rewriter) const {
262e398383fSjeanPerier   auto firBoxType = mlir::dyn_cast<fir::BaseBoxType>(boxTy.fir);
263e398383fSjeanPerier   assert(firBoxType && "must be a BaseBoxType");
264e398383fSjeanPerier   const mlir::DataLayout &dl = lowerTy().getDataLayout();
265e398383fSjeanPerier   if (!firBoxType.isAssumedRank())
266e398383fSjeanPerier     return genConstantOffset(loc, rewriter, dl.getTypeSize(boxTy.llvm));
267e398383fSjeanPerier   fir::BaseBoxType firScalarBoxType = firBoxType.getBoxTypeWithNewShape(0);
268e398383fSjeanPerier   mlir::Type llvmScalarBoxType =
269e398383fSjeanPerier       lowerTy().convertBoxTypeAsStruct(firScalarBoxType);
270e398383fSjeanPerier   llvm::TypeSize scalarBoxSizeCst = dl.getTypeSize(llvmScalarBoxType);
271e398383fSjeanPerier   mlir::Value scalarBoxSize =
272e398383fSjeanPerier       genConstantOffset(loc, rewriter, scalarBoxSizeCst);
273e398383fSjeanPerier   mlir::Value rawRank = getRankFromBox(loc, boxTy, box, rewriter);
274e398383fSjeanPerier   mlir::Value rank =
275e398383fSjeanPerier       integerCast(loc, rewriter, scalarBoxSize.getType(), rawRank);
276e398383fSjeanPerier   mlir::Type llvmDimsType = getBoxEleTy(boxTy.llvm, {kDimsPosInBox, 1});
277e398383fSjeanPerier   llvm::TypeSize sizePerDimCst = dl.getTypeSize(llvmDimsType);
278e398383fSjeanPerier   assert((scalarBoxSizeCst + sizePerDimCst ==
279e398383fSjeanPerier           dl.getTypeSize(lowerTy().convertBoxTypeAsStruct(
280e398383fSjeanPerier               firBoxType.getBoxTypeWithNewShape(1)))) &&
281e398383fSjeanPerier          "descriptor layout requires adding padding for dim field");
282e398383fSjeanPerier   mlir::Value sizePerDim = genConstantOffset(loc, rewriter, sizePerDimCst);
283e398383fSjeanPerier   mlir::Value dimsSize = rewriter.create<mlir::LLVM::MulOp>(
284e398383fSjeanPerier       loc, sizePerDim.getType(), sizePerDim, rank);
285e398383fSjeanPerier   mlir::Value size = rewriter.create<mlir::LLVM::AddOp>(
286e398383fSjeanPerier       loc, scalarBoxSize.getType(), scalarBoxSize, dimsSize);
287e398383fSjeanPerier   return size;
288e398383fSjeanPerier }
289e398383fSjeanPerier 
290e9639e9cSValentin Clement (バレンタイン クレメン) // Find the Block in which the alloca should be inserted.
291e9639e9cSValentin Clement (バレンタイン クレメン) // The order to recursively find the proper block:
292e9639e9cSValentin Clement (バレンタイン クレメン) // 1. An OpenMP Op that will be outlined.
293c0cba519SVijay Kandiah // 2. An OpenMP or OpenACC Op with one or more regions holding executable code.
294c0cba519SVijay Kandiah // 3. A LLVMFuncOp
295c0cba519SVijay Kandiah // 4. The first ancestor that is one of the above.
296c0cba519SVijay Kandiah mlir::Block *ConvertFIRToLLVMPattern::getBlockForAllocaInsert(
297c0cba519SVijay Kandiah     mlir::Operation *op, mlir::Region *parentRegion) const {
298e9639e9cSValentin Clement (バレンタイン クレメン)   if (auto iface = mlir::dyn_cast<mlir::omp::OutlineableOpenMPOpInterface>(op))
299e9639e9cSValentin Clement (バレンタイン クレメン)     return iface.getAllocaBlock();
300c0cba519SVijay Kandiah   if (auto recipeIface = mlir::dyn_cast<mlir::accomp::RecipeInterface>(op))
301c0cba519SVijay Kandiah     return recipeIface.getAllocaBlock(*parentRegion);
302e9639e9cSValentin Clement (バレンタイン クレメン)   if (auto llvmFuncOp = mlir::dyn_cast<mlir::LLVM::LLVMFuncOp>(op))
303e9639e9cSValentin Clement (バレンタイン クレメン)     return &llvmFuncOp.front();
3043785d742SKareem Ergawy 
305c0cba519SVijay Kandiah   return getBlockForAllocaInsert(op->getParentOp(), parentRegion);
306e9639e9cSValentin Clement (バレンタイン クレメン) }
307e9639e9cSValentin Clement (バレンタイン クレメン) 
308e9639e9cSValentin Clement (バレンタイン クレメン) // Generate an alloca of size 1 for an object of type \p llvmObjectTy in the
309e9639e9cSValentin Clement (バレンタイン クレメン) // allocation address space provided for the architecture in the DataLayout
310e9639e9cSValentin Clement (バレンタイン クレメン) // specification. If the address space is different from the devices
311e9639e9cSValentin Clement (バレンタイン クレメン) // program address space we perform a cast. In the case of most architectures
312e9639e9cSValentin Clement (バレンタイン クレメン) // the program and allocation address space will be the default of 0 and no
313e9639e9cSValentin Clement (バレンタイン クレメン) // cast will be emitted.
314e9639e9cSValentin Clement (バレンタイン クレメン) mlir::Value ConvertFIRToLLVMPattern::genAllocaAndAddrCastWithType(
315e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::Location loc, mlir::Type llvmObjectTy, unsigned alignment,
316e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
317e9639e9cSValentin Clement (バレンタイン クレメン)   auto thisPt = rewriter.saveInsertionPoint();
318e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
319e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Region *parentRegion = rewriter.getInsertionBlock()->getParent();
320c0cba519SVijay Kandiah   mlir::Block *insertBlock = getBlockForAllocaInsert(parentOp, parentRegion);
321e9639e9cSValentin Clement (バレンタイン クレメン)   rewriter.setInsertionPointToStart(insertBlock);
322e9639e9cSValentin Clement (バレンタイン クレメン)   auto size = genI32Constant(loc, rewriter, 1);
323e9639e9cSValentin Clement (バレンタイン クレメン)   unsigned allocaAs = getAllocaAddressSpace(rewriter);
324e9639e9cSValentin Clement (バレンタイン クレメン)   unsigned programAs = getProgramAddressSpace(rewriter);
325e9639e9cSValentin Clement (バレンタイン クレメン) 
326e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Value al = rewriter.create<mlir::LLVM::AllocaOp>(
327e9639e9cSValentin Clement (バレンタイン クレメン)       loc, ::getLlvmPtrType(llvmObjectTy.getContext(), allocaAs), llvmObjectTy,
328e9639e9cSValentin Clement (バレンタイン クレメン)       size, alignment);
329e9639e9cSValentin Clement (バレンタイン クレメン) 
330e9639e9cSValentin Clement (バレンタイン クレメン)   // if our allocation address space, is not the same as the program address
331e9639e9cSValentin Clement (バレンタイン クレメン)   // space, then we must emit a cast to the program address space before use.
332e9639e9cSValentin Clement (バレンタイン クレメン)   // An example case would be on AMDGPU, where the allocation address space is
333e9639e9cSValentin Clement (バレンタイン クレメン)   // the numeric value 5 (private), and the program address space is 0
334e9639e9cSValentin Clement (バレンタイン クレメン)   // (generic).
335e9639e9cSValentin Clement (バレンタイン クレメン)   if (allocaAs != programAs) {
336e9639e9cSValentin Clement (バレンタイン クレメン)     al = rewriter.create<mlir::LLVM::AddrSpaceCastOp>(
337e9639e9cSValentin Clement (バレンタイン クレメン)         loc, ::getLlvmPtrType(llvmObjectTy.getContext(), programAs), al);
338e9639e9cSValentin Clement (バレンタイン クレメン)   }
339e9639e9cSValentin Clement (バレンタイン クレメン) 
340e9639e9cSValentin Clement (バレンタイン クレメン)   rewriter.restoreInsertionPoint(thisPt);
341e9639e9cSValentin Clement (バレンタイン クレメン)   return al;
342e9639e9cSValentin Clement (バレンタイン クレメン) }
343e9639e9cSValentin Clement (バレンタイン クレメン) 
344e9639e9cSValentin Clement (バレンタイン クレメン) unsigned ConvertFIRToLLVMPattern::getAllocaAddressSpace(
345e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
346e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
347e9639e9cSValentin Clement (バレンタイン クレメン)   assert(parentOp != nullptr &&
348e9639e9cSValentin Clement (バレンタイン クレメン)          "expected insertion block to have parent operation");
349e9639e9cSValentin Clement (バレンタイン クレメン)   if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
350e9639e9cSValentin Clement (バレンタイン クレメン)     if (mlir::Attribute addrSpace =
351e9639e9cSValentin Clement (バレンタイン クレメン)             mlir::DataLayout(module).getAllocaMemorySpace())
352e9639e9cSValentin Clement (バレンタイン クレメン)       return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
353e9639e9cSValentin Clement (バレンタイン クレメン)   return defaultAddressSpace;
354e9639e9cSValentin Clement (バレンタイン クレメン) }
355e9639e9cSValentin Clement (バレンタイン クレメン) 
356e9639e9cSValentin Clement (バレンタイン クレメン) unsigned ConvertFIRToLLVMPattern::getProgramAddressSpace(
357e9639e9cSValentin Clement (バレンタイン クレメン)     mlir::ConversionPatternRewriter &rewriter) const {
358e9639e9cSValentin Clement (バレンタイン クレメン)   mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp();
359e9639e9cSValentin Clement (バレンタイン クレメン)   assert(parentOp != nullptr &&
360e9639e9cSValentin Clement (バレンタイン クレメン)          "expected insertion block to have parent operation");
361e9639e9cSValentin Clement (バレンタイン クレメン)   if (auto module = parentOp->getParentOfType<mlir::ModuleOp>())
362e9639e9cSValentin Clement (バレンタイン クレメン)     if (mlir::Attribute addrSpace =
363e9639e9cSValentin Clement (バレンタイン クレメン)             mlir::DataLayout(module).getProgramMemorySpace())
364e9639e9cSValentin Clement (バレンタイン クレメン)       return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt();
365e9639e9cSValentin Clement (バレンタイン クレメン)   return defaultAddressSpace;
366e9639e9cSValentin Clement (バレンタイン クレメン) }
367e9639e9cSValentin Clement (バレンタイン クレメン) 
368e9639e9cSValentin Clement (バレンタイン クレメン) } // namespace fir
369