[llvm] My dce (PR #120468)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 19 20:08:52 PST 2025


https://github.com/RashmiSalankar updated https://github.com/llvm/llvm-project/pull/120468

>From 645debab0879a98f13755f5b531f93345708eb80 Mon Sep 17 00:00:00 2001
From: Rashmi Salankar <rashmi.salankar at gmail.com>
Date: Fri, 13 Dec 2024 01:06:54 +0530
Subject: [PATCH 1/5] Dummy pass works now

---
 .../Transforms/Utils/MyDeadCodeEliminationPass.h   | 14 ++++++++++++++
 llvm/lib/Passes/PassBuilder.cpp                    |  1 +
 llvm/lib/Passes/PassRegistry.def                   |  1 +
 llvm/lib/Transforms/Utils/CMakeLists.txt           |  5 +++++
 .../Transforms/Utils/MyDeadCodeEliminationPass.cpp | 10 ++++++++++
 5 files changed, 31 insertions(+)
 create mode 100644 llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
 create mode 100644 llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp

diff --git a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
new file mode 100644
index 00000000000000..1642827e6b2e05
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
@@ -0,0 +1,14 @@
+#ifndef LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
+#define LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class MyDeadCodeEliminationPass : public PassInfoMixin<MyDeadCodeEliminationPass> {
+public:
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+#endif // LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 77dea7d06d0900..80809e3ea1b486 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -302,6 +302,7 @@
 #include "llvm/Transforms/Scalar/StructurizeCFG.h"
 #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
 #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
+#include "llvm/Transforms/Utils/MyDeadCodeEliminationPass.h"
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
 #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 772ec5fd10e633..c797955ee969e9 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -328,6 +328,7 @@ FUNCTION_ALIAS_ANALYSIS("tbaa", TypeBasedAA())
 #ifndef FUNCTION_PASS
 #define FUNCTION_PASS(NAME, CREATE_PASS)
 #endif
+FUNCTION_PASS("my-dce", MyDeadCodeEliminationPass())
 FUNCTION_PASS("aa-eval", AAEvaluator())
 FUNCTION_PASS("adce", ADCEPass())
 FUNCTION_PASS("add-discriminators", AddDiscriminatorsPass())
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 65bd3080662c4d..221cb31e20dd9a 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_llvm_component_library(LLVMTransformUtils
+  MyDeadCodeEliminationPass.cpp	
   AddDiscriminators.cpp
   AMDGPUEmitPrintf.cpp
   ASanStackFrameLayout.cpp
@@ -93,6 +94,10 @@ add_llvm_component_library(LLVMTransformUtils
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/Utils
 
+  target_include_directories(LLVMMyDeadCodeElimination PRIVATE
+    ${LLVM_MAIN_INCLUDE_DIR}
+  )
+
   DEPENDS
   intrinsics_gen
 
diff --git a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
new file mode 100644
index 00000000000000..bb35a05a8140f3
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
@@ -0,0 +1,10 @@
+#include "llvm/Transforms/Utils/MyDeadCodeEliminationPass.h"
+
+using namespace llvm;
+
+PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F,
+                                      FunctionAnalysisManager &AM) {
+  errs() << "I'm here in my Pass" << "\n";
+  return PreservedAnalyses::all();
+/* The PreservedAnalyses return value says that all analyses (e.g. dominator tree) are still valid after this pass since we didn’t modify any functions */
+}

>From a61f476669c59178cf5f2604a68f6718a7dcbc15 Mon Sep 17 00:00:00 2001
From: Rashmi Salankar <rashmi.salankar at gmail.com>
Date: Sun, 15 Dec 2024 03:38:58 +0530
Subject: [PATCH 2/5] Basic implementation of Potential Dead Code intructions
 done.

---
 .../Utils/MyDeadCodeEliminationPass.h         | 12 +++++--
 .../Utils/MyDeadCodeEliminationPass.cpp       | 35 ++++++++++++++++---
 2 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
index 1642827e6b2e05..3876ee32851322 100644
--- a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
+++ b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
@@ -1,14 +1,20 @@
-#ifndef LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
-#define LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
+#ifndef LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
+#define LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
 
 #include "llvm/IR/PassManager.h"
+#include "llvm/IR/Function.h"
 
 namespace llvm {
 
 class MyDeadCodeEliminationPass : public PassInfoMixin<MyDeadCodeEliminationPass> {
 public:
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+private:
+  void analyzeInstructions(Function &F);
 };
 
 } // namespace llvm
-#endif // LLVM_TRANSFORMS_MYDEADCODEELIMINATIONPASS_H
+
+#endif // LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
+
diff --git a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
index bb35a05a8140f3..8045989adf8f2b 100644
--- a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
+++ b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
@@ -1,10 +1,37 @@
 #include "llvm/Transforms/Utils/MyDeadCodeEliminationPass.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
-PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F,
-                                      FunctionAnalysisManager &AM) {
+PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
   errs() << "I'm here in my Pass" << "\n";
-  return PreservedAnalyses::all();
-/* The PreservedAnalyses return value says that all analyses (e.g. dominator tree) are still valid after this pass since we didn’t modify any functions */
+
+  // Call the helper function to analyze instructions
+  analyzeInstructions(F);
+
+  return PreservedAnalyses::all(); // Preserve analyses since the code isn't modified.
 }
+
+void MyDeadCodeEliminationPass::analyzeInstructions(Function &F) {
+  for (BasicBlock &BB : F) {
+    for (Instruction &I : BB) {
+      errs() << "Instruction: " << I << "\n";
+
+      // Check if the instruction is "dead" (not used anywhere)
+      if (I.use_empty()) {
+        errs() << "Potential dead instruction: " << I << "\n";
+      }
+
+      // Count instruction types
+      if (isa<LoadInst>(&I)) {
+        errs() << "Load Instruction\n";
+      } else if (isa<StoreInst>(&I)) {
+        errs() << "Store Instruction\n";
+      }
+    }
+  }
+}
+

>From 9a6d64525443d1383a22670e7825a0a33dc87da8 Mon Sep 17 00:00:00 2001
From: Rashmi Salankar <rashmi.salankar at gmail.com>
Date: Sun, 15 Dec 2024 03:58:07 +0530
Subject: [PATCH 3/5] Implemented Iterative Solution for probable dead
 statements

---
 .../Utils/MyDeadCodeEliminationPass.h         |  9 +++-
 .../Utils/MyDeadCodeEliminationPass.cpp       | 54 +++++++++++++------
 2 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
index 3876ee32851322..24187cb4436b76 100644
--- a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
+++ b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
@@ -3,15 +3,22 @@
 
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include <unordered_set>
 
 namespace llvm {
 
 class MyDeadCodeEliminationPass : public PassInfoMixin<MyDeadCodeEliminationPass> {
 public:
+  // Main run method for the pass
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 
 private:
-  void analyzeInstructions(Function &F);
+  // Helper function for iterative analysis
+  void analyzeInstructionsIteratively(Function &F);
+
+  // Helper function to check if an instruction is dead
+  bool isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
index 8045989adf8f2b..f906341acd3a5f 100644
--- a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
+++ b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
@@ -3,35 +3,57 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/Support/raw_ostream.h"
+#include <unordered_set>
 
 using namespace llvm;
 
 PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
   errs() << "I'm here in my Pass" << "\n";
 
-  // Call the helper function to analyze instructions
-  analyzeInstructions(F);
+  // Call the helper function to iteratively analyze instructions
+  analyzeInstructionsIteratively(F);
 
   return PreservedAnalyses::all(); // Preserve analyses since the code isn't modified.
 }
 
-void MyDeadCodeEliminationPass::analyzeInstructions(Function &F) {
-  for (BasicBlock &BB : F) {
-    for (Instruction &I : BB) {
-      errs() << "Instruction: " << I << "\n";
-
-      // Check if the instruction is "dead" (not used anywhere)
-      if (I.use_empty()) {
-        errs() << "Potential dead instruction: " << I << "\n";
+void MyDeadCodeEliminationPass::analyzeInstructionsIteratively(Function &F) {
+  std::unordered_set<Instruction *> potentialDeadInstructions; // To track potential dead instructions
+  bool foundNewDead; // Flag to track if we find new dead instructions in an iteration
+
+  do {
+    foundNewDead = false; // Reset the flag at the start of each iteration
+
+    for (BasicBlock &BB : F) {
+      for (Instruction &I : BB) {
+        // Skip if already identified as dead
+        if (potentialDeadInstructions.count(&I)) {
+          continue;
+        }
+
+        // Check if the instruction is "dead" (not used anywhere or used only by dead instructions)
+        if (isInstructionDead(&I, potentialDeadInstructions)) {
+          errs() << "Potential dead instruction: " << I << "\n";
+          potentialDeadInstructions.insert(&I);
+          foundNewDead = true; // Mark that we found a new dead instruction
+        }
       }
+    }
+  } while (foundNewDead); // Continue until no new dead instructions are found
+}
 
-      // Count instruction types
-      if (isa<LoadInst>(&I)) {
-        errs() << "Load Instruction\n";
-      } else if (isa<StoreInst>(&I)) {
-        errs() << "Store Instruction\n";
-      }
+bool MyDeadCodeEliminationPass::isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
+  // Check if the instruction's result is not used, or all users are in the potentialDeadInstructions set
+  if (Inst->use_empty()) {
+    return true; // No users, definitely dead
+  }
+
+  for (const Use &U : Inst->uses()) {
+    auto *User = dyn_cast<Instruction>(U.getUser());
+    if (!User || potentialDeadInstructions.find(User) == potentialDeadInstructions.end()) {
+      return false; // Found a user that is not "dead"
     }
   }
+
+  return true; // All users are "dead"
 }
 

>From 4434099c2b5faf74ca0c71c984b9a13373820afd Mon Sep 17 00:00:00 2001
From: Rashmi Salankar <rashmi.salankar at gmail.com>
Date: Thu, 19 Dec 2024 01:59:21 +0530
Subject: [PATCH 4/5] Added more features. Running but needs to be corrected
 and enhanced

---
 .../Utils/MyDeadCodeEliminationPass.h         |  18 +--
 .../Utils/MyDeadCodeEliminationPass.cpp       | 130 +++++++++++++-----
 2 files changed, 106 insertions(+), 42 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
index 24187cb4436b76..913501b5d4b583 100644
--- a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
+++ b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
@@ -2,23 +2,23 @@
 #define LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
 
 #include "llvm/IR/PassManager.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Instruction.h"
+#include "llvm/Analysis/LoopInfo.h"
 #include <unordered_set>
+#include <string>
 
 namespace llvm {
 
 class MyDeadCodeEliminationPass : public PassInfoMixin<MyDeadCodeEliminationPass> {
 public:
-  // Main run method for the pass
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 
 private:
-  // Helper function for iterative analysis
-  void analyzeInstructionsIteratively(Function &F);
-
-  // Helper function to check if an instruction is dead
-  bool isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions);
+    void analyzeInstructionsIteratively(Function &F, FunctionAnalysisManager &AM);
+    bool isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions);
+    void printBasicBlockFeatures(const Instruction &I, const BasicBlock &BB);
+    void printInstructionFeatures(const Instruction &I, const Function &F, const LoopInfo &LI);
+    void printUsageFeatures(const Instruction &I, const std::unordered_set<Instruction *> &potentialDeadInstructions);
+    std::string getInstructionPosition(const Instruction &I, const BasicBlock &BB);
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
index f906341acd3a5f..eb8d6dd472737b 100644
--- a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
+++ b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
@@ -3,57 +3,121 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Analysis/LoopInfo.h"
 #include <unordered_set>
 
 using namespace llvm;
 
 PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
-  errs() << "I'm here in my Pass" << "\n";
+    errs() << "Starting MyDeadCodeEliminationPass\n";
 
-  // Call the helper function to iteratively analyze instructions
-  analyzeInstructionsIteratively(F);
+    analyzeInstructionsIteratively(F, AM);
 
-  return PreservedAnalyses::all(); // Preserve analyses since the code isn't modified.
+    return PreservedAnalyses::all();
 }
 
-void MyDeadCodeEliminationPass::analyzeInstructionsIteratively(Function &F) {
-  std::unordered_set<Instruction *> potentialDeadInstructions; // To track potential dead instructions
-  bool foundNewDead; // Flag to track if we find new dead instructions in an iteration
+void MyDeadCodeEliminationPass::analyzeInstructionsIteratively(Function &F, FunctionAnalysisManager &AM) {
+    auto &LI = AM.getResult<LoopAnalysis>(F);
+    std::unordered_set<Instruction *> potentialDeadInstructions;
+    bool foundNewDead;
 
-  do {
-    foundNewDead = false; // Reset the flag at the start of each iteration
+    do {
+        foundNewDead = false;
 
-    for (BasicBlock &BB : F) {
-      for (Instruction &I : BB) {
-        // Skip if already identified as dead
-        if (potentialDeadInstructions.count(&I)) {
-          continue;
+        for (BasicBlock &BB : F) {
+            for (Instruction &I : BB) {
+                if (potentialDeadInstructions.count(&I)) {
+                    continue;
+                }
+
+                // Check if the instruction is "likely dead"
+                if (isInstructionDead(&I, potentialDeadInstructions)) {
+                    errs() << "Likely Dead Instruction: " << I << "\n";
+                    potentialDeadInstructions.insert(&I);
+                    foundNewDead = true;
+                }
+
+                // Print all features for this instruction
+                errs() << "------------------------------------------\n";
+                errs() << "Instruction: " << I << "\n";
+                printBasicBlockFeatures(I, BB);
+                printInstructionFeatures(I, F, LI);
+                printUsageFeatures(I, potentialDeadInstructions);
+                errs() << "------------------------------------------\n";
+            }
         }
+    } while (foundNewDead);
+}
+
+bool MyDeadCodeEliminationPass::isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
+    if (Inst->use_empty()) {
+        return true;
+    }
 
-        // Check if the instruction is "dead" (not used anywhere or used only by dead instructions)
-        if (isInstructionDead(&I, potentialDeadInstructions)) {
-          errs() << "Potential dead instruction: " << I << "\n";
-          potentialDeadInstructions.insert(&I);
-          foundNewDead = true; // Mark that we found a new dead instruction
+    for (const Use &U : Inst->uses()) {
+        auto *User = dyn_cast<Instruction>(U.getUser());
+        if (!User || potentialDeadInstructions.find(User) == potentialDeadInstructions.end()) {
+            return false;
         }
-      }
     }
-  } while (foundNewDead); // Continue until no new dead instructions are found
+
+    return true;
 }
 
-bool MyDeadCodeEliminationPass::isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
-  // Check if the instruction's result is not used, or all users are in the potentialDeadInstructions set
-  if (Inst->use_empty()) {
-    return true; // No users, definitely dead
-  }
-
-  for (const Use &U : Inst->uses()) {
-    auto *User = dyn_cast<Instruction>(U.getUser());
-    if (!User || potentialDeadInstructions.find(User) == potentialDeadInstructions.end()) {
-      return false; // Found a user that is not "dead"
+void MyDeadCodeEliminationPass::printBasicBlockFeatures(const Instruction &I, const BasicBlock &BB) {
+    errs() << "Parent Basic Block: " << BB.getName() << "\n";
+    errs() << "  Number of Predecessors: " << std::distance(pred_begin(&BB), pred_end(&BB)) << "\n";
+    errs() << "  Number of Successors: " << std::distance(succ_begin(&BB), succ_end(&BB)) << "\n";
+    errs() << "  Position in Basic Block: " << getInstructionPosition(I, BB) << "\n";
+    errs() << "  Total Instructions in Basic Block: " << BB.size() << "\n";
+}
+
+void MyDeadCodeEliminationPass::printInstructionFeatures(const Instruction &I, const Function &F, const LoopInfo &LI) {
+    errs() << "Instruction Type: " << I.getOpcodeName() << "\n";
+    errs() << "Operand Count: " << I.getNumOperands() << "\n";
+    errs() << "Is Terminator: " << (I.isTerminator() ? "Yes" : "No") << "\n";
+    errs() << "Is Memory Related: " << (isa<LoadInst>(&I) || isa<StoreInst>(&I) ? "Yes" : "No") << "\n";
+
+    if (LI.getLoopFor(I.getParent())) {
+        errs() << "Part of a Loop: Yes\n";
+    } else {
+        errs() << "Part of a Loop: No\n";
     }
-  }
+}
+
+
+void MyDeadCodeEliminationPass::printUsageFeatures(const Instruction &I, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
+    errs() << "Uses: ";
+    for (const Use &U : I.uses()) {
+        const auto *User = dyn_cast<Instruction>(U.getUser());
+        if (User) {
+            errs() << User->getOpcodeName() << " ";
+            // Fix: Cast to match the type stored in the set
+            if (potentialDeadInstructions.count(const_cast<Instruction *>(User))) {
+                errs() << "(likely dead) ";
+            }
+        }
+    }
+    errs() << "\n";
+    errs() << "Number of Users: " << I.getNumUses() << "\n";
+}
+
 
-  return true; // All users are "dead"
+std::string MyDeadCodeEliminationPass::getInstructionPosition(const Instruction &I, const BasicBlock &BB) {
+    size_t Position = 1;
+    for (const Instruction &Inst : BB) {
+        if (&Inst == &I) {
+            break;
+        }
+        ++Position;
+    }
+    if (Position == 1) {
+        return "First";
+    } else if (&I == &BB.back()) {
+        return "Last";
+    } else {
+        return "Intermediate (" + std::to_string(Position) + ")";
+    }
 }
 

>From 63ab0c8e166c2a2ccf9b7e546a699a52a8815e05 Mon Sep 17 00:00:00 2001
From: Rashmi Salankar <rashmi.salankar at gmail.com>
Date: Mon, 20 Jan 2025 09:36:14 +0530
Subject: [PATCH 5/5] Added 20 features.

---
 .../Utils/MyDeadCodeEliminationPass.h         |  89 +++--
 .../Utils/MyDeadCodeEliminationPass.cpp       | 303 +++++++++++-------
 2 files changed, 242 insertions(+), 150 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
index 913501b5d4b583..ce18b2153dc7b7 100644
--- a/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
+++ b/llvm/include/llvm/Transforms/Utils/MyDeadCodeEliminationPass.h
@@ -1,27 +1,62 @@
-#ifndef LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
-#define LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
-
-#include "llvm/IR/PassManager.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include <unordered_set>
-#include <string>
-
-namespace llvm {
-
-class MyDeadCodeEliminationPass : public PassInfoMixin<MyDeadCodeEliminationPass> {
-public:
-    PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
-
-private:
-    void analyzeInstructionsIteratively(Function &F, FunctionAnalysisManager &AM);
-    bool isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions);
-    void printBasicBlockFeatures(const Instruction &I, const BasicBlock &BB);
-    void printInstructionFeatures(const Instruction &I, const Function &F, const LoopInfo &LI);
-    void printUsageFeatures(const Instruction &I, const std::unordered_set<Instruction *> &potentialDeadInstructions);
-    std::string getInstructionPosition(const Instruction &I, const BasicBlock &BB);
-};
-
-} // namespace llvm
-
-#endif // LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
-
+#ifndef LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
+#define LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
+
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/PassManager.h"
+#include <string>
+#include <unordered_set>
+
+namespace llvm {
+
+class MyDeadCodeEliminationPass
+    : public PassInfoMixin<MyDeadCodeEliminationPass> {
+public:
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+
+private:
+  void analyzeInstructionsIteratively(Function &F, FunctionAnalysisManager &AM);
+
+  bool isInstructionDead(
+      Instruction *Inst,
+      const std::unordered_set<Instruction *> &potentialDeadInstructions);
+
+  void printInstructionFeatures(const Instruction &I, const Function &F,
+                                const LoopInfo &LI);
+
+  void printBasicBlockFeatures(const Instruction &I, const BasicBlock &BB);
+
+  void printUsageFeatures(
+      const Instruction &I,
+      const std::unordered_set<Instruction *> &potentialDeadInstructions);
+
+  std::string getInstructionPosition(const Instruction &I,
+                                     const BasicBlock &BB);
+
+  int getInstructionDepth(
+      const Instruction &I,
+      const std::unordered_set<Instruction *> &potentialDeadInstructions);
+
+  int getLoopNestingDepth(const LoopInfo &LI, const BasicBlock &BB);
+
+  bool isDominatedByEntry(const DominatorTree &DT, const BasicBlock &BB);
+
+  bool isInColdPath(const BasicBlock &BB, const BlockFrequencyInfo &BFI);
+
+  void writeInstructionFeaturesToCSV(const Instruction &I, const Function &F,
+                                     const LoopInfo &LI,
+                                     const DominatorTree &DT,
+                                     const BlockFrequencyInfo &BFI,
+                                     const std::string &FilePath);
+
+  std::string getFunctionInstructionPosition(const Instruction &I, const Function &F);
+
+  bool isUsingFunctionArguments(const Instruction &I, const Function &F);
+
+  void printInstructionFeatures(const Instruction &I, const BasicBlock &B,
+                                const Function &F, const LoopInfo &L);
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_MYDEADCODEELIMINATIONPASS_H
diff --git a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
index eb8d6dd472737b..2bf628170b10c2 100644
--- a/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
+++ b/llvm/lib/Transforms/Utils/MyDeadCodeEliminationPass.cpp
@@ -1,123 +1,180 @@
-#include "llvm/Transforms/Utils/MyDeadCodeEliminationPass.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Instruction.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include <unordered_set>
-
-using namespace llvm;
-
-PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
-    errs() << "Starting MyDeadCodeEliminationPass\n";
-
-    analyzeInstructionsIteratively(F, AM);
-
-    return PreservedAnalyses::all();
-}
-
-void MyDeadCodeEliminationPass::analyzeInstructionsIteratively(Function &F, FunctionAnalysisManager &AM) {
-    auto &LI = AM.getResult<LoopAnalysis>(F);
-    std::unordered_set<Instruction *> potentialDeadInstructions;
-    bool foundNewDead;
-
-    do {
-        foundNewDead = false;
-
-        for (BasicBlock &BB : F) {
-            for (Instruction &I : BB) {
-                if (potentialDeadInstructions.count(&I)) {
-                    continue;
-                }
-
-                // Check if the instruction is "likely dead"
-                if (isInstructionDead(&I, potentialDeadInstructions)) {
-                    errs() << "Likely Dead Instruction: " << I << "\n";
-                    potentialDeadInstructions.insert(&I);
-                    foundNewDead = true;
-                }
-
-                // Print all features for this instruction
-                errs() << "------------------------------------------\n";
-                errs() << "Instruction: " << I << "\n";
-                printBasicBlockFeatures(I, BB);
-                printInstructionFeatures(I, F, LI);
-                printUsageFeatures(I, potentialDeadInstructions);
-                errs() << "------------------------------------------\n";
-            }
-        }
-    } while (foundNewDead);
-}
-
-bool MyDeadCodeEliminationPass::isInstructionDead(Instruction *Inst, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
-    if (Inst->use_empty()) {
-        return true;
-    }
-
-    for (const Use &U : Inst->uses()) {
-        auto *User = dyn_cast<Instruction>(U.getUser());
-        if (!User || potentialDeadInstructions.find(User) == potentialDeadInstructions.end()) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-void MyDeadCodeEliminationPass::printBasicBlockFeatures(const Instruction &I, const BasicBlock &BB) {
-    errs() << "Parent Basic Block: " << BB.getName() << "\n";
-    errs() << "  Number of Predecessors: " << std::distance(pred_begin(&BB), pred_end(&BB)) << "\n";
-    errs() << "  Number of Successors: " << std::distance(succ_begin(&BB), succ_end(&BB)) << "\n";
-    errs() << "  Position in Basic Block: " << getInstructionPosition(I, BB) << "\n";
-    errs() << "  Total Instructions in Basic Block: " << BB.size() << "\n";
-}
-
-void MyDeadCodeEliminationPass::printInstructionFeatures(const Instruction &I, const Function &F, const LoopInfo &LI) {
-    errs() << "Instruction Type: " << I.getOpcodeName() << "\n";
-    errs() << "Operand Count: " << I.getNumOperands() << "\n";
-    errs() << "Is Terminator: " << (I.isTerminator() ? "Yes" : "No") << "\n";
-    errs() << "Is Memory Related: " << (isa<LoadInst>(&I) || isa<StoreInst>(&I) ? "Yes" : "No") << "\n";
-
-    if (LI.getLoopFor(I.getParent())) {
-        errs() << "Part of a Loop: Yes\n";
-    } else {
-        errs() << "Part of a Loop: No\n";
-    }
-}
-
-
-void MyDeadCodeEliminationPass::printUsageFeatures(const Instruction &I, const std::unordered_set<Instruction *> &potentialDeadInstructions) {
-    errs() << "Uses: ";
-    for (const Use &U : I.uses()) {
-        const auto *User = dyn_cast<Instruction>(U.getUser());
-        if (User) {
-            errs() << User->getOpcodeName() << " ";
-            // Fix: Cast to match the type stored in the set
-            if (potentialDeadInstructions.count(const_cast<Instruction *>(User))) {
-                errs() << "(likely dead) ";
-            }
-        }
-    }
-    errs() << "\n";
-    errs() << "Number of Users: " << I.getNumUses() << "\n";
-}
-
-
-std::string MyDeadCodeEliminationPass::getInstructionPosition(const Instruction &I, const BasicBlock &BB) {
-    size_t Position = 1;
-    for (const Instruction &Inst : BB) {
-        if (&Inst == &I) {
-            break;
-        }
-        ++Position;
-    }
-    if (Position == 1) {
-        return "First";
-    } else if (&I == &BB.back()) {
-        return "Last";
-    } else {
-        return "Intermediate (" + std::to_string(Position) + ")";
-    }
-}
-
+// MyDeadCodeEliminationPass.cpp
+#include "llvm/Transforms/Utils/MyDeadCodeEliminationPass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Support/raw_ostream.h"
+#include <unordered_set>
+#include "llvm/IR/Module.h"
+
+
+using namespace llvm;
+
+PreservedAnalyses MyDeadCodeEliminationPass::run(Function &F,
+                                                 FunctionAnalysisManager &AM) {
+  errs() << "Starting MyDeadCodeEliminationPass\n";
+
+  analyzeInstructionsIteratively(F, AM);
+
+  return PreservedAnalyses::all();
+}
+
+void MyDeadCodeEliminationPass::analyzeInstructionsIteratively(
+    Function &F, FunctionAnalysisManager &AM) {
+  auto &LI = AM.getResult<LoopAnalysis>(F);
+  std::unordered_set<Instruction *> potentialDeadInstructions;
+  bool foundNewDead;
+
+  do {
+    foundNewDead = false;
+
+    for (BasicBlock &BB : F) {
+      for (Instruction &I : BB) {
+        if (potentialDeadInstructions.count(&I)) {
+          continue;
+        }
+
+        // Check if the instruction is "likely dead"
+        if (isInstructionDead(&I, potentialDeadInstructions)) {
+          errs() << "Likely Dead Instruction: " << I << "\n";
+          potentialDeadInstructions.insert(&I);
+          foundNewDead = true;
+        }
+
+        // Print all features for this instruction
+        errs() << "------------------------------------------\n";
+        errs() << "Instruction: " << I << "\n";
+        printInstructionFeatures(I, BB, F, LI);
+        errs() << "------------------------------------------\n";
+      }
+    }
+  } while (foundNewDead);
+}
+
+bool MyDeadCodeEliminationPass::isInstructionDead(
+    Instruction *Inst,
+    const std::unordered_set<Instruction *> &potentialDeadInstructions) {
+  if (Inst->use_empty()) {
+    return true;
+  }
+
+  for (const Use &U : Inst->uses()) {
+    auto *User = dyn_cast<Instruction>(U.getUser());
+    if (!User || potentialDeadInstructions.find(User) ==
+                     potentialDeadInstructions.end()) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void MyDeadCodeEliminationPass::printInstructionFeatures(const Instruction &I,
+                                                         const BasicBlock &BB,
+                                                         const Function &F,
+                                                         const LoopInfo &LI) {
+  // Direct Features
+  errs() << "1. Opcode: " << I.getOpcodeName() << "\n";
+  errs() << "2. Number of Operands: " << I.getNumOperands() << "\n";
+  errs() << "3. Is Terminator: " << (I.isTerminator() ? "Yes" : "No") << "\n";
+  errs() << "4. Is Volatile: "
+         << (isa<LoadInst>(&I) || isa<StoreInst>(&I) ? "Yes" : "No") << "\n";
+  errs() << "5. Has Metadata: " << (I.hasMetadata() ? "Yes" : "No") << "\n";
+
+  if (isa<LoadInst>(&I)) {
+    llvm::Align alignment = cast<LoadInst>(&I)->getAlign();
+    errs() << "6. Alignment: " << alignment.value() << "\n";
+  } else if (isa<StoreInst>(&I)) {
+    llvm::Align alignment = cast<StoreInst>(&I)->getAlign();
+    errs() << "6. Alignment: " << alignment.value() << "\n";
+  } else {
+    errs() << "6. Alignment: Not applicable\n";
+  }
+
+  
+  /* Alignment alignment = cast<LoadInst>(&I)->getAlign();
+  errs() << "6. Alignment: " << alignment.value() << "\n";*/
+  /* errs() << "6. Alignment: "
+         << (isa<LoadInst>(&I)
+                 ? cast<LoadInst>(&I)->getAlign().valueOrOne().value()
+                 : 0)
+         << "\n";*/
+  errs() << "7. Instruction Size: "
+         << (I.getType()->isSized()
+                 ? I.getModule()->getDataLayout().getTypeSizeInBits(I.getType())
+                 : 0)
+         << " bits\n";
+  errs() << "8. Is PHI Node: " << (isa<PHINode>(&I) ? "Yes" : "No") << "\n";
+  errs() << "9. Number of Users: " << I.getNumUses() << "\n";
+  errs() << "10. Is Used in Loops: "
+         << (LI.getLoopFor(I.getParent()) ? "Yes" : "No") << "\n";
+  errs() << "11. Has Side Effects: " << (I.mayHaveSideEffects() ? "Yes" : "No")
+         << "\n";
+
+  // Basic Block-Level Features
+  errs() << "12. Basic Block Predecessor Count: "
+         << std::distance(pred_begin(&BB), pred_end(&BB)) << "\n";
+  errs() << "13. Basic Block Successor Count: "
+         << std::distance(succ_begin(&BB), succ_end(&BB)) << "\n";
+  errs() << "14. Instruction Position in Basic Block: "
+         << getInstructionPosition(I, BB) << "\n";
+  errs() << "15. Basic Block Size: " << BB.size() << "\n";
+  errs() << "16. Is Dominated by Entry: "
+         << (F.getEntryBlock().getName() == BB.getName() ? "Yes" : "No")
+         << "\n";
+  errs() << "17. Loop Nesting Depth: " << (LI.getLoopDepth(&BB)) << "\n";
+
+  // Function-Level Features
+  errs() << "18. Function Argument Usage: "
+         << (isUsingFunctionArguments(I, F) ? "Yes" : "No") << "\n";
+  errs() << "19. Instruction Position in Function: "
+         << getFunctionInstructionPosition(I, F) << "\n";
+  errs() << "20. Function's Loop Count: " << LI.getLoopsInPreorder().size()
+         << "\n";
+}
+
+bool MyDeadCodeEliminationPass::isUsingFunctionArguments(const Instruction &I,
+                                                         const Function &F) {
+  for (const Use &U : I.operands()) {
+    if (isa<Argument>(U)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+std::string
+MyDeadCodeEliminationPass::getInstructionPosition(const Instruction &I,
+                                                  const BasicBlock &BB) {
+  size_t Position = 1;
+  for (const Instruction &Inst : BB) {
+    if (&Inst == &I) {
+      break;
+    }
+    ++Position;
+  }
+  if (Position == 1) {
+    return "First";
+  } else if (&I == &BB.back()) {
+    return "Last";
+  } else {
+    return "Intermediate (" + std::to_string(Position) + ")";
+  }
+}
+
+std::string
+MyDeadCodeEliminationPass::getFunctionInstructionPosition(const Instruction &I,
+                                                          const Function &F) {
+  size_t Position = 1;
+  for (const BasicBlock &BB : F) {
+    for (const Instruction &Inst : BB) {
+      if (&Inst == &I) {
+        return std::to_string(Position);
+      }
+      ++Position;
+    }
+  }
+  return "Unknown";
+}



More information about the llvm-commits mailing list