@@ -657,10 +657,61 @@ static llvm::cl::opt<bool>
657
657
" instead of libm complex operations" ),
658
658
llvm::cl::init(false ));
659
659
660
+ // / Return a string containing the given Fortran intrinsic name
661
+ // / with the type of its arguments specified in funcType
662
+ // / surrounded by the given prefix/suffix.
663
+ static std::string
664
+ prettyPrintIntrinsicName (fir::FirOpBuilder &builder, mlir::Location loc,
665
+ llvm::StringRef prefix, llvm::StringRef name,
666
+ llvm::StringRef suffix, mlir::FunctionType funcType) {
667
+ std::string output = prefix.str ();
668
+ llvm::raw_string_ostream sstream (output);
669
+ if (name == " pow" ) {
670
+ assert (funcType.getNumInputs () == 2 && " power operator has two arguments" );
671
+ std::string displayName{" ** " };
672
+ sstream << numericMlirTypeToFortran (builder, funcType.getInput (0 ), loc,
673
+ displayName)
674
+ << displayName
675
+ << numericMlirTypeToFortran (builder, funcType.getInput (1 ), loc,
676
+ displayName);
677
+ } else {
678
+ sstream << name.upper () << " (" ;
679
+ if (funcType.getNumInputs () > 0 )
680
+ sstream << numericMlirTypeToFortran (builder, funcType.getInput (0 ), loc,
681
+ name);
682
+ for (mlir::Type argType : funcType.getInputs ().drop_front ()) {
683
+ sstream << " , " << numericMlirTypeToFortran (builder, argType, loc, name);
684
+ }
685
+ sstream << " )" ;
686
+ }
687
+ sstream << suffix;
688
+ return output;
689
+ }
690
+
691
+ // Generate a call to the Fortran runtime library providing
692
+ // support for 128-bit float math via a third-party library.
693
+ // If the compiler is built without FLANG_RUNTIME_F128_MATH_LIB,
694
+ // this function will report an error.
695
+ static mlir::Value genLibF128Call (fir::FirOpBuilder &builder,
696
+ mlir::Location loc,
697
+ const MathOperation &mathOp,
698
+ mlir::FunctionType libFuncType,
699
+ llvm::ArrayRef<mlir::Value> args) {
700
+ #ifndef FLANG_RUNTIME_F128_MATH_LIB
701
+ std::string message = prettyPrintIntrinsicName (
702
+ builder, loc, " compiler is built without support for '" , mathOp.key , " '" ,
703
+ libFuncType);
704
+ fir::emitFatalError (loc, message, /* genCrashDiag=*/ false );
705
+ #else // FLANG_RUNTIME_F128_MATH_LIB
706
+ return genLibCall (builder, loc, mathOp, libFuncType, args);
707
+ #endif // FLANG_RUNTIME_F128_MATH_LIB
708
+ }
709
+
660
710
mlir::Value genLibCall (fir::FirOpBuilder &builder, mlir::Location loc,
661
- llvm::StringRef libFuncName ,
711
+ const MathOperation &mathOp ,
662
712
mlir::FunctionType libFuncType,
663
713
llvm::ArrayRef<mlir::Value> args) {
714
+ llvm::StringRef libFuncName = mathOp.runtimeFunc ;
664
715
LLVM_DEBUG (llvm::dbgs () << " Generating '" << libFuncName
665
716
<< " ' call with type " ;
666
717
libFuncType.dump (); llvm::dbgs () << " \n " );
@@ -718,7 +769,7 @@ mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc,
718
769
719
770
mlir::Value genLibSplitComplexArgsCall (fir::FirOpBuilder &builder,
720
771
mlir::Location loc,
721
- llvm::StringRef libFuncName ,
772
+ const MathOperation &mathOp ,
722
773
mlir::FunctionType libFuncType,
723
774
llvm::ArrayRef<mlir::Value> args) {
724
775
assert (args.size () == 2 && " Incorrect #args to genLibSplitComplexArgsCall" );
@@ -762,13 +813,12 @@ mlir::Value genLibSplitComplexArgsCall(fir::FirOpBuilder &builder,
762
813
cplx2, /* isImagPart=*/ true );
763
814
splitArgs.push_back (imag2);
764
815
765
- return genLibCall (builder, loc, libFuncName, getSplitComplexArgsType (),
766
- splitArgs);
816
+ return genLibCall (builder, loc, mathOp, getSplitComplexArgsType (), splitArgs);
767
817
}
768
818
769
819
template <typename T>
770
820
mlir::Value genMathOp (fir::FirOpBuilder &builder, mlir::Location loc,
771
- llvm::StringRef mathLibFuncName ,
821
+ const MathOperation &mathOp ,
772
822
mlir::FunctionType mathLibFuncType,
773
823
llvm::ArrayRef<mlir::Value> args) {
774
824
// TODO: we have to annotate the math operations with flags
@@ -791,13 +841,14 @@ mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
791
841
// can be also lowered to libm calls for "fast" and "relaxed"
792
842
// modes.
793
843
mlir::Value result;
844
+ llvm::StringRef mathLibFuncName = mathOp.runtimeFunc ;
794
845
if (mathRuntimeVersion == preciseVersion &&
795
846
// Some operations do not have to be lowered as conservative
796
847
// calls, since they do not affect strict FP behavior.
797
848
// For example, purely integer operations like exponentiation
798
849
// with integer operands fall into this class.
799
850
!mathLibFuncName.empty ()) {
800
- result = genLibCall (builder, loc, mathLibFuncName , mathLibFuncType, args);
851
+ result = genLibCall (builder, loc, mathOp , mathLibFuncType, args);
801
852
} else {
802
853
LLVM_DEBUG (llvm::dbgs () << " Generating '" << mathLibFuncName
803
854
<< " ' operation with type " ;
@@ -810,7 +861,7 @@ mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
810
861
811
862
template <typename T>
812
863
mlir::Value genComplexMathOp (fir::FirOpBuilder &builder, mlir::Location loc,
813
- llvm::StringRef mathLibFuncName ,
864
+ const MathOperation &mathOp ,
814
865
mlir::FunctionType mathLibFuncType,
815
866
llvm::ArrayRef<mlir::Value> args) {
816
867
mlir::Value result;
@@ -819,11 +870,12 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
819
870
820
871
// If we have libm functions, we can attempt to generate the more precise
821
872
// version of the complex math operation.
873
+ llvm::StringRef mathLibFuncName = mathOp.runtimeFunc ;
822
874
if (!mathLibFuncName.empty ()) {
823
875
// If we enabled MLIR complex or can use approximate operations, we should
824
876
// NOT use libm.
825
877
if (!forceMlirComplex && !canUseApprox) {
826
- result = genLibCall (builder, loc, mathLibFuncName , mathLibFuncType, args);
878
+ result = genLibCall (builder, loc, mathOp , mathLibFuncType, args);
827
879
LLVM_DEBUG (result.dump (); llvm::dbgs () << " \n " );
828
880
return result;
829
881
}
@@ -863,6 +915,10 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
863
915
// / TODO: support remaining Fortran math intrinsics.
864
916
// / See https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gfortran/\
865
917
/// Intrinsic-Procedures.html for a reference.
918
+ constexpr auto FuncTypeReal16Real16 = genFuncType<Ty::Real<16 >, Ty::Real<16 >>;
919
+ constexpr auto FuncTypeReal16Complex16 =
920
+ genFuncType<Ty::Real<16 >, Ty::Complex<16 >>;
921
+
866
922
static constexpr MathOperation mathOperations[] = {
867
923
{" abs" , " fabsf" , genFuncType<Ty::Real<4 >, Ty::Real<4 >>,
868
924
genMathOp<mlir::math::AbsFOp>},
@@ -874,6 +930,7 @@ static constexpr MathOperation mathOperations[] = {
874
930
genComplexMathOp<mlir::complex::AbsOp>},
875
931
{" abs" , " cabs" , genFuncType<Ty::Real<8 >, Ty::Complex<8 >>,
876
932
genComplexMathOp<mlir::complex::AbsOp>},
933
+ {" abs" , RTNAME_STRING (CAbsF128), FuncTypeReal16Complex16, genLibF128Call},
877
934
{" acos" , " acosf" , genFuncType<Ty::Real<4 >, Ty::Real<4 >>, genLibCall},
878
935
{" acos" , " acos" , genFuncType<Ty::Real<8 >, Ty::Real<8 >>, genLibCall},
879
936
{" acos" , " cacosf" , genFuncType<Ty::Complex<4 >, Ty::Complex<4 >>, genLibCall},
@@ -1110,6 +1167,7 @@ static constexpr MathOperation mathOperations[] = {
1110
1167
genMathOp<mlir::math::SinOp>},
1111
1168
{" sin" , " sin" , genFuncType<Ty::Real<8 >, Ty::Real<8 >>,
1112
1169
genMathOp<mlir::math::SinOp>},
1170
+ {" sin" , RTNAME_STRING (SinF128), FuncTypeReal16Real16, genLibF128Call},
1113
1171
{" sin" , " csinf" , genFuncType<Ty::Complex<4 >, Ty::Complex<4 >>,
1114
1172
genComplexMathOp<mlir::complex::SinOp>},
1115
1173
{" sin" , " csin" , genFuncType<Ty::Complex<8 >, Ty::Complex<8 >>,
@@ -1122,6 +1180,7 @@ static constexpr MathOperation mathOperations[] = {
1122
1180
genMathOp<mlir::math::SqrtOp>},
1123
1181
{" sqrt" , " sqrt" , genFuncType<Ty::Real<8 >, Ty::Real<8 >>,
1124
1182
genMathOp<mlir::math::SqrtOp>},
1183
+ {" sqrt" , RTNAME_STRING (SqrtF128), FuncTypeReal16Real16, genLibF128Call},
1125
1184
{" sqrt" , " csqrtf" , genFuncType<Ty::Complex<4 >, Ty::Complex<4 >>,
1126
1185
genComplexMathOp<mlir::complex::SqrtOp>},
1127
1186
{" sqrt" , " csqrt" , genFuncType<Ty::Complex<8 >, Ty::Complex<8 >>,
@@ -1345,27 +1404,9 @@ static void checkPrecisionLoss(llvm::StringRef name,
1345
1404
// lowering and could be used here. Emit an error and continue
1346
1405
// generating the code with the narrowing cast so that the user
1347
1406
// can get a complete list of the problematic intrinsic calls.
1348
- std::string message (" not yet implemented: no math runtime available for '" );
1349
- llvm::raw_string_ostream sstream (message);
1350
- if (name == " pow" ) {
1351
- assert (funcType.getNumInputs () == 2 && " power operator has two arguments" );
1352
- std::string displayName{" ** " };
1353
- sstream << numericMlirTypeToFortran (builder, funcType.getInput (0 ), loc,
1354
- displayName)
1355
- << displayName
1356
- << numericMlirTypeToFortran (builder, funcType.getInput (1 ), loc,
1357
- displayName);
1358
- } else {
1359
- sstream << name.upper () << " (" ;
1360
- if (funcType.getNumInputs () > 0 )
1361
- sstream << numericMlirTypeToFortran (builder, funcType.getInput (0 ), loc,
1362
- name);
1363
- for (mlir::Type argType : funcType.getInputs ().drop_front ()) {
1364
- sstream << " , " << numericMlirTypeToFortran (builder, argType, loc, name);
1365
- }
1366
- sstream << " )" ;
1367
- }
1368
- sstream << " '" ;
1407
+ std::string message = prettyPrintIntrinsicName (
1408
+ builder, loc, " not yet implemented: no math runtime available for '" ,
1409
+ name, " '" , funcType);
1369
1410
mlir::emitError (loc, message);
1370
1411
}
1371
1412
@@ -1887,7 +1928,7 @@ IntrinsicLibrary::getRuntimeCallGenerator(llvm::StringRef name,
1887
1928
for (auto [fst, snd] : llvm::zip (actualFuncType.getInputs (), args))
1888
1929
convertedArguments.push_back (builder.createConvert (loc, fst, snd));
1889
1930
mlir::Value result = mathOp->funcGenerator (
1890
- builder, loc, mathOp-> runtimeFunc , actualFuncType, convertedArguments);
1931
+ builder, loc, * mathOp, actualFuncType, convertedArguments);
1891
1932
mlir::Type soughtType = soughtFuncType.getResult (0 );
1892
1933
return builder.createConvert (loc, soughtType, result);
1893
1934
};
0 commit comments