Skip to content

Commit 35b729b

Browse files
[flang] Only use saturated intrinsics for narrowing conversions
1 parent 982527e commit 35b729b

File tree

2 files changed

+138
-32
lines changed

2 files changed

+138
-32
lines changed

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,28 @@ struct CmpcOpConversion : public fir::FIROpConversion<fir::CmpcOp> {
688688
}
689689
};
690690

691+
static mlir::LogicalResult
692+
convertFpToInteger(mlir::ConversionPatternRewriter &rewriter,
693+
fir::ConvertOp opToReplace, mlir::Value op0,
694+
mlir::Type fromTy, mlir::Type toTy, bool isSigned) {
695+
auto fromBits = mlir::LLVM::getPrimitiveTypeSizeInBits(fromTy);
696+
auto toBits = mlir::LLVM::getPrimitiveTypeSizeInBits(toTy);
697+
const bool useSaturatedIntrinsic = fromBits > toBits;
698+
if (useSaturatedIntrinsic) {
699+
const char* intrinsicStr = isSigned ? "llvm.fptosi.sat" : "llvm.fptoui.sat";
700+
auto intrinsicName = mlir::StringAttr::get(opToReplace.getContext(), intrinsicStr);
701+
rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
702+
opToReplace, toTy, intrinsicName, op0);
703+
} else {
704+
if (isSigned) {
705+
rewriter.replaceOpWithNewOp<mlir::LLVM::FPToSIOp>(opToReplace, toTy, op0);
706+
} else {
707+
rewriter.replaceOpWithNewOp<mlir::LLVM::FPToUIOp>(opToReplace, toTy, op0);
708+
}
709+
}
710+
return mlir::success();
711+
}
712+
691713
/// convert value of from-type to value of to-type
692714
struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
693715
using FIROpConversion::FIROpConversion;
@@ -838,18 +860,8 @@ struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> {
838860
// NOTE: We are checking the fir type here because toTy is an LLVM type
839861
// which is signless, and we need to use the intrinsic that matches the
840862
// sign of the output in fir.
841-
if (toFirTy.isUnsignedInteger()) {
842-
auto intrinsicName =
843-
mlir::StringAttr::get(convert.getContext(), "llvm.fptoui.sat");
844-
rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
845-
convert, toTy, intrinsicName, op0);
846-
} else {
847-
auto intrinsicName =
848-
mlir::StringAttr::get(convert.getContext(), "llvm.fptosi.sat");
849-
rewriter.replaceOpWithNewOp<mlir::LLVM::CallIntrinsicOp>(
850-
convert, toTy, intrinsicName, op0);
851-
}
852-
return mlir::success();
863+
const bool isSigned = !toFirTy.isUnsignedInteger();
864+
return convertFpToInteger(rewriter, convert, op0, fromTy, toTy, isSigned);
853865
}
854866
} else if (mlir::isa<mlir::IntegerType>(fromTy)) {
855867
// Integer to integer conversion.

flang/test/Fir/convert-to-llvm.fir

Lines changed: 114 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -690,40 +690,134 @@ func.func @compare_complex_other(%a : complex<f64>, %b : complex<f64>) -> i1 {
690690

691691
// Test `fir.convert` operation conversion from Float type.
692692

693-
func.func @convert_from_float(%arg0 : f32) {
693+
func.func @convert_from_float_to_float(%arg0 : f32) {
694694
%0 = fir.convert %arg0 : (f32) -> f16
695695
%1 = fir.convert %arg0 : (f32) -> f32
696696
%2 = fir.convert %arg0 : (f32) -> f64
697697
%3 = fir.convert %arg0 : (f32) -> f80
698698
%4 = fir.convert %arg0 : (f32) -> f128
699-
%5 = fir.convert %arg0 : (f32) -> i1
700-
%6 = fir.convert %arg0 : (f32) -> i8
701-
%7 = fir.convert %arg0 : (f32) -> i16
702-
%8 = fir.convert %arg0 : (f32) -> i32
703-
%9 = fir.convert %arg0 : (f32) -> i64
704-
%10 = fir.convert %arg0 : (f32) -> ui8
705-
%11 = fir.convert %arg0 : (f32) -> ui16
706-
%12 = fir.convert %arg0 : (f32) -> ui32
707-
%13 = fir.convert %arg0 : (f32) -> ui64
708699
return
709700
}
710701

711-
// CHECK-LABEL: convert_from_float(
702+
// CHECK-LABEL: convert_from_float_to_float(
712703
// CHECK-SAME: %[[ARG0:.*]]: f32
713704
// CHECK: %{{.*}} = llvm.fptrunc %[[ARG0]] : f32 to f16
714705
// CHECK-NOT: f32 to f32
715706
// CHECK: %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f64
716707
// CHECK: %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f80
717708
// CHECK: %{{.*}} = llvm.fpext %[[ARG0]] : f32 to f128
718-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptosi.sat"(%[[ARG0]]) : (f32) -> i1
719-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptosi.sat"(%[[ARG0]]) : (f32) -> i8
720-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptosi.sat"(%[[ARG0]]) : (f32) -> i16
721-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptosi.sat"(%[[ARG0]]) : (f32) -> i32
722-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptosi.sat"(%[[ARG0]]) : (f32) -> i64
723-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptoui.sat"(%[[ARG0]]) : (f32) -> i8
724-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptoui.sat"(%[[ARG0]]) : (f32) -> i16
725-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptoui.sat"(%[[ARG0]]) : (f32) -> i32
726-
// CHECK: %{{.*}} = llvm.call_intrinsic "llvm.fptoui.sat"(%[[ARG0]]) : (f32) -> i64
709+
710+
func.func @convert_from_f16_to_integer(%arg0 : f16) {
711+
%1 = fir.convert %arg0 : (f16) -> i1
712+
%2 = fir.convert %arg0 : (f16) -> i8
713+
%3 = fir.convert %arg0 : (f16) -> i16
714+
%4 = fir.convert %arg0 : (f16) -> i32
715+
%5 = fir.convert %arg0 : (f16) -> i64
716+
%6 = fir.convert %arg0 : (f16) -> i128
717+
%7 = fir.convert %arg0 : (f16) -> ui8
718+
%8 = fir.convert %arg0 : (f16) -> ui16
719+
%9 = fir.convert %arg0 : (f16) -> ui32
720+
%10 = fir.convert %arg0 : (f16) -> ui64
721+
%11 = fir.convert %arg0 : (f16) -> ui128
722+
return
723+
}
724+
725+
// CHECK-LABEL: @convert_from_f16_to_integer(%arg0:
726+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f16) -> i1
727+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f16) -> i8
728+
// CHECK: llvm.fptosi %arg0 : f16 to i16
729+
// CHECK: llvm.fptosi %arg0 : f16 to i32
730+
// CHECK: llvm.fptosi %arg0 : f16 to i64
731+
// CHECK: llvm.fptosi %arg0 : f16 to i128
732+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f16) -> i8
733+
// CHECK: llvm.fptoui %arg0 : f16 to i16
734+
// CHECK: llvm.fptoui %arg0 : f16 to i32
735+
// CHECK: llvm.fptoui %arg0 : f16 to i64
736+
// CHECK: llvm.fptoui %arg0 : f16 to i128
737+
738+
func.func @convert_from_f32_to_integer(%arg0 : f32) {
739+
%1 = fir.convert %arg0 : (f32) -> i1
740+
%2 = fir.convert %arg0 : (f32) -> i8
741+
%3 = fir.convert %arg0 : (f32) -> i16
742+
%4 = fir.convert %arg0 : (f32) -> i32
743+
%5 = fir.convert %arg0 : (f32) -> i64
744+
%6 = fir.convert %arg0 : (f32) -> i128
745+
%7 = fir.convert %arg0 : (f32) -> ui8
746+
%8 = fir.convert %arg0 : (f32) -> ui16
747+
%9 = fir.convert %arg0 : (f32) -> ui32
748+
%10 = fir.convert %arg0 : (f32) -> ui64
749+
%11 = fir.convert %arg0 : (f32) -> ui128
750+
return
751+
}
752+
753+
// CHECK-LABEL: @convert_from_f32_to_integer(%arg0:
754+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f32) -> i1
755+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f32) -> i8
756+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f32) -> i16
757+
// CHECK: llvm.fptosi %arg0 : f32 to i32
758+
// CHECK: llvm.fptosi %arg0 : f32 to i64
759+
// CHECK: llvm.fptosi %arg0 : f32 to i128
760+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f32) -> i8
761+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f32) -> i16
762+
// CHECK: llvm.fptoui %arg0 : f32 to i32
763+
// CHECK: llvm.fptoui %arg0 : f32 to i64
764+
// CHECK: llvm.fptoui %arg0 : f32 to i128
765+
766+
func.func @convert_from_f64_to_integer(%arg0 : f64) {
767+
%1 = fir.convert %arg0 : (f64) -> i1
768+
%2 = fir.convert %arg0 : (f64) -> i8
769+
%3 = fir.convert %arg0 : (f64) -> i16
770+
%4 = fir.convert %arg0 : (f64) -> i32
771+
%5 = fir.convert %arg0 : (f64) -> i64
772+
%6 = fir.convert %arg0 : (f64) -> i128
773+
%7 = fir.convert %arg0 : (f64) -> ui8
774+
%8 = fir.convert %arg0 : (f64) -> ui16
775+
%9 = fir.convert %arg0 : (f64) -> ui32
776+
%10 = fir.convert %arg0 : (f64) -> ui64
777+
%11 = fir.convert %arg0 : (f64) -> ui128
778+
return
779+
}
780+
781+
// CHECK-LABEL: @convert_from_f64_to_integer(%arg0:
782+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f64) -> i1
783+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f64) -> i8
784+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f64) -> i16
785+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f64) -> i32
786+
// CHECK: llvm.fptosi %arg0 : f64 to i64
787+
// CHECK: llvm.fptosi %arg0 : f64 to i128
788+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f64) -> i8
789+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f64) -> i16
790+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f64) -> i32
791+
// CHECK: llvm.fptoui %arg0 : f64 to i64
792+
// CHECK: llvm.fptoui %arg0 : f64 to i128
793+
794+
func.func @convert_from_f128_to_integer(%arg0 : f128) {
795+
%1 = fir.convert %arg0 : (f128) -> i1
796+
%2 = fir.convert %arg0 : (f128) -> i8
797+
%3 = fir.convert %arg0 : (f128) -> i16
798+
%4 = fir.convert %arg0 : (f128) -> i32
799+
%5 = fir.convert %arg0 : (f128) -> i64
800+
%6 = fir.convert %arg0 : (f128) -> i128
801+
%7 = fir.convert %arg0 : (f128) -> ui8
802+
%8 = fir.convert %arg0 : (f128) -> ui16
803+
%9 = fir.convert %arg0 : (f128) -> ui32
804+
%10 = fir.convert %arg0 : (f128) -> ui64
805+
%11 = fir.convert %arg0 : (f128) -> ui128
806+
return
807+
}
808+
809+
// CHECK-LABEL: @convert_from_f128_to_integer(%arg0:
810+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f128) -> i1
811+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f128) -> i8
812+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f128) -> i16
813+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f128) -> i32
814+
// CHECK: llvm.call_intrinsic "llvm.fptosi.sat"(%{{.+}}) : (f128) -> i64
815+
// CHECK: llvm.fptosi %arg0 : f128 to i128
816+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f128) -> i8
817+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f128) -> i16
818+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f128) -> i32
819+
// CHECK: llvm.call_intrinsic "llvm.fptoui.sat"(%{{.+}}) : (f128) -> i64
820+
// CHECK: llvm.fptoui %arg0 : f128 to i128
727821

728822
// -----
729823

0 commit comments

Comments
 (0)