[llvm] [BDCE] Eliminate unreachable blocks to prevent incorrect replacement (PR #194614)

Hongyu Chen via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 28 08:24:11 PDT 2026


https://github.com/XChy updated https://github.com/llvm/llvm-project/pull/194614

>From c07f753d50f86ff38327050410e6cc9de63e4e10 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 20:57:30 +0800
Subject: [PATCH 1/6] [BDCE] Eliminate unreachable blocks to prevent incorrect
 replacement

---
 llvm/lib/Transforms/Scalar/BDCE.cpp    |  9 +++++++--
 llvm/test/Transforms/BDCE/dead-uses.ll | 15 +++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index d96dbca30fdb1..81d43e10784fd 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -26,6 +26,7 @@
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
 
 using namespace llvm;
@@ -201,10 +202,14 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
 
 PreservedAnalyses BDCEPass::run(Function &F, FunctionAnalysisManager &AM) {
   auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
-  if (!bitTrackingDCE(F, DB))
+
+  // Avoid incorrect replacement of non-SSA values in unreachable blocks.
+  bool CFGChanged = EliminateUnreachableBlocks(F);
+  if (!CFGChanged && !bitTrackingDCE(F, DB))
     return PreservedAnalyses::all();
 
   PreservedAnalyses PA;
-  PA.preserveSet<CFGAnalyses>();
+  if (!CFGChanged)
+    PA.preserveSet<CFGAnalyses>();
   return PA;
 }
diff --git a/llvm/test/Transforms/BDCE/dead-uses.ll b/llvm/test/Transforms/BDCE/dead-uses.ll
index 5c1677e59a8b8..449da755a7efa 100644
--- a/llvm/test/Transforms/BDCE/dead-uses.ll
+++ b/llvm/test/Transforms/BDCE/dead-uses.ll
@@ -101,3 +101,18 @@ define void @dead_use_invalidation(i32 %a) {
   ret void
 }
 declare void @dummy(i32)
+
+define i64 @deadcode_self_reference() {
+; CHECK-LABEL: @deadcode_self_reference(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i64 0
+;
+entry:
+  ret i64 0
+
+loop:
+  %or = or i32 %or, 0
+  %conv = trunc i32 %or to i16
+  %call = call i16 null(i16 0, i16 %conv)
+  br label %loop
+}

>From 948b3b98213759233d47564bb69562ffbc7926b5 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 22:47:10 +0800
Subject: [PATCH 2/6] skip self-referential values

---
 llvm/lib/Transforms/Scalar/BDCE.cpp    | 13 ++++++++-----
 llvm/test/Transforms/BDCE/dead-uses.ll |  5 +++++
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 81d43e10784fd..658b5fc28edbe 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Scalar/BDCE.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
@@ -104,6 +105,11 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
     if (I.mayHaveSideEffects() && I.use_empty())
       continue;
 
+    // Avoid incorrect replacement of self-referential values in unreachable
+    // blocks.
+    if (llvm::is_contained(I.operands(), &I))
+      continue;
+
     // Remove instructions that are dead, either because they were not reached
     // during analysis or have no demanded bits.
     if (DB.isInstructionDead(&I) ||
@@ -203,13 +209,10 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
 PreservedAnalyses BDCEPass::run(Function &F, FunctionAnalysisManager &AM) {
   auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
 
-  // Avoid incorrect replacement of non-SSA values in unreachable blocks.
-  bool CFGChanged = EliminateUnreachableBlocks(F);
-  if (!CFGChanged && !bitTrackingDCE(F, DB))
+  if (!bitTrackingDCE(F, DB))
     return PreservedAnalyses::all();
 
   PreservedAnalyses PA;
-  if (!CFGChanged)
-    PA.preserveSet<CFGAnalyses>();
+  PA.preserveSet<CFGAnalyses>();
   return PA;
 }
diff --git a/llvm/test/Transforms/BDCE/dead-uses.ll b/llvm/test/Transforms/BDCE/dead-uses.ll
index 449da755a7efa..493a6fcca3493 100644
--- a/llvm/test/Transforms/BDCE/dead-uses.ll
+++ b/llvm/test/Transforms/BDCE/dead-uses.ll
@@ -106,6 +106,11 @@ define i64 @deadcode_self_reference() {
 ; CHECK-LABEL: @deadcode_self_reference(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    ret i64 0
+; CHECK:       loop:
+; CHECK-NEXT:    [[OR:%.*]] = or i32 [[OR]], 0
+; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[OR]] to i16
+; CHECK-NEXT:    [[CALL:%.*]] = call i16 null(i16 0, i16 [[CONV]])
+; CHECK-NEXT:    br label [[LOOP:%.*]]
 ;
 entry:
   ret i64 0

>From b4ce57f6763c748d894940503d96665a649ace00 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 22:47:43 +0800
Subject: [PATCH 3/6] format

---
 llvm/lib/Transforms/Scalar/BDCE.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 658b5fc28edbe..56f6f3ceb92d2 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -208,7 +208,6 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
 
 PreservedAnalyses BDCEPass::run(Function &F, FunctionAnalysisManager &AM) {
   auto &DB = AM.getResult<DemandedBitsAnalysis>(F);
-
   if (!bitTrackingDCE(F, DB))
     return PreservedAnalyses::all();
 

>From e9852aa3476e7a2eda4958c68f7ae40cb9f0d6e2 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 23:16:06 +0800
Subject: [PATCH 4/6] case by case

---
 llvm/lib/Transforms/Scalar/BDCE.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 56f6f3ceb92d2..12680951c2ae0 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -15,7 +15,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Scalar/BDCE.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
@@ -27,7 +26,6 @@
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
 
 using namespace llvm;
@@ -105,11 +103,6 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
     if (I.mayHaveSideEffects() && I.use_empty())
       continue;
 
-    // Avoid incorrect replacement of self-referential values in unreachable
-    // blocks.
-    if (llvm::is_contained(I.operands(), &I))
-      continue;
-
     // Remove instructions that are dead, either because they were not reached
     // during analysis or have no demanded bits.
     if (DB.isInstructionDead(&I) ||
@@ -126,7 +119,9 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
       const uint32_t SrcBitSize = SE->getSrcTy()->getScalarSizeInBits();
       auto *const DstTy = SE->getDestTy();
       const uint32_t DestBitSize = DstTy->getScalarSizeInBits();
-      if (Demanded.countl_zero() >= (DestBitSize - SrcBitSize)) {
+      // Avoid incorrect replacement of self-referential
+      if (SE != SE->getOperand(0) &&
+          Demanded.countl_zero() >= (DestBitSize - SrcBitSize)) {
         clearAssumptionsOfUsers(SE, DB);
         IRBuilder<> Builder(SE);
         I.replaceAllUsesWith(
@@ -158,7 +153,7 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
             break;
           }
 
-          if (CanBeSimplified) {
+          if (CanBeSimplified && BO != BO->getOperand(0)) {
             clearAssumptionsOfUsers(BO, DB);
             BO->replaceAllUsesWith(BO->getOperand(0));
             Worklist.push_back(BO);

>From 86fc8d126fbe77c1c78568a4ec9ef4c5b9c0a8b1 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 23:16:57 +0800
Subject: [PATCH 5/6] add comments

---
 llvm/lib/Transforms/Scalar/BDCE.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/BDCE.cpp b/llvm/lib/Transforms/Scalar/BDCE.cpp
index 12680951c2ae0..c907b9cd86c43 100644
--- a/llvm/lib/Transforms/Scalar/BDCE.cpp
+++ b/llvm/lib/Transforms/Scalar/BDCE.cpp
@@ -119,7 +119,7 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
       const uint32_t SrcBitSize = SE->getSrcTy()->getScalarSizeInBits();
       auto *const DstTy = SE->getDestTy();
       const uint32_t DestBitSize = DstTy->getScalarSizeInBits();
-      // Avoid incorrect replacement of self-referential
+      // Avoid incorrect replacement of self-referential values.
       if (SE != SE->getOperand(0) &&
           Demanded.countl_zero() >= (DestBitSize - SrcBitSize)) {
         clearAssumptionsOfUsers(SE, DB);
@@ -153,6 +153,7 @@ static bool bitTrackingDCE(Function &F, DemandedBits &DB) {
             break;
           }
 
+          // Avoid incorrect replacement of self-referential values.
           if (CanBeSimplified && BO != BO->getOperand(0)) {
             clearAssumptionsOfUsers(BO, DB);
             BO->replaceAllUsesWith(BO->getOperand(0));

>From c22dda3e00dd1959ec266183cf791c6cf89ed2f7 Mon Sep 17 00:00:00 2001
From: XChy <xxs_chy at outlook.com>
Date: Tue, 28 Apr 2026 23:23:52 +0800
Subject: [PATCH 6/6] update test

---
 llvm/test/Transforms/BDCE/dead-uses.ll | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/BDCE/dead-uses.ll b/llvm/test/Transforms/BDCE/dead-uses.ll
index 493a6fcca3493..62a1e30adcf93 100644
--- a/llvm/test/Transforms/BDCE/dead-uses.ll
+++ b/llvm/test/Transforms/BDCE/dead-uses.ll
@@ -109,7 +109,7 @@ define i64 @deadcode_self_reference() {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[OR:%.*]] = or i32 [[OR]], 0
 ; CHECK-NEXT:    [[CONV:%.*]] = trunc i32 [[OR]] to i16
-; CHECK-NEXT:    [[CALL:%.*]] = call i16 null(i16 0, i16 [[CONV]])
+; CHECK-NEXT:    [[CALL:%.*]] = call i16 @use(i16 [[CONV]])
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ;
 entry:
@@ -118,6 +118,8 @@ entry:
 loop:
   %or = or i32 %or, 0
   %conv = trunc i32 %or to i16
-  %call = call i16 null(i16 0, i16 %conv)
+  %call = call i16 @use(i16 %conv)
   br label %loop
 }
+
+declare void @use(i16)



More information about the llvm-commits mailing list