|
21 | 21 | #include "mlir/IR/OpImplementation.h"
|
22 | 22 | #include "mlir/IR/PatternMatch.h"
|
23 | 23 | #include "mlir/IR/TypeUtilities.h"
|
| 24 | +#include "mlir/Support/LogicalResult.h" |
24 | 25 |
|
25 | 26 | #include "llvm/ADT/APFloat.h"
|
26 | 27 | #include "llvm/ADT/APInt.h"
|
@@ -1258,6 +1259,20 @@ static bool checkWidthChangeCast(TypeRange inputs, TypeRange outputs) {
|
1258 | 1259 | srcType.getIntOrFloatBitWidth());
|
1259 | 1260 | }
|
1260 | 1261 |
|
| 1262 | +/// Attempts to convert `sourceValue` to an APFloat value with |
| 1263 | +/// `targetSemantics`, without any information loss or rounding. |
| 1264 | +static FailureOr<APFloat> |
| 1265 | +convertFloatValue(APFloat sourceValue, |
| 1266 | + const llvm::fltSemantics &targetSemantics) { |
| 1267 | + bool losesInfo = false; |
| 1268 | + auto status = sourceValue.convert( |
| 1269 | + targetSemantics, llvm::RoundingMode::NearestTiesToEven, &losesInfo); |
| 1270 | + if (losesInfo || status != APFloat::opOK) |
| 1271 | + return failure(); |
| 1272 | + |
| 1273 | + return sourceValue; |
| 1274 | +} |
| 1275 | + |
1261 | 1276 | //===----------------------------------------------------------------------===//
|
1262 | 1277 | // ExtUIOp
|
1263 | 1278 | //===----------------------------------------------------------------------===//
|
@@ -1321,14 +1336,21 @@ LogicalResult arith::ExtSIOp::verify() {
|
1321 | 1336 | // ExtFOp
|
1322 | 1337 | //===----------------------------------------------------------------------===//
|
1323 | 1338 |
|
1324 |
| -/// Always fold extension of FP constants. |
| 1339 | +/// Fold extension of float constants when there is no information loss due the |
| 1340 | +/// difference in fp semantics. |
1325 | 1341 | OpFoldResult arith::ExtFOp::fold(FoldAdaptor adaptor) {
|
1326 |
| - auto constOperand = llvm::dyn_cast_if_present<FloatAttr>(adaptor.getIn()); |
1327 |
| - if (!constOperand) |
1328 |
| - return {}; |
1329 |
| - |
1330 |
| - // Convert to target type via 'double'. |
1331 |
| - return FloatAttr::get(getType(), constOperand.getValue().convertToDouble()); |
| 1342 | + auto resElemType = cast<FloatType>(getElementTypeOrSelf(getType())); |
| 1343 | + const llvm::fltSemantics &targetSemantics = resElemType.getFloatSemantics(); |
| 1344 | + return constFoldCastOp<FloatAttr, FloatAttr>( |
| 1345 | + adaptor.getOperands(), getType(), |
| 1346 | + [&targetSemantics](const APFloat &a, bool &castStatus) { |
| 1347 | + FailureOr<APFloat> result = convertFloatValue(a, targetSemantics); |
| 1348 | + if (failed(result)) { |
| 1349 | + castStatus = false; |
| 1350 | + return a; |
| 1351 | + } |
| 1352 | + return *result; |
| 1353 | + }); |
1332 | 1354 | }
|
1333 | 1355 |
|
1334 | 1356 | bool arith::ExtFOp::areCastCompatible(TypeRange inputs, TypeRange outputs) {
|
@@ -1403,12 +1425,13 @@ OpFoldResult arith::TruncFOp::fold(FoldAdaptor adaptor) {
|
1403 | 1425 | const llvm::fltSemantics &targetSemantics = resElemType.getFloatSemantics();
|
1404 | 1426 | return constFoldCastOp<FloatAttr, FloatAttr>(
|
1405 | 1427 | adaptor.getOperands(), getType(),
|
1406 |
| - [&targetSemantics](APFloat a, bool &castStatus) { |
1407 |
| - bool losesInfo = false; |
1408 |
| - auto status = a.convert( |
1409 |
| - targetSemantics, llvm::RoundingMode::NearestTiesToEven, &losesInfo); |
1410 |
| - castStatus = !losesInfo && status == APFloat::opOK; |
1411 |
| - return a; |
| 1428 | + [&targetSemantics](const APFloat &a, bool &castStatus) { |
| 1429 | + FailureOr<APFloat> result = convertFloatValue(a, targetSemantics); |
| 1430 | + if (failed(result)) { |
| 1431 | + castStatus = false; |
| 1432 | + return a; |
| 1433 | + } |
| 1434 | + return *result; |
1412 | 1435 | });
|
1413 | 1436 | }
|
1414 | 1437 |
|
@@ -1496,6 +1519,7 @@ OpFoldResult arith::SIToFPOp::fold(FoldAdaptor adaptor) {
|
1496 | 1519 | return apf;
|
1497 | 1520 | });
|
1498 | 1521 | }
|
| 1522 | + |
1499 | 1523 | //===----------------------------------------------------------------------===//
|
1500 | 1524 | // FPToUIOp
|
1501 | 1525 | //===----------------------------------------------------------------------===//
|
|
0 commit comments