1 //===- FIRBuilderTest.cpp -- FIRBuilder unit tests ------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
17 struct FIRBuilderTest
: public testing::Test
{
19 void SetUp() override
{
20 fir::support::loadDialects(context
);
22 llvm::ArrayRef
<fir::KindTy
> defs
;
23 fir::KindMapping
kindMap(&context
, defs
);
24 mlir::OpBuilder
builder(&context
);
25 auto loc
= builder
.getUnknownLoc();
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();
34 builder
.setInsertionPointToStart(entryBlock
);
36 firBuilder
= std::make_unique
<fir::FirOpBuilder
>(mod
, kindMap
);
39 fir::FirOpBuilder
&getBuilder() { return *firBuilder
; }
41 mlir::MLIRContext context
;
42 std::unique_ptr
<fir::FirOpBuilder
> firBuilder
;
45 static 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
);
53 static 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());
61 //===----------------------------------------------------------------------===//
63 //===----------------------------------------------------------------------===//
65 TEST_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());
74 TEST_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());
83 TEST_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());
92 TEST_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());
101 //===----------------------------------------------------------------------===//
102 // Helper functions tests
103 //===----------------------------------------------------------------------===//
105 TEST_F(FIRBuilderTest
, genIsNotNullAddr
) {
106 auto builder
= getBuilder();
107 auto loc
= builder
.getUnknownLoc();
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());
116 TEST_F(FIRBuilderTest
, genIsNullAddr
) {
117 auto builder
= getBuilder();
118 auto loc
= builder
.getUnknownLoc();
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());
127 TEST_F(FIRBuilderTest
, createZeroConstant
) {
128 auto builder
= getBuilder();
129 auto loc
= builder
.getUnknownLoc();
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();
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());
144 TEST_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());
154 0u, cstOp
.getValue().cast
<FloatAttr
>().getValue().convertToDouble());
157 TEST_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);
164 TEST_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));
173 TEST_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
);
184 TEST_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());
196 builder
.createInternalLinkage().getValue(), global
.getLinkName().value());
197 EXPECT_FALSE(global
.getInitVal().has_value());
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
);
207 TEST_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
>());
221 16, global
.getInitVal().value().cast
<mlir::IntegerAttr
>().getValue());
222 EXPECT_TRUE(global
.getLinkName().has_value());
224 builder
.createLinkOnceLinkage().getValue(), global
.getLinkName().value());
227 TEST_F(FIRBuilderTest
, uniqueCFIdent
) {
228 auto str1
= fir::factory::uniqueCGIdent("", "func1");
229 EXPECT_EQ("_QQ.66756E6331", str1
);
230 str1
= fir::factory::uniqueCGIdent("", "");
231 EXPECT_EQ("_QQ.", str1
);
232 str1
= fir::factory::uniqueCGIdent("pr", "func1");
233 EXPECT_EQ("_QQpr.66756E6331", str1
);
234 str1
= fir::factory::uniqueCGIdent(
235 "", "longnamemorethan32characterneedshashing");
236 EXPECT_EQ("_QQ.c22a886b2f30ea8c064ef1178377fc31", str1
);
237 str1
= fir::factory::uniqueCGIdent(
238 "pr", "longnamemorethan32characterneedshashing");
239 EXPECT_EQ("_QQpr.c22a886b2f30ea8c064ef1178377fc31", str1
);
242 TEST_F(FIRBuilderTest
, locationToLineNo
) {
243 auto builder
= getBuilder();
244 auto loc
= mlir::FileLineColLoc::get(builder
.getStringAttr("file1"), 10, 5);
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);
253 TEST_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()));
263 TEST_F(FIRBuilderTest
, locationToFilename
) {
264 auto builder
= getBuilder();
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
>());
277 strcmp("file1.f90\0",
279 .dyn_cast
<StringAttr
>()
286 TEST_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());
296 TEST_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
);
314 builder
.createLinkOnceLinkage().getValue(), global
.getLinkName().value());
315 EXPECT_EQ(fir::CharacterType::get(builder
.getContext(), 1, strValue
.size()),
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());
327 TEST_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());
344 static 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]);
354 TEST_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
);
364 TEST_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());
381 TEST_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
);
393 TEST_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
);
402 TEST_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());
421 TEST_F(FIRBuilderTest
, createZeroValue
) {
422 auto builder
= getBuilder();
423 auto loc
= builder
.getUnknownLoc();
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
);
429 mlir::dyn_cast_or_null
<mlir::arith::ConstantOp
>(zeroInt
.getDefiningOp());
431 auto intAttr
= cst
.getValue().dyn_cast
<mlir::IntegerAttr
>();
432 EXPECT_TRUE(intAttr
&& intAttr
.getInt() == 0);
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());
440 auto floatAttr
= cst2
.getValue().dyn_cast
<mlir::FloatAttr
>();
441 EXPECT_TRUE(floatAttr
&& floatAttr
.getValueAsDouble() == 0.);
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());
449 auto intAttr2
= cst
.getValue().dyn_cast
<mlir::IntegerAttr
>();
450 EXPECT_TRUE(intAttr2
&& intAttr2
.getInt() == 0);
453 TEST_F(FIRBuilderTest
, getBaseTypeOf
) {
454 auto builder
= getBuilder();
455 auto loc
= builder
.getUnknownLoc();
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
);
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
);
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(), {}));
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(),
487 arrays
.emplace_back(fir::ArrayBoxValue(ptrValArray
, extents
));
488 arrays
.emplace_back(fir::BoxValue(boxValArray
));
490 fir::MutableBoxValue(boxRefValArray
, mlir::ValueRange(), {}));
491 return {scalars
, arrays
};
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
));
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
));
508 auto derivedWithLengthTy
=
509 fir::RecordType::get(builder
.getContext(), "derived_test");
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
));
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
));
532 TEST_F(FIRBuilderTest
, genArithFastMath
) {
533 auto builder
= getBuilder();
534 auto ctx
= builder
.getContext();
535 auto loc
= builder
.getUnknownLoc();
537 auto realTy
= mlir::FloatType::getF32(ctx
);
538 auto arg
= builder
.create
<fir::UndefOp
>(loc
, realTy
);
540 // Test that FastMathFlags is 'none' by default.
541 mlir::Operation
*op1
= builder
.create
<mlir::arith::AddFOp
>(loc
, arg
, arg
);
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
);
548 // Test that the builder is copied properly.
549 fir::FirOpBuilder
builder_copy(builder
);
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
);
558 // Modifying FastMathFlags for the copy must not affect the original builder.
559 mlir::Operation
*op2
= builder
.create
<mlir::arith::AddFOp
>(loc
, arg
, arg
);
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
);
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
);
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
);
575 // Test that the builder copy inherits FastMathFlags from the original.
576 fir::FirOpBuilder
builder_copy2(builder
);
578 mlir::Operation
*op4
=
579 builder_copy2
.create
<mlir::arith::AddFOp
>(loc
, arg
, arg
);
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
);