From db6e682b3a580d55c23833ef0fdc8358dabc1153 Mon Sep 17 00:00:00 2001 From: Rex Xu Date: Thu, 26 Oct 2023 17:12:32 +0800 Subject: [PATCH] Fix issues of tanh(x) when x=INF or -INF We didn't check this special case. We just computed tanh(x) by sinh(x)/cosh(x). But when x=INF or -INF, the limit of tanh(x) is defined as follow: lim(tanh(x)) = 1.0, x -> INF; lim(tanh(x)) = -1.0, x -> -INF --- lgc/builder/ArithBuilder.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lgc/builder/ArithBuilder.cpp b/lgc/builder/ArithBuilder.cpp index 6e63f5f57c..3fa1a7dbff 100644 --- a/lgc/builder/ArithBuilder.cpp +++ b/lgc/builder/ArithBuilder.cpp @@ -514,6 +514,18 @@ Value *BuilderImpl::CreateTanh(Value *x, const Twine &instName) { Value *doubleSinh = CreateFSub(exp, expNeg); Value *doubleCosh = CreateFAdd(exp, expNeg); Value *result = fDivFast(doubleSinh, doubleCosh); + + if (!getFastMathFlags().noInfs()) { + // NOTE: If the fast math flags might have INFs, we should check the special case when the input is +INF or -INF. + // According to the limit of tanh(x), we have following definitions: + // / 1.0, when x -> +INF + // lim(tanh(x)) = + // \ -1.0, when x -> -INF + Value *one = ConstantFP::get(x->getType(), 1.0); + Value *isInf = CreateIsInf(x); + result = CreateSelect(isInf, CreateCopySign(one, x), result); + } + result->setName(instName); return result; }