[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