[Mlir-commits] [mlir] [mlir][complex] Fix exp special values for infinite real part (PR #232791)
Chang Yong Lik
llvmlistbot at llvm.org
Mon Oct 19 06:56:32 PDT 2026
https://github.com/ahlag updated https://github.com/llvm/llvm-project/pull/232791
>From 6183461e74e45f8c9b4195d5869ce59f792e7bdd Mon Sep 17 00:00:00 2001
From: ahlag <theeahlag at gmail.com>
Date: Sat, 17 Oct 2026 00:00:57 +0900
Subject: [PATCH 1/4] [mlir][complex] Fix exp special values for infinite real
part
complex.exp lowering returned nan + nan*i for exp(-inf +- inf*i) and
exp(-inf + nan*i) instead of +-0 +- 0*i, and NaN instead of +-inf for the
real part of exp(+inf + inf*i), because of 0 * NaN and inf * NaN in
exp(x) * cos(y). Handle these cases as C99 Annex G.6.3.1 and the Python
array API specify.
Fixes https://github.com/tensorflow/tensorflow/issues/128988 for XLA CPU
and GPU, which use this lowering.
Assisted-by: Claude
---
.../ComplexToStandard/ComplexToStandard.cpp | 18 ++++++++++
.../convert-to-standard.mlir | 24 ++++++++++++--
.../Dialect/Complex/CPU/correctness.mlir | 33 +++++++++++++++++--
3 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
index d1cdd8ae17e3f..9dea16f9da505 100644
--- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
+++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
@@ -361,6 +361,24 @@ struct ExpOpConversion : public OpConversionPattern<complex::ExpOp> {
arith::SelectOp::create(b, expIsInf, imagOverflow, imagNormal);
Value resultImag = arith::SelectOp::create(b, yIsZero, zero, imagNonZero);
+ // When x is +-inf and y is +-inf or NaN, exp(x) * cos(y) is inf * NaN or
+ // 0 * NaN. C99 Annex G gives exp(-inf + I*y) = +-0 +- 0*I and
+ // exp(+inf + I*y) = +-inf + NaN*I for these y.
+ Value absX = math::AbsFOp::create(b, x);
+ Value absY = math::AbsFOp::create(b, y);
+ Value negInf = arith::ConstantOp::create(
+ b, ET, b.getFloatAttr(ET, APFloat::getInf(floatSemantics, true)));
+ Value yIsNotFinite =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::UGE, absY, inf);
+ Value xIsInf =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, absX, inf);
+ Value xIsNegInf =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, x, negInf);
+ Value useExpX = arith::AndIOp::create(b, xIsInf, yIsNotFinite);
+ Value useZeroImag = arith::AndIOp::create(b, xIsNegInf, yIsNotFinite);
+ resultReal = arith::SelectOp::create(b, useExpX, exp, resultReal);
+ resultImag = arith::SelectOp::create(b, useZeroImag, zero, resultImag);
+
rewriter.replaceOpWithNewOp<complex::CreateOp>(op, type, resultReal,
resultImag);
return success();
diff --git a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
index 448d82df50320..907595b0a395e 100644
--- a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
+++ b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
@@ -230,7 +230,17 @@ func.func @complex_exp(%arg: complex<f32>) -> complex<f32> {
// CHECK-DAG: %[[IMAG_OVERFLOW:.*]] = arith.mulf %[[EXP_HALF_SIN]], %[[EXP_HALF]] : f32
// CHECK-DAG: %[[IMAG_NONZERO:.*]] = arith.select %[[IS_INF]], %[[IMAG_OVERFLOW]], %[[IMAG_NORMAL]] : f32
// CHECK: %[[RESULT_IMAG:.*]] = arith.select %[[IS_IMAG_ZERO]], %[[ZERO]], %[[IMAG_NONZERO]] : f32
-// CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : complex<f32>
+// CHECK-DAG: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32
+// CHECK-DAG: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32
+// CHECK-DAG: %[[NEG_INF:.*]] = arith.constant 0xFF800000 : f32
+// CHECK-DAG: %[[IMAG_NOT_FINITE:.*]] = arith.cmpf uge, %[[ABS_IMAG]], %[[INF]] : f32
+// CHECK-DAG: %[[REAL_IS_INF:.*]] = arith.cmpf oeq, %[[ABS_REAL]], %[[INF]] : f32
+// CHECK-DAG: %[[REAL_IS_NEG_INF:.*]] = arith.cmpf oeq, %[[REAL]], %[[NEG_INF]] : f32
+// CHECK-DAG: %[[USE_EXP_REAL:.*]] = arith.andi %[[REAL_IS_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[REAL_IS_NEG_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK: %[[SPECIAL_REAL:.*]] = arith.select %[[USE_EXP_REAL]], %[[EXP_REAL]], %[[RESULT_REAL]] : f32
+// CHECK: %[[SPECIAL_IMAG:.*]] = arith.select %[[USE_ZERO_IMAG]], %[[ZERO]], %[[RESULT_IMAG]] : f32
+// CHECK: %[[RESULT:.*]] = complex.create %[[SPECIAL_REAL]], %[[SPECIAL_IMAG]] : complex<f32>
// CHECK: return %[[RESULT]] : complex<f32>
// -----
@@ -866,7 +876,17 @@ func.func @complex_exp_with_fmf(%arg: complex<f32>) -> complex<f32> {
// CHECK-DAG: %[[IMAG_OVERFLOW:.*]] = arith.mulf %[[EXP_HALF_SIN]], %[[EXP_HALF]] fastmath<nnan,contract> : f32
// CHECK-DAG: %[[IMAG_NONZERO:.*]] = arith.select %[[IS_INF]], %[[IMAG_OVERFLOW]], %[[IMAG_NORMAL]] : f32
// CHECK: %[[RESULT_IMAG:.*]] = arith.select %[[IS_IMAG_ZERO]], %[[ZERO]], %[[IMAG_NONZERO]] : f32
-// CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : complex<f32>
+// CHECK-DAG: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32
+// CHECK-DAG: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32
+// CHECK-DAG: %[[NEG_INF:.*]] = arith.constant 0xFF800000 : f32
+// CHECK-DAG: %[[IMAG_NOT_FINITE:.*]] = arith.cmpf uge, %[[ABS_IMAG]], %[[INF]] : f32
+// CHECK-DAG: %[[REAL_IS_INF:.*]] = arith.cmpf oeq, %[[ABS_REAL]], %[[INF]] : f32
+// CHECK-DAG: %[[REAL_IS_NEG_INF:.*]] = arith.cmpf oeq, %[[REAL]], %[[NEG_INF]] : f32
+// CHECK-DAG: %[[USE_EXP_REAL:.*]] = arith.andi %[[REAL_IS_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[REAL_IS_NEG_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK: %[[SPECIAL_REAL:.*]] = arith.select %[[USE_EXP_REAL]], %[[EXP_REAL]], %[[RESULT_REAL]] : f32
+// CHECK: %[[SPECIAL_IMAG:.*]] = arith.select %[[USE_ZERO_IMAG]], %[[ZERO]], %[[RESULT_IMAG]] : f32
+// CHECK: %[[RESULT:.*]] = complex.create %[[SPECIAL_REAL]], %[[SPECIAL_IMAG]] : complex<f32>
// CHECK: return %[[RESULT]] : complex<f32>
// -----
diff --git a/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir b/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir
index 29ad9603d1b9b..e07ba8ee1cd54 100644
--- a/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir
+++ b/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir
@@ -377,13 +377,40 @@ func.func @entry() {
// In this case, the overflow of exp(real_part) is compensated when
// sin(imag_part) is close to zero, yielding a finite imaginary part.
- (90.0238094, 5.900613e-39)
+ (90.0238094, 5.900613e-39),
// CHECK-NEXT: inf
// CHECK-NOT: inf
// CHECK-NEXT: 7.3746
- ]> : tensor<3xcomplex<f32>>
+
+ // C99 Annex G special values: exp(-inf + I*y) = +-0 +- 0*I and
+ // exp(+inf + I*y) = +-inf + NaN*I for y = +-inf or NaN, not NaN + NaN*I.
+ // (-inf, inf)
+ (0xFF800000, 0x7F800000),
+ // CHECK-NEXT: 0
+ // CHECK-NEXT: 0
+ // (-inf, -inf)
+ (0xFF800000, 0xFF800000),
+ // CHECK-NEXT: 0
+ // CHECK-NEXT: 0
+ // (-inf, nan)
+ (0xFF800000, 0x7FC00000),
+ // CHECK-NEXT: 0
+ // CHECK-NEXT: 0
+ // (inf, inf)
+ (0x7F800000, 0x7F800000),
+ // CHECK-NEXT: inf
+ // CHECK-NEXT: nan
+ // (inf, -inf)
+ (0x7F800000, 0xFF800000),
+ // CHECK-NEXT: inf
+ // CHECK-NEXT: nan
+ // (inf, nan)
+ (0x7F800000, 0x7FC00000)
+ // CHECK-NEXT: inf
+ // CHECK-NEXT: nan
+ ]> : tensor<9xcomplex<f32>>
%exp_test_cast = tensor.cast %exp_test
- : tensor<3xcomplex<f32>> to tensor<?xcomplex<f32>>
+ : tensor<9xcomplex<f32>> to tensor<?xcomplex<f32>>
%exp_func = func.constant @exp : (complex<f32>) -> complex<f32>
call @test_unary(%exp_test_cast, %exp_func)
>From a0547ab61cd4c7d8948c3c28fd930864abb2d2e3 Mon Sep 17 00:00:00 2001
From: ahlag <theeahlag at gmail.com>
Date: Sat, 17 Oct 2026 00:39:25 +0900
Subject: [PATCH 2/4] [mlir][complex] Skip exp special cases under ninf
Assisted-by: Claude
---
.../ComplexToStandard/ComplexToStandard.cpp | 30 ++++++++++---------
.../convert-to-standard.mlir | 13 ++++++++
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
index 9dea16f9da505..c21f046ddc0cd 100644
--- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
+++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
@@ -364,20 +364,22 @@ struct ExpOpConversion : public OpConversionPattern<complex::ExpOp> {
// When x is +-inf and y is +-inf or NaN, exp(x) * cos(y) is inf * NaN or
// 0 * NaN. C99 Annex G gives exp(-inf + I*y) = +-0 +- 0*I and
// exp(+inf + I*y) = +-inf + NaN*I for these y.
- Value absX = math::AbsFOp::create(b, x);
- Value absY = math::AbsFOp::create(b, y);
- Value negInf = arith::ConstantOp::create(
- b, ET, b.getFloatAttr(ET, APFloat::getInf(floatSemantics, true)));
- Value yIsNotFinite =
- arith::CmpFOp::create(b, arith::CmpFPredicate::UGE, absY, inf);
- Value xIsInf =
- arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, absX, inf);
- Value xIsNegInf =
- arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, x, negInf);
- Value useExpX = arith::AndIOp::create(b, xIsInf, yIsNotFinite);
- Value useZeroImag = arith::AndIOp::create(b, xIsNegInf, yIsNotFinite);
- resultReal = arith::SelectOp::create(b, useExpX, exp, resultReal);
- resultImag = arith::SelectOp::create(b, useZeroImag, zero, resultImag);
+ if (!arith::bitEnumContainsAll(fmf, arith::FastMathFlags::ninf)) {
+ Value absX = math::AbsFOp::create(b, x);
+ Value absY = math::AbsFOp::create(b, y);
+ Value negInf = arith::ConstantOp::create(
+ b, ET, b.getFloatAttr(ET, APFloat::getInf(floatSemantics, true)));
+ Value yIsNotFinite =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::UGE, absY, inf);
+ Value xIsInf =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, absX, inf);
+ Value xIsNegInf =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, x, negInf);
+ Value useExpX = arith::AndIOp::create(b, xIsInf, yIsNotFinite);
+ Value useZeroImag = arith::AndIOp::create(b, xIsNegInf, yIsNotFinite);
+ resultReal = arith::SelectOp::create(b, useExpX, exp, resultReal);
+ resultImag = arith::SelectOp::create(b, useZeroImag, zero, resultImag);
+ }
rewriter.replaceOpWithNewOp<complex::CreateOp>(op, type, resultReal,
resultImag);
diff --git a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
index 907595b0a395e..a9525d9e6be73 100644
--- a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
+++ b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
@@ -891,6 +891,19 @@ func.func @complex_exp_with_fmf(%arg: complex<f32>) -> complex<f32> {
// -----
+// CHECK-LABEL: func @complex_exp_ninf
+// CHECK-SAME: %[[ARG:.*]]: complex<f32>
+func.func @complex_exp_ninf(%arg: complex<f32>) -> complex<f32> {
+ %exp = complex.exp %arg fastmath<ninf> : complex<f32>
+ return %exp : complex<f32>
+}
+// CHECK-NOT: math.absf
+// CHECK-NOT: arith.cmpf uge
+// CHECK: %[[RESULT:.*]] = complex.create
+// CHECK: return %[[RESULT]] : complex<f32>
+
+// -----
+
// CHECK-LABEL: func @complex_log_with_fmf
// CHECK-SAME: %[[ARG:.*]]: complex<f32>
func.func @complex_log_with_fmf(%arg: complex<f32>) -> complex<f32> {
>From f168710a6e0032c8de0f43a8f5ffe2d7bc310436 Mon Sep 17 00:00:00 2001
From: ahlag <theeahlag at gmail.com>
Date: Sat, 17 Oct 2026 09:05:10 +0900
Subject: [PATCH 3/4] [mlir][complex] Check the sign of x instead of comparing
with -inf
Assisted-by: Claude
---
.../Conversion/ComplexToStandard/ComplexToStandard.cpp | 8 +++-----
.../ComplexToStandard/convert-to-standard.mlir | 10 ++++------
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
index c21f046ddc0cd..ec09761f1edeb 100644
--- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
+++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
@@ -367,16 +367,14 @@ struct ExpOpConversion : public OpConversionPattern<complex::ExpOp> {
if (!arith::bitEnumContainsAll(fmf, arith::FastMathFlags::ninf)) {
Value absX = math::AbsFOp::create(b, x);
Value absY = math::AbsFOp::create(b, y);
- Value negInf = arith::ConstantOp::create(
- b, ET, b.getFloatAttr(ET, APFloat::getInf(floatSemantics, true)));
Value yIsNotFinite =
arith::CmpFOp::create(b, arith::CmpFPredicate::UGE, absY, inf);
Value xIsInf =
arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, absX, inf);
- Value xIsNegInf =
- arith::CmpFOp::create(b, arith::CmpFPredicate::OEQ, x, negInf);
+ Value xIsNeg =
+ arith::CmpFOp::create(b, arith::CmpFPredicate::OLT, x, zero);
Value useExpX = arith::AndIOp::create(b, xIsInf, yIsNotFinite);
- Value useZeroImag = arith::AndIOp::create(b, xIsNegInf, yIsNotFinite);
+ Value useZeroImag = arith::AndIOp::create(b, useExpX, xIsNeg);
resultReal = arith::SelectOp::create(b, useExpX, exp, resultReal);
resultImag = arith::SelectOp::create(b, useZeroImag, zero, resultImag);
}
diff --git a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
index a9525d9e6be73..6d77d8f7be799 100644
--- a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
+++ b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir
@@ -232,12 +232,11 @@ func.func @complex_exp(%arg: complex<f32>) -> complex<f32> {
// CHECK: %[[RESULT_IMAG:.*]] = arith.select %[[IS_IMAG_ZERO]], %[[ZERO]], %[[IMAG_NONZERO]] : f32
// CHECK-DAG: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32
// CHECK-DAG: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32
-// CHECK-DAG: %[[NEG_INF:.*]] = arith.constant 0xFF800000 : f32
// CHECK-DAG: %[[IMAG_NOT_FINITE:.*]] = arith.cmpf uge, %[[ABS_IMAG]], %[[INF]] : f32
// CHECK-DAG: %[[REAL_IS_INF:.*]] = arith.cmpf oeq, %[[ABS_REAL]], %[[INF]] : f32
-// CHECK-DAG: %[[REAL_IS_NEG_INF:.*]] = arith.cmpf oeq, %[[REAL]], %[[NEG_INF]] : f32
+// CHECK-DAG: %[[REAL_IS_NEG:.*]] = arith.cmpf olt, %[[REAL]], %[[ZERO]] : f32
// CHECK-DAG: %[[USE_EXP_REAL:.*]] = arith.andi %[[REAL_IS_INF]], %[[IMAG_NOT_FINITE]] : i1
-// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[REAL_IS_NEG_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[USE_EXP_REAL]], %[[REAL_IS_NEG]] : i1
// CHECK: %[[SPECIAL_REAL:.*]] = arith.select %[[USE_EXP_REAL]], %[[EXP_REAL]], %[[RESULT_REAL]] : f32
// CHECK: %[[SPECIAL_IMAG:.*]] = arith.select %[[USE_ZERO_IMAG]], %[[ZERO]], %[[RESULT_IMAG]] : f32
// CHECK: %[[RESULT:.*]] = complex.create %[[SPECIAL_REAL]], %[[SPECIAL_IMAG]] : complex<f32>
@@ -878,12 +877,11 @@ func.func @complex_exp_with_fmf(%arg: complex<f32>) -> complex<f32> {
// CHECK: %[[RESULT_IMAG:.*]] = arith.select %[[IS_IMAG_ZERO]], %[[ZERO]], %[[IMAG_NONZERO]] : f32
// CHECK-DAG: %[[ABS_REAL:.*]] = math.absf %[[REAL]] : f32
// CHECK-DAG: %[[ABS_IMAG:.*]] = math.absf %[[IMAG]] : f32
-// CHECK-DAG: %[[NEG_INF:.*]] = arith.constant 0xFF800000 : f32
// CHECK-DAG: %[[IMAG_NOT_FINITE:.*]] = arith.cmpf uge, %[[ABS_IMAG]], %[[INF]] : f32
// CHECK-DAG: %[[REAL_IS_INF:.*]] = arith.cmpf oeq, %[[ABS_REAL]], %[[INF]] : f32
-// CHECK-DAG: %[[REAL_IS_NEG_INF:.*]] = arith.cmpf oeq, %[[REAL]], %[[NEG_INF]] : f32
+// CHECK-DAG: %[[REAL_IS_NEG:.*]] = arith.cmpf olt, %[[REAL]], %[[ZERO]] : f32
// CHECK-DAG: %[[USE_EXP_REAL:.*]] = arith.andi %[[REAL_IS_INF]], %[[IMAG_NOT_FINITE]] : i1
-// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[REAL_IS_NEG_INF]], %[[IMAG_NOT_FINITE]] : i1
+// CHECK-DAG: %[[USE_ZERO_IMAG:.*]] = arith.andi %[[USE_EXP_REAL]], %[[REAL_IS_NEG]] : i1
// CHECK: %[[SPECIAL_REAL:.*]] = arith.select %[[USE_EXP_REAL]], %[[EXP_REAL]], %[[RESULT_REAL]] : f32
// CHECK: %[[SPECIAL_IMAG:.*]] = arith.select %[[USE_ZERO_IMAG]], %[[ZERO]], %[[RESULT_IMAG]] : f32
// CHECK: %[[RESULT:.*]] = complex.create %[[SPECIAL_REAL]], %[[SPECIAL_IMAG]] : complex<f32>
>From a24e5bc1c0f0ac8593ad6a25dea654255d3692cf Mon Sep 17 00:00:00 2001
From: ahlag <theeahlag at gmail.com>
Date: Mon, 19 Oct 2026 22:48:40 +0900
Subject: [PATCH 4/4] [mlir][complex] Document exp non-finite special cases
---
mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
index ec09761f1edeb..34b9a30428c63 100644
--- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
+++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp
@@ -317,6 +317,9 @@ struct ExpOpConversion : public OpConversionPattern<complex::ExpOp> {
// Handle special cases as StableHLO implementation does:
// 1. When b == 0, set imag(exp(z)) = 0
// 2. When exp(x) == inf, use exp(x/2)*(cos(y)+I*sin(y))*exp(x/2)
+ // Handle non-finite inputs according to C99 annex G:
+ // 3. When x == -inf and y is non-finite, return 0 + I*0.
+ // 4. When x == +inf and y is non-finite, return inf + I*NaN.
LogicalResult
matchAndRewrite(complex::ExpOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
More information about the Mlir-commits
mailing list