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