-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[InstCombine] Optimize sinh
and cosh
divisions
#81433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c123427
34be781
6e46426
17916a6
54d4706
bde4310
c743711
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py | ||
; RUN: opt --mtriple "arm-apple-macosx15.0.0" -S -passes=instcombine < %s | FileCheck %s | ||
; RUN: opt --mtriple "x86_64-apple-macosx14.7.0" -S -passes=instcombine < %s | FileCheck %s | ||
; RUN: opt --mtriple "x86_64-microsoft-windows" -S -passes=instcombine < %s | FileCheck %s | ||
|
||
define double @fdiv_cosh_sinh(double %a) { | ||
; CHECK-LABEL: @fdiv_cosh_sinh( | ||
; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[TMP2:%.*]] = call double @sinh(double [[A]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call double @cosh(double %a) | ||
%sinh = call double @sinh(double %a) | ||
%div = fdiv double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_strict_cosh_strict_sinh_reassoc(double %a) { | ||
; CHECK-LABEL: @fdiv_strict_cosh_strict_sinh_reassoc( | ||
; CHECK-NEXT: [[TMP1:%.*]] = call double @cosh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[TMP1]], [[TMP2]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceable(2) %dummy) { | ||
; CHECK-LABEL: @fdiv_reassoc_cosh_strict_sinh_strict( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call double @cosh(double %a) | ||
%sinh = call double @sinh(double %a) | ||
%div = fdiv reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_contract_reassoc_cosh_strict_sinh_strict(double %a, ptr dereferenceable(2) %dummy) { | ||
; CHECK-LABEL: @fdiv_contract_reassoc_cosh_strict_sinh_strict( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call double @cosh(double %a) | ||
%sinh = call double @sinh(double %a) | ||
%div = fdiv contract reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_reassoc_cosh_reassoc_sinh_strict(double %a) { | ||
; CHECK-LABEL: @fdiv_reassoc_cosh_reassoc_sinh_strict( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call double @sinh(double %a) | ||
%div = fdiv reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_contract_reassoc_cosh_reassoc_sinh_strict(double %a) { | ||
; CHECK-LABEL: @fdiv_contract_reassoc_cosh_reassoc_sinh_strict( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call double @sinh(double %a) | ||
%div = fdiv contract reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_reassoc_cosh_sinh_reassoc_multiple_uses_sinh(double %a) { | ||
; CHECK-LABEL: @fdiv_reassoc_cosh_sinh_reassoc_multiple_uses_sinh( | ||
; CHECK-NEXT: [[COSH:%.*]] = call reassoc double @cosh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[SINH:%.*]] = call reassoc double @sinh(double [[A]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double [[COSH]], [[SINH]] | ||
; CHECK-NEXT: call void @use(double [[SINH]]) | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv reassoc double %cosh, %sinh | ||
call void @use(double %sinh) | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_contract_reassoc_cosh_sinh_reassoc_multiple_uses_sinh(double %a) { | ||
; CHECK-LABEL: @fdiv_contract_reassoc_cosh_sinh_reassoc_multiple_uses_sinh( | ||
; CHECK-NEXT: [[TMP1:%.*]] = call reassoc double @cosh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @sinh(double [[A]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double [[TMP1]], [[TMP2]] | ||
; CHECK-NEXT: call void @use(double [[TMP2]]) | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv contract reassoc double %cosh, %sinh | ||
call void @use(double %sinh) | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_contract_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_contract_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc contract double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc contract double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv contract reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define fp128 @fdiv_coshl_sinhl_reassoc(fp128 %a){ | ||
%cosh = call reassoc fp128 @coshl(fp128 %a) | ||
%sinh = call reassoc fp128 @sinhl(fp128 %a) | ||
%div = fdiv reassoc fp128 %cosh, %sinh | ||
ret fp128 %div | ||
} | ||
|
||
define float @fdiv_coshf_sinhf_reassoc(float %a){ | ||
; CHECK-LABEL: @fdiv_coshf_sinhf_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc float @tanhf(float [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc float 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret float [[DIV]] | ||
; | ||
%coshf = call reassoc float @coshf(float %a) | ||
%sinhf = call reassoc float @sinhf(float %a) | ||
%div = fdiv reassoc float %coshf, %sinhf | ||
ret float %div | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add the tests with contract combinations? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test preservation of other flags? Maybe !fpmath too, just in case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added tests for all the flags I could find (if I missed any please let me know) that test for flag preservation in case of replacement. I also added the contract combinations and the target triples. |
||
define double @fdiv_fast_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_fast_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc ninf double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc ninf double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv ninf reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_nnan_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_nnan_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc nnan double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv nnan reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_nsz_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_nsz_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc nsz double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nsz double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv nsz reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_arcp_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_arcp_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc arcp double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc arcp double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv arcp reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
define double @fdiv_afn_reassoc_cosh_sinh_reassoc(double %a){ | ||
; CHECK-LABEL: @fdiv_afn_reassoc_cosh_sinh_reassoc( | ||
; CHECK-NEXT: [[TANH:%.*]] = call reassoc afn double @tanh(double [[A:%.*]]) | ||
; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc afn double 1.000000e+00, [[TANH]] | ||
; CHECK-NEXT: ret double [[DIV]] | ||
; | ||
%cosh = call reassoc double @cosh(double %a) | ||
%sinh = call reassoc double @sinh(double %a) | ||
%div = fdiv afn reassoc double %cosh, %sinh | ||
ret double %div | ||
} | ||
|
||
declare double @cosh(double) | ||
declare float @coshf(float) | ||
declare fp128 @coshl(fp128) | ||
|
||
declare double @sinh(double) | ||
declare float @sinhf(float) | ||
declare fp128 @sinhl(fp128) | ||
Comment on lines
+217
to
+219
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is TargetLibraryInfo still oblivious to half functions? |
||
|
||
declare void @use(double) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
their are hyperbolic trig instrunctions now so you can do:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that's additive since now you have to consider the libcall and intrinsic cases (really I think these new intrinsics just increase the amount of code required to support anything)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There aren’t any
LibFunc_sin
orLibFunc_cos
inInstCombineMulDivRem.cpp
. Seems like in this case the intrinsic would result in a more simplistic ArgMatch similar to the sine and cosine cases.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is handling the intrinsics is not a complete solution. You can still do transforms on errno-writing libcalls, in addition to the intrinsics as long as you go from intrinsic->intrinsic and libcall->libcall. But intrinsics also suffer from another issue where there's no plausible mechanism for querying whether the intrinsic can lower, since in principle it should always be lowerable (but in the real world it's just an alias for an environment dependent libcall)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not disputing the correctness of your assertion. I mearly stating that there are no
InstCombine
cases of sine\cosine libfuncs. so doing these changes here to handle libcalls is adding a new pattern.https://github.com/search?q=repo%3Allvm%2Fllvm-project%20LibFunc_sin&type=code
https://github.com/search?q=repo%3Allvm%2Fllvm-project+LibFunc_cos&type=code
In fact looking at the main branch the libcall pattern only exists in three other cases one of which is
LibFunc_tan
which I think should also be an intrinsic.By adding
LibFunc
handling here we are increasing the exposure and usage ofLibFunc
unecessarily.