@@ -96,6 +96,121 @@ struct CallOpConversion : public FIROpConversion<fir::CallOp> {
96
96
}
97
97
};
98
98
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
+
99
214
// / Lower `fir.has_value` operation to `llvm.return` operation.
100
215
struct HasValueOpConversion : public FIROpConversion <fir::HasValueOp> {
101
216
using FIROpConversion::FIROpConversion;
@@ -489,12 +604,6 @@ struct InsertOnRangeOpConversion
489
604
}
490
605
};
491
606
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
-
498
607
//
499
608
// Primitive operations on Complex types
500
609
//
@@ -679,13 +788,14 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
679
788
auto *context = getModule ().getContext ();
680
789
fir::LLVMTypeConverter typeConverter{getModule ()};
681
790
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);
689
799
mlir::populateStdToLLVMConversionPatterns (typeConverter, pattern);
690
800
mlir::arith::populateArithmeticToLLVMConversionPatterns (typeConverter,
691
801
pattern);
0 commit comments