[llvm] Revert "[LLVM] Add IRNormalizer Pass" (PR #113392)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 22 15:59:21 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Justin Fargnoli (justinfargnoli)

<details>
<summary>Changes</summary>

Reverts llvm/llvm-project#<!-- -->68176

---

Patch is 54.49 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113392.diff


17 Files Affected:

- (modified) llvm/docs/Passes.rst (-8) 
- (modified) llvm/docs/ReleaseNotes.md (-5) 
- (removed) llvm/include/llvm/Transforms/Utils/IRNormalizer.h (-15) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (-1) 
- (modified) llvm/lib/Passes/PassRegistry.def (-1) 
- (modified) llvm/lib/Transforms/Utils/CMakeLists.txt (-1) 
- (removed) llvm/lib/Transforms/Utils/IRNormalizer.cpp (-695) 
- (removed) llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll (-18) 
- (removed) llvm/test/Transforms/IRNormalizer/naming-arguments.ll (-13) 
- (removed) llvm/test/Transforms/IRNormalizer/naming.ll (-30) 
- (removed) llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll (-27) 
- (removed) llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll (-21) 
- (removed) llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll (-18) 
- (removed) llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll (-20) 
- (removed) llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll (-195) 
- (removed) llvm/test/Transforms/IRNormalizer/reordering-basic.ll (-58) 
- (removed) llvm/test/Transforms/IRNormalizer/reordering.ll (-163) 


``````````diff
diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
index 5e436db62be3a1..49f633e98d16fe 100644
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -543,14 +543,6 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 <passes-sccp>`.
 
-``ir-normalizer``: Transforms IR into a normal form that's easier to diff
-----------------------------------------------------------------------------
-
-This pass aims to transform LLVM Modules into a normal form by reordering and
-renaming instructions while preserving the same semantics. The normalizer makes
-it easier to spot semantic differences while diffing two modules which have
-undergone two different passes.
-
 ``jump-threading``: Jump Threading
 ----------------------------------
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 0c4cd437dac0b4..c8f5d22c15472a 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -42,11 +42,6 @@ point (e.g. maybe you would like to give an example of the
 functionality, or simply have a lot to talk about), see the comment below
 for adding a new subsection. -->
 
-* Added a new IRNormalizer pass which aims to transform LLVM modules into
-  a normal form by reordering and renaming instructions while preserving the
-  same semantics. The normalizer makes it easier to spot semantic differences
-  when diffing two modules which have undergone different passes.
-
 * ...
 
 <!-- If you would like to document a larger change, then you can add a
diff --git a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
deleted file mode 100644
index af1f715d4940d8..00000000000000
--- a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef LLVM_TRANSFORMS_UTILS_IRNORMALIZER_H
-#define LLVM_TRANSFORMS_UTILS_IRNORMALIZER_H
-
-#include "llvm/IR/PassManager.h"
-
-namespace llvm {
-
-/// IRNormalizer aims to transform LLVM IR into normal form.
-struct IRNormalizerPass : public PassInfoMixin<IRNormalizerPass> {
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) const;
-};
-
-} // namespace llvm
-
-#endif // LLVM_TRANSFORMS_UTILS_IRNORMALIZER_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 67ebc3015a46df..19e8a96bf78972 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -303,7 +303,6 @@
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/FixIrreducible.h"
 #include "llvm/Transforms/Utils/HelloWorld.h"
-#include "llvm/Transforms/Utils/IRNormalizer.h"
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
 #include "llvm/Transforms/Utils/InstructionNamer.h"
 #include "llvm/Transforms/Utils/Instrumentation.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index d1fac824fdcd5f..549c1359b5852c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -412,7 +412,6 @@ FUNCTION_PASS("move-auto-init", MoveAutoInitPass())
 FUNCTION_PASS("nary-reassociate", NaryReassociatePass())
 FUNCTION_PASS("newgvn", NewGVNPass())
 FUNCTION_PASS("no-op-function", NoOpFunctionPass())
-FUNCTION_PASS("normalize", IRNormalizerPass())
 FUNCTION_PASS("objc-arc", ObjCARCOptPass())
 FUNCTION_PASS("objc-arc-contract", ObjCARCContractPass())
 FUNCTION_PASS("objc-arc-expand", ObjCARCExpandPass())
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 65bd3080662c4d..36761cf3569741 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -37,7 +37,6 @@ add_llvm_component_library(LLVMTransformUtils
   InstructionNamer.cpp
   Instrumentation.cpp
   IntegerDivision.cpp
-  IRNormalizer.cpp
   LCSSA.cpp
   LibCallsShrinkWrap.cpp
   Local.cpp
diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
deleted file mode 100644
index 74c8fc26a0acd5..00000000000000
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ /dev/null
@@ -1,695 +0,0 @@
-//===--------------- IRNormalizer.cpp - IR Normalizer ---------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file implements the IRNormalizer class which aims to transform LLVM
-/// Modules into a normal form by reordering and renaming instructions while
-/// preserving the same semantics. The normalizer makes it easier to spot
-/// semantic differences while diffing two modules which have undergone
-/// different passes.
-///
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Transforms/Utils/IRNormalizer.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/InstIterator.h"
-#include "llvm/IR/Module.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Pass.h"
-#include "llvm/PassRegistry.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/Utils.h"
-#include <algorithm>
-#include <stack>
-
-#define DEBUG_TYPE "normalize"
-
-using namespace llvm;
-
-namespace {
-/// IRNormalizer aims to transform LLVM IR into normal form.
-class IRNormalizer {
-public:
-  /// \name Normalizer flags.
-  /// @{
-  /// Preserves original order of instructions.
-  static cl::opt<bool> PreserveOrder;
-  /// Renames all instructions (including user-named).
-  static cl::opt<bool> RenameAll; // TODO: Don't rename on empty name
-  /// Folds all regular instructions (including pre-outputs).
-  static cl::opt<bool> FoldPreOutputs;
-  /// Sorts and reorders operands in commutative instructions.
-  static cl::opt<bool> ReorderOperands;
-  /// @}
-
-  bool runOnFunction(Function &F);
-
-private:
-  // Random constant for hashing, so the state isn't zero.
-  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
-  DenseSet<const Instruction *> NamedInstructions;
-
-  SmallVector<Instruction *, 16> Outputs;
-
-  /// \name Naming.
-  /// @{
-  void nameFunctionArguments(Function &F) const;
-  void nameBasicBlocks(Function &F) const;
-  void nameInstruction(Instruction *I);
-  void nameAsInitialInstruction(Instruction *I) const;
-  void nameAsRegularInstruction(Instruction *I);
-  void foldInstructionName(Instruction *I) const;
-  /// @}
-
-  /// \name Reordering.
-  /// @{
-  void reorderInstructions(Function &F) const;
-  void reorderDefinition(Instruction *Definition,
-                         std::stack<Instruction *> &TopologicalSort,
-                         SmallPtrSet<const Instruction *, 32> &Visited) const;
-  void reorderInstructionOperandsByNames(Instruction *I) const;
-  void reorderPHIIncomingValues(PHINode *Phi) const;
-  /// @}
-
-  /// \name Utility methods.
-  /// @{
-  template <typename T>
-  void sortCommutativeOperands(Instruction *I, T &Operands) const;
-  SmallVector<Instruction *, 16> collectOutputInstructions(Function &F) const;
-  bool isOutput(const Instruction *I) const;
-  bool isInitialInstruction(const Instruction *I) const;
-  bool hasOnlyImmediateOperands(const Instruction *I) const;
-  SetVector<int>
-  getOutputFootprint(Instruction *I,
-                     SmallPtrSet<const Instruction *, 32> &Visited) const;
-  /// @}
-};
-} // namespace
-
-cl::opt<bool> IRNormalizer::PreserveOrder(
-    "norm-preserve-order", cl::Hidden, cl::init(false),
-    cl::desc("Preserves original instruction order"));
-cl::opt<bool> IRNormalizer::RenameAll(
-    "norm-rename-all", cl::Hidden, cl::init(true),
-    cl::desc("Renames all instructions (including user-named)"));
-cl::opt<bool> IRNormalizer::FoldPreOutputs(
-    "norm-fold-all", cl::Hidden, cl::init(true),
-    cl::desc("Folds all regular instructions (including pre-outputs)"));
-cl::opt<bool> IRNormalizer::ReorderOperands(
-    "norm-reorder-operands", cl::Hidden, cl::init(true),
-    cl::desc("Sorts and reorders operands in commutative instructions"));
-
-/// Entry method to the IRNormalizer.
-///
-/// \param F Function to normalize.
-bool IRNormalizer::runOnFunction(Function &F) {
-  nameFunctionArguments(F);
-  nameBasicBlocks(F);
-
-  Outputs = collectOutputInstructions(F);
-
-  if (!PreserveOrder)
-    reorderInstructions(F);
-
-  // TODO: Reorder basic blocks via a topological sort.
-
-  for (auto &I : Outputs)
-    nameInstruction(I);
-
-  for (auto &I : instructions(F)) {
-    if (!PreserveOrder) {
-      if (ReorderOperands)
-        reorderInstructionOperandsByNames(&I);
-
-      if (auto *Phi = dyn_cast<PHINode>(&I))
-        reorderPHIIncomingValues(Phi);
-    }
-    foldInstructionName(&I);
-  }
-
-  return true;
-}
-
-/// Numbers arguments.
-///
-/// \param F Function whose arguments will be renamed.
-void IRNormalizer::nameFunctionArguments(Function &F) const {
-  int ArgumentCounter = 0;
-  for (auto &A : F.args()) {
-    if (RenameAll || A.getName().empty()) {
-      A.setName("a" + Twine(ArgumentCounter));
-      ArgumentCounter += 1;
-    }
-  }
-}
-
-/// Names basic blocks using a generated hash for each basic block in
-/// a function considering the opcode and the order of output instructions.
-///
-/// \param F Function containing basic blocks to rename.
-void IRNormalizer::nameBasicBlocks(Function &F) const {
-  for (auto &B : F) {
-    // Initialize to a magic constant, so the state isn't zero.
-    uint64_t Hash = MagicHashConstant;
-
-    // Hash considering output instruction opcodes.
-    for (auto &I : B)
-      if (isOutput(&I))
-        Hash = hashing::detail::hash_16_bytes(Hash, I.getOpcode());
-
-    if (RenameAll || B.getName().empty()) {
-      // Name basic block. Substring hash to make diffs more readable.
-      B.setName("bb" + std::to_string(Hash).substr(0, 5));
-    }
-  }
-}
-
-/// Names instructions graphically (recursive) in accordance with the
-/// def-use tree, starting from the initial instructions (defs), finishing at
-/// the output (top-most user) instructions (depth-first).
-///
-/// \param I Instruction to be renamed.
-void IRNormalizer::nameInstruction(Instruction *I) {
-  // Ensure instructions are not renamed. This is done
-  // to prevent situation where instructions are used
-  // before their definition (in phi nodes)
-  if (NamedInstructions.contains(I))
-    return;
-  NamedInstructions.insert(I);
-  if (isInitialInstruction(I)) {
-    nameAsInitialInstruction(I);
-  } else {
-    // This must be a regular instruction.
-    nameAsRegularInstruction(I);
-  }
-}
-
-template <typename T>
-void IRNormalizer::sortCommutativeOperands(Instruction *I, T &Operands) const {
-  if (!(I->isCommutative() && Operands.size() >= 2))
-    return;
-  auto CommutativeEnd = Operands.begin();
-  std::advance(CommutativeEnd, 2);
-  llvm::sort(Operands.begin(), CommutativeEnd);
-}
-
-/// Names instruction following the scheme:
-/// vl00000Callee(Operands)
-///
-/// Where 00000 is a hash calculated considering instruction's opcode and output
-/// footprint. Callee's name is only included when instruction's type is
-/// CallInst. In cases where instruction is commutative, operands list is also
-/// sorted.
-///
-/// Renames instruction only when RenameAll flag is raised or instruction is
-/// unnamed.
-///
-/// \see getOutputFootprint()
-/// \param I Instruction to be renamed.
-void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
-  if (I->getType()->isVoidTy())
-    return;
-  if (!(I->getName().empty() || RenameAll))
-    return;
-  LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
-
-  // Instruction operands for further sorting.
-  SmallVector<SmallString<64>, 4> Operands;
-
-  // Collect operands.
-  for (auto &Op : I->operands()) {
-    if (!isa<Function>(Op)) {
-      std::string TextRepresentation;
-      raw_string_ostream Stream(TextRepresentation);
-      Op->printAsOperand(Stream, false);
-      Operands.push_back(StringRef(Stream.str()));
-    }
-  }
-
-  sortCommutativeOperands(I, Operands);
-
-  // Initialize to a magic constant, so the state isn't zero.
-  uint64_t Hash = MagicHashConstant;
-
-  // Consider instruction's opcode in the hash.
-  Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
-
-  SmallPtrSet<const Instruction *, 32> Visited;
-  // Get output footprint for I.
-  SetVector<int> OutputFootprint = getOutputFootprint(I, Visited);
-
-  // Consider output footprint in the hash.
-  for (const int &Output : OutputFootprint)
-    Hash = hashing::detail::hash_16_bytes(Hash, Output);
-
-  // Base instruction name.
-  SmallString<256> Name;
-  Name.append("vl" + std::to_string(Hash).substr(0, 5));
-
-  // In case of CallInst, consider callee in the instruction name.
-  if (const auto *CI = dyn_cast<CallInst>(I)) {
-    Function *F = CI->getCalledFunction();
-
-    if (F != nullptr)
-      Name.append(F->getName());
-  }
-
-  Name.append("(");
-  for (size_t i = 0; i < Operands.size(); ++i) {
-    Name.append(Operands[i]);
-
-    if (i < Operands.size() - 1)
-      Name.append(", ");
-  }
-  Name.append(")");
-
-  I->setName(Name);
-}
-
-/// Names instruction following the scheme:
-/// op00000Callee(Operands)
-///
-/// Where 00000 is a hash calculated considering instruction's opcode, its
-/// operands' opcodes and order. Callee's name is only included when
-/// instruction's type is CallInst. In cases where instruction is commutative,
-/// operand list is also sorted.
-///
-/// Names instructions recursively in accordance with the def-use tree,
-/// starting from the initial instructions (defs), finishing at
-/// the output (top-most user) instructions (depth-first).
-///
-/// Renames instruction only when RenameAll flag is raised or instruction is
-/// unnamed.
-///
-/// \see getOutputFootprint()
-/// \param I Instruction to be renamed.
-void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
-  LLVM_DEBUG(dbgs() << "Naming regular instruction: " << *I << "\n");
-
-  // Instruction operands for further sorting.
-  SmallVector<SmallString<128>, 4> Operands;
-
-  // The name of a regular instruction depends
-  // on the names of its operands. Hence, all
-  // operands must be named first in the use-def
-  // walk.
-
-  // Collect operands.
-  for (auto &Op : I->operands()) {
-    if (auto *I = dyn_cast<Instruction>(Op)) {
-      // Walk down the use-def chain.
-      nameInstruction(I);
-      Operands.push_back(I->getName());
-    } else if (!isa<Function>(Op)) {
-      // This must be an immediate value.
-      std::string TextRepresentation;
-      raw_string_ostream Stream(TextRepresentation);
-      Op->printAsOperand(Stream, false);
-      Operands.push_back(StringRef(Stream.str()));
-    }
-  }
-
-  sortCommutativeOperands(I, Operands);
-
-  // Initialize to a magic constant, so the state isn't zero.
-  uint64_t Hash = MagicHashConstant;
-
-  // Consider instruction opcode in the hash.
-  Hash = hashing::detail::hash_16_bytes(Hash, I->getOpcode());
-
-  // Operand opcodes for further sorting (commutative).
-  SmallVector<int, 4> OperandsOpcodes;
-
-  // Collect operand opcodes for hashing.
-  for (auto &Op : I->operands())
-    if (auto *I = dyn_cast<Instruction>(Op))
-      OperandsOpcodes.push_back(I->getOpcode());
-
-  sortCommutativeOperands(I, OperandsOpcodes);
-
-  // Consider operand opcodes in the hash.
-  for (const int Code : OperandsOpcodes)
-    Hash = hashing::detail::hash_16_bytes(Hash, Code);
-
-  // Base instruction name.
-  SmallString<512> Name;
-  Name.append("op" + std::to_string(Hash).substr(0, 5));
-
-  // In case of CallInst, consider callee in the instruction name.
-  if (const auto *CI = dyn_cast<CallInst>(I))
-    if (const Function *F = CI->getCalledFunction())
-      Name.append(F->getName());
-
-  Name.append("(");
-  for (size_t i = 0; i < Operands.size(); ++i) {
-    Name.append(Operands[i]);
-
-    if (i < Operands.size() - 1)
-      Name.append(", ");
-  }
-  Name.append(")");
-
-  if ((I->getName().empty() || RenameAll) && !I->getType()->isVoidTy())
-    I->setName(Name);
-}
-
-/// Shortens instruction's name. This method removes called function name from
-/// the instruction name and substitutes the call chain with a corresponding
-/// list of operands.
-///
-/// Examples:
-/// op00000Callee(op00001Callee(...), vl00000Callee(1, 2), ...)  ->
-/// op00000(op00001, vl00000, ...) vl00000Callee(1, 2)  ->  vl00000(1, 2)
-///
-/// This method omits output instructions and pre-output (instructions directly
-/// used by an output instruction) instructions (by default). By default it also
-/// does not affect user named instructions.
-///
-/// \param I Instruction whose name will be folded.
-void IRNormalizer::foldInstructionName(Instruction *I) const {
-  // If this flag is raised, fold all regular
-  // instructions (including pre-outputs).
-  if (!FoldPreOutputs) {
-    // Don't fold if one of the users is an output instruction.
-    for (auto *U : I->users())
-      if (auto *IU = dyn_cast<Instruction>(U))
-        if (isOutput(IU))
-          return;
-  }
-
-  // Don't fold if it is an output instruction or has no op prefix.
-  if (isOutput(I) || I->getName().substr(0, 2) != "op")
-    return;
-
-  // Instruction operands.
-  SmallVector<SmallString<64>, 4> Operands;
-
-  for (auto &Op : I->operands()) {
-    if (const auto *I = dyn_cast<Instruction>(Op)) {
-      bool HasNormalName = I->getName().substr(0, 2) == "op" ||
-                           I->getName().substr(0, 2) == "vl";
-
-      Operands.push_back(HasNormalName ? I->getName().substr(0, 7)
-                                       : I->getName());
-    }
-  }
-
-  sortCommutativeOperands(I, Operands);
-
-  SmallString<256> Name;
-  Name.append(I->getName().substr(0, 7));
-
-  Name.append("(");
-  for (size_t i = 0; i < Operands.size(); ++i) {
-    Name.append(Operands[i]);
-
-    if (i < Operands.size() - 1)
-      Name.append(", ");
-  }
-  Name.append(")");
-
-  I->setName(Name);
-}
-
-/// Reorders instructions by walking up the tree from each operand of an output
-/// instruction and reducing the def-use distance.
-/// This method assumes that output instructions were collected top-down,
-/// otherwise the def-use chain may be broken.
-/// This method is a wrapper for recursive reorderInstruction().
-///
-/// \see reorderInstruction()
-void IRNormalizer::reorderInstructions(Function &F) const {
-  for (auto &BB : F) {
-    LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: "
-                      << BB.getName() << "\n");
-    // Find the source nodes of the DAG of instructions in this basic block.
-    // Source nodes are instructions that have side effects, are terminators, or
-    // don't have a parent in the DAG of instructions.
-    //
-    // We must iterate from the first to the last instruction otherwise side
-    // effecting instructions could be reordered.
-
-    std::stack<Instruction *> TopologicalSort;
-    SmallPtrSet<const Instruction *, 32> Visited;
-    for (auto &I : BB) {
-      // First process side effecting and terminating instructions.
-      if (!(isOutput(&I) || I.isTerminator()))
-        continue;
-      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
-                 I.dump());
-      reorderDefinition(&I, TopologicalSort, Visited);
-    }
-
-    for (auto &I : BB) {
-      // Process the remaining instructions.
-      //
-      // TODO: Do more a intelligent sorting of these instructions. For example,
-      // seperate between dead instructinos and instructions used in another
-      // block. Use properties of the CFG the order instructions that are used
-      // in another block.
-      if (Visited.contains(&I))
-        continue;
-      LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
-      reorderDefinition(&I, TopologicalSort, Visited);
-    }
-
-    LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName()
-                      << "\n");
-    // Reorder based on the topological sort.
-    while (!TopologicalSort.empty()) {
-      auto *Instruction = TopologicalSort.top();
-      auto FirstNonPHIOr...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list