1//===- FIRBuilderTest.cpp -- FIRBuilder unit tests ------------------------===//
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#include "flang/Optimizer/Builder/FIRBuilder.h"
10#include "gtest/gtest.h"
11#include "flang/Optimizer/Builder/BoxValue.h"
12#include "flang/Optimizer/Dialect/Support/KindMapping.h"
13#include "flang/Optimizer/Support/InitFIR.h"
14
15using namespace mlir;
16
17struct FIRBuilderTest : public testing::Test {
18public:
19 void SetUp() override {
20 fir::support::loadDialects(context);
21
22 llvm::ArrayRef<fir::KindTy> defs;
23 fir::KindMapping kindMap(&context, defs);
24 mlir::OpBuilder builder(&context);
25 auto loc = builder.getUnknownLoc();
26
27 // Set up a Module with a dummy function operation inside.
28 // Set the insertion point in the function entry block.
29 mlir::ModuleOp mod = builder.create<mlir::ModuleOp>(loc);
30 mlir::func::FuncOp func = mlir::func::FuncOp::create(
31 loc, "func1", builder.getFunctionType(std::nullopt, std::nullopt));
32 auto *entryBlock = func.addEntryBlock();
33 mod.push_back(mod);
34 builder.setInsertionPointToStart(entryBlock);
35
36 firBuilder = std::make_unique<fir::FirOpBuilder>(mod, kindMap);
37 }
38
39 fir::FirOpBuilder &getBuilder() { return *firBuilder; }
40
41 mlir::MLIRContext context;
42 std::unique_ptr<fir::FirOpBuilder> firBuilder;
43};
44
45static arith::CmpIOp createCondition(fir::FirOpBuilder &builder) {
46 auto loc = builder.getUnknownLoc();
47 auto zero1 = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
48 auto zero2 = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
49 return builder.create<arith::CmpIOp>(
50 loc, arith::CmpIPredicate::eq, zero1, zero2);
51}
52
53static void checkIntegerConstant(mlir::Value value, mlir::Type ty, int64_t v) {
54 EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
55 auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
56 EXPECT_EQ(ty, cstOp.getType());
57 auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
58 EXPECT_EQ(v, valueAttr.getInt());
59}
60
61//===----------------------------------------------------------------------===//
62// IfBuilder tests
63//===----------------------------------------------------------------------===//
64
65TEST_F(FIRBuilderTest, genIfThen) {
66 auto builder = getBuilder();
67 auto loc = builder.getUnknownLoc();
68 auto cdt = createCondition(builder);
69 auto ifBuilder = builder.genIfThen(loc, cdt);
70 EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
71 EXPECT_TRUE(ifBuilder.getIfOp().getElseRegion().empty());
72}
73
74TEST_F(FIRBuilderTest, genIfThenElse) {
75 auto builder = getBuilder();
76 auto loc = builder.getUnknownLoc();
77 auto cdt = createCondition(builder);
78 auto ifBuilder = builder.genIfThenElse(loc, cdt);
79 EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
80 EXPECT_FALSE(ifBuilder.getIfOp().getElseRegion().empty());
81}
82
83TEST_F(FIRBuilderTest, genIfWithThen) {
84 auto builder = getBuilder();
85 auto loc = builder.getUnknownLoc();
86 auto cdt = createCondition(builder);
87 auto ifBuilder = builder.genIfOp(loc, {}, cdt, false);
88 EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
89 EXPECT_TRUE(ifBuilder.getIfOp().getElseRegion().empty());
90}
91
92TEST_F(FIRBuilderTest, genIfWithThenAndElse) {
93 auto builder = getBuilder();
94 auto loc = builder.getUnknownLoc();
95 auto cdt = createCondition(builder);
96 auto ifBuilder = builder.genIfOp(loc, {}, cdt, true);
97 EXPECT_FALSE(ifBuilder.getIfOp().getThenRegion().empty());
98 EXPECT_FALSE(ifBuilder.getIfOp().getElseRegion().empty());
99}
100
101//===----------------------------------------------------------------------===//
102// Helper functions tests
103//===----------------------------------------------------------------------===//
104
105TEST_F(FIRBuilderTest, genIsNotNullAddr) {
106 auto builder = getBuilder();
107 auto loc = builder.getUnknownLoc();
108 auto dummyValue =
109 builder.createIntegerConstant(loc, builder.getIndexType(), 0);
110 auto res = builder.genIsNotNullAddr(loc, dummyValue);
111 EXPECT_TRUE(mlir::isa<arith::CmpIOp>(res.getDefiningOp()));
112 auto cmpOp = dyn_cast<arith::CmpIOp>(res.getDefiningOp());
113 EXPECT_EQ(arith::CmpIPredicate::ne, cmpOp.getPredicate());
114}
115
116TEST_F(FIRBuilderTest, genIsNullAddr) {
117 auto builder = getBuilder();
118 auto loc = builder.getUnknownLoc();
119 auto dummyValue =
120 builder.createIntegerConstant(loc, builder.getIndexType(), 0);
121 auto res = builder.genIsNullAddr(loc, dummyValue);
122 EXPECT_TRUE(mlir::isa<arith::CmpIOp>(res.getDefiningOp()));
123 auto cmpOp = dyn_cast<arith::CmpIOp>(res.getDefiningOp());
124 EXPECT_EQ(arith::CmpIPredicate::eq, cmpOp.getPredicate());
125}
126
127TEST_F(FIRBuilderTest, createZeroConstant) {
128 auto builder = getBuilder();
129 auto loc = builder.getUnknownLoc();
130
131 auto cst = builder.createNullConstant(loc);
132 EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
133 auto zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
134 EXPECT_EQ(fir::ReferenceType::get(builder.getNoneType()),
135 zeroOp.getResult().getType());
136 auto idxTy = builder.getIndexType();
137
138 cst = builder.createNullConstant(loc, idxTy);
139 EXPECT_TRUE(mlir::isa<fir::ZeroOp>(cst.getDefiningOp()));
140 zeroOp = dyn_cast<fir::ZeroOp>(cst.getDefiningOp());
141 EXPECT_EQ(builder.getIndexType(), zeroOp.getResult().getType());
142}
143
144TEST_F(FIRBuilderTest, createRealZeroConstant) {
145 auto builder = getBuilder();
146 auto ctx = builder.getContext();
147 auto loc = builder.getUnknownLoc();
148 auto realTy = mlir::FloatType::getF64(ctx);
149 auto cst = builder.createRealZeroConstant(loc, realTy);
150 EXPECT_TRUE(mlir::isa<arith::ConstantOp>(cst.getDefiningOp()));
151 auto cstOp = dyn_cast<arith::ConstantOp>(cst.getDefiningOp());
152 EXPECT_EQ(realTy, cstOp.getType());
153 EXPECT_EQ(
154 0u, cstOp.getValue().cast<FloatAttr>().getValue().convertToDouble());
155}
156
157TEST_F(FIRBuilderTest, createBool) {
158 auto builder = getBuilder();
159 auto loc = builder.getUnknownLoc();
160 auto b = builder.createBool(loc, false);
161 checkIntegerConstant(b, builder.getIntegerType(1), 0);
162}
163
164TEST_F(FIRBuilderTest, getVarLenSeqTy) {
165 auto builder = getBuilder();
166 auto ty = builder.getVarLenSeqTy(builder.getI64Type());
167 EXPECT_TRUE(ty.isa<fir::SequenceType>());
168 fir::SequenceType seqTy = ty.dyn_cast<fir::SequenceType>();
169 EXPECT_EQ(1u, seqTy.getDimension());
170 EXPECT_TRUE(fir::unwrapSequenceType(ty).isInteger(64));
171}
172
173TEST_F(FIRBuilderTest, getNamedFunction) {
174 auto builder = getBuilder();
175 auto func2 = builder.getNamedFunction("func2");
176 EXPECT_EQ(nullptr, func2);
177 auto loc = builder.getUnknownLoc();
178 func2 = builder.createFunction(
179 loc, "func2", builder.getFunctionType(std::nullopt, std::nullopt));
180 auto func2query = builder.getNamedFunction("func2");
181 EXPECT_EQ(func2, func2query);
182}
183
184TEST_F(FIRBuilderTest, createGlobal1) {
185 auto builder = getBuilder();
186 auto loc = builder.getUnknownLoc();
187 auto i64Type = IntegerType::get(builder.getContext(), 64);
188 auto global = builder.createGlobal(
189 loc, i64Type, "global1", builder.createInternalLinkage(), {}, true);
190 EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
191 EXPECT_EQ("global1", global.getSymName());
192 EXPECT_TRUE(global.getConstant().has_value());
193 EXPECT_EQ(i64Type, global.getType());
194 EXPECT_TRUE(global.getLinkName().has_value());
195 EXPECT_EQ(
196 builder.createInternalLinkage().getValue(), global.getLinkName().value());
197 EXPECT_FALSE(global.getInitVal().has_value());
198
199 auto g1 = builder.getNamedGlobal("global1");
200 EXPECT_EQ(global, g1);
201 auto g2 = builder.getNamedGlobal("global7");
202 EXPECT_EQ(nullptr, g2);
203 auto g3 = builder.getNamedGlobal("");
204 EXPECT_EQ(nullptr, g3);
205}
206
207TEST_F(FIRBuilderTest, createGlobal2) {
208 auto builder = getBuilder();
209 auto loc = builder.getUnknownLoc();
210 auto i32Type = IntegerType::get(builder.getContext(), 32);
211 auto attr = builder.getIntegerAttr(i32Type, 16);
212 auto global = builder.createGlobal(
213 loc, i32Type, "global2", builder.createLinkOnceLinkage(), attr, false);
214 EXPECT_TRUE(mlir::isa<fir::GlobalOp>(global));
215 EXPECT_EQ("global2", global.getSymName());
216 EXPECT_FALSE(global.getConstant().has_value());
217 EXPECT_EQ(i32Type, global.getType());
218 EXPECT_TRUE(global.getInitVal().has_value());
219 EXPECT_TRUE(global.getInitVal().value().isa<mlir::IntegerAttr>());
220 EXPECT_EQ(
221 16, global.getInitVal().value().cast<mlir::IntegerAttr>().getValue());
222 EXPECT_TRUE(global.getLinkName().has_value());
223 EXPECT_EQ(
224 builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
225}
226
227TEST_F(FIRBuilderTest, uniqueCFIdent) {
228 auto str1 = fir::factory::uniqueCGIdent("", "func1");
229 EXPECT_EQ("_QQX66756E6331", str1);
230 str1 = fir::factory::uniqueCGIdent("", "");
231 EXPECT_EQ("_QQX", str1);
232 str1 = fir::factory::uniqueCGIdent("pr", "func1");
233 EXPECT_EQ("_QQprX66756E6331", str1);
234 str1 = fir::factory::uniqueCGIdent(
235 "", "longnamemorethan32characterneedshashing");
236 EXPECT_EQ("_QQXc22a886b2f30ea8c064ef1178377fc31", str1);
237 str1 = fir::factory::uniqueCGIdent(
238 "pr", "longnamemorethan32characterneedshashing");
239 EXPECT_EQ("_QQprXc22a886b2f30ea8c064ef1178377fc31", str1);
240}
241
242TEST_F(FIRBuilderTest, locationToLineNo) {
243 auto builder = getBuilder();
244 auto loc = mlir::FileLineColLoc::get(builder.getStringAttr("file1"), 10, 5);
245 mlir::Value line =
246 fir::factory::locationToLineNo(builder, loc, builder.getI64Type());
247 checkIntegerConstant(line, builder.getI64Type(), 10);
248 line = fir::factory::locationToLineNo(
249 builder, builder.getUnknownLoc(), builder.getI64Type());
250 checkIntegerConstant(line, builder.getI64Type(), 0);
251}
252
253TEST_F(FIRBuilderTest, hasDynamicSize) {
254 auto builder = getBuilder();
255 auto type = fir::CharacterType::get(builder.getContext(), 1, 16);
256 EXPECT_FALSE(fir::hasDynamicSize(type));
257 EXPECT_TRUE(fir::SequenceType::getUnknownExtent());
258 auto seqTy = builder.getVarLenSeqTy(builder.getI64Type(), 10);
259 EXPECT_TRUE(fir::hasDynamicSize(seqTy));
260 EXPECT_FALSE(fir::hasDynamicSize(builder.getI64Type()));
261}
262
263TEST_F(FIRBuilderTest, locationToFilename) {
264 auto builder = getBuilder();
265 auto loc =
266 mlir::FileLineColLoc::get(builder.getStringAttr("file1.f90"), 10, 5);
267 mlir::Value locToFile = fir::factory::locationToFilename(builder, loc);
268 auto addrOp = dyn_cast<fir::AddrOfOp>(locToFile.getDefiningOp());
269 auto symbol = addrOp.getSymbol().getRootReference().getValue();
270 auto global = builder.getNamedGlobal(symbol);
271 auto stringLitOps = global.getRegion().front().getOps<fir::StringLitOp>();
272 EXPECT_TRUE(llvm::hasSingleElement(stringLitOps));
273 for (auto stringLit : stringLitOps) {
274 EXPECT_EQ(10, stringLit.getSize().cast<mlir::IntegerAttr>().getValue());
275 EXPECT_TRUE(stringLit.getValue().isa<StringAttr>());
276 EXPECT_EQ(0,
277 strcmp("file1.f90\0",
278 stringLit.getValue()
279 .dyn_cast<StringAttr>()
280 .getValue()
281 .str()
282 .c_str()));
283 }
284}
285
286TEST_F(FIRBuilderTest, createStringLitOp) {
287 auto builder = getBuilder();
288 llvm::StringRef data("mystringlitdata");
289 auto loc = builder.getUnknownLoc();
290 auto op = builder.createStringLitOp(loc, data);
291 EXPECT_EQ(15, op.getSize().cast<mlir::IntegerAttr>().getValue());
292 EXPECT_TRUE(op.getValue().isa<StringAttr>());
293 EXPECT_EQ(data, op.getValue().dyn_cast<StringAttr>().getValue());
294}
295
296TEST_F(FIRBuilderTest, createStringLiteral) {
297 auto builder = getBuilder();
298 auto loc = builder.getUnknownLoc();
299 llvm::StringRef strValue("onestringliteral");
300 auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
301 EXPECT_EQ(0u, strLit.rank());
302 EXPECT_TRUE(strLit.getCharBox() != nullptr);
303 auto *charBox = strLit.getCharBox();
304 EXPECT_FALSE(fir::isArray(*charBox));
305 checkIntegerConstant(charBox->getLen(), builder.getCharacterLengthType(), 16);
306 auto generalGetLen = fir::getLen(strLit);
307 checkIntegerConstant(generalGetLen, builder.getCharacterLengthType(), 16);
308 auto addr = charBox->getBuffer();
309 EXPECT_TRUE(mlir::isa<fir::AddrOfOp>(addr.getDefiningOp()));
310 auto addrOp = dyn_cast<fir::AddrOfOp>(addr.getDefiningOp());
311 auto symbol = addrOp.getSymbol().getRootReference().getValue();
312 auto global = builder.getNamedGlobal(symbol);
313 EXPECT_EQ(
314 builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
315 EXPECT_EQ(fir::CharacterType::get(builder.getContext(), 1, strValue.size()),
316 global.getType());
317
318 auto stringLitOps = global.getRegion().front().getOps<fir::StringLitOp>();
319 EXPECT_TRUE(llvm::hasSingleElement(stringLitOps));
320 for (auto stringLit : stringLitOps) {
321 EXPECT_EQ(16, stringLit.getSize().cast<mlir::IntegerAttr>().getValue());
322 EXPECT_TRUE(stringLit.getValue().isa<StringAttr>());
323 EXPECT_EQ(strValue, stringLit.getValue().dyn_cast<StringAttr>().getValue());
324 }
325}
326
327TEST_F(FIRBuilderTest, allocateLocal) {
328 auto builder = getBuilder();
329 auto loc = builder.getUnknownLoc();
330 llvm::StringRef varName = "var1";
331 auto var = builder.allocateLocal(
332 loc, builder.getI64Type(), "", varName, {}, {}, false);
333 EXPECT_TRUE(mlir::isa<fir::AllocaOp>(var.getDefiningOp()));
334 auto allocaOp = dyn_cast<fir::AllocaOp>(var.getDefiningOp());
335 EXPECT_EQ(builder.getI64Type(), allocaOp.getInType());
336 EXPECT_TRUE(allocaOp.getBindcName().has_value());
337 EXPECT_EQ(varName, allocaOp.getBindcName().value());
338 EXPECT_FALSE(allocaOp.getUniqName().has_value());
339 EXPECT_FALSE(allocaOp.getPinned());
340 EXPECT_EQ(0u, allocaOp.getTypeparams().size());
341 EXPECT_EQ(0u, allocaOp.getShape().size());
342}
343
344static void checkShapeOp(mlir::Value shape, mlir::Value c10, mlir::Value c100) {
345 EXPECT_TRUE(mlir::isa<fir::ShapeOp>(shape.getDefiningOp()));
346 fir::ShapeOp op = dyn_cast<fir::ShapeOp>(shape.getDefiningOp());
347 auto shapeTy = op.getType().dyn_cast<fir::ShapeType>();
348 EXPECT_EQ(2u, shapeTy.getRank());
349 EXPECT_EQ(2u, op.getExtents().size());
350 EXPECT_EQ(c10, op.getExtents()[0]);
351 EXPECT_EQ(c100, op.getExtents()[1]);
352}
353
354TEST_F(FIRBuilderTest, genShapeWithExtents) {
355 auto builder = getBuilder();
356 auto loc = builder.getUnknownLoc();
357 auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
358 auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
359 llvm::SmallVector<mlir::Value> extents = {c10, c100};
360 auto shape = builder.genShape(loc, extents);
361 checkShapeOp(shape, c10, c100);
362}
363
364TEST_F(FIRBuilderTest, genShapeWithExtentsAndShapeShift) {
365 auto builder = getBuilder();
366 auto loc = builder.getUnknownLoc();
367 auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
368 auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
369 auto c1 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
370 llvm::SmallVector<mlir::Value> shifts = {c1, c1};
371 llvm::SmallVector<mlir::Value> extents = {c10, c100};
372 auto shape = builder.genShape(loc, shifts, extents);
373 EXPECT_TRUE(mlir::isa<fir::ShapeShiftOp>(shape.getDefiningOp()));
374 fir::ShapeShiftOp op = dyn_cast<fir::ShapeShiftOp>(shape.getDefiningOp());
375 auto shapeTy = op.getType().dyn_cast<fir::ShapeShiftType>();
376 EXPECT_EQ(2u, shapeTy.getRank());
377 EXPECT_EQ(2u, op.getExtents().size());
378 EXPECT_EQ(2u, op.getOrigins().size());
379}
380
381TEST_F(FIRBuilderTest, genShapeWithAbstractArrayBox) {
382 auto builder = getBuilder();
383 auto loc = builder.getUnknownLoc();
384 auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
385 auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
386 llvm::SmallVector<mlir::Value> extents = {c10, c100};
387 fir::AbstractArrayBox aab(extents, {});
388 EXPECT_TRUE(aab.lboundsAllOne());
389 auto shape = builder.genShape(loc, aab);
390 checkShapeOp(shape, c10, c100);
391}
392
393TEST_F(FIRBuilderTest, readCharLen) {
394 auto builder = getBuilder();
395 auto loc = builder.getUnknownLoc();
396 llvm::StringRef strValue("length");
397 auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
398 auto len = fir::factory::readCharLen(builder, loc, strLit);
399 EXPECT_EQ(strLit.getCharBox()->getLen(), len);
400}
401
402TEST_F(FIRBuilderTest, getExtents) {
403 auto builder = getBuilder();
404 auto loc = builder.getUnknownLoc();
405 llvm::StringRef strValue("length");
406 auto strLit = fir::factory::createStringLiteral(builder, loc, strValue);
407 auto ext = fir::factory::getExtents(loc, builder, strLit);
408 EXPECT_EQ(0u, ext.size());
409 auto c10 = builder.createIntegerConstant(loc, builder.getI64Type(), 10);
410 auto c100 = builder.createIntegerConstant(loc, builder.getI64Type(), 100);
411 llvm::SmallVector<mlir::Value> extents = {c10, c100};
412 fir::SequenceType::Shape shape(2, fir::SequenceType::getUnknownExtent());
413 auto arrayTy = fir::SequenceType::get(shape, builder.getI64Type());
414 mlir::Value array = builder.create<fir::UndefOp>(loc, arrayTy);
415 fir::ArrayBoxValue aab(array, extents, {});
416 fir::ExtendedValue ex(aab);
417 auto readExtents = fir::factory::getExtents(loc, builder, ex);
418 EXPECT_EQ(2u, readExtents.size());
419}
420
421TEST_F(FIRBuilderTest, createZeroValue) {
422 auto builder = getBuilder();
423 auto loc = builder.getUnknownLoc();
424
425 mlir::Type i64Ty = mlir::IntegerType::get(builder.getContext(), 64);
426 mlir::Value zeroInt = fir::factory::createZeroValue(builder, loc, i64Ty);
427 EXPECT_TRUE(zeroInt.getType() == i64Ty);
428 auto cst =
429 mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(zeroInt.getDefiningOp());
430 EXPECT_TRUE(cst);
431 auto intAttr = cst.getValue().dyn_cast<mlir::IntegerAttr>();
432 EXPECT_TRUE(intAttr && intAttr.getInt() == 0);
433
434 mlir::Type f32Ty = mlir::FloatType::getF32(builder.getContext());
435 mlir::Value zeroFloat = fir::factory::createZeroValue(builder, loc, f32Ty);
436 EXPECT_TRUE(zeroFloat.getType() == f32Ty);
437 auto cst2 = mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(
438 zeroFloat.getDefiningOp());
439 EXPECT_TRUE(cst2);
440 auto floatAttr = cst2.getValue().dyn_cast<mlir::FloatAttr>();
441 EXPECT_TRUE(floatAttr && floatAttr.getValueAsDouble() == 0.);
442
443 mlir::Type boolTy = mlir::IntegerType::get(builder.getContext(), 1);
444 mlir::Value flaseBool = fir::factory::createZeroValue(builder, loc, boolTy);
445 EXPECT_TRUE(flaseBool.getType() == boolTy);
446 auto cst3 = mlir::dyn_cast_or_null<mlir::arith::ConstantOp>(
447 flaseBool.getDefiningOp());
448 EXPECT_TRUE(cst3);
449 auto intAttr2 = cst.getValue().dyn_cast<mlir::IntegerAttr>();
450 EXPECT_TRUE(intAttr2 && intAttr2.getInt() == 0);
451}
452
453TEST_F(FIRBuilderTest, getBaseTypeOf) {
454 auto builder = getBuilder();
455 auto loc = builder.getUnknownLoc();
456
457 auto makeExv = [&](mlir::Type elementType, mlir::Type arrayType)
458 -> std::tuple<llvm::SmallVector<fir::ExtendedValue, 4>,
459 llvm::SmallVector<fir::ExtendedValue, 4>> {
460 auto ptrTyArray = fir::PointerType::get(arrayType);
461 auto ptrTyScalar = fir::PointerType::get(elementType);
462 auto ptrBoxTyArray = fir::BoxType::get(ptrTyArray);
463 auto ptrBoxTyScalar = fir::BoxType::get(ptrTyScalar);
464 auto boxRefTyArray = fir::ReferenceType::get(ptrBoxTyArray);
465 auto boxRefTyScalar = fir::ReferenceType::get(ptrBoxTyScalar);
466 auto boxTyArray = fir::BoxType::get(arrayType);
467 auto boxTyScalar = fir::BoxType::get(elementType);
468
469 auto ptrValArray = builder.create<fir::UndefOp>(loc, ptrTyArray);
470 auto ptrValScalar = builder.create<fir::UndefOp>(loc, ptrTyScalar);
471 auto boxRefValArray = builder.create<fir::UndefOp>(loc, boxRefTyArray);
472 auto boxRefValScalar = builder.create<fir::UndefOp>(loc, boxRefTyScalar);
473 auto boxValArray = builder.create<fir::UndefOp>(loc, boxTyArray);
474 auto boxValScalar = builder.create<fir::UndefOp>(loc, boxTyScalar);
475
476 llvm::SmallVector<fir::ExtendedValue, 4> scalars;
477 scalars.emplace_back(fir::UnboxedValue(ptrValScalar));
478 scalars.emplace_back(fir::BoxValue(boxValScalar));
479 scalars.emplace_back(
480 fir::MutableBoxValue(boxRefValScalar, mlir::ValueRange(), {}));
481
482 llvm::SmallVector<fir::ExtendedValue, 4> arrays;
483 auto extent = builder.create<fir::UndefOp>(loc, builder.getIndexType());
484 llvm::SmallVector<mlir::Value> extents(
485 arrayType.dyn_cast<fir::SequenceType>().getDimension(),
486 extent.getResult());
487 arrays.emplace_back(fir::ArrayBoxValue(ptrValArray, extents));
488 arrays.emplace_back(fir::BoxValue(boxValArray));
489 arrays.emplace_back(
490 fir::MutableBoxValue(boxRefValArray, mlir::ValueRange(), {}));
491 return {scalars, arrays};
492 };
493
494 auto f32Ty = mlir::FloatType::getF32(builder.getContext());
495 mlir::Type f32SeqTy = builder.getVarLenSeqTy(f32Ty);
496 auto [f32Scalars, f32Arrays] = makeExv(f32Ty, f32SeqTy);
497 for (const auto &scalar : f32Scalars) {
498 EXPECT_EQ(fir::getBaseTypeOf(scalar), f32Ty);
499 EXPECT_EQ(fir::getElementTypeOf(scalar), f32Ty);
500 EXPECT_FALSE(fir::isDerivedWithLenParameters(scalar));
501 }
502 for (const auto &array : f32Arrays) {
503 EXPECT_EQ(fir::getBaseTypeOf(array), f32SeqTy);
504 EXPECT_EQ(fir::getElementTypeOf(array), f32Ty);
505 EXPECT_FALSE(fir::isDerivedWithLenParameters(array));
506 }
507
508 auto derivedWithLengthTy =
509 fir::RecordType::get(builder.getContext(), "derived_test");
510
511 llvm::SmallVector<std::pair<std::string, mlir::Type>> parameters;
512 llvm::SmallVector<std::pair<std::string, mlir::Type>> components;
513 parameters.emplace_back("p1", builder.getI64Type());
514 components.emplace_back("c1", f32Ty);
515 derivedWithLengthTy.finalize(parameters, components);
516 mlir::Type derivedWithLengthSeqTy =
517 builder.getVarLenSeqTy(derivedWithLengthTy);
518 auto [derivedWithLengthScalars, derivedWithLengthArrays] =
519 makeExv(derivedWithLengthTy, derivedWithLengthSeqTy);
520 for (const auto &scalar : derivedWithLengthScalars) {
521 EXPECT_EQ(fir::getBaseTypeOf(scalar), derivedWithLengthTy);
522 EXPECT_EQ(fir::getElementTypeOf(scalar), derivedWithLengthTy);
523 EXPECT_TRUE(fir::isDerivedWithLenParameters(scalar));
524 }
525 for (const auto &array : derivedWithLengthArrays) {
526 EXPECT_EQ(fir::getBaseTypeOf(array), derivedWithLengthSeqTy);
527 EXPECT_EQ(fir::getElementTypeOf(array), derivedWithLengthTy);
528 EXPECT_TRUE(fir::isDerivedWithLenParameters(array));
529 }
530}
531
532TEST_F(FIRBuilderTest, genArithFastMath) {
533 auto builder = getBuilder();
534 auto ctx = builder.getContext();
535 auto loc = builder.getUnknownLoc();
536
537 auto realTy = mlir::FloatType::getF32(ctx);
538 auto arg = builder.create<fir::UndefOp>(loc, realTy);
539
540 // Test that FastMathFlags is 'none' by default.
541 mlir::Operation *op1 = builder.create<mlir::arith::AddFOp>(loc, arg, arg);
542 auto op1_fmi =
543 mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op1);
544 EXPECT_TRUE(op1_fmi);
545 auto op1_fmf = op1_fmi.getFastMathFlagsAttr().getValue();
546 EXPECT_EQ(op1_fmf, arith::FastMathFlags::none);
547
548 // Test that the builder is copied properly.
549 fir::FirOpBuilder builder_copy(builder);
550
551 arith::FastMathFlags FMF1 =
552 arith::FastMathFlags::contract | arith::FastMathFlags::reassoc;
553 builder.setFastMathFlags(FMF1);
554 arith::FastMathFlags FMF2 =
555 arith::FastMathFlags::nnan | arith::FastMathFlags::ninf;
556 builder_copy.setFastMathFlags(FMF2);
557
558 // Modifying FastMathFlags for the copy must not affect the original builder.
559 mlir::Operation *op2 = builder.create<mlir::arith::AddFOp>(loc, arg, arg);
560 auto op2_fmi =
561 mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op2);
562 EXPECT_TRUE(op2_fmi);
563 auto op2_fmf = op2_fmi.getFastMathFlagsAttr().getValue();
564 EXPECT_EQ(op2_fmf, FMF1);
565
566 // Modifying FastMathFlags for the original builder must not affect the copy.
567 mlir::Operation *op3 =
568 builder_copy.create<mlir::arith::AddFOp>(loc, arg, arg);
569 auto op3_fmi =
570 mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op3);
571 EXPECT_TRUE(op3_fmi);
572 auto op3_fmf = op3_fmi.getFastMathFlagsAttr().getValue();
573 EXPECT_EQ(op3_fmf, FMF2);
574
575 // Test that the builder copy inherits FastMathFlags from the original.
576 fir::FirOpBuilder builder_copy2(builder);
577
578 mlir::Operation *op4 =
579 builder_copy2.create<mlir::arith::AddFOp>(loc, arg, arg);
580 auto op4_fmi =
581 mlir::dyn_cast_or_null<mlir::arith::ArithFastMathInterface>(op4);
582 EXPECT_TRUE(op4_fmi);
583 auto op4_fmf = op4_fmi.getFastMathFlagsAttr().getValue();
584 EXPECT_EQ(op4_fmf, FMF1);
585}
586

source code of flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp