[llvm] [SelectionDAG] Disable FastISel for swiftasync functions (PR #70741)

Felipe de Azevedo Piovezan via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 31 14:34:48 PDT 2023


https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/70741

>From 2bfef12aec01b3f33ddfa8217d34ed6a79508395 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 26 Oct 2023 14:08:27 -0700
Subject: [PATCH 1/2] [SelectionDAG] Disable FastISel for swiftasync functions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Most (x86) swiftasync functions tend to use both SelectionDAGISel and FastISel
lowering:
  * FastISel argument lowering can only handle C calling convention.
  * FastISel fails mid-BB in a number of ways, including in simple `ret void`
instructions under certain circumstances.

This dance of SelectionDAG (argument) -> FastISel (some instructions) ->
SelectionDAG(remaining instructions) is lossy; in particular, Argument
information lowering is cleared after that first SelectionDAG run.

Since swiftasync functions rely heavily on proper Argument lowering for debug
information, this patch disables the use of FastISel in such functions.

This was tested by compiling a big translation unit from the Swift concurrency
library, and there was no measurable performance impact:

/ Without patch (i.e. using FastISel)
  Time (mean ± σ):      2.416 s ±  0.016 s    [User: 2.321 s, System: 0.068 s]
  Range (min … max):    2.403 s …  2.458 s    10 runs

// With patch (i.e. not using FastISel)
  Time (mean ± σ):      2.407 s ±  0.011 s    [User: 2.313 s, System: 0.067 s]
  Range (min … max):    2.396 s …  2.424 s    10 runs
---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 5be9ff0300b0485..d9d1b7d21a3c528 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1441,11 +1441,21 @@ static void processSingleLocVars(FunctionLoweringInfo &FuncInfo,
   }
 }
 
+static bool shouldEnableFastISel(const Function &Fn) {
+  // Don't enable FastISel for functions with swiftasync Arguments.
+  // Debug info on those is reliant on good Argument lowering, and FastISel is
+  // not capable of lowering the entire function. Mixing the two selectors tend
+  // to result in poor lowering of Arguments.
+  return none_of(Fn.args(), [](const Argument &Arg) {
+    return Arg.hasAttribute(Attribute::AttrKind::SwiftAsync);
+  });
+}
+
 void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
   FastISelFailed = false;
   // Initialize the Fast-ISel state, if needed.
   FastISel *FastIS = nullptr;
-  if (TM.Options.EnableFastISel) {
+  if (TM.Options.EnableFastISel && shouldEnableFastISel(Fn)) {
     LLVM_DEBUG(dbgs() << "Enabling fast-isel\n");
     FastIS = TLI->createFastISel(*FuncInfo, LibInfo);
   }

>From 91addc5bec0e15c7501f9893c868c6ab4a52244d Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Tue, 31 Oct 2023 14:34:25 -0700
Subject: [PATCH 2/2] fixup! [SelectionDAG] Disable FastISel for swiftasync
 functions

---
 .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 35 ++++++++++---------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index d9d1b7d21a3c528..d0fb77ef1617309 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -204,6 +204,16 @@ static RegisterScheduler
 defaultListDAGScheduler("default", "Best scheduler for the target",
                         createDefaultScheduler);
 
+static bool dontUseFastISelFor(const Function &Fn) {
+  // Don't enable FastISel for functions with swiftasync Arguments.
+  // Debug info on those is reliant on good Argument lowering, and FastISel is
+  // not capable of lowering the entire function. Mixing the two selectors tend
+  // to result in poor lowering of Arguments.
+  return any_of(Fn.args(), [](const Argument &Arg) {
+    return Arg.hasAttribute(Attribute::AttrKind::SwiftAsync);
+  });
+}
+
 namespace llvm {
 
   //===--------------------------------------------------------------------===//
@@ -227,13 +237,14 @@ namespace llvm {
                         << IS.MF->getFunction().getName() << "\n");
       LLVM_DEBUG(dbgs() << "\tBefore: -O" << static_cast<int>(SavedOptLevel) << " ; After: -O"
                         << static_cast<int>(NewOptLevel) << "\n");
-      if (NewOptLevel == CodeGenOptLevel::None) {
+      if (NewOptLevel == CodeGenOptLevel::None)
         IS.TM.setFastISel(IS.TM.getO0WantsFastISel());
-        LLVM_DEBUG(
-            dbgs() << "\tFastISel is "
-                   << (IS.TM.Options.EnableFastISel ? "enabled" : "disabled")
-                   << "\n");
-      }
+      if (dontUseFastISelFor(IS.MF->getFunction()))
+        IS.TM.setFastISel(false);
+      LLVM_DEBUG(
+          dbgs() << "\tFastISel is "
+                 << (IS.TM.Options.EnableFastISel ? "enabled" : "disabled")
+                 << "\n");
     }
 
     ~OptLevelChanger() {
@@ -1441,21 +1452,11 @@ static void processSingleLocVars(FunctionLoweringInfo &FuncInfo,
   }
 }
 
-static bool shouldEnableFastISel(const Function &Fn) {
-  // Don't enable FastISel for functions with swiftasync Arguments.
-  // Debug info on those is reliant on good Argument lowering, and FastISel is
-  // not capable of lowering the entire function. Mixing the two selectors tend
-  // to result in poor lowering of Arguments.
-  return none_of(Fn.args(), [](const Argument &Arg) {
-    return Arg.hasAttribute(Attribute::AttrKind::SwiftAsync);
-  });
-}
-
 void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
   FastISelFailed = false;
   // Initialize the Fast-ISel state, if needed.
   FastISel *FastIS = nullptr;
-  if (TM.Options.EnableFastISel && shouldEnableFastISel(Fn)) {
+  if (TM.Options.EnableFastISel) {
     LLVM_DEBUG(dbgs() << "Enabling fast-isel\n");
     FastIS = TLI->createFastISel(*FuncInfo, LibInfo);
   }



More information about the llvm-commits mailing list