[llvm] [InstCombine] Optimize `sinh` and `cosh` divisions (PR #81433)
Farzon Lotfi via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 16 11:42:55 PDT 2024
================
@@ -1886,23 +1886,82 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
Value *X;
bool IsTan = match(Op0, m_Intrinsic<Intrinsic::sin>(m_Value(X))) &&
match(Op1, m_Intrinsic<Intrinsic::cos>(m_Specific(X)));
- bool IsCot =
- !IsTan && match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
- match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
+ bool IsCot = !IsTan &&
+ match(Op0, m_Intrinsic<Intrinsic::cos>(m_Value(X))) &&
+ match(Op1, m_Intrinsic<Intrinsic::sin>(m_Specific(X)));
- if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
- LibFunc_tanf, LibFunc_tanl)) {
+ auto GetReplacement = [&](Value *Arg, bool IsInv, LibFunc DoubleFunc,
+ LibFunc FloatFunc,
+ LibFunc LongDoubleFunc) -> Value * {
IRBuilder<> B(&I);
IRBuilder<>::FastMathFlagGuard FMFGuard(B);
B.setFastMathFlags(I.getFastMathFlags());
AttributeList Attrs =
cast<CallBase>(Op0)->getCalledFunction()->getAttributes();
- Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
- LibFunc_tanl, B, Attrs);
- if (IsCot)
+ Value *Res = emitUnaryFloatFnCall(Arg, &TLI, DoubleFunc, FloatFunc,
+ LongDoubleFunc, B, Attrs);
+
+ if (IsInv)
Res = B.CreateFDiv(ConstantFP::get(I.getType(), 1.0), Res);
+
+ return Res;
+ };
+
+ if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
+ LibFunc_tanf, LibFunc_tanl)) {
+
+ Value *Res =
+ GetReplacement(X, IsCot, LibFunc_tan, LibFunc_tanf, LibFunc_tanl);
+
return replaceInstUsesWith(I, Res);
}
+
+ // sinh(X) / cosh(X) -> tanh(X)
+ // cosh(X) / sinh(X) -> 1/tanh(X)
+ Value *Y;
+ CallBase *Op0AsCallBase = dyn_cast<CallBase>(Op0);
+ CallBase *Op1AsCallBase = dyn_cast<CallBase>(Op1);
+ LibFunc Op0LibFunc, Op1LibFunc;
+
+ if (Op1AsCallBase && Op0AsCallBase) {
+ TLI.getLibFunc(*Op1AsCallBase, Op1LibFunc);
+ TLI.getLibFunc(*Op0AsCallBase, Op0LibFunc);
+
+ bool ArgsMatch = match(Op0AsCallBase->getArgOperand(0), m_Value(Y)) &&
+ match(Op1AsCallBase->getArgOperand(0), m_Specific(Y));
+
+ bool IsTanH =
----------------
farzonl wrote:
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 two other cases one of which is `LibFunc_tan` which I think should also be an intrinsic.
```bash
git grep -n "LibFunc_"
InstCombineMulDivRem.cpp:1943: if ((IsTan || IsCot) && hasFloatFn(M, &TLI, I.getType(), LibFunc_tan,
InstCombineMulDivRem.cpp:1944: LibFunc_tanf, LibFunc_tanl)) {
InstCombineMulDivRem.cpp:1950: Value *Res = emitUnaryFloatFnCall(X, &TLI, LibFunc_tan, LibFunc_tanf,
InstCombineMulDivRem.cpp:1951: LibFunc_tanl, B, Attrs);
InstructionCombining.cpp:3162: TLI.has(TheLibFunc) && TheLibFunc == LibFunc_aligned_alloc &&
InstructionCombining.cpp:3484: if (TLI.getLibFunc(FI, Func) && TLI.has(Func) && Func == LibFunc_free
```
By adding `LibFunc` handling here we are increasing the exposure and usage of `LibFunc` unecessarily.
https://github.com/llvm/llvm-project/pull/81433
More information about the llvm-commits
mailing list