Skip to content

Commit 1066e81

Browse files
kiranchandramohanjeanPerierschweitzpgi
authored
[Flang] Add a factory class for creating Complex Ops (#1266)
Use the factory class in the FIRBuilder. Add unit tests for the factory class function and the convert function of the Complex class. Reviewed By: clementval, rovka Differential Revision: https://reviews.llvm.org/D114125 Co-authored-by: Jean Perier <[email protected]> Co-authored-by: Eric Schweitz <[email protected]>
1 parent 14406e3 commit 1066e81

File tree

4 files changed

+40
-22
lines changed

4 files changed

+40
-22
lines changed

flang/include/flang/Optimizer/Builder/Complex.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class Complex {
2929
enum class Part { Real = 0, Imag = 1 };
3030

3131
/// Get the Complex Type. Determine the type. Do not create MLIR operations.
32-
mlir::Type getComplexPartType(mlir::Value cplx);
33-
mlir::Type getComplexPartType(mlir::Type complexType);
32+
mlir::Type getComplexPartType(mlir::Value cplx) const;
33+
mlir::Type getComplexPartType(mlir::Type complexType) const;
3434

3535
/// Complex operation creation. They create MLIR operations.
3636
mlir::Value createComplex(fir::KindTy kind, mlir::Value real,
@@ -40,6 +40,7 @@ class Complex {
4040
mlir::Value createComplex(mlir::Type complexType, mlir::Value real,
4141
mlir::Value imag);
4242

43+
/// Returns the Real/Imag part of \p cplx
4344
mlir::Value extractComplexPart(mlir::Value cplx, bool isImagPart) {
4445
return isImagPart ? extract<Part::Imag>(cplx) : extract<Part::Real>(cplx);
4546
}

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ class FirOpBuilder : public mlir::OpBuilder {
6262
/// The LHS and RHS are not always in agreement in terms of
6363
/// type. In some cases, the disagreement is between COMPLEX and other scalar
6464
/// types. In that case, the conversion must insert/extract out of a COMPLEX
65-
/// value to have the proper semantics and be strongly typed.
65+
/// value to have the proper semantics and be strongly typed. For e.g for
66+
/// converting an integer/real to a complex, the real part is filled using
67+
/// the integer/real after type conversion and the imaginary part is zero.
6668
mlir::Value convertWithSemantics(mlir::Location loc, mlir::Type toTy,
6769
mlir::Value val);
6870

flang/lib/Optimizer/Builder/Complex.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@
1212
// Complex Factory implementation
1313
//===----------------------------------------------------------------------===//
1414

15-
mlir::Type fir::factory::Complex::getComplexPartType(mlir::Type complexType) {
15+
mlir::Type
16+
fir::factory::Complex::getComplexPartType(mlir::Type complexType) const {
1617
return builder.getRealType(complexType.cast<fir::ComplexType>().getFKind());
1718
}
1819

19-
mlir::Type fir::factory::Complex::getComplexPartType(mlir::Value cplx) {
20+
mlir::Type fir::factory::Complex::getComplexPartType(mlir::Value cplx) const {
2021
return getComplexPartType(cplx.getType());
2122
}
2223

2324
mlir::Value fir::factory::Complex::createComplex(fir::KindTy kind,
2425
mlir::Value real,
2526
mlir::Value imag) {
2627
auto complexTy = fir::ComplexType::get(builder.getContext(), kind);
27-
mlir::Value und = builder.create<fir::UndefOp>(loc, complexTy);
28-
return insert<Part::Imag>(insert<Part::Real>(und, real), imag);
28+
return createComplex(complexTy, real, imag);
2929
}
3030

3131
mlir::Value fir::factory::Complex::createComplex(mlir::Type cplxTy,

flang/unittests/Optimizer/Builder/ComplexTest.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,26 @@ struct ComplexTest : public testing::Test {
3333
helper = std::make_unique<fir::factory::Complex>(*firBuilder, loc);
3434

3535
// Init commonly used types
36-
realTy = mlir::FloatType::getF32(&context);
37-
cType1 = fir::ComplexType::get(&context, 4);
36+
realTy1 = mlir::FloatType::getF32(&context);
37+
complexTy1 = fir::ComplexType::get(&context, 4);
38+
integerTy1 = mlir::IntegerType::get(&context, 32);
3839

39-
// Init commonly used numbers
40-
rOne = firBuilder->createRealConstant(loc, realTy, 1u);
41-
rTwo = firBuilder->createRealConstant(loc, realTy, 2u);
42-
rThree = firBuilder->createRealConstant(loc, realTy, 3u);
43-
rFour = firBuilder->createRealConstant(loc, realTy, 4u);
40+
// Create commonly used reals
41+
rOne = firBuilder->createRealConstant(loc, realTy1, 1u);
42+
rTwo = firBuilder->createRealConstant(loc, realTy1, 2u);
43+
rThree = firBuilder->createRealConstant(loc, realTy1, 3u);
44+
rFour = firBuilder->createRealConstant(loc, realTy1, 4u);
4445
}
4546

4647
mlir::MLIRContext context;
4748
std::unique_ptr<fir::KindMapping> kindMap;
4849
std::unique_ptr<fir::FirOpBuilder> firBuilder;
4950
std::unique_ptr<fir::factory::Complex> helper;
5051

51-
// Commonly used real/complex types
52-
mlir::FloatType realTy;
53-
fir::ComplexType cType1;
52+
// Commonly used real/complex/integer types
53+
mlir::FloatType realTy1;
54+
fir::ComplexType complexTy1;
55+
mlir::IntegerType integerTy1;
5456

5557
// Commonly used real numbers
5658
mlir::Value rOne;
@@ -60,7 +62,7 @@ struct ComplexTest : public testing::Test {
6062
};
6163

6264
TEST_F(ComplexTest, verifyTypes) {
63-
mlir::Value cVal1 = helper->createComplex(cType1, rOne, rTwo);
65+
mlir::Value cVal1 = helper->createComplex(complexTy1, rOne, rTwo);
6466
mlir::Value cVal2 = helper->createComplex(4, rOne, rTwo);
6567
EXPECT_TRUE(fir::isa_complex(cVal1.getType()));
6668
EXPECT_TRUE(fir::isa_complex(cVal2.getType()));
@@ -71,10 +73,10 @@ TEST_F(ComplexTest, verifyTypes) {
7173
mlir::Value imag1 = helper->extractComplexPart(cVal1, /*isImagPart=*/true);
7274
mlir::Value real2 = helper->extractComplexPart(cVal2, /*isImagPart=*/false);
7375
mlir::Value imag2 = helper->extractComplexPart(cVal2, /*isImagPart=*/true);
74-
EXPECT_EQ(realTy, real1.getType());
75-
EXPECT_EQ(realTy, imag1.getType());
76-
EXPECT_EQ(realTy, real2.getType());
77-
EXPECT_EQ(realTy, imag2.getType());
76+
EXPECT_EQ(realTy1, real1.getType());
77+
EXPECT_EQ(realTy1, imag1.getType());
78+
EXPECT_EQ(realTy1, real2.getType());
79+
EXPECT_EQ(realTy1, imag2.getType());
7880

7981
mlir::Value cVal3 =
8082
helper->insertComplexPart(cVal1, rThree, /*isImagPart=*/false);
@@ -83,3 +85,16 @@ TEST_F(ComplexTest, verifyTypes) {
8385
EXPECT_TRUE(fir::isa_complex(cVal4.getType()));
8486
EXPECT_TRUE(fir::isa_real(helper->getComplexPartType(cVal4)));
8587
}
88+
89+
TEST_F(ComplexTest, verifyConvertWithSemantics) {
90+
auto loc = firBuilder->getUnknownLoc();
91+
rOne = firBuilder->createRealConstant(loc, realTy1, 1u);
92+
// Convert real to complex
93+
mlir::Value v1 = firBuilder->convertWithSemantics(loc, complexTy1, rOne);
94+
EXPECT_TRUE(fir::isa_complex(v1.getType()));
95+
96+
// Convert complex to integer
97+
mlir::Value v2 = firBuilder->convertWithSemantics(loc, integerTy1, v1);
98+
EXPECT_TRUE(v2.getType().isa<mlir::IntegerType>());
99+
EXPECT_TRUE(mlir::dyn_cast<fir::ConvertOp>(v2.getDefiningOp()));
100+
}

0 commit comments

Comments
 (0)