@@ -96,6 +96,121 @@ struct CallOpConversion : public FIROpConversion<fir::CallOp> {
9696 }
9797};
9898
99+ static mlir::Type getComplexEleTy (mlir::Type complex ) {
100+ if (auto cc = complex .dyn_cast <mlir::ComplexType>())
101+ return cc.getElementType ();
102+ return complex .cast <fir::ComplexType>().getElementType ();
103+ }
104+
105+ // / convert value of from-type to value of to-type
106+ struct ConvertOpConversion : public FIROpConversion <fir::ConvertOp> {
107+ using FIROpConversion::FIROpConversion;
108+
109+ static bool isFloatingPointTy (mlir::Type ty) {
110+ return ty.isa <mlir::FloatType>();
111+ }
112+
113+ mlir::LogicalResult
114+ matchAndRewrite (fir::ConvertOp convert, OpAdaptor adaptor,
115+ mlir::ConversionPatternRewriter &rewriter) const override {
116+ auto fromTy = convertType (convert.value ().getType ());
117+ auto toTy = convertType (convert.res ().getType ());
118+ mlir::Value op0 = adaptor.getOperands ()[0 ];
119+ if (fromTy == toTy) {
120+ rewriter.replaceOp (convert, op0);
121+ return success ();
122+ }
123+ auto loc = convert.getLoc ();
124+ auto convertFpToFp = [&](mlir::Value val, unsigned fromBits,
125+ unsigned toBits, mlir::Type toTy) -> mlir::Value {
126+ if (fromBits == toBits) {
127+ // TODO: Converting between two floating-point representations with the
128+ // same bitwidth is not allowed for now.
129+ mlir::emitError (loc,
130+ " cannot implicitly convert between two floating-point "
131+ " representations of the same bitwidth" );
132+ return {};
133+ }
134+ if (fromBits > toBits)
135+ return rewriter.create <mlir::LLVM::FPTruncOp>(loc, toTy, val);
136+ return rewriter.create <mlir::LLVM::FPExtOp>(loc, toTy, val);
137+ };
138+ // Complex to complex conversion.
139+ if (fir::isa_complex (convert.value ().getType ()) &&
140+ fir::isa_complex (convert.res ().getType ())) {
141+ // Special case: handle the conversion of a complex such that both the
142+ // real and imaginary parts are converted together.
143+ auto zero = mlir::ArrayAttr::get (convert.getContext (),
144+ rewriter.getI32IntegerAttr (0 ));
145+ auto one = mlir::ArrayAttr::get (convert.getContext (),
146+ rewriter.getI32IntegerAttr (1 ));
147+ auto ty = convertType (getComplexEleTy (convert.value ().getType ()));
148+ auto rp = rewriter.create <mlir::LLVM::ExtractValueOp>(loc, ty, op0, zero);
149+ auto ip = rewriter.create <mlir::LLVM::ExtractValueOp>(loc, ty, op0, one);
150+ auto nt = convertType (getComplexEleTy (convert.res ().getType ()));
151+ auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits (ty);
152+ auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits (nt);
153+ auto rc = convertFpToFp (rp, fromBits, toBits, nt);
154+ auto ic = convertFpToFp (ip, fromBits, toBits, nt);
155+ auto un = rewriter.create <mlir::LLVM::UndefOp>(loc, toTy);
156+ auto i1 =
157+ rewriter.create <mlir::LLVM::InsertValueOp>(loc, toTy, un, rc, zero);
158+ rewriter.replaceOpWithNewOp <mlir::LLVM::InsertValueOp>(convert, toTy, i1,
159+ ic, one);
160+ return mlir::success ();
161+ }
162+ // Floating point to floating point conversion.
163+ if (isFloatingPointTy (fromTy)) {
164+ if (isFloatingPointTy (toTy)) {
165+ auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits (fromTy);
166+ auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits (toTy);
167+ auto v = convertFpToFp (op0, fromBits, toBits, toTy);
168+ rewriter.replaceOp (convert, v);
169+ return mlir::success ();
170+ }
171+ if (toTy.isa <mlir::IntegerType>()) {
172+ rewriter.replaceOpWithNewOp <mlir::LLVM::FPToSIOp>(convert, toTy, op0);
173+ return mlir::success ();
174+ }
175+ } else if (fromTy.isa <mlir::IntegerType>()) {
176+ // Integer to integer conversion.
177+ if (toTy.isa <mlir::IntegerType>()) {
178+ auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits (fromTy);
179+ auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits (toTy);
180+ assert (fromBits != toBits);
181+ if (fromBits > toBits) {
182+ rewriter.replaceOpWithNewOp <mlir::LLVM::TruncOp>(convert, toTy, op0);
183+ return mlir::success ();
184+ }
185+ rewriter.replaceOpWithNewOp <mlir::LLVM::SExtOp>(convert, toTy, op0);
186+ return mlir::success ();
187+ }
188+ // Integer to floating point conversion.
189+ if (isFloatingPointTy (toTy)) {
190+ rewriter.replaceOpWithNewOp <mlir::LLVM::SIToFPOp>(convert, toTy, op0);
191+ return mlir::success ();
192+ }
193+ // Integer to pointer conversion.
194+ if (toTy.isa <mlir::LLVM::LLVMPointerType>()) {
195+ rewriter.replaceOpWithNewOp <mlir::LLVM::IntToPtrOp>(convert, toTy, op0);
196+ return mlir::success ();
197+ }
198+ } else if (fromTy.isa <mlir::LLVM::LLVMPointerType>()) {
199+ // Pointer to integer conversion.
200+ if (toTy.isa <mlir::IntegerType>()) {
201+ rewriter.replaceOpWithNewOp <mlir::LLVM::PtrToIntOp>(convert, toTy, op0);
202+ return mlir::success ();
203+ }
204+ // Pointer to pointer conversion.
205+ if (toTy.isa <mlir::LLVM::LLVMPointerType>()) {
206+ rewriter.replaceOpWithNewOp <mlir::LLVM::BitcastOp>(convert, toTy, op0);
207+ return mlir::success ();
208+ }
209+ }
210+ return emitError (loc) << " cannot convert " << fromTy << " to " << toTy;
211+ }
212+ };
213+
99214// / Lower `fir.has_value` operation to `llvm.return` operation.
100215struct HasValueOpConversion : public FIROpConversion <fir::HasValueOp> {
101216 using FIROpConversion::FIROpConversion;
@@ -489,12 +604,6 @@ struct InsertOnRangeOpConversion
489604 }
490605};
491606
492- static mlir::Type getComplexEleTy (mlir::Type complex ) {
493- if (auto cc = complex .dyn_cast <mlir::ComplexType>())
494- return cc.getElementType ();
495- return complex .cast <fir::ComplexType>().getElementType ();
496- }
497-
498607//
499608// Primitive operations on Complex types
500609//
@@ -679,13 +788,14 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
679788 auto *context = getModule ().getContext ();
680789 fir::LLVMTypeConverter typeConverter{getModule ()};
681790 mlir::OwningRewritePatternList pattern (context);
682- pattern.insert <AddcOpConversion, AddrOfOpConversion, CallOpConversion,
683- DivcOpConversion, ExtractValueOpConversion,
684- HasValueOpConversion, GlobalOpConversion,
685- InsertOnRangeOpConversion, InsertValueOpConversion,
686- NegcOpConversion, MulcOpConversion, SelectOpConversion,
687- SelectRankOpConversion, SubcOpConversion, UndefOpConversion,
688- UnreachableOpConversion, ZeroOpConversion>(typeConverter);
791+ pattern
792+ .insert <AddcOpConversion, AddrOfOpConversion, CallOpConversion,
793+ ConvertOpConversion, DivcOpConversion, ExtractValueOpConversion,
794+ HasValueOpConversion, GlobalOpConversion,
795+ InsertOnRangeOpConversion, InsertValueOpConversion,
796+ NegcOpConversion, MulcOpConversion, SelectOpConversion,
797+ SelectRankOpConversion, SubcOpConversion, UndefOpConversion,
798+ UnreachableOpConversion, ZeroOpConversion>(typeConverter);
689799 mlir::populateStdToLLVMConversionPatterns (typeConverter, pattern);
690800 mlir::arith::populateArithmeticToLLVMConversionPatterns (typeConverter,
691801 pattern);
0 commit comments