[llvm] [PartiallyInlineLibCalls] Emit missed- and passed-optimization remarks when partially inlining sqrt (PR #123966)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 23 12:10:40 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (TiborGY)

<details>
<summary>Changes</summary>

**PR 2/2**
### Introduction
This build on PR #<!-- -->122654 and adds both passed- and missed-optimization remarks to the PartiallyInlineLibCalls pass. This pass is currently only responsible for the partial inlining of sqrt/sqrtf C library calls, on targets that have a fast HW instruction for square root but demand that `errno` is set on invalid input. One such target is x86_64-unknown-linux-gnu.
### About this PR
Before this PR, the pass was silent, which can be confusing if someone is looking at the asm output and finds the branch it is inserting. So I have added a passed-optimization remark.
At the same time this branch may also impede vectorization in some cases, sqrt is often found in scientific code with nested loops, etc. Therefore I have also added a missed-optimization remark alerting the user to the fact that the `errno` requirement is having an effect on optimizations.

I have also added some further missed-optimization remarks that are emitted when a C library call cannot be optimized by the pass due to strict FP exception behavior or a tail call circumstance.
### Testing
I have added some regression testing to the existing tests that I could find for this pass. I am not 100% sure they are good/sufficient tests, but they are passing. Let me know if more testing is required for new opt-remarks.

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


4 Files Affected:

- (modified) llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp (+35-3) 
- (modified) llvm/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll (+5-1) 
- (modified) llvm/test/Transforms/PartiallyInlineLibCalls/X86/musttail.ll (+3-1) 
- (modified) llvm/test/Transforms/PartiallyInlineLibCalls/strictfp.ll (+3-1) 


``````````diff
diff --git a/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp b/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp
index 2b50ccdc2eeb4f..e56b561ef1f591 100644
--- a/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp
+++ b/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp
@@ -56,6 +56,20 @@ static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
   // dst = phi(v0, v1)
   //
 
+  ORE->emit([&]() {
+    return OptimizationRemark(DEBUG_TYPE, "SqrtPartiallyInlined",
+                              Call->getDebugLoc(), &CurrBB)
+           << "Partially inlined call to sqrt function despite having to use "
+              "errno for error handling: target has fast sqrt instruction";
+  });
+  ORE->emit([&]() {
+    return OptimizationRemarkMissed(DEBUG_TYPE, "BranchInserted",
+                                    Call->getDebugLoc(), &CurrBB)
+           << "Branch to library sqrt fn had to be inserted to satisfy the "
+              "current target's requirement for math functions to set errno on "
+              "invalid inputs";
+  });
+
   Type *Ty = Call->getType();
   IRBuilder<> Builder(Call->getNextNode());
 
@@ -125,11 +139,29 @@ static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI,
       if (!Call || !(CalledFunc = Call->getCalledFunction()))
         continue;
 
-      if (Call->isNoBuiltin() || Call->isStrictFP())
+      if (Call->isNoBuiltin())
         continue;
-
-      if (Call->isMustTailCall())
+      if (Call->isStrictFP()) {
+        ORE->emit([&]() {
+          return OptimizationRemarkMissed(DEBUG_TYPE, "StrictFloat",
+                                          Call->getDebugLoc(), &*CurrBB)
+                 << "Could not consider library function for partial inlining:"
+                    " strict FP exception behavior is active";
+        });
         continue;
+      }
+      // Partially inlining a libcall that has the musttail attribute leads to
+      // broken LLVM IR, triggering an assertion in the IR verifier.
+      // Work around that by forgoing this optimization for musttail calls.
+      if (Call->isMustTailCall()) {
+        ORE->emit([&]() {
+          return OptimizationRemarkMissed(DEBUG_TYPE, "MustTailCall",
+                                          Call->getDebugLoc(), &*CurrBB)
+                 << "Could not consider library function for partial inlining:"
+                    " must tail call";
+        });
+        continue;
+      }
 
       // Skip if function either has local linkage or is not a known library
       // function.
diff --git a/llvm/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll b/llvm/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll
index e6c2a7e629a5d6..49a34d9d4a0a6f 100644
--- a/llvm/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll
+++ b/llvm/test/Transforms/PartiallyInlineLibCalls/X86/good-prototype.ll
@@ -1,8 +1,12 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu -pass-remarks=partially-inline-libcalls \
+; RUN:     -pass-remarks-missed=partially-inline-libcalls 2>%t < %s | FileCheck %s
+; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARK
 
 define float @f(float %val) {
 ; CHECK-LABEL: @f(
+; CHECK-REMARK: Partially inlined call to sqrt function despite having to use errno for error handling: target has fast sqrt instruction
+; CHECK-REMARK: Branch to library sqrt fn had to be inserted to satisfy the current target's requirement for math functions to set errno on invalid inputs
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[RES:%.*]] = tail call float @sqrtf(float [[VAL:%.*]]) #[[READNONE:.*]]
 ; CHECK-NEXT:    [[TMP0:%.*]] = fcmp oge float [[VAL]], 0.000000e+00
diff --git a/llvm/test/Transforms/PartiallyInlineLibCalls/X86/musttail.ll b/llvm/test/Transforms/PartiallyInlineLibCalls/X86/musttail.ll
index 65dd616b43ea69..c877990df309a0 100644
--- a/llvm/test/Transforms/PartiallyInlineLibCalls/X86/musttail.ll
+++ b/llvm/test/Transforms/PartiallyInlineLibCalls/X86/musttail.ll
@@ -1,8 +1,10 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu -pass-remarks-missed=partially-inline-libcalls 2>%t < %s | FileCheck %s
+; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARK
 
 define double @foo(double %x) {
 ; CHECK-LABEL: @foo(
+; CHECK-REMARK: Could not consider library function for partial inlining: must tail call
 ; CHECK-NEXT:    [[R:%.*]] = musttail call double @sqrt(double [[X:%.*]])
 ; CHECK-NEXT:    ret double [[R]]
 ;
diff --git a/llvm/test/Transforms/PartiallyInlineLibCalls/strictfp.ll b/llvm/test/Transforms/PartiallyInlineLibCalls/strictfp.ll
index 8d18d1969b04d3..6a58de096b84a5 100644
--- a/llvm/test/Transforms/PartiallyInlineLibCalls/strictfp.ll
+++ b/llvm/test/Transforms/PartiallyInlineLibCalls/strictfp.ll
@@ -1,7 +1,9 @@
-; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: opt -S -passes=partially-inline-libcalls -mtriple=x86_64-unknown-linux-gnu -pass-remarks-missed=partially-inline-libcalls 2>%t < %s | FileCheck %s
+; RUN: cat %t | FileCheck %s -check-prefix=CHECK-REMARK
 
 define float @f(float %val) strictfp {
 ; CHECK-LABEL: @f
+; CHECK-REMARK: Could not consider library function for partial inlining: strict FP exception behavior is active
 ; CHECK: call{{.*}}@sqrtf
 ; CHECK-NOT: call{{.*}}@sqrtf
   %res = tail call float @sqrtf(float %val) strictfp

``````````

</details>


https://github.com/llvm/llvm-project/pull/123966


More information about the llvm-commits mailing list