Skip to content
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

ConstantFold logl calls #94944

Merged
merged 4 commits into from
Jun 18, 2024
Merged

ConstantFold logl calls #94944

merged 4 commits into from
Jun 18, 2024

Conversation

MDevereau
Copy link
Contributor

@MDevereau MDevereau commented Jun 10, 2024

This is a follow up patch from #90611 which folds logl calls in the same manner as log.f128 calls. logl suffers from the same problem as logf128 of having slow calls to fp128 log functions which can be constant folded. However, logl is emitted with -fmath-errno and log.f128 is emitted by -fno-math-errno by certain intrinsics.

This is a follow up patch from llvm#90611 which folds logl calls in the same manner
as log.f128 calls. Logl suffers from the same problem as logf128 of having slow
calls to fp128 log functions which can be constant folded. However, Logl is
emitted at the O3 level instead whereas log.f128 is emitted by Ofast by various
intrinsics.
@llvmbot
Copy link
Member

llvmbot commented Jun 10, 2024

@llvm/pr-subscribers-llvm-analysis

@llvm/pr-subscribers-llvm-transforms

Author: Matthew Devereau (MDevereau)

Changes

This is a follow up patch from #90611 which folds logl calls in the same manner as log.f128 calls. Logl suffers from the same problem as logf128 of having slow calls to fp128 log functions which can be constant folded. However, Logl is emitted at the O3 level instead whereas log.f128 is emitted by Ofast by various intrinsics.


Full diff: https://github.com/llvm/llvm-project/pull/94944.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/ConstantFolding.cpp (+15-9)
  • (modified) llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll (+10)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 3ca3ae951fcd7..c0b9f7a4d68da 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1669,9 +1669,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
            Name == "floor" || Name == "floorf" ||
            Name == "fmod" || Name == "fmodf";
   case 'l':
-    return Name == "log" || Name == "logf" ||
-           Name == "log2" || Name == "log2f" ||
-           Name == "log10" || Name == "log10f";
+    return Name == "log" || Name == "logf" || Name == "log2" ||
+           Name == "log2f" || Name == "log10" || Name == "log10f" ||
+           Name == "logl";
   case 'n':
     return Name == "nearbyint" || Name == "nearbyintf";
   case 'p':
@@ -2085,15 +2085,19 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
     if (IntrinsicID == Intrinsic::canonicalize)
       return constantFoldCanonicalize(Ty, Call, U);
 
+      // Try to handle special fp128 cases before bailing
 #if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128)
     if (Ty->isFP128Ty()) {
-      switch (IntrinsicID) {
-      default:
-        return nullptr;
-      case Intrinsic::log:
-        return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad()));
-      }
+      const APFloat &Fp128APF = Op->getValueAPF();
+      if (IntrinsicID == Intrinsic::log)
+        return ConstantFP::get(Ty, logf128(Fp128APF.convertToQuad()));
     }
+
+    LibFunc Fp128Func = NotLibFunc;
+    if (Ty->isFP128Ty() && TLI->getLibFunc(Name, Fp128Func) &&
+        TLI->has(Fp128Func) && Fp128Func == LibFunc_logl &&
+        !Op->getValueAPF().isNegative() && !Op->getValueAPF().isZero())
+      return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad()));
 #endif
 
     if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
@@ -2356,6 +2360,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
         // TODO: What about hosts that lack a C99 library?
         return ConstantFoldFP(log10, APF, Ty);
       break;
+    case LibFunc_logl:
+      return nullptr;
     case LibFunc_nearbyint:
     case LibFunc_nearbyintf:
     case LibFunc_rint:
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll
index da56997f69382..051d514058ccc 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/logf128.ll
@@ -3,6 +3,7 @@
 
 ; REQUIRES: has_logf128
 declare fp128 @llvm.log.f128(fp128)
+declare fp128 @logl(fp128)
 
 define fp128 @log_e_64(){
 ; CHECK-LABEL: define fp128 @log_e_64() {
@@ -124,3 +125,12 @@ define <2 x fp128> @log_e_negative_2_vector(){
   %A = call <2 x fp128> @llvm.log.v2f128(<2 x fp128> <fp128 0xL0000000000000000C000000000000000, fp128 0xL0000000000000000C000000000000001>)
   ret <2 x fp128> %A
 }
+
+define fp128 @logl_e_64(){
+; CHECK-LABEL: define fp128 @logl_e_64() {
+; CHECK-NEXT:    %A = call fp128 @logl(fp128 noundef 0xL00000000000000004005000000000000)
+; CHECK-NEXT:    ret fp128 0xL300000000000000040010A2B23F3BAB7
+;
+  %A = call fp128 @logl(fp128 noundef 0xL00000000000000004005000000000000)
+  ret fp128 %A
+}

@arsenm
Copy link
Contributor

arsenm commented Jun 10, 2024

Description is imprecise, intrinsic or libcall depends on using -fmath-errno/-fno-math-errno only. Don't mention -Ofast

@MDevereau
Copy link
Contributor Author

Description is imprecise, intrinsic or libcall depends on using -fmath-errno/-fno-math-errno only. Don't mention -Ofast

I've removed -Ofast/-O3 references, thanks.

Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add tests with out-of-range values? 0 and inf and nan and negatives?

@MDevereau
Copy link
Contributor Author

Could you add tests with out-of-range values? 0 and inf and nan and negatives?

Done, I've removed the zero and negative checks as well to keep it consistent with the logf.128 behaviour.

@davemgreen
Copy link
Collaborator

Done, I've removed the zero and negative checks as well to keep it consistent with the logf.128 behaviour.

It needs to produce the same errno and fpexeption values. I can see that the intrinsic remains, but would recommend making it work the same as floats: https://godbolt.org/z/T5x7foe4Y

Comment on lines 2090 to 2099
if (Ty->isFP128Ty()) {
switch (IntrinsicID) {
default:
return nullptr;
case Intrinsic::log:
return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad()));
}
const APFloat &Fp128APF = Op->getValueAPF();
if (IntrinsicID == Intrinsic::log)
return ConstantFP::get(Ty, logf128(Fp128APF.convertToQuad()));
}

LibFunc Fp128Func = NotLibFunc;
if (Ty->isFP128Ty() && TLI->getLibFunc(Name, Fp128Func) &&
TLI->has(Fp128Func) && Fp128Func == LibFunc_logl)
return ConstantFP::get(Ty, logf128(Op->getValueAPF().convertToQuad()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine these under 1 isFP128Ty check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@MDevereau
Copy link
Contributor Author

Done, I've removed the zero and negative checks as well to keep it consistent with the logf.128 behaviour.

It needs to produce the same errno and fpexeption values. I can see that the intrinsic remains, but would recommend making it work the same as floats: https://godbolt.org/z/T5x7foe4Y

I think I've done what you asked for. I'm a bit unsure about the infinity test case though.

Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand the difference between logl and llvm.log.f128 is that logl needs to set errno in the right places and has side-effects, llvm.log.f128 doesn't require that. That is why we convert logl to llvm.log.f128 under Ofast/-fno-math-errno. So llvm.log.f128(0) should still be fine to be constant-folded to Nan, it is only the logl calls that need to be more careful.

@MDevereau
Copy link
Contributor Author

As far as I understand the difference between logl and llvm.log.f128 is that logl needs to set errno in the right places and has side-effects, llvm.log.f128 doesn't require that. That is why we convert logl to llvm.log.f128 under Ofast/-fno-math-errno. So llvm.log.f128(0) should still be fine to be constant-folded to Nan, it is only the logl calls that need to be more careful.

Makes sense, I've removed the checks for log.f128 then. With logl infinity, I was unsure whether the fact it hasn't retained the original logl call was correct behaviour or not.

Copy link
Collaborator

@davemgreen davemgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, I've removed the checks for log.f128 then. With logl infinity, I was unsure whether the fact it hasn't retained the original logl call was correct behaviour or not.

It looks like it doesn't generate a pole error for infinity when I tried it (only for zero), so I think that sounds OK. From what I can tell this LGTM, thanks.

@MDevereau MDevereau merged commit d38c8a7 into llvm:main Jun 18, 2024
7 checks passed
@MDevereau MDevereau deleted the fold-logl branch June 18, 2024 12:27
MDevereau added a commit that referenced this pull request Jun 18, 2024
Uses of __float128 in (#94944) should be float128. Although ConstantFoldFP128
is not reliant on HAS_LOGF128, it is only used by conditional code controlled
by HAS_LOGF128, and will cause unused errors on buildbots.
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
Uses of __float128 in (llvm#94944) should be float128. Although ConstantFoldFP128
is not reliant on HAS_LOGF128, it is only used by conditional code controlled
by HAS_LOGF128, and will cause unused errors on buildbots.
chenzheng1030 pushed a commit that referenced this pull request Jul 30, 2024
Fix the build failure caused by
#94944

Fixes #100296
banach-space pushed a commit to banach-space/llvm-project that referenced this pull request Aug 7, 2024
Fix the build failure caused by
llvm#94944

Fixes llvm#100296
llvmbot pushed a commit to llvmbot/llvm-project that referenced this pull request Oct 16, 2024
Fix the build failure caused by
llvm#94944

Fixes llvm#100296

(cherry picked from commit 40b4fd7)
tru pushed a commit to llvmbot/llvm-project that referenced this pull request Oct 29, 2024
Fix the build failure caused by
llvm#94944

Fixes llvm#100296

(cherry picked from commit 40b4fd7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants