[llvm] [InstCombine] Treat `asin`, `asinh`, `atan`, `atan2` and `cbrt` as odd-functions (PR #227336)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 07:47:50 PDT 2026


https://github.com/suogesi created https://github.com/llvm/llvm-project/pull/227336

Add `asin`, `asinh`, `atan`, `atan2` and `cbrt` into the odd-functions list. They should be treated as odd-functions now.

For #227011

>From 38ad8e7e0f289ef3dad68be79fd41f95a02a38ff Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Tue, 29 Sep 2026 22:24:25 +0800
Subject: [PATCH 1/2] [InstCombine] Add tests for a few math functions

---
 .../InstCombine/math-odd-even-parity.ll       | 87 ++++++++++++++++++-
 1 file changed, 85 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/math-odd-even-parity.ll b/llvm/test/Transforms/InstCombine/math-odd-even-parity.ll
index 4c8cf7a99d895..d2c5bc3b74ffa 100644
--- a/llvm/test/Transforms/InstCombine/math-odd-even-parity.ll
+++ b/llvm/test/Transforms/InstCombine/math-odd-even-parity.ll
@@ -2,6 +2,11 @@
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
 declare double @erf(double)
+declare double @asin(double)
+declare double @asinh(double)
+declare double @atan(double)
+declare double @atan2(double, double)
+declare double @cbrt(double)
 declare double @cos(double)
 declare double @fabs(double)
 
@@ -11,7 +16,9 @@ declare void @use(double) nounwind
 define double @test_erf(double %x) {
 ; CHECK-LABEL: define double @test_erf(
 ; CHECK-SAME: double [[X:%.*]]) {
-; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @erf(double [[X]])
+; CHECK-NEXT:    [[NEG_X:%.*]] = fneg double [[X]]
+; CHECK-NEXT:    [[RES1:%.*]] = tail call reassoc double @erf(double [[NEG_X]])
+; CHECK-NEXT:    [[RES:%.*]] = fneg double [[RES1]]
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %neg_x = fneg double %x
@@ -20,11 +27,87 @@ define double @test_erf(double %x) {
   ret double %neg_res
 }
 
+; Check odd parity: -asin(-x) == asin(x)
+define double @test_asin(double %x) {
+; CHECK-LABEL: define double @test_asin(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT:    [[NEG_X:%.*]] = fneg double [[X]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @asin(double [[NEG_X]])
+; CHECK-NEXT:    [[NEG_RES:%.*]] = fneg double [[RES]]
+; CHECK-NEXT:    ret double [[NEG_RES]]
+;
+  %neg_x = fneg double %x
+  %res = tail call reassoc double @asin(double %neg_x)
+  %neg_res = fneg double %res
+  ret double %neg_res
+}
+
+; Check odd parity: -asinh(-x) == asinh(x)
+define double @test_asinh(double %x) {
+; CHECK-LABEL: define double @test_asinh(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT:    [[NEG_X:%.*]] = fneg double [[X]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @asinh(double [[NEG_X]])
+; CHECK-NEXT:    [[NEG_RES:%.*]] = fneg double [[RES]]
+; CHECK-NEXT:    ret double [[NEG_RES]]
+;
+  %neg_x = fneg double %x
+  %res = tail call reassoc double @asinh(double %neg_x)
+  %neg_res = fneg double %res
+  ret double %neg_res
+}
+
+; Check odd parity: -atan(-x) == atan(x)
+define double @test_atan(double %x) {
+; CHECK-LABEL: define double @test_atan(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT:    [[NEG_X:%.*]] = fneg double [[X]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @atan(double [[NEG_X]])
+; CHECK-NEXT:    [[NEG_RES:%.*]] = fneg double [[RES]]
+; CHECK-NEXT:    ret double [[NEG_RES]]
+;
+  %neg_x = fneg double %x
+  %res = tail call reassoc double @atan(double %neg_x)
+  %neg_res = fneg double %res
+  ret double %neg_res
+}
+
+; Check odd parity: -atan2(-y, x) == atan2(y, x)
+define double @test_atan2(double %y, double %x) {
+; CHECK-LABEL: define double @test_atan2(
+; CHECK-SAME: double [[Y:%.*]], double [[X:%.*]]) {
+; CHECK-NEXT:    [[NEG_Y:%.*]] = fneg double [[Y]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @atan2(double [[NEG_Y]], double [[X]])
+; CHECK-NEXT:    [[NEG_RES:%.*]] = fneg double [[RES]]
+; CHECK-NEXT:    ret double [[NEG_RES]]
+;
+  %neg_y = fneg double %y
+  %res = tail call reassoc double @atan2(double %neg_y, double %x)
+  %neg_res = fneg double %res
+  ret double %neg_res
+}
+
+; Check odd parity: -cbrt(-x) == cbrt(x)
+define double @test_cbrt(double %x) {
+; CHECK-LABEL: define double @test_cbrt(
+; CHECK-SAME: double [[X:%.*]]) {
+; CHECK-NEXT:    [[NEG_X:%.*]] = fneg double [[X]]
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @cbrt(double [[NEG_X]])
+; CHECK-NEXT:    [[NEG_RES:%.*]] = fneg double [[RES]]
+; CHECK-NEXT:    ret double [[NEG_RES]]
+;
+  %neg_x = fneg double %x
+  %res = tail call reassoc double @cbrt(double %neg_x)
+  %neg_res = fneg double %res
+  ret double %neg_res
+}
+
 ; Check even parity: cos(fabs(x)) == cos(x)
 define double @test_cos_fabs(double %x) {
 ; CHECK-LABEL: define double @test_cos_fabs(
 ; CHECK-SAME: double [[X:%.*]]) {
-; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @cos(double [[X]])
+; CHECK-NEXT:    [[FABS_RES:%.*]] = call double @llvm.fabs.f64(double [[X]])
+; CHECK-NEXT:    [[RES:%.*]] = tail call reassoc double @cos(double [[FABS_RES]])
 ; CHECK-NEXT:    ret double [[RES]]
 ;
   %fabs_res = call double @fabs(double %x)

>From 66166315fe3300eeaa2e842cd16eda5f3c64f166 Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Tue, 29 Sep 2026 22:26:58 +0800
Subject: [PATCH 2/2] [InstCombine] Treat a few math functions as odd-functions

Math functions `asin`, `asinh`, `atan`, `atan2` and `cbrt` are added
into the list. `atan2(-y, x) == -atan2(y, x)` so `atan2` is odd.

Meets needs of #227011
---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 5da7349b4d9c9..571efbd508c33 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -3156,6 +3156,10 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,
   case LibFunc_coshl:
     return optimizeSymmetricCall(CI, /*IsEven*/ true, B);
 
+  case LibFunc_cbrt:
+  case LibFunc_cbrtf:
+  case LibFunc_cbrtl:
+
   case LibFunc_sin:
   case LibFunc_sinf:
   case LibFunc_sinl:
@@ -3164,6 +3168,14 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,
   case LibFunc_sinhf:
   case LibFunc_sinhl:
 
+  case LibFunc_asin:
+  case LibFunc_asinf:
+  case LibFunc_asinl:
+
+  case LibFunc_asinh:
+  case LibFunc_asinhf:
+  case LibFunc_asinhl:
+
   case LibFunc_tan:
   case LibFunc_tanf:
   case LibFunc_tanl:
@@ -3172,6 +3184,14 @@ Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,
   case LibFunc_tanhf:
   case LibFunc_tanhl:
 
+  case LibFunc_atan:
+  case LibFunc_atanf:
+  case LibFunc_atanl:
+
+  case LibFunc_atan2:
+  case LibFunc_atan2f:
+  case LibFunc_atan2l:
+
   case LibFunc_erf:
   case LibFunc_erff:
   case LibFunc_erfl:



More information about the llvm-commits mailing list