diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -98,6 +98,11 @@ mlir::Value genMin(fir::FirOpBuilder &, mlir::Location, llvm::ArrayRef args); +/// Generate Complex divide with the given expected +/// result type. +mlir::Value genDivC(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type resultType, mlir::Value x, mlir::Value y); + /// Generate power function x**y with the given expected /// result type. mlir::Value genPow(fir::FirOpBuilder &, mlir::Location, mlir::Type resultType, diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -1075,7 +1075,16 @@ GENBIN(Multiply, Complex, fir::MulcOp) GENBIN(Divide, Integer, mlir::arith::DivSIOp) GENBIN(Divide, Real, mlir::arith::DivFOp) - GENBIN(Divide, Complex, fir::DivcOp) + + template + ExtValue genval(const Fortran::evaluate::Divide> &op) { + mlir::Type ty = + converter.genType(Fortran::common::TypeCategory::Complex, KIND); + mlir::Value lhs = genunbox(op.left()); + mlir::Value rhs = genunbox(op.right()); + return fir::genDivC(builder, getLoc(), ty, lhs, rhs); + } template ExtValue genval( @@ -5077,7 +5086,21 @@ GENBIN(Multiply, Complex, fir::MulcOp) GENBIN(Divide, Integer, mlir::arith::DivSIOp) GENBIN(Divide, Real, mlir::arith::DivFOp) - GENBIN(Divide, Complex, fir::DivcOp) + + template + CC genarr(const Fortran::evaluate::Divide> &x) { + mlir::Location loc = getLoc(); + mlir::Type ty = + converter.genType(Fortran::common::TypeCategory::Complex, KIND); + auto lf = genarr(x.left()); + auto rf = genarr(x.right()); + return [=](IterSpace iters) -> ExtValue { + mlir::Value lhs = fir::getBase(lf(iters)); + mlir::Value rhs = fir::getBase(rf(iters)); + return fir::genDivC(builder, loc, ty, lhs, rhs); + }; + } template CC genarr( diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -1345,6 +1345,18 @@ {"cosh", "cosh", genF64F64FuncType, genLibCall}, {"cosh", "ccoshf", genComplexComplexFuncType<4>, genLibCall}, {"cosh", "ccosh", genComplexComplexFuncType<8>, genLibCall}, + {"divc", + {}, + genComplexComplexComplexFuncType<2>, + genComplexMathOp}, + {"divc", + {}, + genComplexComplexComplexFuncType<3>, + genComplexMathOp}, + {"divc", "__divsc3", genComplexComplexComplexFuncType<4>, genLibCall}, + {"divc", "__divdc3", genComplexComplexComplexFuncType<8>, genLibCall}, + {"divc", "__divxc3", genComplexComplexComplexFuncType<10>, genLibCall}, + {"divc", "__divtc3", genComplexComplexComplexFuncType<16>, genLibCall}, {"erf", "erff", genF32F32FuncType, genMathOp}, {"erf", "erf", genF64F64FuncType, genMathOp}, {"erfc", "erfcf", genF32F32FuncType, genLibCall}, @@ -5661,6 +5673,11 @@ args); } +mlir::Value fir::genDivC(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Type type, mlir::Value x, mlir::Value y) { + return IntrinsicLibrary{builder, loc}.genRuntimeCall("divc", type, {x, y}); +} + mlir::Value fir::genPow(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, mlir::Value x, mlir::Value y) { // TODO: since there is no libm version of pow with integer exponent, diff --git a/flang/test/Lower/assignment.f90 b/flang/test/Lower/assignment.f90 --- a/flang/test/Lower/assignment.f90 +++ b/flang/test/Lower/assignment.f90 @@ -251,7 +251,7 @@ ! CHECK: %[[FCTRES:.*]] = fir.alloca !fir.complex<4> ! CHECK: %[[A_VAL:.*]] = fir.load %[[A]] : !fir.ref> ! CHECK: %[[B_VAL:.*]] = fir.load %[[B]] : !fir.ref> -! CHECK: %[[DIV:.*]] = fir.divc %[[A_VAL]], %[[B_VAL]] : !fir.complex<4> +! CHECK: %[[DIV:.*]] = fir.call @__divsc3(%[[A_VAL]], %[[B_VAL]]) fastmath : (!fir.complex<4>, !fir.complex<4>) -> !fir.complex<4> ! CHECK: fir.store %[[DIV]] to %[[FCTRES]] : !fir.ref> ! CHECK: %[[RET:.*]] = fir.load %[[FCTRES]] : !fir.ref> ! CHECK: return %[[RET]] : !fir.complex<4> diff --git a/flang/test/Lower/complex-operations.f90 b/flang/test/Lower/complex-operations.f90 --- a/flang/test/Lower/complex-operations.f90 +++ b/flang/test/Lower/complex-operations.f90 @@ -27,11 +27,74 @@ a = b * c end subroutine mul_test -! CHECK-LABEL: @_QPdiv_test -subroutine div_test(a,b,c) - complex :: a, b, c - ! CHECK-NOT: fir.extract_value - ! CHECK-NOT: fir.insert_value - ! CHECK: fir.divc {{.*}}: !fir.complex +! CHECK-LABEL: @_QPdiv_test_half +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[BVAL_CVT:.*]] = fir.convert %[[BVAL]] : (!fir.complex<2>) -> complex +! CHECK: %[[CVAL_CVT:.*]] = fir.convert %[[CVAL]] : (!fir.complex<2>) -> complex +! CHECK: %[[AVAL_CVT:.*]] = complex.div %[[BVAL_CVT]], %[[CVAL_CVT]] : complex +! CHECK: %[[AVAL:.*]] = fir.convert %[[AVAL_CVT]] : (complex) -> !fir.complex<2> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_half(a,b,c) + complex(kind=2) :: a, b, c + a = b / c +end subroutine div_test_half + +! CHECK-LABEL: @_QPdiv_test_bfloat +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[BVAL_CVT:.*]] = fir.convert %[[BVAL]] : (!fir.complex<3>) -> complex +! CHECK: %[[CVAL_CVT:.*]] = fir.convert %[[CVAL]] : (!fir.complex<3>) -> complex +! CHECK: %[[AVAL_CVT:.*]] = complex.div %[[BVAL_CVT]], %[[CVAL_CVT]] : complex +! CHECK: %[[AVAL:.*]] = fir.convert %[[AVAL_CVT]] : (complex) -> !fir.complex<3> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_bfloat(a,b,c) + complex(kind=3) :: a, b, c + a = b / c +end subroutine div_test_bfloat + +! CHECK-LABEL: @_QPdiv_test_single +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[AVAL:.*]] = fir.call @__divsc3(%[[BVAL]], %[[CVAL]]) fastmath : (!fir.complex<4>, !fir.complex<4>) -> !fir.complex<4> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_single(a,b,c) + complex(kind=4) :: a, b, c + a = b / c +end subroutine div_test_single + +! CHECK-LABEL: @_QPdiv_test_double +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[AVAL:.*]] = fir.call @__divdc3(%[[BVAL]], %[[CVAL]]) fastmath : (!fir.complex<8>, !fir.complex<8>) -> !fir.complex<8> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_double(a,b,c) + complex(kind=8) :: a, b, c + a = b / c +end subroutine div_test_double + +! CHECK-LABEL: @_QPdiv_test_extended +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[AVAL:.*]] = fir.call @__divxc3(%[[BVAL]], %[[CVAL]]) fastmath : (!fir.complex<10>, !fir.complex<10>) -> !fir.complex<10> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_extended(a,b,c) + complex(kind=10) :: a, b, c + a = b / c +end subroutine div_test_extended + +! CHECK-LABEL: @_QPdiv_test_quad +! CHECK-SAME: %[[AREF:.*]]: !fir.ref> {{.*}}, %[[BREF:.*]]: !fir.ref> {{.*}}, %[[CREF:.*]]: !fir.ref> {{.*}}) +! CHECK: %[[BVAL:.*]] = fir.load %[[BREF]] : !fir.ref> +! CHECK: %[[CVAL:.*]] = fir.load %[[CREF]] : !fir.ref> +! CHECK: %[[AVAL:.*]] = fir.call @__divtc3(%[[BVAL]], %[[CVAL]]) fastmath : (!fir.complex<16>, !fir.complex<16>) -> !fir.complex<16> +! CHECK: fir.store %[[AVAL]] to %[[AREF]] : !fir.ref> +subroutine div_test_quad(a,b,c) + complex(kind=16) :: a, b, c a = b / c -end subroutine div_test +end subroutine div_test_quad