@@ -241,6 +241,72 @@ struct FpToIntConversion final : OpRewritePattern<OpTy> {
241241 bool isUnsigned;
242242};
243243
244+ template <typename OpTy>
245+ struct IntToFpConversion final : OpRewritePattern<OpTy> {
246+ IntToFpConversion (MLIRContext *context, SymbolOpInterface symTable,
247+ bool isUnsigned, PatternBenefit benefit = 1 )
248+ : OpRewritePattern<OpTy>(context, benefit), symTable(symTable),
249+ isUnsigned (isUnsigned){};
250+
251+ LogicalResult matchAndRewrite (OpTy op,
252+ PatternRewriter &rewriter) const override {
253+ // Get APFloat function from runtime library.
254+ auto i1Type = IntegerType::get (symTable->getContext (), 1 );
255+ auto i32Type = IntegerType::get (symTable->getContext (), 32 );
256+ auto i64Type = IntegerType::get (symTable->getContext (), 64 );
257+ FailureOr<FuncOp> fn =
258+ lookupOrCreateApFloatFn (rewriter, symTable, " convert_from_int" ,
259+ {i32Type, i32Type, i1Type, i64Type});
260+ if (failed (fn))
261+ return fn;
262+
263+ rewriter.setInsertionPoint (op);
264+ // Cast operands to 64-bit integers.
265+ Location loc = op.getLoc ();
266+ auto inIntTy = cast<IntegerType>(op.getOperand ().getType ());
267+ auto int64Type = rewriter.getI64Type ();
268+ Value operandBits = op.getOperand ();
269+ if (operandBits.getType ().getIntOrFloatBitWidth () < 64 ) {
270+ if (isUnsigned) {
271+ operandBits =
272+ arith::ExtUIOp::create (rewriter, loc, int64Type, operandBits);
273+ } else {
274+ operandBits =
275+ arith::ExtSIOp::create (rewriter, loc, int64Type, operandBits);
276+ }
277+ } else if (operandBits.getType ().getIntOrFloatBitWidth () > 64 ) {
278+ return rewriter.notifyMatchFailure (
279+ loc, " integer bitwidth > 64 is not supported" );
280+ }
281+
282+ // Call APFloat function.
283+ auto outFloatTy = cast<FloatType>(op.getType ());
284+ Value outSemValue = getSemanticsValue (rewriter, loc, outFloatTy);
285+ Value inWidthValue = arith::ConstantOp::create (
286+ rewriter, loc, i32Type,
287+ rewriter.getIntegerAttr (i32Type, inIntTy.getWidth ()));
288+ Value isUnsignedValue = arith::ConstantOp::create (
289+ rewriter, loc, i1Type, rewriter.getIntegerAttr (i1Type, isUnsigned));
290+ SmallVector<Value> params = {outSemValue, inWidthValue, isUnsignedValue,
291+ operandBits};
292+ auto resultOp =
293+ func::CallOp::create (rewriter, loc, TypeRange (rewriter.getI64Type ()),
294+ SymbolRefAttr::get (*fn), params);
295+
296+ // Truncate result to the original width.
297+ auto outIntWType = rewriter.getIntegerType (outFloatTy.getWidth ());
298+ Value truncatedBits = arith::TruncIOp::create (rewriter, loc, outIntWType,
299+ resultOp->getResult (0 ));
300+ Value result =
301+ arith::BitcastOp::create (rewriter, loc, outFloatTy, truncatedBits);
302+ rewriter.replaceOp (op, result);
303+ return success ();
304+ }
305+
306+ SymbolOpInterface symTable;
307+ bool isUnsigned;
308+ };
309+
244310namespace {
245311struct ArithToAPFloatConversionPass final
246312 : impl::ArithToAPFloatConversionPassBase<ArithToAPFloatConversionPass> {
@@ -269,6 +335,10 @@ void ArithToAPFloatConversionPass::runOnOperation() {
269335 /* isUnsigned=*/ false );
270336 patterns.add <FpToIntConversion<arith::FPToUIOp>>(context, getOperation (),
271337 /* isUnsigned=*/ true );
338+ patterns.add <IntToFpConversion<arith::SIToFPOp>>(context, getOperation (),
339+ /* isUnsigned=*/ false );
340+ patterns.add <IntToFpConversion<arith::UIToFPOp>>(context, getOperation (),
341+ /* isUnsigned=*/ true );
272342 LogicalResult result = success ();
273343 ScopedDiagnosticHandler scopedHandler (context, [&result](Diagnostic &diag) {
274344 if (diag.getSeverity () == DiagnosticSeverity::Error) {
0 commit comments