[llvm] [NVPTX] Handle unreachable default in llvm::SwitchIns. (PR #72641)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 15 01:54:40 PST 2024


https://github.com/mmoadeli updated https://github.com/llvm/llvm-project/pull/72641

>From 98061eca09243138eed168b0856758ea25a17359 Mon Sep 17 00:00:00 2001
From: m moadeli <mahmoud.moadeli at codeplay.com>
Date: Fri, 17 Nov 2023 12:07:26 +0000
Subject: [PATCH 1/2] Handle unreachable default in llvm::SwitchIns.

---
 .../Target/NVPTX/NVPTXLowerUnreachable.cpp    | 26 ++++++++++++++++
 .../CodeGen/NVPTX/unreachable-switch-case.ll  | 31 +++++++++++++++++++
 2 files changed, 57 insertions(+)
 create mode 100644 llvm/test/CodeGen/NVPTX/unreachable-switch-case.ll

diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
index 34f06b548db260..0a5e7667f1bbdc 100644
--- a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
@@ -138,7 +138,32 @@ bool NVPTXLowerUnreachable::runOnFunction(Function &F) {
   InlineAsm *Exit = InlineAsm::get(ExitFTy, "exit;", "", true);
 
   bool Changed = false;
+
+  // In scenarios where a Switch Instruction has an unreachable default
+  // successor, substituting the unreachable instruction with an exit
+  // instruction introduces an additional block in the Control Flow Graph
+  // (CFG), thereby negatively impacting performance. To mitigate this
+  // undesirable impact, we proactively refrain from processing blocks that
+  // serve as successors to the unreachable default in the switch instruction.
+  // It is noteworthy that these blocks are subsequently optimized out by other
+  // passes in the optimization pipeline.
+
+  SmallPtrSet<const BasicBlock *, 4> BlocksToAvoid;
+
   for (auto &BB : F)
+    for (auto &I : BB) {
+      if (auto SI = dyn_cast<SwitchInst>(&I)) {
+        const auto DefaultSuccessorBlock = SI->getDefaultDest();
+        if (DefaultSuccessorBlock->size() == 1 &&
+            dyn_cast<UnreachableInst>(DefaultSuccessorBlock->begin())) {
+          BlocksToAvoid.insert(DefaultSuccessorBlock);
+        }
+      }
+    }
+
+  for (auto &BB : F) {
+    if (BlocksToAvoid.find(&BB) != BlocksToAvoid.end())
+      continue;
     for (auto &I : BB) {
       if (auto unreachableInst = dyn_cast<UnreachableInst>(&I)) {
         if (isLoweredToTrap(*unreachableInst))
@@ -147,6 +172,7 @@ bool NVPTXLowerUnreachable::runOnFunction(Function &F) {
         Changed = true;
       }
     }
+  }
   return Changed;
 }
 
diff --git a/llvm/test/CodeGen/NVPTX/unreachable-switch-case.ll b/llvm/test/CodeGen/NVPTX/unreachable-switch-case.ll
new file mode 100644
index 00000000000000..b2bdffc7eedb60
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/unreachable-switch-case.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -march=nvptx -mcpu=sm_20 -verify-machineinstrs | FileCheck %s  
+
+declare noundef i32 @llvm.nvvm.read.ptx.sreg.tid.x() #1
+
+define void @kernel_func() {
+
+  %1 = tail call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
+
+  switch i32 %1, label %unreachabledefault [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb1
+    i32 3, label %bb2
+  ]
+
+  bb0:
+    ret void
+
+  bb1:
+    ret void
+
+  bb2:
+    ret void
+
+  unreachabledefault:
+    unreachable
+
+; CHECK:  @kernel_func
+; CHECK-NOT: unreachabledefault
+; CHECK:  -- End function
+}

>From 70fa78e0102bdcc6cccbb787b982b7ae6738eb7b Mon Sep 17 00:00:00 2001
From: M Moadeli <mahmoud.moadeli at codeplay.com>
Date: Thu, 15 Feb 2024 09:54:13 +0000
Subject: [PATCH 2/2] Skip processing BasicBlocks with single unreachable
 instruction.

Updates the `nvptx-lower-unreachable` pass to bypass BasicBlocks containing just one unreachable instruction. This allows
further optimization by subsequent passes, enhancing overall performance and efficiency.
---
 .../Target/NVPTX/NVPTXLowerUnreachable.cpp    | 31 ++++++-------------
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
index 0a5e7667f1bbdc..be70fa51b2f6b7 100644
--- a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp
@@ -139,30 +139,17 @@ bool NVPTXLowerUnreachable::runOnFunction(Function &F) {
 
   bool Changed = false;
 
-  // In scenarios where a Switch Instruction has an unreachable default
-  // successor, substituting the unreachable instruction with an exit
-  // instruction introduces an additional block in the Control Flow Graph
-  // (CFG), thereby negatively impacting performance. To mitigate this
-  // undesirable impact, we proactively refrain from processing blocks that
-  // serve as successors to the unreachable default in the switch instruction.
-  // It is noteworthy that these blocks are subsequently optimized out by other
-  // passes in the optimization pipeline.
-
-  SmallPtrSet<const BasicBlock *, 4> BlocksToAvoid;
-
-  for (auto &BB : F)
-    for (auto &I : BB) {
-      if (auto SI = dyn_cast<SwitchInst>(&I)) {
-        const auto DefaultSuccessorBlock = SI->getDefaultDest();
-        if (DefaultSuccessorBlock->size() == 1 &&
-            dyn_cast<UnreachableInst>(DefaultSuccessorBlock->begin())) {
-          BlocksToAvoid.insert(DefaultSuccessorBlock);
-        }
-      }
-    }
+  // In scenarios where a BasicBlock contains only one unreachable instruction,
+  // the joint action of nvptx-isel and unreachable-mbb-elimination
+  // effectively optimizes the BasicBlock out. However, adding an exit
+  // command to such a BasicBlock, as suggested by this pass, preserves it
+  // within the Control Flow Graph (CFG), thereby negatively impacting size and
+  // performance. To counteract this undesirable consequence, we choose to
+  // refrain from processing BasicBlocks with just one unreachable instruction
+  // in this pass.
 
   for (auto &BB : F) {
-    if (BlocksToAvoid.find(&BB) != BlocksToAvoid.end())
+    if ((BB.size() == 1) && (isa<UnreachableInst>(BB.front())))
       continue;
     for (auto &I : BB) {
       if (auto unreachableInst = dyn_cast<UnreachableInst>(&I)) {



More information about the llvm-commits mailing list