@@ -241,6 +241,73 @@ 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+ Location loc = op.getLoc ();
254+ if (op.getIn ().getType ().getIntOrFloatBitWidth () > 64 ) {
255+ return rewriter.notifyMatchFailure (
256+ loc, " integer bitwidth > 64 is not supported" );
257+ }
258+
259+ // Get APFloat function from runtime library.
260+ auto i1Type = IntegerType::get (symTable->getContext (), 1 );
261+ auto i32Type = IntegerType::get (symTable->getContext (), 32 );
262+ auto i64Type = IntegerType::get (symTable->getContext (), 64 );
263+ FailureOr<FuncOp> fn =
264+ lookupOrCreateApFloatFn (rewriter, symTable, " convert_from_int" ,
265+ {i32Type, i32Type, i1Type, i64Type});
266+ if (failed (fn))
267+ return fn;
268+
269+ rewriter.setInsertionPoint (op);
270+ // Cast operands to 64-bit integers.
271+ auto inIntTy = cast<IntegerType>(op.getOperand ().getType ());
272+ Value operandBits = op.getOperand ();
273+ if (operandBits.getType ().getIntOrFloatBitWidth () < 64 ) {
274+ if (isUnsigned) {
275+ operandBits =
276+ arith::ExtUIOp::create (rewriter, loc, i64Type, operandBits);
277+ } else {
278+ operandBits =
279+ arith::ExtSIOp::create (rewriter, loc, i64Type, operandBits);
280+ }
281+ }
282+
283+ // Call APFloat function.
284+ auto outFloatTy = cast<FloatType>(op.getType ());
285+ Value outSemValue = getSemanticsValue (rewriter, loc, outFloatTy);
286+ Value inWidthValue = arith::ConstantOp::create (
287+ rewriter, loc, i32Type,
288+ rewriter.getIntegerAttr (i32Type, inIntTy.getWidth ()));
289+ Value isUnsignedValue = arith::ConstantOp::create (
290+ rewriter, loc, i1Type, rewriter.getIntegerAttr (i1Type, isUnsigned));
291+ SmallVector<Value> params = {outSemValue, inWidthValue, isUnsignedValue,
292+ operandBits};
293+ auto resultOp =
294+ func::CallOp::create (rewriter, loc, TypeRange (rewriter.getI64Type ()),
295+ SymbolRefAttr::get (*fn), params);
296+
297+ // Truncate result to the original width.
298+ auto outIntWType = rewriter.getIntegerType (outFloatTy.getWidth ());
299+ Value truncatedBits = arith::TruncIOp::create (rewriter, loc, outIntWType,
300+ resultOp->getResult (0 ));
301+ Value result =
302+ arith::BitcastOp::create (rewriter, loc, outFloatTy, truncatedBits);
303+ rewriter.replaceOp (op, result);
304+ return success ();
305+ }
306+
307+ SymbolOpInterface symTable;
308+ bool isUnsigned;
309+ };
310+
244311namespace {
245312struct ArithToAPFloatConversionPass final
246313 : impl::ArithToAPFloatConversionPassBase<ArithToAPFloatConversionPass> {
@@ -269,6 +336,10 @@ void ArithToAPFloatConversionPass::runOnOperation() {
269336 /* isUnsigned=*/ false );
270337 patterns.add <FpToIntConversion<arith::FPToUIOp>>(context, getOperation (),
271338 /* isUnsigned=*/ true );
339+ patterns.add <IntToFpConversion<arith::SIToFPOp>>(context, getOperation (),
340+ /* isUnsigned=*/ false );
341+ patterns.add <IntToFpConversion<arith::UIToFPOp>>(context, getOperation (),
342+ /* isUnsigned=*/ true );
272343 LogicalResult result = success ();
273344 ScopedDiagnosticHandler scopedHandler (context, [&result](Diagnostic &diag) {
274345 if (diag.getSeverity () == DiagnosticSeverity::Error) {
0 commit comments