[clang] [llvm] Reland "[LLVM] Add IRNormalizer Pass" (PR #113780)

Justin Fargnoli via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 12 19:13:31 PST 2024


https://github.com/justinfargnoli updated https://github.com/llvm/llvm-project/pull/113780

>From 286728eb275d3544620b0f01a92a1f173b5aad49 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 12 Aug 2023 10:58:45 -0700
Subject: [PATCH 01/70] Add IRCanonicalizer.cpp

---
 llvm/lib/Transforms/Utils/CMakeLists.txt      |   1 +
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 632 ++++++++++++++++++
 2 files changed, 633 insertions(+)
 create mode 100644 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp

diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 36761cf3569741..968bfb81875351 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -37,6 +37,7 @@ add_llvm_component_library(LLVMTransformUtils
   InstructionNamer.cpp
   Instrumentation.cpp
   IntegerDivision.cpp
+  IRCanonicalizer.cpp
   LCSSA.cpp
   LibCallsShrinkWrap.cpp
   Local.cpp
diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
new file mode 100644
index 00000000000000..58e2dce0b96685
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -0,0 +1,632 @@
+//===--------------- IRCanonicalizer.cpp - IR Canonicalizer ---------------===//
+//
+// 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 IRCanonicalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The canonicalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===----------------------------------------------------------------------===//
+
+#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 <vector>
+
+#define DEBUG_TYPE "canon"
+
+using namespace llvm;
+
+namespace {
+/// IRCanonicalizer aims to transform LLVM IR into canonical form.
+class IRCanonicalizer : public FunctionPass {
+public:
+  static char ID;
+
+  /// \name Canonicalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt<bool> PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt<bool> RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt<bool> FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt<bool> ReorderOperands;
+  /// @}
+
+  /// Constructor for the IRCanonicalizer.
+  IRCanonicalizer() : FunctionPass(ID) {}
+
+  bool runOnFunction(Function &F) override;
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector<Instruction *, 16> &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+                          SmallPtrSet<const Instruction *, 32> &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector<Instruction *, 16> collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector<int>
+  getOutputFootprint(Instruction *I,
+                     SmallPtrSet<const Instruction *, 32> &Visited);
+  /// @}
+};
+} // namespace
+
+char IRCanonicalizer::ID = 0;
+static RegisterPass<IRCanonicalizer> X("canon", "Canonicalize the IR",
+                                       false /* Only looks at CFG */,
+                                       false /* Analysis Pass */);
+
+cl::opt<bool> IRCanonicalizer::PreserveOrder(
+    "preserve-order", cl::Hidden,
+    cl::desc("Preserves original instruction order"));
+cl::opt<bool> IRCanonicalizer::RenameAll(
+    "rename-all", cl::Hidden,
+    cl::desc("Renames all instructions (including user-named)"));
+cl::opt<bool> IRCanonicalizer::FoldPreoutputs(
+    "fold-all", cl::Hidden,
+    cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt<bool> IRCanonicalizer::ReorderOperands(
+    "reorder-operands", cl::Hidden,
+    cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRCanonicalizer.
+///
+/// \param M Module to canonicalize.
+bool IRCanonicalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector<Instruction *, 16> Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+    reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+    nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+    if (!PreserveOrder) {
+      if (ReorderOperands && I.isCommutative())
+        reorderInstructionOperandsByNames(&I);
+
+      if (auto *PN = dyn_cast<PHINode>(&I))
+        reorderPHIIncomingValues(PN);
+    }
+
+    foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRCanonicalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+    if (RenameAll || A.getName().empty()) {
+      A.setName("a" + Twine(ArgumentCounter));
+      ++ArgumentCounter;
+    }
+  }
+}
+
+/// 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 IRCanonicalizer::nameBasicBlocks(Function &F) {
+  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 IRCanonicalizer::nameInstruction(Instruction *I) {
+  // Determine the type of instruction to name.
+  if (isInitialInstruction(I)) {
+    // This is an initial instruction.
+    nameAsInitialInstruction(I);
+  } else {
+    // This must be a regular instruction.
+    nameAsRegularInstruction(I);
+  }
+}
+
+/// 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 IRCanonicalizer::nameAsInitialInstruction(Instruction *I) {
+  if (I->getType()->isVoidTy() || (!I->getName().empty() && !RenameAll))
+    return;
+
+  // 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()));
+    }
+  }
+
+  if (I->isCommutative())
+    llvm::sort(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 (unsigned long 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 IRCanonicalizer::nameAsRegularInstruction(Instruction *I) {
+  // 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 *IOP = dyn_cast<Instruction>(OP)) {
+      // Walk down the use-def chain.
+      nameInstruction(IOP);
+      Operands.push_back(IOP->getName());
+    } else if (isa<Value>(OP) && !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()));
+    }
+  }
+
+  if (I->isCommutative())
+    llvm::sort(Operands.begin(), Operands.end());
+
+  // 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 *IOP = dyn_cast<Instruction>(OP))
+      OperandsOpcodes.push_back(IOP->getOpcode());
+
+  if (I->isCommutative())
+    llvm::sort(OperandsOpcodes.begin(), OperandsOpcodes.end());
+
+  // 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 (unsigned long 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 IRCanonicalizer::foldInstructionName(Instruction *I) {
+  // 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 Instruction *IOP = dyn_cast<Instruction>(OP)) {
+      bool HasCanonicalName = I->getName().substr(0, 2) == "op" ||
+                              I->getName().substr(0, 2) == "vl";
+
+      Operands.push_back(HasCanonicalName ? IOP->getName().substr(0, 7)
+                                          : IOP->getName());
+    }
+  }
+
+  if (I->isCommutative())
+    llvm::sort(Operands.begin(), Operands.end());
+
+  SmallString<256> Name;
+  Name.append(I->getName().substr(0, 7));
+
+  Name.append("(");
+  for (unsigned long 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()
+/// \param Outputs Vector of pointers to output instructions collected top-down.
+void IRCanonicalizer::reorderInstructions(
+    SmallVector<Instruction *, 16> &Outputs) {
+  // This method assumes output instructions were collected top-down,
+  // otherwise the def-use chain may be broken.
+
+  SmallPtrSet<const Instruction *, 32> Visited;
+
+  // Walk up the tree.
+  for (auto &I : Outputs)
+    for (auto &OP : I->operands())
+      if (auto *IOP = dyn_cast<Instruction>(OP))
+        reorderInstruction(IOP, I, Visited);
+}
+
+/// Reduces def-use distance or places instruction at the end of the basic
+/// block. Continues to walk up the def-use tree recursively. Used by
+/// reorderInstructions().
+///
+/// \see reorderInstructions()
+/// \param Used Pointer to the instruction whose value is used by the \p User.
+/// \param User Pointer to the instruction which uses the \p Used.
+/// \param Visited Set of visited instructions.
+void IRCanonicalizer::reorderInstruction(
+    Instruction *Used, Instruction *User,
+    SmallPtrSet<const Instruction *, 32> &Visited) {
+
+  if (!Visited.count(Used)) {
+    Visited.insert(Used);
+
+    if (Used->getParent() == User->getParent()) {
+      // If Used and User share the same basic block move Used just before User.
+      Used->moveBefore(User);
+    } else {
+      // Otherwise move Used to the very end of its basic block.
+      Used->moveBefore(&Used->getParent()->back());
+    }
+
+    for (auto &OP : Used->operands()) {
+      if (auto *IOP = dyn_cast<Instruction>(OP)) {
+        // Walk up the def-use tree.
+        reorderInstruction(IOP, Used, Visited);
+      }
+    }
+  }
+}
+
+/// Reorders instruction's operands alphabetically. This method assumes
+/// that passed instruction is commutative. Changing the operand order
+/// in other instructions may change the semantics.
+///
+/// \param I Instruction whose operands will be reordered.
+void IRCanonicalizer::reorderInstructionOperandsByNames(Instruction *I) {
+  // This method assumes that passed I is commutative,
+  // changing the order of operands in other instructions
+  // may change the semantics.
+
+  // Instruction operands for further sorting.
+  SmallVector<std::pair<std::string, Value *>, 4> Operands;
+
+  // Collect operands.
+  for (auto &OP : I->operands()) {
+    if (auto *VOP = dyn_cast<Value>(OP)) {
+      if (isa<Instruction>(VOP)) {
+        // This is an an instruction.
+        Operands.push_back(
+            std::pair<std::string, Value *>(VOP->getName(), VOP));
+      } else {
+        std::string TextRepresentation;
+        raw_string_ostream Stream(TextRepresentation);
+        OP->printAsOperand(Stream, false);
+        Operands.push_back(std::pair<std::string, Value *>(Stream.str(), VOP));
+      }
+    }
+  }
+
+  // Sort operands.
+  llvm::sort(Operands.begin(), Operands.end(), llvm::less_first());
+
+  // Reorder operands.
+  unsigned Position = 0;
+  for (auto &OP : I->operands()) {
+    OP.set(Operands[Position].second);
+    Position++;
+  }
+}
+
+/// Reorders PHI node's values according to the names of corresponding basic
+/// blocks.
+///
+/// \param PN PHI node to canonicalize.
+void IRCanonicalizer::reorderPHIIncomingValues(PHINode *PN) {
+  // Values for further sorting.
+  SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
+
+  // Collect blocks and corresponding values.
+  for (auto &BB : PN->blocks()) {
+    Value *V = PN->getIncomingValueForBlock(BB);
+    Values.push_back(std::pair<Value *, BasicBlock *>(V, BB));
+  }
+
+  // Sort values according to the name of a basic block.
+  llvm::sort(Values, [](const std::pair<Value *, BasicBlock *> &LHS,
+                        const std::pair<Value *, BasicBlock *> &RHS) {
+    return LHS.second->getName() < RHS.second->getName();
+  });
+
+  // Swap.
+  for (unsigned i = 0; i < Values.size(); ++i) {
+    PN->setIncomingBlock(i, Values[i].second);
+    PN->setIncomingValue(i, Values[i].first);
+  }
+}
+
+/// Returns a vector of output instructions. An output is an instruction which
+/// has side-effects or is ReturnInst. Uses isOutput().
+///
+/// \see isOutput()
+/// \param F Function to collect outputs from.
+SmallVector<Instruction *, 16>
+IRCanonicalizer::collectOutputInstructions(Function &F) {
+  // Output instructions are collected top-down in each function,
+  // any change may break the def-use chain in reordering methods.
+  SmallVector<Instruction *, 16> Outputs;
+
+  for (auto &I : instructions(F))
+    if (isOutput(&I))
+      Outputs.push_back(&I);
+
+  return Outputs;
+}
+
+/// Helper method checking whether the instruction may have side effects or is
+/// ReturnInst.
+///
+/// \param I Considered instruction.
+bool IRCanonicalizer::isOutput(const Instruction *I) {
+  // Outputs are such instructions which may have side effects or is ReturnInst.
+  if (I->mayHaveSideEffects() || isa<ReturnInst>(I))
+    return true;
+
+  return false;
+}
+
+/// Helper method checking whether the instruction has users and only
+/// immediate operands.
+///
+/// \param I Considered instruction.
+bool IRCanonicalizer::isInitialInstruction(const Instruction *I) {
+  // Initial instructions are such instructions whose values are used by
+  // other instructions, yet they only depend on immediate values.
+  return !I->user_empty() && hasOnlyImmediateOperands(I);
+}
+
+/// Helper method checking whether the instruction has only immediate operands.
+///
+/// \param I Considered instruction.
+bool IRCanonicalizer::hasOnlyImmediateOperands(const Instruction *I) {
+  for (const auto &OP : I->operands())
+    if (isa<Instruction>(OP))
+      return false; // Found non-immediate operand (instruction).
+
+  return true;
+}
+
+/// Helper method returning indices (distance from the beginning of the basic
+/// block) of outputs using the \p I (eliminates repetitions). Walks down the
+/// def-use tree recursively.
+///
+/// \param I Considered instruction.
+/// \param Visited Set of visited instructions.
+SetVector<int> IRCanonicalizer::getOutputFootprint(
+    Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) {
+
+  // Vector containing indexes of outputs (no repetitions),
+  // which use I in the order of walking down the def-use tree.
+  SetVector<int> Outputs;
+
+  if (!Visited.count(I)) {
+    Visited.insert(I);
+
+    if (isOutput(I)) {
+      // Gets output instruction's parent function.
+      Function *Func = I->getParent()->getParent();
+
+      // Finds and inserts the index of the output to the vector.
+      unsigned Count = 0;
+      for (const auto &B : *Func) {
+        for (const auto &E : B) {
+          if (&E == I)
+            Outputs.insert(Count);
+          Count++;
+        }
+      }
+
+      // Returns to the used instruction.
+      return Outputs;
+    }
+
+    for (auto *U : I->users()) {
+      if (auto *UI = dyn_cast<Instruction>(U)) {
+        // Vector for outputs which use UI.
+        SetVector<int> OutputsUsingUI = getOutputFootprint(UI, Visited);
+
+        // Insert the indexes of outputs using UI.
+        Outputs.insert(OutputsUsingUI.begin(), OutputsUsingUI.end());
+      }
+    }
+  }
+
+  // Return to the used instruction.
+  return Outputs;
+}

>From b2e1e7388a26de59c2aecff44a1aea86fb0c66f0 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 12 Aug 2023 15:55:40 -0700
Subject: [PATCH 02/70] Port IRCanonicalizer to new pass manager

---
 .../llvm/Transforms/Utils/IRCanonicalizer.h   | 15 +++++++++++++
 llvm/lib/Passes/PassBuilder.cpp               |  1 +
 llvm/lib/Passes/PassRegistry.def              |  4 ++++
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 22 +++++++++----------
 4 files changed, 30 insertions(+), 12 deletions(-)
 create mode 100644 llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h

diff --git a/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h b/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h
new file mode 100644
index 00000000000000..81bfd1bcfd2ad9
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h
@@ -0,0 +1,15 @@
+#ifndef LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
+#define LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+/// IRCanonicalizer aims to transform LLVM IR into canonical form.
+struct IRCanonicalizerPass : public PassInfoMixin<IRCanonicalizerPass> {
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index e0d042598348c9..efea7a50393f18 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -309,6 +309,7 @@
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
 #include "llvm/Transforms/Utils/InstructionNamer.h"
 #include "llvm/Transforms/Utils/Instrumentation.h"
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include "llvm/Transforms/Utils/LCSSA.h"
 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
 #include "llvm/Transforms/Utils/LoopSimplify.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 02c8053ea39d6d..de39af190947a1 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -340,6 +340,10 @@ FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
+FUNCTION_PASS("canon", IRCanonicalizerPass())
+FUNCTION_PASS("consthoist", ConstantHoistingPass())
+FUNCTION_PASS("count-visits", CountVisitsPass())
+FUNCTION_PASS("constraint-elimination", ConstraintEliminationPass())
 FUNCTION_PASS("chr", ControlHeightReductionPass())
 FUNCTION_PASS("codegenprepare", CodeGenPreparePass(TM))
 FUNCTION_PASS("complex-deinterleaving", ComplexDeinterleavingPass(TM))
diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 58e2dce0b96685..afa3d94e7f55be 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -28,6 +28,7 @@
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include <algorithm>
 #include <vector>
 
@@ -37,10 +38,8 @@ using namespace llvm;
 
 namespace {
 /// IRCanonicalizer aims to transform LLVM IR into canonical form.
-class IRCanonicalizer : public FunctionPass {
+class IRCanonicalizer {
 public:
-  static char ID;
-
   /// \name Canonicalizer flags.
   /// @{
   /// Preserves original order of instructions.
@@ -53,10 +52,7 @@ class IRCanonicalizer : public FunctionPass {
   static cl::opt<bool> ReorderOperands;
   /// @}
 
-  /// Constructor for the IRCanonicalizer.
-  IRCanonicalizer() : FunctionPass(ID) {}
-
-  bool runOnFunction(Function &F) override;
+  bool runOnFunction(Function &F);
 
 private:
   // Random constant for hashing, so the state isn't zero.
@@ -94,11 +90,6 @@ class IRCanonicalizer : public FunctionPass {
 };
 } // namespace
 
-char IRCanonicalizer::ID = 0;
-static RegisterPass<IRCanonicalizer> X("canon", "Canonicalize the IR",
-                                       false /* Only looks at CFG */,
-                                       false /* Analysis Pass */);
-
 cl::opt<bool> IRCanonicalizer::PreserveOrder(
     "preserve-order", cl::Hidden,
     cl::desc("Preserves original instruction order"));
@@ -630,3 +621,10 @@ SetVector<int> IRCanonicalizer::getOutputFootprint(
   // Return to the used instruction.
   return Outputs;
 }
+
+PreservedAnalyses IRCanonicalizerPass::run(Function &F,
+                                           FunctionAnalysisManager &AM) {
+  errs() << F.getName() << "\n";
+  IRCanonicalizer{}.runOnFunction(F);
+  return PreservedAnalyses::all();
+}

>From c1d9b512ec816a7d8437ad0142647ff713d3d4b4 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 12 Aug 2023 16:06:29 -0700
Subject: [PATCH 03/70] Port doc updates

---
 llvm/docs/Passes.rst      | 12 ++++++++++--
 llvm/docs/ReleaseNotes.md |  5 ++++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
index 49f633e98d16fe..aabd0f98a4c457 100644
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -543,8 +543,16 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 <passes-sccp>`.
 
-``jump-threading``: Jump Threading
-----------------------------------
+``-ir-canonicalizer``: Transforms IR into canonical form
+--------------------------------------------------------
+
+This pass aims to transform LLVM Modules into a canonical form by reordering and
+renaming instructions while preserving the same semantics. The canonicalizer makes
+it easier to spot semantic differences while diffing two modules which have undergone
+two different passes.
+
+``-jump-threading``: Jump Threading
+-----------------------------------
 
 Jump threading tries to find distinct threads of control flow running through a
 basic block.  This pass looks at blocks that have multiple predecessors and
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 5252ae5aadcf6a..3bd0843267fd80 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -42,7 +42,10 @@ 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 IRCanonicalizer pass which aims to transform LLVM modules into
+  a canonical form by reordering and renaming instructions while preserving the
+  same semantics. The canonicalizer 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
 subsection about it right here. You can copy the following boilerplate:

>From b9e003d5f20f33ebfbc2d87f44bdfff729a018ef Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 12 Aug 2023 16:29:46 -0700
Subject: [PATCH 04/70] Port tests

---
 .../IRCanonicalizer/naming-arguments.ll       |  7 ++++++
 .../IRCanonicalizer/naming-basic-blocks.ll    |  8 +++++++
 .../IRCanonicalizer/naming-instructions.ll    | 12 ++++++++++
 .../reordering-instructions.ll                | 14 +++++++++++
 .../reordering-phi-node-values.ll             | 24 +++++++++++++++++++
 5 files changed, 65 insertions(+)
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll

diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
new file mode 100644
index 00000000000000..b3f7630abd042f
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
@@ -0,0 +1,7 @@
+; RUN: opt -S -passes=canon < %s | FileCheck %s
+
+; CHECK: @foo(i32 %a0, i32 %a1)
+define i32 @foo(i32, i32) {
+  %tmp = mul i32 %0, %1
+  ret i32 %tmp
+}
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll b/llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll
new file mode 100644
index 00000000000000..79e526f8efb7ac
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll
@@ -0,0 +1,8 @@
+; RUN: opt -S -passes=canon --rename-all < %s | FileCheck %s
+
+define i32 @foo(i32 %a0) {
+; CHECK: bb{{([0-9]{5})}}
+entry:
+  %a = add i32 %a0, 2
+  ret i32 %a
+}
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll b/llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll
new file mode 100644
index 00000000000000..a22e816f5bf01e
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll
@@ -0,0 +1,12 @@
+; RUN: opt -S -passes=canon --rename-all < %s | FileCheck %s
+
+define i32 @foo(i32 %a0) {
+entry:
+; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
+  %a = add i32 %a0, 2
+; CHECK: %"op{{([0-9]{5})}}(vl{{([0-9]{5})}})"
+  %b = add i32 %a, 6
+; CHECK: %"op{{([0-9]{5})}}(8, op{{([0-9]{5})}}(6, vl{{([0-9]{5})}}(%a0, 2)))"
+  %c = add i32 %b, 8
+  ret i32 %c
+}
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
new file mode 100644
index 00000000000000..04660ac73c11bd
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
@@ -0,0 +1,14 @@
+; RUN: opt -S -passes=canon < %s | FileCheck %s
+
+define double @foo(double %a0, double %a1) {
+entry:
+; CHECK: %a
+; CHECK: %c
+; CHECK: %b
+; CHECK: %d
+  %a = fmul double %a0, %a1
+  %b = fmul double %a0, 2.000000e+00
+  %c = fmul double %a, 6.000000e+00
+  %d = fmul double %b, 6.000000e+00
+  ret double %d
+}
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
new file mode 100644
index 00000000000000..5f344ec29be66f
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
@@ -0,0 +1,24 @@
+; RUN: opt -S -passes=canon < %s | FileCheck %s
+
+declare double @foo()
+
+declare double @bar()
+
+define double @baz(double %x) {
+entry:
+  %ifcond = fcmp one double %x, 0.000000e+00
+  br i1 %ifcond, label %then, label %else
+
+then:       ; preds = %entry
+  %calltmp = call double @foo()
+  br label %ifcont
+
+else:       ; preds = %entry
+  %calltmp1 = call double @bar()
+  br label %ifcont
+
+ifcont:     ; preds = %else, %then
+; CHECK: %iftmp = phi double [ %calltmp1, %else ], [ %calltmp, %then ]
+  %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
+  ret double %iftmp
+}

>From 57b3710f7bc8a660bcc4037b5d89505c8bb8951d Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 19 Aug 2023 15:23:09 -0700
Subject: [PATCH 05/70] Turn rename-all and -reorder-operands on by default

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp               | 6 ++++--
 llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll    | 2 +-
 .../Transforms/IRCanonicalizer/reordering-instructions.ll   | 2 +-
 .../IRCanonicalizer/reordering-phi-node-values.ll           | 2 +-
 4 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index afa3d94e7f55be..b5a007c80b32b3 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -95,13 +95,15 @@ cl::opt<bool> IRCanonicalizer::PreserveOrder(
     cl::desc("Preserves original instruction order"));
 cl::opt<bool> IRCanonicalizer::RenameAll(
     "rename-all", cl::Hidden,
-    cl::desc("Renames all instructions (including user-named)"));
+    cl::desc("Renames all instructions (including user-named)"), 
+    cl::init(true));
 cl::opt<bool> IRCanonicalizer::FoldPreoutputs(
     "fold-all", cl::Hidden,
     cl::desc("Folds all regular instructions (including pre-outputs)"));
 cl::opt<bool> IRCanonicalizer::ReorderOperands(
     "reorder-operands", cl::Hidden,
-    cl::desc("Sorts and reorders operands in commutative instructions"));
+    cl::desc("Sorts and reorders operands in commutative instructions"),
+    cl::init(true));
 
 /// Entry method to the IRCanonicalizer.
 ///
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
index b3f7630abd042f..5a274f7cc5a3b7 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
 
 ; CHECK: @foo(i32 %a0, i32 %a1)
 define i32 @foo(i32, i32) {
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
index 04660ac73c11bd..3ea19e8b6c78c9 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
 
 define double @foo(double %a0, double %a1) {
 entry:
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
index 5f344ec29be66f..3ea0bab50b5b9a 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
 
 declare double @foo()
 

>From fa1eadf569ae0cdc30226ad7212117965ff90432 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 19 Aug 2023 15:25:12 -0700
Subject: [PATCH 06/70] Add infinite loop regression test

---
 .../IRCanonicalizer/infinite-loop.ll          | 100 ++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll

diff --git a/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll b/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
new file mode 100644
index 00000000000000..f67c1eb7fa5b22
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
@@ -0,0 +1,100 @@
+; RUN: opt -passes=canon < %s
+
+; XFAIL: *
+; FIXME: Infinite loop in name instructions
+
+define void @test(ptr) {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb1, %bb
+  %tmp = phi i32 [ undef, %bb ], [ %tmp87, %bb1 ]
+  %tmp2 = phi i32 [ undef, %bb ], [ %tmp86, %bb1 ]
+  %tmp3 = mul i32 %tmp, undef
+  %tmp4 = xor i32 %tmp3, -1
+  %tmp5 = add i32 %tmp, %tmp4
+  %tmp6 = add i32 %tmp2, -1
+  %tmp7 = add i32 %tmp5, %tmp6
+  %tmp8 = mul i32 %tmp7, %tmp3
+  %tmp9 = xor i32 %tmp8, -1
+  %tmp10 = add i32 %tmp7, %tmp9
+  %tmp11 = add i32 %tmp10, undef
+  %tmp12 = mul i32 %tmp11, %tmp8
+  %tmp13 = xor i32 %tmp12, -1
+  %tmp14 = add i32 %tmp11, %tmp13
+  %tmp15 = add i32 %tmp14, undef
+  %tmp16 = mul i32 %tmp15, %tmp12
+  %tmp17 = add i32 %tmp15, undef
+  %tmp18 = add i32 %tmp17, undef
+  %tmp19 = mul i32 %tmp18, %tmp16
+  %tmp20 = xor i32 %tmp19, -1
+  %tmp21 = add i32 %tmp18, %tmp20
+  %tmp22 = add i32 %tmp21, undef
+  %tmp23 = mul i32 %tmp22, %tmp19
+  %tmp24 = xor i32 %tmp23, -1
+  %tmp25 = add i32 %tmp22, %tmp24
+  %tmp26 = add i32 %tmp25, undef
+  %tmp27 = mul i32 %tmp26, %tmp23
+  %tmp28 = xor i32 %tmp27, -1
+  %tmp29 = add i32 %tmp26, %tmp28
+  %tmp30 = add i32 %tmp29, undef
+  %tmp31 = mul i32 %tmp30, %tmp27
+  %tmp32 = xor i32 %tmp31, -1
+  %tmp33 = add i32 %tmp30, %tmp32
+  %tmp34 = add i32 %tmp33, undef
+  %tmp35 = mul i32 %tmp34, %tmp31
+  %tmp36 = xor i32 %tmp35, -1
+  %tmp37 = add i32 %tmp34, %tmp36
+  %tmp38 = add i32 %tmp2, -9
+  %tmp39 = add i32 %tmp37, %tmp38
+  %tmp40 = mul i32 %tmp39, %tmp35
+  %tmp41 = xor i32 %tmp40, -1
+  %tmp42 = add i32 %tmp39, %tmp41
+  %tmp43 = add i32 %tmp42, undef
+  %tmp44 = mul i32 %tmp43, %tmp40
+  %tmp45 = xor i32 %tmp44, -1
+  %tmp46 = add i32 %tmp43, %tmp45
+  %tmp47 = add i32 %tmp46, undef
+  %tmp48 = mul i32 %tmp47, %tmp44
+  %tmp49 = xor i32 %tmp48, -1
+  %tmp50 = add i32 %tmp47, %tmp49
+  %tmp51 = add i32 %tmp50, undef
+  %tmp52 = mul i32 %tmp51, %tmp48
+  %tmp53 = xor i32 %tmp52, -1
+  %tmp54 = add i32 %tmp51, %tmp53
+  %tmp55 = add i32 %tmp54, undef
+  %tmp56 = mul i32 %tmp55, %tmp52
+  %tmp57 = xor i32 %tmp56, -1
+  %tmp58 = add i32 %tmp55, %tmp57
+  %tmp59 = add i32 %tmp2, -14
+  %tmp60 = add i32 %tmp58, %tmp59
+  %tmp61 = mul i32 %tmp60, %tmp56
+  %tmp62 = xor i32 %tmp61, -1
+  %tmp63 = add i32 %tmp60, %tmp62
+  %tmp64 = add i32 %tmp63, undef
+  %tmp65 = mul i32 %tmp64, %tmp61
+  %tmp66 = xor i32 %tmp65, -1
+  %tmp67 = add i32 %tmp64, %tmp66
+  %tmp68 = add i32 %tmp67, undef
+  %tmp69 = mul i32 %tmp68, %tmp65
+  %tmp70 = xor i32 %tmp69, -1
+  %tmp71 = add i32 %tmp68, %tmp70
+  %tmp72 = add i32 %tmp71, undef
+  %tmp73 = mul i32 %tmp72, %tmp69
+  %tmp74 = xor i32 %tmp73, -1
+  %tmp75 = add i32 %tmp72, %tmp74
+  %tmp76 = add i32 %tmp75, undef
+  %tmp77 = mul i32 %tmp76, %tmp73
+  %tmp78 = xor i32 %tmp77, -1
+  %tmp79 = add i32 %tmp76, %tmp78
+  %tmp80 = add i32 %tmp79, undef
+  %tmp81 = mul i32 %tmp80, %tmp77
+  %tmp82 = xor i32 %tmp81, -1
+  %tmp83 = add i32 %tmp80, %tmp82
+  %tmp84 = add i32 %tmp83, undef
+  %tmp85 = add i32 %tmp84, undef
+  %tmp86 = add i32 %tmp2, -21
+  %tmp87 = add i32 %tmp85, %tmp86
+  store i32 %tmp87, ptr %0
+  br label %bb1
+}

>From a1af028febf3160afa22eef162ba529313372aea Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 27 Aug 2023 15:19:36 -0700
Subject: [PATCH 07/70] Add visited set to fix infinite loop bug

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index b5a007c80b32b3..73433a9a05c0d4 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -57,6 +57,7 @@ class IRCanonicalizer {
 private:
   // Random constant for hashing, so the state isn't zero.
   const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet<const Instruction *> NamedInstructions;
 
   /// \name Naming.
   /// @{
@@ -175,6 +176,9 @@ void IRCanonicalizer::nameBasicBlocks(Function &F) {
 ///
 /// \param I Instruction to be renamed.
 void IRCanonicalizer::nameInstruction(Instruction *I) {
+  if (NamedInstructions.contains(I))
+    return;
+  NamedInstructions.insert(I); 
   // Determine the type of instruction to name.
   if (isInitialInstruction(I)) {
     // This is an initial instruction.

>From 3b8d999b79315c59dd16ca218261cf6a4bbd2f57 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 27 Aug 2023 15:20:12 -0700
Subject: [PATCH 08/70] Expand test to expose reordering bug

---
 .../Transforms/IRCanonicalizer/infinite-loop.ll     | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll b/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
index f67c1eb7fa5b22..3438a05b4aee48 100644
--- a/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
@@ -1,15 +1,14 @@
-; RUN: opt -passes=canon < %s
+; RUN: opt -passes=canon -preserve-order=true < %s
+; RUN: opt -passes=canon -preserve-order=false < %s
 
-; XFAIL: *
-; FIXME: Infinite loop in name instructions
-
-define void @test(ptr) {
+define void @test(ptr, i32) {
 bb:
+  %a = add i32 %1, 1
   br label %bb1
 
 bb1:                                              ; preds = %bb1, %bb
-  %tmp = phi i32 [ undef, %bb ], [ %tmp87, %bb1 ]
-  %tmp2 = phi i32 [ undef, %bb ], [ %tmp86, %bb1 ]
+  %tmp = phi i32 [ %a, %bb ], [ %tmp87, %bb1 ]
+  %tmp2 = phi i32 [ %a, %bb ], [ %tmp86, %bb1 ]
   %tmp3 = mul i32 %tmp, undef
   %tmp4 = xor i32 %tmp3, -1
   %tmp5 = add i32 %tmp, %tmp4

>From 98281e8a803e5b5d6e5d1478b4c828813bcbe4ce Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 28 Aug 2023 12:28:20 -0400
Subject: [PATCH 09/70] added some documentation

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 73433a9a05c0d4..600c2baf6e013a 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -176,6 +176,9 @@ void IRCanonicalizer::nameBasicBlocks(Function &F) {
 ///
 /// \param I Instruction to be renamed.
 void IRCanonicalizer::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); 

>From 09d50eb9d9262c60989625e72826b3538c6feec3 Mon Sep 17 00:00:00 2001
From: Aidan <aidan.goldfarb at mail.mcgill.ca>
Date: Mon, 28 Aug 2023 13:56:05 -0400
Subject: [PATCH 10/70] pushed broken int test

---
 .../IRCanonicalizer/naming-args-instr-blocks.ll   | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll

diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll b/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
new file mode 100644
index 00000000000000..74e1944825011b
--- /dev/null
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
@@ -0,0 +1,15 @@
+; RUN: opt -S -passes=canon --rename-all --preserve-order < %s | FileCheck %s
+
+
+; CHECK: @foo(i32 %a0)
+define i32 @foo(i32) {
+; CHECK: bb{{([0-9]{5})}}
+entry:
+    ; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
+    %a = add i32 %0, 2
+    
+    ; CHECK: %"op{{([0-9]{5})}}(vl{{([0-9]{5})}})"
+    %b = add i32 %a, 6
+
+    ret i32 %a
+}

>From 4eb996f63b70c1436ca4e82fea7d9257b99243b4 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Mon, 11 Sep 2023 12:27:35 -0700
Subject: [PATCH 11/70] Reformat `reorderInstruction`

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 600c2baf6e013a..6f60d3d261d828 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -443,23 +443,23 @@ void IRCanonicalizer::reorderInstructions(
 void IRCanonicalizer::reorderInstruction(
     Instruction *Used, Instruction *User,
     SmallPtrSet<const Instruction *, 32> &Visited) {
+  if (Visited.contains(Used)) {
+    return;
+  }
+  Visited.insert(Used);
 
-  if (!Visited.count(Used)) {
-    Visited.insert(Used);
-
-    if (Used->getParent() == User->getParent()) {
-      // If Used and User share the same basic block move Used just before User.
-      Used->moveBefore(User);
-    } else {
-      // Otherwise move Used to the very end of its basic block.
-      Used->moveBefore(&Used->getParent()->back());
-    }
+  if (Used->getParent() == User->getParent()) {
+    // If Used and User share the same basic block move Used just before User.
+    Used->moveBefore(User);
+  } else {
+    // Otherwise move Used to the very end of its basic block.
+    Used->moveBefore(&Used->getParent()->back());
+  }
 
-    for (auto &OP : Used->operands()) {
-      if (auto *IOP = dyn_cast<Instruction>(OP)) {
-        // Walk up the def-use tree.
-        reorderInstruction(IOP, Used, Visited);
-      }
+  for (auto &OP : Used->operands()) {
+    if (auto *IOP = dyn_cast<Instruction>(OP)) {
+      // Walk up the def-use tree.
+      reorderInstruction(IOP, Used, Visited);
     }
   }
 }

>From f608049c4b63ee067365949a66da02781c57daf4 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Mon, 11 Sep 2023 13:05:30 -0700
Subject: [PATCH 12/70] Bug fix: don't reorder PHI nodes

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 6f60d3d261d828..a40435f7b82293 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -443,9 +443,10 @@ void IRCanonicalizer::reorderInstructions(
 void IRCanonicalizer::reorderInstruction(
     Instruction *Used, Instruction *User,
     SmallPtrSet<const Instruction *, 32> &Visited) {
-  if (Visited.contains(Used)) {
+  if(isa<PHINode>(Used))
+    return;
+  if (Visited.contains(Used))
     return;
-  }
   Visited.insert(Used);
 
   if (Used->getParent() == User->getParent()) {

>From ac9230f198e4e4418cae341ae06afddbcdbbea02 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Mon, 11 Sep 2023 13:29:27 -0700
Subject: [PATCH 13/70] Revert "Turn rename-all and -reorder-operands on by
 default"

This reverts commit f5b7445662310a2f329e0f4aaf45822058f307ba.
---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp               | 6 ++----
 llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll    | 2 +-
 .../Transforms/IRCanonicalizer/reordering-instructions.ll   | 2 +-
 .../IRCanonicalizer/reordering-phi-node-values.ll           | 2 +-
 4 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index a40435f7b82293..45dc954f97b9c7 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -96,15 +96,13 @@ cl::opt<bool> IRCanonicalizer::PreserveOrder(
     cl::desc("Preserves original instruction order"));
 cl::opt<bool> IRCanonicalizer::RenameAll(
     "rename-all", cl::Hidden,
-    cl::desc("Renames all instructions (including user-named)"), 
-    cl::init(true));
+    cl::desc("Renames all instructions (including user-named)"));
 cl::opt<bool> IRCanonicalizer::FoldPreoutputs(
     "fold-all", cl::Hidden,
     cl::desc("Folds all regular instructions (including pre-outputs)"));
 cl::opt<bool> IRCanonicalizer::ReorderOperands(
     "reorder-operands", cl::Hidden,
-    cl::desc("Sorts and reorders operands in commutative instructions"),
-    cl::init(true));
+    cl::desc("Sorts and reorders operands in commutative instructions"));
 
 /// Entry method to the IRCanonicalizer.
 ///
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
index 5a274f7cc5a3b7..b3f7630abd042f 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
+; RUN: opt -S -passes=canon < %s | FileCheck %s
 
 ; CHECK: @foo(i32 %a0, i32 %a1)
 define i32 @foo(i32, i32) {
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
index 3ea19e8b6c78c9..04660ac73c11bd 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
+; RUN: opt -S -passes=canon < %s | FileCheck %s
 
 define double @foo(double %a0, double %a1) {
 entry:
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
index 3ea0bab50b5b9a..5f344ec29be66f 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all=false < %s | FileCheck %s
+; RUN: opt -S -passes=canon < %s | FileCheck %s
 
 declare double @foo()
 

>From a32ebe15d22f7b35e30b0fdcd277cff9f21c6088 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Mon, 25 Sep 2023 11:13:25 -0500
Subject: [PATCH 14/70] Fix naming-args-instr-blocks.ll

---
 .../Transforms/IRCanonicalizer/naming-args-instr-blocks.ll    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll b/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
index 74e1944825011b..605c62863f2ad3 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
+++ b/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
@@ -8,8 +8,8 @@ entry:
     ; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
     %a = add i32 %0, 2
     
-    ; CHECK: %"op{{([0-9]{5})}}(vl{{([0-9]{5})}})"
+    ; CHECK: %"op{{([0-9]{5})}}(6, vl{{([0-9]{5})}}(%a0, 2))"
     %b = add i32 %a, 6
 
-    ret i32 %a
+    ret i32 %b
 }

>From 1ee5e0bee6c2a1f23cd5a11d03d8b4eb181eb963 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 3 Oct 2023 21:55:04 -0700
Subject: [PATCH 15/70] clang format changes

---
 llvm/lib/Passes/PassBuilder.cpp               |  3 +--
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 12 ++++++------
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index efea7a50393f18..5be5659d25efd8 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -306,10 +306,9 @@
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/FixIrreducible.h"
 #include "llvm/Transforms/Utils/HelloWorld.h"
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
 #include "llvm/Transforms/Utils/InstructionNamer.h"
-#include "llvm/Transforms/Utils/Instrumentation.h"
-#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include "llvm/Transforms/Utils/LCSSA.h"
 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
 #include "llvm/Transforms/Utils/LoopSimplify.h"
diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 45dc954f97b9c7..7ea3959e5e90d0 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -174,12 +174,12 @@ void IRCanonicalizer::nameBasicBlocks(Function &F) {
 ///
 /// \param I Instruction to be renamed.
 void IRCanonicalizer::nameInstruction(Instruction *I) {
-  //ensure instructions are not renamed. This is done
-  //to prevent situation where instructions are used
-  //before their definition (in phi nodes)
+  // 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); 
+  NamedInstructions.insert(I);
   // Determine the type of instruction to name.
   if (isInitialInstruction(I)) {
     // This is an initial instruction.
@@ -381,7 +381,7 @@ void IRCanonicalizer::foldInstructionName(Instruction *I) {
   SmallVector<SmallString<64>, 4> Operands;
 
   for (auto &OP : I->operands()) {
-    if (const Instruction *IOP = dyn_cast<Instruction>(OP)) {
+    if (const auto *IOP = dyn_cast<Instruction>(OP)) {
       bool HasCanonicalName = I->getName().substr(0, 2) == "op" ||
                               I->getName().substr(0, 2) == "vl";
 
@@ -441,7 +441,7 @@ void IRCanonicalizer::reorderInstructions(
 void IRCanonicalizer::reorderInstruction(
     Instruction *Used, Instruction *User,
     SmallPtrSet<const Instruction *, 32> &Visited) {
-  if(isa<PHINode>(Used))
+  if (isa<PHINode>(Used))
     return;
   if (Visited.contains(Used))
     return;

>From ffea116251a639d4ebdd81922d39970f94780057 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 4 Oct 2023 08:12:40 -0700
Subject: [PATCH 16/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRCanonicalizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
index 7ea3959e5e90d0..c12595ba48a3f7 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
@@ -14,6 +14,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -28,7 +29,6 @@
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Utils.h"
-#include "llvm/Transforms/Utils/IRCanonicalizer.h"
 #include <algorithm>
 #include <vector>
 

>From 0dade127fe7d09e21d226293e639d0c39ddd0f37 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 14 Oct 2023 18:04:58 -0400
Subject: [PATCH 17/70] Rename to IRNormalizer

---
 llvm/docs/Passes.rst                          |  2 +-
 llvm/docs/ReleaseNotes.md                     |  2 +-
 .../llvm/Transforms/Utils/IRCanonicalizer.h   | 15 -----
 .../llvm/Transforms/Utils/IRNormalizer.h      | 15 +++++
 llvm/lib/Passes/PassBuilder.cpp               |  2 +-
 llvm/lib/Passes/PassRegistry.def              | 12 +++-
 llvm/lib/Transforms/Utils/CMakeLists.txt      |  2 +-
 .../{IRCanonicalizer.cpp => IRNormalizer.cpp} | 60 +++++++++----------
 .../infinite-loop.ll                          |  4 +-
 .../naming-args-instr-blocks.ll               |  2 +-
 .../naming-arguments.ll                       |  2 +-
 .../naming-basic-blocks.ll                    |  2 +-
 .../naming-instructions.ll                    |  2 +-
 .../reordering-instructions.ll                |  2 +-
 .../reordering-phi-node-values.ll             |  2 +-
 15 files changed, 67 insertions(+), 59 deletions(-)
 delete mode 100644 llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h
 create mode 100644 llvm/include/llvm/Transforms/Utils/IRNormalizer.h
 rename llvm/lib/Transforms/Utils/{IRCanonicalizer.cpp => IRNormalizer.cpp} (92%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/infinite-loop.ll (96%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/naming-args-instr-blocks.ll (75%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/naming-arguments.ll (66%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/naming-basic-blocks.ll (60%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/naming-instructions.ll (80%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/reordering-instructions.ll (83%)
 rename llvm/test/Transforms/{IRCanonicalizer => IRNormalizer}/reordering-phi-node-values.ll (91%)

diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
index aabd0f98a4c457..ef8fe643fb7e9d 100644
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -543,7 +543,7 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 <passes-sccp>`.
 
-``-ir-canonicalizer``: Transforms IR into canonical form
+``ir-normalizer``: Transforms IR into a canonical form that's easier to diff
 --------------------------------------------------------
 
 This pass aims to transform LLVM Modules into a canonical form by reordering and
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 3bd0843267fd80..131e7871e9c274 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -42,7 +42,7 @@ 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 IRCanonicalizer pass which aims to transform LLVM modules into
+* Added a new IRNormalizer pass which aims to transform LLVM modules into
   a canonical form by reordering and renaming instructions while preserving the
   same semantics. The canonicalizer makes it easier to spot semantic differences
   when diffing two modules which have undergone different passes.
diff --git a/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h b/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h
deleted file mode 100644
index 81bfd1bcfd2ad9..00000000000000
--- a/llvm/include/llvm/Transforms/Utils/IRCanonicalizer.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
-#define LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
-
-#include "llvm/IR/PassManager.h"
-
-namespace llvm {
-
-/// IRCanonicalizer aims to transform LLVM IR into canonical form.
-struct IRCanonicalizerPass : public PassInfoMixin<IRCanonicalizerPass> {
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
-};
-
-} // namespace llvm
-
-#endif // LLVM_TRANSFORMS_UTILS_IRCANONICALIZER_H
diff --git a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
new file mode 100644
index 00000000000000..2e3e23340bc5bc
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
@@ -0,0 +1,15 @@
+#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 canonical form.
+struct IRNormalizerPass : public PassInfoMixin<IRNormalizerPass> {
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_IRNORMALIZER_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 5be5659d25efd8..041638b5271662 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -306,7 +306,7 @@
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/FixIrreducible.h"
 #include "llvm/Transforms/Utils/HelloWorld.h"
-#include "llvm/Transforms/Utils/IRCanonicalizer.h"
+#include "llvm/Transforms/Utils/IRNormalizer.h"
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
 #include "llvm/Transforms/Utils/InstructionNamer.h"
 #include "llvm/Transforms/Utils/LCSSA.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index de39af190947a1..aa7e99c7fe1225 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -340,7 +340,6 @@ FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
-FUNCTION_PASS("canon", IRCanonicalizerPass())
 FUNCTION_PASS("consthoist", ConstantHoistingPass())
 FUNCTION_PASS("count-visits", CountVisitsPass())
 FUNCTION_PASS("constraint-elimination", ConstraintEliminationPass())
@@ -418,7 +417,16 @@ FUNCTION_PASS("mergereturn", UnifyFunctionExitNodesPass())
 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("jump-threading", JumpThreadingPass())
+FUNCTION_PASS("partially-inline-libcalls", PartiallyInlineLibCallsPass())
+FUNCTION_PASS("kcfi", KCFIPass())
+FUNCTION_PASS("lcssa", LCSSAPass())
+FUNCTION_PASS("loop-data-prefetch", LoopDataPrefetchPass())
+FUNCTION_PASS("loop-load-elim", LoopLoadEliminationPass())
+FUNCTION_PASS("loop-fusion", LoopFusePass())
+FUNCTION_PASS("loop-distribute", LoopDistributePass())
+FUNCTION_PASS("loop-versioning", LoopVersioningPass())
 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 968bfb81875351..65bd3080662c4d 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -37,7 +37,7 @@ add_llvm_component_library(LLVMTransformUtils
   InstructionNamer.cpp
   Instrumentation.cpp
   IntegerDivision.cpp
-  IRCanonicalizer.cpp
+  IRNormalizer.cpp
   LCSSA.cpp
   LibCallsShrinkWrap.cpp
   Local.cpp
diff --git a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
similarity index 92%
rename from llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
rename to llvm/lib/Transforms/Utils/IRNormalizer.cpp
index c12595ba48a3f7..da2cbc41346d01 100644
--- a/llvm/lib/Transforms/Utils/IRCanonicalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -1,4 +1,4 @@
-//===--------------- IRCanonicalizer.cpp - IR Canonicalizer ---------------===//
+//===--------------- IRNormalizer.cpp - IR Canonicalizer ---------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 /// \file
-/// This file implements the IRCanonicalizer class which aims to transform LLVM
+/// This file implements the IRNormalizer class which aims to transform LLVM
 /// Modules into a canonical form by reordering and renaming instructions while
-/// preserving the same semantics. The canonicalizer makes it easier to spot
+/// 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/IRCanonicalizer.h"
+#include "llvm/Transforms/Utils/IRNormalizer.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
@@ -32,13 +32,13 @@
 #include <algorithm>
 #include <vector>
 
-#define DEBUG_TYPE "canon"
+#define DEBUG_TYPE "normalize"
 
 using namespace llvm;
 
 namespace {
-/// IRCanonicalizer aims to transform LLVM IR into canonical form.
-class IRCanonicalizer {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
 public:
   /// \name Canonicalizer flags.
   /// @{
@@ -91,23 +91,23 @@ class IRCanonicalizer {
 };
 } // namespace
 
-cl::opt<bool> IRCanonicalizer::PreserveOrder(
+cl::opt<bool> IRNormalizer::PreserveOrder(
     "preserve-order", cl::Hidden,
     cl::desc("Preserves original instruction order"));
-cl::opt<bool> IRCanonicalizer::RenameAll(
+cl::opt<bool> IRNormalizer::RenameAll(
     "rename-all", cl::Hidden,
     cl::desc("Renames all instructions (including user-named)"));
-cl::opt<bool> IRCanonicalizer::FoldPreoutputs(
+cl::opt<bool> IRNormalizer::FoldPreoutputs(
     "fold-all", cl::Hidden,
     cl::desc("Folds all regular instructions (including pre-outputs)"));
-cl::opt<bool> IRCanonicalizer::ReorderOperands(
+cl::opt<bool> IRNormalizer::ReorderOperands(
     "reorder-operands", cl::Hidden,
     cl::desc("Sorts and reorders operands in commutative instructions"));
 
-/// Entry method to the IRCanonicalizer.
+/// Entry method to the IRNormalizer.
 ///
 /// \param M Module to canonicalize.
-bool IRCanonicalizer::runOnFunction(Function &F) {
+bool IRNormalizer::runOnFunction(Function &F) {
   nameFunctionArguments(F);
   nameBasicBlocks(F);
 
@@ -137,7 +137,7 @@ bool IRCanonicalizer::runOnFunction(Function &F) {
 /// Numbers arguments.
 ///
 /// \param F Function whose arguments will be renamed.
-void IRCanonicalizer::nameFunctionArguments(Function &F) {
+void IRNormalizer::nameFunctionArguments(Function &F) {
   int ArgumentCounter = 0;
   for (auto &A : F.args()) {
     if (RenameAll || A.getName().empty()) {
@@ -151,7 +151,7 @@ void IRCanonicalizer::nameFunctionArguments(Function &F) {
 /// a function considering the opcode and the order of output instructions.
 ///
 /// \param F Function containing basic blocks to rename.
-void IRCanonicalizer::nameBasicBlocks(Function &F) {
+void IRNormalizer::nameBasicBlocks(Function &F) {
   for (auto &B : F) {
     // Initialize to a magic constant, so the state isn't zero.
     uint64_t Hash = MagicHashConstant;
@@ -173,7 +173,7 @@ void IRCanonicalizer::nameBasicBlocks(Function &F) {
 /// the output (top-most user) instructions (depth-first).
 ///
 /// \param I Instruction to be renamed.
-void IRCanonicalizer::nameInstruction(Instruction *I) {
+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)
@@ -203,7 +203,7 @@ void IRCanonicalizer::nameInstruction(Instruction *I) {
 ///
 /// \see getOutputFootprint()
 /// \param I Instruction to be renamed.
-void IRCanonicalizer::nameAsInitialInstruction(Instruction *I) {
+void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
   if (I->getType()->isVoidTy() || (!I->getName().empty() && !RenameAll))
     return;
 
@@ -279,7 +279,7 @@ void IRCanonicalizer::nameAsInitialInstruction(Instruction *I) {
 ///
 /// \see getOutputFootprint()
 /// \param I Instruction to be renamed.
-void IRCanonicalizer::nameAsRegularInstruction(Instruction *I) {
+void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
   // Instruction operands for further sorting.
   SmallVector<SmallString<128>, 4> Operands;
 
@@ -362,7 +362,7 @@ void IRCanonicalizer::nameAsRegularInstruction(Instruction *I) {
 /// does not affect user named instructions.
 ///
 /// \param I Instruction whose name will be folded.
-void IRCanonicalizer::foldInstructionName(Instruction *I) {
+void IRNormalizer::foldInstructionName(Instruction *I) {
   // If this flag is raised, fold all regular
   // instructions (including pre-outputs).
   if (!FoldPreoutputs) {
@@ -416,7 +416,7 @@ void IRCanonicalizer::foldInstructionName(Instruction *I) {
 ///
 /// \see reorderInstruction()
 /// \param Outputs Vector of pointers to output instructions collected top-down.
-void IRCanonicalizer::reorderInstructions(
+void IRNormalizer::reorderInstructions(
     SmallVector<Instruction *, 16> &Outputs) {
   // This method assumes output instructions were collected top-down,
   // otherwise the def-use chain may be broken.
@@ -438,7 +438,7 @@ void IRCanonicalizer::reorderInstructions(
 /// \param Used Pointer to the instruction whose value is used by the \p User.
 /// \param User Pointer to the instruction which uses the \p Used.
 /// \param Visited Set of visited instructions.
-void IRCanonicalizer::reorderInstruction(
+void IRNormalizer::reorderInstruction(
     Instruction *Used, Instruction *User,
     SmallPtrSet<const Instruction *, 32> &Visited) {
   if (isa<PHINode>(Used))
@@ -468,7 +468,7 @@ void IRCanonicalizer::reorderInstruction(
 /// in other instructions may change the semantics.
 ///
 /// \param I Instruction whose operands will be reordered.
-void IRCanonicalizer::reorderInstructionOperandsByNames(Instruction *I) {
+void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) {
   // This method assumes that passed I is commutative,
   // changing the order of operands in other instructions
   // may change the semantics.
@@ -507,7 +507,7 @@ void IRCanonicalizer::reorderInstructionOperandsByNames(Instruction *I) {
 /// blocks.
 ///
 /// \param PN PHI node to canonicalize.
-void IRCanonicalizer::reorderPHIIncomingValues(PHINode *PN) {
+void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) {
   // Values for further sorting.
   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
 
@@ -536,7 +536,7 @@ void IRCanonicalizer::reorderPHIIncomingValues(PHINode *PN) {
 /// \see isOutput()
 /// \param F Function to collect outputs from.
 SmallVector<Instruction *, 16>
-IRCanonicalizer::collectOutputInstructions(Function &F) {
+IRNormalizer::collectOutputInstructions(Function &F) {
   // Output instructions are collected top-down in each function,
   // any change may break the def-use chain in reordering methods.
   SmallVector<Instruction *, 16> Outputs;
@@ -552,7 +552,7 @@ IRCanonicalizer::collectOutputInstructions(Function &F) {
 /// ReturnInst.
 ///
 /// \param I Considered instruction.
-bool IRCanonicalizer::isOutput(const Instruction *I) {
+bool IRNormalizer::isOutput(const Instruction *I) {
   // Outputs are such instructions which may have side effects or is ReturnInst.
   if (I->mayHaveSideEffects() || isa<ReturnInst>(I))
     return true;
@@ -564,7 +564,7 @@ bool IRCanonicalizer::isOutput(const Instruction *I) {
 /// immediate operands.
 ///
 /// \param I Considered instruction.
-bool IRCanonicalizer::isInitialInstruction(const Instruction *I) {
+bool IRNormalizer::isInitialInstruction(const Instruction *I) {
   // Initial instructions are such instructions whose values are used by
   // other instructions, yet they only depend on immediate values.
   return !I->user_empty() && hasOnlyImmediateOperands(I);
@@ -573,7 +573,7 @@ bool IRCanonicalizer::isInitialInstruction(const Instruction *I) {
 /// Helper method checking whether the instruction has only immediate operands.
 ///
 /// \param I Considered instruction.
-bool IRCanonicalizer::hasOnlyImmediateOperands(const Instruction *I) {
+bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) {
   for (const auto &OP : I->operands())
     if (isa<Instruction>(OP))
       return false; // Found non-immediate operand (instruction).
@@ -587,7 +587,7 @@ bool IRCanonicalizer::hasOnlyImmediateOperands(const Instruction *I) {
 ///
 /// \param I Considered instruction.
 /// \param Visited Set of visited instructions.
-SetVector<int> IRCanonicalizer::getOutputFootprint(
+SetVector<int> IRNormalizer::getOutputFootprint(
     Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) {
 
   // Vector containing indexes of outputs (no repetitions),
@@ -630,9 +630,9 @@ SetVector<int> IRCanonicalizer::getOutputFootprint(
   return Outputs;
 }
 
-PreservedAnalyses IRCanonicalizerPass::run(Function &F,
+PreservedAnalyses IRNormalizerPass::run(Function &F,
                                            FunctionAnalysisManager &AM) {
   errs() << F.getName() << "\n";
-  IRCanonicalizer{}.runOnFunction(F);
+  IRNormalizer{}.runOnFunction(F);
   return PreservedAnalyses::all();
 }
diff --git a/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll b/llvm/test/Transforms/IRNormalizer/infinite-loop.ll
similarity index 96%
rename from llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
rename to llvm/test/Transforms/IRNormalizer/infinite-loop.ll
index 3438a05b4aee48..9b10e91e49b4de 100644
--- a/llvm/test/Transforms/IRCanonicalizer/infinite-loop.ll
+++ b/llvm/test/Transforms/IRNormalizer/infinite-loop.ll
@@ -1,5 +1,5 @@
-; RUN: opt -passes=canon -preserve-order=true < %s
-; RUN: opt -passes=canon -preserve-order=false < %s
+; RUN: opt -passes=normalize -preserve-order=true < %s
+; RUN: opt -passes=normalize -preserve-order=false < %s
 
 define void @test(ptr, i32) {
 bb:
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
similarity index 75%
rename from llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
rename to llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
index 605c62863f2ad3..afb99585db2ccf 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-args-instr-blocks.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all --preserve-order < %s | FileCheck %s
+; RUN: opt -S -passes=normalize --rename-all --preserve-order < %s | FileCheck %s
 
 
 ; CHECK: @foo(i32 %a0)
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll b/llvm/test/Transforms/IRNormalizer/naming-arguments.ll
similarity index 66%
rename from llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
rename to llvm/test/Transforms/IRNormalizer/naming-arguments.ll
index b3f7630abd042f..3a1d435f76fdd0 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-arguments.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-arguments.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 ; CHECK: @foo(i32 %a0, i32 %a1)
 define i32 @foo(i32, i32) {
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
similarity index 60%
rename from llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll
rename to llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
index 79e526f8efb7ac..f50c56bcca53f3 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-basic-blocks.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all < %s | FileCheck %s
+; RUN: opt -S -passes=normalize --rename-all < %s | FileCheck %s
 
 define i32 @foo(i32 %a0) {
 ; CHECK: bb{{([0-9]{5})}}
diff --git a/llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll b/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
similarity index 80%
rename from llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll
rename to llvm/test/Transforms/IRNormalizer/naming-instructions.ll
index a22e816f5bf01e..f1fe503f53ca1d 100644
--- a/llvm/test/Transforms/IRCanonicalizer/naming-instructions.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon --rename-all < %s | FileCheck %s
+; RUN: opt -S -passes=normalize --rename-all < %s | FileCheck %s
 
 define i32 @foo(i32 %a0) {
 entry:
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll b/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
similarity index 83%
rename from llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
rename to llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
index 04660ac73c11bd..8978b01c3caa6d 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-instructions.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 define double @foo(double %a0, double %a1) {
 entry:
diff --git a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll b/llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll
similarity index 91%
rename from llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
rename to llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll
index 5f344ec29be66f..cba92e8eaf9ac5 100644
--- a/llvm/test/Transforms/IRCanonicalizer/reordering-phi-node-values.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=canon < %s | FileCheck %s
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 declare double @foo()
 

>From 50b8686645ce53c0850dc8ffc9c5cafbf993c74e Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 14 Oct 2023 18:07:59 -0400
Subject: [PATCH 18/70] Removing debugging line

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index da2cbc41346d01..a3bf5d1b940913 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -632,7 +632,6 @@ SetVector<int> IRNormalizer::getOutputFootprint(
 
 PreservedAnalyses IRNormalizerPass::run(Function &F,
                                            FunctionAnalysisManager &AM) {
-  errs() << F.getName() << "\n";
   IRNormalizer{}.runOnFunction(F);
   return PreservedAnalyses::all();
 }

>From 5f5473e1a8c1f4b2e0eef73425b70aeffadd2d2d Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 15 Oct 2023 23:13:32 -0400
Subject: [PATCH 19/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index a3bf5d1b940913..dd6ad517ddd763 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -631,7 +631,7 @@ SetVector<int> IRNormalizer::getOutputFootprint(
 }
 
 PreservedAnalyses IRNormalizerPass::run(Function &F,
-                                           FunctionAnalysisManager &AM) {
+                                        FunctionAnalysisManager &AM) {
   IRNormalizer{}.runOnFunction(F);
   return PreservedAnalyses::all();
 }

>From 8fcac36c583795b36b9c486ac75fb4d89b16f9d1 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 21 Oct 2023 14:04:05 -0700
Subject: [PATCH 20/70] Incorporate fixes

---
 llvm/docs/Passes.rst                       | 12 ++++++------
 llvm/docs/ReleaseNotes.md                  |  2 +-
 llvm/lib/Transforms/Utils/IRNormalizer.cpp |  6 +++---
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
index ef8fe643fb7e9d..abf015e829a28e 100644
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -544,15 +544,15 @@ An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 <passes-sccp>`.
 
 ``ir-normalizer``: Transforms IR into a canonical form that's easier to diff
---------------------------------------------------------
+----------------------------------------------------------------------------
 
 This pass aims to transform LLVM Modules into a canonical form by reordering and
-renaming instructions while preserving the same semantics. The canonicalizer makes
-it easier to spot semantic differences while diffing two modules which have undergone
-two different passes.
+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
------------------------------------
+``jump-threading``: Jump Threading
+----------------------------------
 
 Jump threading tries to find distinct threads of control flow running through a
 basic block.  This pass looks at blocks that have multiple predecessors and
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 131e7871e9c274..38f5a4085a15ab 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -44,7 +44,7 @@ for adding a new subsection. -->
 
 * Added a new IRNormalizer pass which aims to transform LLVM modules into
   a canonical form by reordering and renaming instructions while preserving the
-  same semantics. The canonicalizer makes it easier to spot semantic differences
+  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/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index dd6ad517ddd763..539a5388799717 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -1,4 +1,4 @@
-//===--------------- IRNormalizer.cpp - IR Canonicalizer ---------------===//
+//===--------------- 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.
@@ -40,7 +40,7 @@ namespace {
 /// IRNormalizer aims to transform LLVM IR into canonical form.
 class IRNormalizer {
 public:
-  /// \name Canonicalizer flags.
+  /// \name Normalizer flags.
   /// @{
   /// Preserves original order of instructions.
   static cl::opt<bool> PreserveOrder;
@@ -106,7 +106,7 @@ cl::opt<bool> IRNormalizer::ReorderOperands(
 
 /// Entry method to the IRNormalizer.
 ///
-/// \param M Module to canonicalize.
+/// \param M Module to normalize.
 bool IRNormalizer::runOnFunction(Function &F) {
   nameFunctionArguments(F);
   nameBasicBlocks(F);

>From 1f47284476f9b8eacd9eeae76b694ea0b625416d Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 12:16:44 -0800
Subject: [PATCH 21/70] Add LLVM_DEBUG() for reordering code

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 539a5388799717..378db63e0bb77e 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -424,10 +424,12 @@ void IRNormalizer::reorderInstructions(
   SmallPtrSet<const Instruction *, 32> Visited;
 
   // Walk up the tree.
-  for (auto &I : Outputs)
+  for (auto &I : Outputs) {
+    LLVM_DEBUG(dbgs() << "Reordering operands of: "; I->dump());
     for (auto &OP : I->operands())
       if (auto *IOP = dyn_cast<Instruction>(OP))
         reorderInstruction(IOP, I, Visited);
+  }
 }
 
 /// Reduces def-use distance or places instruction at the end of the basic
@@ -449,9 +451,12 @@ void IRNormalizer::reorderInstruction(
 
   if (Used->getParent() == User->getParent()) {
     // If Used and User share the same basic block move Used just before User.
+    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " before " << *User << "\n");
     Used->moveBefore(User);
   } else {
     // Otherwise move Used to the very end of its basic block.
+    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block " << 
+               Used->getParent()->getName() << "\n");
     Used->moveBefore(&Used->getParent()->back());
   }
 

>From f8764cf69a8889999286be466339c3e9e8cbc550 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 12:17:32 -0800
Subject: [PATCH 22/70] Accepts F not M

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 378db63e0bb77e..01f6c923dbfcfc 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -106,7 +106,7 @@ cl::opt<bool> IRNormalizer::ReorderOperands(
 
 /// Entry method to the IRNormalizer.
 ///
-/// \param M Module to normalize.
+/// \param F Function to normalize.
 bool IRNormalizer::runOnFunction(Function &F) {
   nameFunctionArguments(F);
   nameBasicBlocks(F);

>From 3ac9b7658e9f437b26ded8a054b65d4edf3b9bab Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 12:20:11 -0800
Subject: [PATCH 23/70] Fix nits

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 01f6c923dbfcfc..6b615ad729e751 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -180,9 +180,7 @@ void IRNormalizer::nameInstruction(Instruction *I) {
   if (NamedInstructions.contains(I))
     return;
   NamedInstructions.insert(I);
-  // Determine the type of instruction to name.
   if (isInitialInstruction(I)) {
-    // This is an initial instruction.
     nameAsInitialInstruction(I);
   } else {
     // This must be a regular instruction.
@@ -245,9 +243,8 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
   if (const auto *CI = dyn_cast<CallInst>(I)) {
     Function *F = CI->getCalledFunction();
 
-    if (F != nullptr) {
+    if (F != nullptr)
       Name.append(F->getName());
-    }
   }
 
   Name.append("(");
@@ -294,7 +291,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
       // Walk down the use-def chain.
       nameInstruction(IOP);
       Operands.push_back(IOP->getName());
-    } else if (isa<Value>(OP) && !isa<Function>(OP)) {
+    } else if (!isa<Function>(OP)) {
       // This must be an immediate value.
       std::string TextRepresentation;
       raw_string_ostream Stream(TextRepresentation);

>From 9b7d155a85d4c6395c3e802406c00d4cf539af6f Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 12:28:46 -0800
Subject: [PATCH 24/70] Spelling fix

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 6b615ad729e751..956f0ff8799f3f 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -47,7 +47,7 @@ class IRNormalizer {
   /// Renames all instructions (including user-named).
   static cl::opt<bool> RenameAll;
   /// Folds all regular instructions (including pre-outputs).
-  static cl::opt<bool> FoldPreoutputs;
+  static cl::opt<bool> FoldPreOutputs;
   /// Sorts and reorders operands in commutative instructions.
   static cl::opt<bool> ReorderOperands;
   /// @}
@@ -97,7 +97,7 @@ cl::opt<bool> IRNormalizer::PreserveOrder(
 cl::opt<bool> IRNormalizer::RenameAll(
     "rename-all", cl::Hidden,
     cl::desc("Renames all instructions (including user-named)"));
-cl::opt<bool> IRNormalizer::FoldPreoutputs(
+cl::opt<bool> IRNormalizer::FoldPreOutputs(
     "fold-all", cl::Hidden,
     cl::desc("Folds all regular instructions (including pre-outputs)"));
 cl::opt<bool> IRNormalizer::ReorderOperands(
@@ -362,7 +362,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
 void IRNormalizer::foldInstructionName(Instruction *I) {
   // If this flag is raised, fold all regular
   // instructions (including pre-outputs).
-  if (!FoldPreoutputs) {
+  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))

>From 16194809fa8a467824094d56cd696aa32e6378d6 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 15:06:01 -0800
Subject: [PATCH 25/70] Only sort the first two commutative operands

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 32 ++++++++++++++++++----
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 956f0ff8799f3f..66013dcc206cd5 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -80,6 +80,10 @@ class IRNormalizer {
 
   /// \name Utility methods.
   /// @{
+  template<typename T>
+  void sortCommutativeOperands(T &Operands) const; 
+  template<typename T, typename Compare>
+  void sortCommutativeOperands(T &Operands, Compare Comp) const; 
   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F);
   bool isOutput(const Instruction *I);
   bool isInitialInstruction(const Instruction *I);
@@ -188,6 +192,24 @@ void IRNormalizer::nameInstruction(Instruction *I) {
   }
 }
 
+template<typename T>
+void IRNormalizer::sortCommutativeOperands(T &Operands) const {
+  if (Operands.size() < 2)
+    return;
+  auto CommutativeEnd = Operands.begin();
+  std::advance(CommutativeEnd, 2);
+  llvm::sort(Operands.begin(), CommutativeEnd);
+}
+
+template<typename T, typename Compare>
+void IRNormalizer::sortCommutativeOperands(T &Operands, Compare Comp) const {
+  if (Operands.size() < 2)
+    return;
+  auto CommutativeEnd = Operands.begin();
+  std::advance(CommutativeEnd, 2);
+  llvm::sort(Operands.begin(), CommutativeEnd, Comp);
+}
+
 /// Names instruction following the scheme:
 /// vl00000Callee(Operands)
 ///
@@ -219,7 +241,7 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
   }
 
   if (I->isCommutative())
-    llvm::sort(Operands);
+    sortCommutativeOperands(Operands);
 
   // Initialize to a magic constant, so the state isn't zero.
   uint64_t Hash = MagicHashConstant;
@@ -301,7 +323,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
   }
 
   if (I->isCommutative())
-    llvm::sort(Operands.begin(), Operands.end());
+    sortCommutativeOperands(Operands);
 
   // Initialize to a magic constant, so the state isn't zero.
   uint64_t Hash = MagicHashConstant;
@@ -318,7 +340,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
       OperandsOpcodes.push_back(IOP->getOpcode());
 
   if (I->isCommutative())
-    llvm::sort(OperandsOpcodes.begin(), OperandsOpcodes.end());
+    sortCommutativeOperands(OperandsOpcodes);
 
   // Consider operand opcodes in the hash.
   for (const int Code : OperandsOpcodes)
@@ -388,7 +410,7 @@ void IRNormalizer::foldInstructionName(Instruction *I) {
   }
 
   if (I->isCommutative())
-    llvm::sort(Operands.begin(), Operands.end());
+    sortCommutativeOperands(Operands);
 
   SmallString<256> Name;
   Name.append(I->getName().substr(0, 7));
@@ -495,7 +517,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) {
   }
 
   // Sort operands.
-  llvm::sort(Operands.begin(), Operands.end(), llvm::less_first());
+  sortCommutativeOperands(Operands, llvm::less_first());
 
   // Reorder operands.
   unsigned Position = 0;

>From a8b688b500282d8c66f54ee7b0e3414ce8e54073 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 15:19:11 -0800
Subject: [PATCH 26/70] Add LLVM_DEBUG for instruction renaming

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 66013dcc206cd5..7e609199482036 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -226,6 +226,7 @@ void IRNormalizer::sortCommutativeOperands(T &Operands, Compare Comp) const {
 void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
   if (I->getType()->isVoidTy() || (!I->getName().empty() && !RenameAll))
     return;
+  LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
 
   // Instruction operands for further sorting.
   SmallVector<SmallString<64>, 4> Operands;
@@ -299,6 +300,8 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
 /// \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;
 

>From 3937f151d88b6fe3ac24dcd574b1feda4de91e80 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 17:16:30 -0800
Subject: [PATCH 27/70] Canonical -> Normal

---
 llvm/docs/Passes.rst                              |  4 ++--
 llvm/docs/ReleaseNotes.md                         |  2 +-
 llvm/include/llvm/Transforms/Utils/IRNormalizer.h |  2 +-
 llvm/lib/Transforms/Utils/IRNormalizer.cpp        | 12 ++++++------
 4 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/docs/Passes.rst b/llvm/docs/Passes.rst
index abf015e829a28e..5e436db62be3a1 100644
--- a/llvm/docs/Passes.rst
+++ b/llvm/docs/Passes.rst
@@ -543,10 +543,10 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 <passes-sccp>`.
 
-``ir-normalizer``: Transforms IR into a canonical form that's easier to diff
+``ir-normalizer``: Transforms IR into a normal form that's easier to diff
 ----------------------------------------------------------------------------
 
-This pass aims to transform LLVM Modules into a canonical form by reordering and
+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.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 38f5a4085a15ab..322e1ecfd3a9c3 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -43,7 +43,7 @@ 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 canonical form by reordering and renaming instructions while preserving the
+  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.
 
diff --git a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
index 2e3e23340bc5bc..b5df02e6ac87cc 100644
--- a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
+++ b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
@@ -5,7 +5,7 @@
 
 namespace llvm {
 
-/// IRNormalizer aims to transform LLVM IR into canonical form.
+/// IRNormalizer aims to transform LLVM IR into normal form.
 struct IRNormalizerPass : public PassInfoMixin<IRNormalizerPass> {
   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
 };
diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 7e609199482036..42dad3d4eceb56 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 /// \file
 /// This file implements the IRNormalizer class which aims to transform LLVM
-/// Modules into a canonical form by reordering and renaming instructions while
+/// 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.
@@ -37,7 +37,7 @@
 using namespace llvm;
 
 namespace {
-/// IRNormalizer aims to transform LLVM IR into canonical form.
+/// IRNormalizer aims to transform LLVM IR into normal form.
 class IRNormalizer {
 public:
   /// \name Normalizer flags.
@@ -301,7 +301,7 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
 /// \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;
 
@@ -404,10 +404,10 @@ void IRNormalizer::foldInstructionName(Instruction *I) {
 
   for (auto &OP : I->operands()) {
     if (const auto *IOP = dyn_cast<Instruction>(OP)) {
-      bool HasCanonicalName = I->getName().substr(0, 2) == "op" ||
+      bool HasNormalName = I->getName().substr(0, 2) == "op" ||
                               I->getName().substr(0, 2) == "vl";
 
-      Operands.push_back(HasCanonicalName ? IOP->getName().substr(0, 7)
+      Operands.push_back(HasNormalName ? IOP->getName().substr(0, 7)
                                           : IOP->getName());
     }
   }
@@ -533,7 +533,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) {
 /// Reorders PHI node's values according to the names of corresponding basic
 /// blocks.
 ///
-/// \param PN PHI node to canonicalize.
+/// \param PN PHI node to normalize.
 void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) {
   // Values for further sorting.
   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;

>From 6a59b5f545c21c64d82f2919b2ca2c444d8ebefc Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 17:18:33 -0800
Subject: [PATCH 28/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 42dad3d4eceb56..a93f1e2c30b7b5 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -80,9 +80,8 @@ class IRNormalizer {
 
   /// \name Utility methods.
   /// @{
-  template<typename T>
-  void sortCommutativeOperands(T &Operands) const; 
-  template<typename T, typename Compare>
+  template <typename T> void sortCommutativeOperands(T &Operands) const; 
+  template <typename T, typename Compare>
   void sortCommutativeOperands(T &Operands, Compare Comp) const; 
   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F);
   bool isOutput(const Instruction *I);
@@ -192,7 +191,7 @@ void IRNormalizer::nameInstruction(Instruction *I) {
   }
 }
 
-template<typename T>
+template <typename T>
 void IRNormalizer::sortCommutativeOperands(T &Operands) const {
   if (Operands.size() < 2)
     return;
@@ -201,7 +200,7 @@ void IRNormalizer::sortCommutativeOperands(T &Operands) const {
   llvm::sort(Operands.begin(), CommutativeEnd);
 }
 
-template<typename T, typename Compare>
+template <typename T, typename Compare>
 void IRNormalizer::sortCommutativeOperands(T &Operands, Compare Comp) const {
   if (Operands.size() < 2)
     return;
@@ -477,8 +476,8 @@ void IRNormalizer::reorderInstruction(
     Used->moveBefore(User);
   } else {
     // Otherwise move Used to the very end of its basic block.
-    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block " << 
-               Used->getParent()->getName() << "\n");
+    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block " 
+                      << Used->getParent()->getName() << "\n");
     Used->moveBefore(&Used->getParent()->back());
   }
 

>From 484966a47dad97dcc347c071a73f1a8150040cc9 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 19:16:35 -0800
Subject: [PATCH 29/70] Prefix cli arguments with "norm"

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp                | 8 ++++----
 llvm/test/Transforms/IRNormalizer/infinite-loop.ll        | 4 ++--
 .../Transforms/IRNormalizer/naming-args-instr-blocks.ll   | 3 +--
 llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll  | 2 +-
 llvm/test/Transforms/IRNormalizer/naming-instructions.ll  | 2 +-
 5 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index a93f1e2c30b7b5..8d6ea64405495c 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -95,16 +95,16 @@ class IRNormalizer {
 } // namespace
 
 cl::opt<bool> IRNormalizer::PreserveOrder(
-    "preserve-order", cl::Hidden,
+    "norm-preserve-order", cl::Hidden,
     cl::desc("Preserves original instruction order"));
 cl::opt<bool> IRNormalizer::RenameAll(
-    "rename-all", cl::Hidden,
+    "norm-rename-all", cl::Hidden,
     cl::desc("Renames all instructions (including user-named)"));
 cl::opt<bool> IRNormalizer::FoldPreOutputs(
-    "fold-all", cl::Hidden,
+    "norm-fold-all", cl::Hidden,
     cl::desc("Folds all regular instructions (including pre-outputs)"));
 cl::opt<bool> IRNormalizer::ReorderOperands(
-    "reorder-operands", cl::Hidden,
+    "norm-reorder-operands", cl::Hidden,
     cl::desc("Sorts and reorders operands in commutative instructions"));
 
 /// Entry method to the IRNormalizer.
diff --git a/llvm/test/Transforms/IRNormalizer/infinite-loop.ll b/llvm/test/Transforms/IRNormalizer/infinite-loop.ll
index 9b10e91e49b4de..109858e97fd36a 100644
--- a/llvm/test/Transforms/IRNormalizer/infinite-loop.ll
+++ b/llvm/test/Transforms/IRNormalizer/infinite-loop.ll
@@ -1,5 +1,5 @@
-; RUN: opt -passes=normalize -preserve-order=true < %s
-; RUN: opt -passes=normalize -preserve-order=false < %s
+; RUN: opt -passes=normalize -norm-preserve-order=true < %s
+; RUN: opt -passes=normalize -norm-preserve-order=false < %s
 
 define void @test(ptr, i32) {
 bb:
diff --git a/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
index afb99585db2ccf..104ffc8dd6e39f 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
@@ -1,5 +1,4 @@
-; RUN: opt -S -passes=normalize --rename-all --preserve-order < %s | FileCheck %s
-
+; RUN: opt -S -passes=normalize -norm-rename-all -norm-preserve-order < %s | FileCheck %s
 
 ; CHECK: @foo(i32 %a0)
 define i32 @foo(i32) {
diff --git a/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
index f50c56bcca53f3..9493b3f70ef763 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=normalize --rename-all < %s | FileCheck %s
+; RUN: opt -S -passes=normalize -norm-rename-all < %s | FileCheck %s
 
 define i32 @foo(i32 %a0) {
 ; CHECK: bb{{([0-9]{5})}}
diff --git a/llvm/test/Transforms/IRNormalizer/naming-instructions.ll b/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
index f1fe503f53ca1d..c08ef18f948c83 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -passes=normalize --rename-all < %s | FileCheck %s
+; RUN: opt -S -passes=normalize -norm-rename-all < %s | FileCheck %s
 
 define i32 @foo(i32 %a0) {
 entry:

>From 3a945ef00a423c238aa07b62863e40d85b8dd7a7 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Fri, 10 Nov 2023 19:18:16 -0800
Subject: [PATCH 30/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 8d6ea64405495c..7fed01e540d94c 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -80,9 +80,9 @@ class IRNormalizer {
 
   /// \name Utility methods.
   /// @{
-  template <typename T> void sortCommutativeOperands(T &Operands) const; 
+  template <typename T> void sortCommutativeOperands(T &Operands) const;
   template <typename T, typename Compare>
-  void sortCommutativeOperands(T &Operands, Compare Comp) const; 
+  void sortCommutativeOperands(T &Operands, Compare Comp) const;
   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F);
   bool isOutput(const Instruction *I);
   bool isInitialInstruction(const Instruction *I);
@@ -407,7 +407,7 @@ void IRNormalizer::foldInstructionName(Instruction *I) {
                               I->getName().substr(0, 2) == "vl";
 
       Operands.push_back(HasNormalName ? IOP->getName().substr(0, 7)
-                                          : IOP->getName());
+                                       : IOP->getName());
     }
   }
 
@@ -476,7 +476,7 @@ void IRNormalizer::reorderInstruction(
     Used->moveBefore(User);
   } else {
     // Otherwise move Used to the very end of its basic block.
-    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block " 
+    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block "
                       << Used->getParent()->getName() << "\n");
     Used->moveBefore(&Used->getParent()->back());
   }

>From a762631dada20c2454752fd1720852f95a4c6057 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 11 Nov 2023 13:37:20 -0800
Subject: [PATCH 31/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 7fed01e540d94c..61193c4b794842 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -404,7 +404,7 @@ void IRNormalizer::foldInstructionName(Instruction *I) {
   for (auto &OP : I->operands()) {
     if (const auto *IOP = dyn_cast<Instruction>(OP)) {
       bool HasNormalName = I->getName().substr(0, 2) == "op" ||
-                              I->getName().substr(0, 2) == "vl";
+                           I->getName().substr(0, 2) == "vl";
 
       Operands.push_back(HasNormalName ? IOP->getName().substr(0, 7)
                                        : IOP->getName());

>From d1b4e9b5e08fe67fa353dcc0e5bab79e49db6b5a Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sat, 11 Nov 2023 17:32:07 -0800
Subject: [PATCH 32/70] Use const + WIP

---
 .../llvm/Transforms/Utils/IRNormalizer.h      |  2 +-
 llvm/lib/Transforms/Utils/IRNormalizer.cpp    | 81 +++++++++----------
 2 files changed, 41 insertions(+), 42 deletions(-)

diff --git a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
index b5df02e6ac87cc..af1f715d4940d8 100644
--- a/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
+++ b/llvm/include/llvm/Transforms/Utils/IRNormalizer.h
@@ -7,7 +7,7 @@ namespace llvm {
 
 /// IRNormalizer aims to transform LLVM IR into normal form.
 struct IRNormalizerPass : public PassInfoMixin<IRNormalizerPass> {
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) const;
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 61193c4b794842..2ce155233df6bf 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -59,23 +59,26 @@ class IRNormalizer {
   const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
   DenseSet<const Instruction *> NamedInstructions;
 
+  SmallVector<Instruction *, 16> Outputs;
+
   /// \name Naming.
   /// @{
-  void nameFunctionArguments(Function &F);
-  void nameBasicBlocks(Function &F);
+  void nameFunctionArguments(Function &F) const;
+  void nameBasicBlocks(Function &F) const;
   void nameInstruction(Instruction *I);
-  void nameAsInitialInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I) const;
   void nameAsRegularInstruction(Instruction *I);
-  void foldInstructionName(Instruction *I);
+  void foldInstructionName(Instruction *I) const;
   /// @}
 
   /// \name Reordering.
   /// @{
-  void reorderInstructions(SmallVector<Instruction *, 16> &Outputs);
+  void reorderInstructions(Function &F) const;
+  void reorderInstructionsInBasicBlock(BasicBlock &BB) const;
   void reorderInstruction(Instruction *Used, Instruction *User,
-                          SmallPtrSet<const Instruction *, 32> &Visited);
-  void reorderInstructionOperandsByNames(Instruction *I);
-  void reorderPHIIncomingValues(PHINode *PN);
+                          SmallPtrSet<const Instruction *, 32> &Visited) const;
+  void reorderInstructionOperandsByNames(Instruction *I) const;
+  void reorderPHIIncomingValues(PHINode *PN) const;
   /// @}
 
   /// \name Utility methods.
@@ -83,13 +86,13 @@ class IRNormalizer {
   template <typename T> void sortCommutativeOperands(T &Operands) const;
   template <typename T, typename Compare>
   void sortCommutativeOperands(T &Operands, Compare Comp) const;
-  SmallVector<Instruction *, 16> collectOutputInstructions(Function &F);
-  bool isOutput(const Instruction *I);
-  bool isInitialInstruction(const Instruction *I);
-  bool hasOnlyImmediateOperands(const Instruction *I);
+  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);
+                     SmallPtrSet<const Instruction *, 32> &Visited) const;
   /// @}
 };
 } // namespace
@@ -114,10 +117,10 @@ bool IRNormalizer::runOnFunction(Function &F) {
   nameFunctionArguments(F);
   nameBasicBlocks(F);
 
-  SmallVector<Instruction *, 16> Outputs = collectOutputInstructions(F);
+  Outputs = collectOutputInstructions(F);
 
   if (!PreserveOrder)
-    reorderInstructions(Outputs);
+    reorderInstructions(F);
 
   for (auto &I : Outputs)
     nameInstruction(I);
@@ -140,7 +143,7 @@ bool IRNormalizer::runOnFunction(Function &F) {
 /// Numbers arguments.
 ///
 /// \param F Function whose arguments will be renamed.
-void IRNormalizer::nameFunctionArguments(Function &F) {
+void IRNormalizer::nameFunctionArguments(Function &F) const {
   int ArgumentCounter = 0;
   for (auto &A : F.args()) {
     if (RenameAll || A.getName().empty()) {
@@ -154,7 +157,7 @@ void IRNormalizer::nameFunctionArguments(Function &F) {
 /// a function considering the opcode and the order of output instructions.
 ///
 /// \param F Function containing basic blocks to rename.
-void IRNormalizer::nameBasicBlocks(Function &F) {
+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;
@@ -222,7 +225,7 @@ void IRNormalizer::sortCommutativeOperands(T &Operands, Compare Comp) const {
 ///
 /// \see getOutputFootprint()
 /// \param I Instruction to be renamed.
-void IRNormalizer::nameAsInitialInstruction(Instruction *I) {
+void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
   if (I->getType()->isVoidTy() || (!I->getName().empty() && !RenameAll))
     return;
   LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
@@ -383,7 +386,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
 /// does not affect user named instructions.
 ///
 /// \param I Instruction whose name will be folded.
-void IRNormalizer::foldInstructionName(Instruction *I) {
+void IRNormalizer::foldInstructionName(Instruction *I) const {
   // If this flag is raised, fold all regular
   // instructions (including pre-outputs).
   if (!FoldPreOutputs) {
@@ -436,21 +439,17 @@ void IRNormalizer::foldInstructionName(Instruction *I) {
 /// This method is a wrapper for recursive reorderInstruction().
 ///
 /// \see reorderInstruction()
-/// \param Outputs Vector of pointers to output instructions collected top-down.
-void IRNormalizer::reorderInstructions(
-    SmallVector<Instruction *, 16> &Outputs) {
-  // This method assumes output instructions were collected top-down,
-  // otherwise the def-use chain may be broken.
+void IRNormalizer::reorderInstructions(Function &F) const {
+  SmallPtrSet<const Instruction *, 32> UsedInFunction;
+  for (auto &BB : F) {
+    LLVM_DEBUG(dbgs() << "Reordering instructions of basic block: " 
+                      << BB.getName());
+    reorderInstructionsInBasicBlock(BB);
+  }
+}
 
-  SmallPtrSet<const Instruction *, 32> Visited;
+void IRNormalizer::reorderInstructionsInBasicBlock(BasicBlock &BB) const {
 
-  // Walk up the tree.
-  for (auto &I : Outputs) {
-    LLVM_DEBUG(dbgs() << "Reordering operands of: "; I->dump());
-    for (auto &OP : I->operands())
-      if (auto *IOP = dyn_cast<Instruction>(OP))
-        reorderInstruction(IOP, I, Visited);
-  }
 }
 
 /// Reduces def-use distance or places instruction at the end of the basic
@@ -463,7 +462,7 @@ void IRNormalizer::reorderInstructions(
 /// \param Visited Set of visited instructions.
 void IRNormalizer::reorderInstruction(
     Instruction *Used, Instruction *User,
-    SmallPtrSet<const Instruction *, 32> &Visited) {
+    SmallPtrSet<const Instruction *, 32> &Visited) const {
   if (isa<PHINode>(Used))
     return;
   if (Visited.contains(Used))
@@ -494,7 +493,7 @@ void IRNormalizer::reorderInstruction(
 /// in other instructions may change the semantics.
 ///
 /// \param I Instruction whose operands will be reordered.
-void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) {
+void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
   // This method assumes that passed I is commutative,
   // changing the order of operands in other instructions
   // may change the semantics.
@@ -533,7 +532,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) {
 /// blocks.
 ///
 /// \param PN PHI node to normalize.
-void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) {
+void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) const {
   // Values for further sorting.
   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
 
@@ -562,7 +561,7 @@ void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) {
 /// \see isOutput()
 /// \param F Function to collect outputs from.
 SmallVector<Instruction *, 16>
-IRNormalizer::collectOutputInstructions(Function &F) {
+IRNormalizer::collectOutputInstructions(Function &F) const {
   // Output instructions are collected top-down in each function,
   // any change may break the def-use chain in reordering methods.
   SmallVector<Instruction *, 16> Outputs;
@@ -578,7 +577,7 @@ IRNormalizer::collectOutputInstructions(Function &F) {
 /// ReturnInst.
 ///
 /// \param I Considered instruction.
-bool IRNormalizer::isOutput(const Instruction *I) {
+bool IRNormalizer::isOutput(const Instruction *I) const {
   // Outputs are such instructions which may have side effects or is ReturnInst.
   if (I->mayHaveSideEffects() || isa<ReturnInst>(I))
     return true;
@@ -590,7 +589,7 @@ bool IRNormalizer::isOutput(const Instruction *I) {
 /// immediate operands.
 ///
 /// \param I Considered instruction.
-bool IRNormalizer::isInitialInstruction(const Instruction *I) {
+bool IRNormalizer::isInitialInstruction(const Instruction *I) const {
   // Initial instructions are such instructions whose values are used by
   // other instructions, yet they only depend on immediate values.
   return !I->user_empty() && hasOnlyImmediateOperands(I);
@@ -599,7 +598,7 @@ bool IRNormalizer::isInitialInstruction(const Instruction *I) {
 /// Helper method checking whether the instruction has only immediate operands.
 ///
 /// \param I Considered instruction.
-bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) {
+bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) const {
   for (const auto &OP : I->operands())
     if (isa<Instruction>(OP))
       return false; // Found non-immediate operand (instruction).
@@ -614,7 +613,7 @@ bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) {
 /// \param I Considered instruction.
 /// \param Visited Set of visited instructions.
 SetVector<int> IRNormalizer::getOutputFootprint(
-    Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) {
+    Instruction *I, SmallPtrSet<const Instruction *, 32> &Visited) const {
 
   // Vector containing indexes of outputs (no repetitions),
   // which use I in the order of walking down the def-use tree.
@@ -657,7 +656,7 @@ SetVector<int> IRNormalizer::getOutputFootprint(
 }
 
 PreservedAnalyses IRNormalizerPass::run(Function &F,
-                                        FunctionAnalysisManager &AM) {
+                                        FunctionAnalysisManager &AM) const {
   IRNormalizer{}.runOnFunction(F);
   return PreservedAnalyses::all();
 }

>From a6ee6ed2eec60c8e7c93c0497728f90f0678a879 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Tue, 14 Nov 2023 20:57:44 -0800
Subject: [PATCH 33/70] First draft of new reordering

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp    | 91 +++++++++++++++++--
 .../IRNormalizer/reordering-instructions.ll   |  4 +-
 2 files changed, 86 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 2ce155233df6bf..85230a8beb8fc2 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -30,7 +30,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Utils.h"
 #include <algorithm>
-#include <vector>
+#include <stack>
 
 #define DEBUG_TYPE "normalize"
 
@@ -74,7 +74,13 @@ class IRNormalizer {
   /// \name Reordering.
   /// @{
   void reorderInstructions(Function &F) const;
-  void reorderInstructionsInBasicBlock(BasicBlock &BB) const;
+  void reorderSourceInstruction(Instruction *I,
+      std::stack<Instruction *> &TopologicalSort, 
+      SmallPtrSet<const Instruction *, 32> &Visited) const;
+  void reorderDefinition(Instruction *Definition,
+      std::stack<Instruction *> &TopologicalSort,
+      SmallPtrSet<const Instruction *, 32> &Visited) const;
+  // TODO: Delete reorderInstruction
   void reorderInstruction(Instruction *Used, Instruction *User,
                           SmallPtrSet<const Instruction *, 32> &Visited) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
@@ -440,16 +446,87 @@ void IRNormalizer::foldInstructionName(Instruction *I) const {
 ///
 /// \see reorderInstruction()
 void IRNormalizer::reorderInstructions(Function &F) const {
-  SmallPtrSet<const Instruction *, 32> UsedInFunction;
   for (auto &BB : F) {
-    LLVM_DEBUG(dbgs() << "Reordering instructions of basic block: " 
-                      << BB.getName());
-    reorderInstructionsInBasicBlock(BB);
+    LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: " 
+                      << BB.getName() << "\n");
+    // Find the source nodes of the DAG of instructions in this basic block.
+    // 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) { 
+      if (!isOutput(&I) && !I.isTerminator()) 
+        continue; // I is not a source node. 
+      LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
+      reorderDefinition(&I, TopologicalSort, Visited);
+    }
+
+    for (auto &I : BB) { 
+      if (Visited.contains(&I)) 
+        continue; // I is not a source node. 
+      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 *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
+      // if (Instruction == FirstNonPHIOrDbgOrAlloca) {
+      //   // If the first instruction in the block is the instruction that we're
+      //   // currently trying to insert, then leave it at the top of the block
+      //   // and insert the next instruction above it. 
+      //   TopologicalSort.pop();
+      //   if (TopologicalSort.empty())
+      //     break;
+      //   auto *NextInstruction = TopologicalSort.top();
+      //   LLVM_DEBUG(dbgs() << "\tInserting "; NextInstruction->dump(); 
+      //              dbgs() << "\t\tbefore"; Instruction->dump());
+      //   NextInstruction->moveBefore(Instruction);
+      //   TopologicalSort.pop();
+      // } else {
+      //   LLVM_DEBUG(dbgs() << "\tInserting "; Instruction->dump(); 
+      //              dbgs() << "\t\tafter"; FirstNonPHIOrDbgOrAlloca->dump());
+      //   Instruction->moveAfter(FirstNonPHIOrDbgOrAlloca);
+      //   TopologicalSort.pop();
+      // }
+      Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
+        TopologicalSort.pop();
+    }
   }
 }
 
-void IRNormalizer::reorderInstructionsInBasicBlock(BasicBlock &BB) const {
+void IRNormalizer::reorderSourceInstruction(Instruction *I,
+    std::stack<Instruction *> &TopologicalSort,
+    SmallPtrSet<const Instruction *, 32> &Visited) const {
+  LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I->dump());
+}
+
+void IRNormalizer::reorderDefinition(Instruction *Definition,
+    std::stack<Instruction *> &TopologicalSort,
+    SmallPtrSet<const Instruction *, 32> &Visited) const {
+  if (Visited.contains(Definition))
+    return;
+  Visited.insert(Definition);
+
+  if (Definition->comesBefore(&*Definition->getParent()
+                                          ->getFirstNonPHIOrDbgOrAlloca()))
+    return; // TODO: Do some kind of ordering for these instructions. 
+
+  for (auto &Operand : Definition->operands()) {
+    if (auto *Op = dyn_cast<Instruction>(Operand)) {
+      if (Op->getParent() != Definition->getParent())
+        continue; // Only reorder instruction within the same basic block
+      reorderDefinition(Op, TopologicalSort, Visited);
+    }
+  }
 
+  LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
+  if (!Definition->isTerminator())
+    TopologicalSort.emplace(Definition);
 }
 
 /// Reduces def-use distance or places instruction at the end of the basic
diff --git a/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll b/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
index 8978b01c3caa6d..338fbbe974cce7 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
@@ -2,10 +2,10 @@
 
 define double @foo(double %a0, double %a1) {
 entry:
-; CHECK: %a
-; CHECK: %c
 ; CHECK: %b
 ; CHECK: %d
+; CHECK: %a
+; CHECK: %c
   %a = fmul double %a0, %a1
   %b = fmul double %a0, 2.000000e+00
   %c = fmul double %a, 6.000000e+00

>From 3aba164f6e6acb9928de7b42a8ca53506d5824ff Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 17:01:47 -0800
Subject: [PATCH 34/70] New reordering

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 88 +++++-----------------
 1 file changed, 18 insertions(+), 70 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 85230a8beb8fc2..8220217cc6fe44 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -74,15 +74,9 @@ class IRNormalizer {
   /// \name Reordering.
   /// @{
   void reorderInstructions(Function &F) const;
-  void reorderSourceInstruction(Instruction *I,
-      std::stack<Instruction *> &TopologicalSort, 
-      SmallPtrSet<const Instruction *, 32> &Visited) const;
   void reorderDefinition(Instruction *Definition,
       std::stack<Instruction *> &TopologicalSort,
       SmallPtrSet<const Instruction *, 32> &Visited) const;
-  // TODO: Delete reorderInstruction
-  void reorderInstruction(Instruction *Used, Instruction *User,
-                          SmallPtrSet<const Instruction *, 32> &Visited) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
   void reorderPHIIncomingValues(PHINode *PN) const;
   /// @}
@@ -458,7 +452,8 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     for (auto &I : BB) { 
       if (!isOutput(&I) && !I.isTerminator()) 
         continue; // I is not a source node. 
-      LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
+      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: "; 
+                 I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
@@ -475,36 +470,12 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     while (!TopologicalSort.empty()) {
       auto *Instruction = TopologicalSort.top();
       auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
-      // if (Instruction == FirstNonPHIOrDbgOrAlloca) {
-      //   // If the first instruction in the block is the instruction that we're
-      //   // currently trying to insert, then leave it at the top of the block
-      //   // and insert the next instruction above it. 
-      //   TopologicalSort.pop();
-      //   if (TopologicalSort.empty())
-      //     break;
-      //   auto *NextInstruction = TopologicalSort.top();
-      //   LLVM_DEBUG(dbgs() << "\tInserting "; NextInstruction->dump(); 
-      //              dbgs() << "\t\tbefore"; Instruction->dump());
-      //   NextInstruction->moveBefore(Instruction);
-      //   TopologicalSort.pop();
-      // } else {
-      //   LLVM_DEBUG(dbgs() << "\tInserting "; Instruction->dump(); 
-      //              dbgs() << "\t\tafter"; FirstNonPHIOrDbgOrAlloca->dump());
-      //   Instruction->moveAfter(FirstNonPHIOrDbgOrAlloca);
-      //   TopologicalSort.pop();
-      // }
       Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
         TopologicalSort.pop();
     }
   }
 }
 
-void IRNormalizer::reorderSourceInstruction(Instruction *I,
-    std::stack<Instruction *> &TopologicalSort,
-    SmallPtrSet<const Instruction *, 32> &Visited) const {
-  LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I->dump());
-}
-
 void IRNormalizer::reorderDefinition(Instruction *Definition,
     std::stack<Instruction *> &TopologicalSort,
     SmallPtrSet<const Instruction *, 32> &Visited) const {
@@ -512,9 +483,14 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     return;
   Visited.insert(Definition);
 
-  if (Definition->comesBefore(&*Definition->getParent()
-                                          ->getFirstNonPHIOrDbgOrAlloca()))
-    return; // TODO: Do some kind of ordering for these instructions. 
+  {
+    const auto *BasicBlock = Definition->getParent();
+    const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
+    if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
+      return;
+    if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
+      return; // TODO: Do some kind of ordering for these instructions. 
+  }
 
   for (auto &Operand : Definition->operands()) {
     if (auto *Op = dyn_cast<Instruction>(Operand)) {
@@ -525,44 +501,16 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
   }
 
   LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
-  if (!Definition->isTerminator())
-    TopologicalSort.emplace(Definition);
-}
-
-/// Reduces def-use distance or places instruction at the end of the basic
-/// block. Continues to walk up the def-use tree recursively. Used by
-/// reorderInstructions().
-///
-/// \see reorderInstructions()
-/// \param Used Pointer to the instruction whose value is used by the \p User.
-/// \param User Pointer to the instruction which uses the \p Used.
-/// \param Visited Set of visited instructions.
-void IRNormalizer::reorderInstruction(
-    Instruction *Used, Instruction *User,
-    SmallPtrSet<const Instruction *, 32> &Visited) const {
-  if (isa<PHINode>(Used))
-    return;
-  if (Visited.contains(Used))
+  if (Definition->isTerminator())
     return;
-  Visited.insert(Used);
-
-  if (Used->getParent() == User->getParent()) {
-    // If Used and User share the same basic block move Used just before User.
-    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " before " << *User << "\n");
-    Used->moveBefore(User);
-  } else {
-    // Otherwise move Used to the very end of its basic block.
-    LLVM_DEBUG(dbgs() << "\tMoved " << *Used << " to end of block "
-                      << Used->getParent()->getName() << "\n");
-    Used->moveBefore(&Used->getParent()->back());
-  }
-
-  for (auto &OP : Used->operands()) {
-    if (auto *IOP = dyn_cast<Instruction>(OP)) {
-      // Walk up the def-use tree.
-      reorderInstruction(IOP, Used, Visited);
-    }
+  if (auto *Call = dyn_cast<CallInst>(Definition)) {
+    if (Call->isMustTailCall())
+      return;
+    if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
+      return;
   }
+  // TODO: return on llvm.experimental.deopt...
+  TopologicalSort.emplace(Definition);
 }
 
 /// Reorders instruction's operands alphabetically. This method assumes

>From cf71b4a810987d653a2467f18bc7d5c4a26b1628 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 17:47:57 -0800
Subject: [PATCH 35/70] Change the output ordering

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 47 +++++++++++++++-------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 8220217cc6fe44..045ef08c77ffe0 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -77,6 +77,8 @@ class IRNormalizer {
   void reorderDefinition(Instruction *Definition,
       std::stack<Instruction *> &TopologicalSort,
       SmallPtrSet<const Instruction *, 32> &Visited) const;
+  void reorderBasedOnTopologicalSort(BasicBlock &BB, 
+      std::stack<Instruction *> &TopologicalSort) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
   void reorderPHIIncomingValues(PHINode *PN) const;
   /// @}
@@ -447,32 +449,35 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     // 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;
+    std::stack<Instruction *> TopologicalSort;
     for (auto &I : BB) { 
       if (!isOutput(&I) && !I.isTerminator()) 
-        continue; // I is not a source node. 
-      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: "; 
+        continue; // I is not side effecting. 
+      LLVM_DEBUG(dbgs() << "\tReordering from effecting source instruction: "; 
                  I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
+    std::stack<Instruction *> UsedOutsideOfBBTopologicalSort;
+    for (auto &I : BB) { 
+      if (Visited.contains(&I) || !I.isUsedOutsideOfBlock(I.getParent())) 
+        continue;
+      LLVM_DEBUG(dbgs() << "\tReordering from source instruction that's used in another block: "; I.dump());
+      reorderDefinition(&I, UsedOutsideOfBBTopologicalSort, Visited);
+    }
+
     for (auto &I : BB) { 
       if (Visited.contains(&I)) 
-        continue; // I is not a source node. 
-      LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
+        continue;
+      LLVM_DEBUG(dbgs() << "\tReordering from dead 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 *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
-      Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
-        TopologicalSort.pop();
-    }
+    reorderBasedOnTopologicalSort(BB, UsedOutsideOfBBTopologicalSort);
+    reorderBasedOnTopologicalSort(BB, TopologicalSort);
   }
 }
 
@@ -488,7 +493,7 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
       return;
-    if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
+    else if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
       return; // TODO: Do some kind of ordering for these instructions. 
   }
 
@@ -500,7 +505,7 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     }
   }
 
-  LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
+  // Don't reorder certain instructions. 
   if (Definition->isTerminator())
     return;
   if (auto *Call = dyn_cast<CallInst>(Definition)) {
@@ -509,10 +514,22 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
       return;
   }
-  // TODO: return on llvm.experimental.deopt...
+
+  LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
   TopologicalSort.emplace(Definition);
 }
 
+void IRNormalizer::reorderBasedOnTopologicalSort(BasicBlock &BB, 
+    std::stack<Instruction *> &TopologicalSort) const {
+  // Reorder based on the topological sort. 
+  while (!TopologicalSort.empty()) {
+    auto *Instruction = TopologicalSort.top();
+    auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
+    Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
+      TopologicalSort.pop();
+  }
+}
+
 /// Reorders instruction's operands alphabetically. This method assumes
 /// that passed instruction is commutative. Changing the operand order
 /// in other instructions may change the semantics.

>From 10575853969cf19a338c14139651e31086b17a03 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 17:51:33 -0800
Subject: [PATCH 36/70] Add comments

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 045ef08c77ffe0..f5371aafe321a8 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -474,6 +474,10 @@ void IRNormalizer::reorderInstructions(Function &F) const {
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
+    // Output order should be:
+    // 1 - Unused Instructions.
+    // 2 - Side effecting instructions .
+    // 3 - Instructions used outside of the basic block.
     LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName() 
                       << "\n");
     reorderBasedOnTopologicalSort(BB, UsedOutsideOfBBTopologicalSort);
@@ -489,12 +493,14 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
   Visited.insert(Definition);
 
   {
+    // TODO: Do some kind of ordering for instructions that come before the 
+    // result of getFirstNonPHIOrDbgOrAlloca().
     const auto *BasicBlock = Definition->getParent();
     const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
       return;
     else if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
-      return; // TODO: Do some kind of ordering for these instructions. 
+      return; 
   }
 
   for (auto &Operand : Definition->operands()) {

>From 5256745672f6985af3effcda6d59e30cdeab0c2c Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 18:21:56 -0800
Subject: [PATCH 37/70] Revert "Add comments"

This reverts commit dd8d2846a62b099127fcb5cb2ba4b231f317747a.
---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index f5371aafe321a8..045ef08c77ffe0 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -474,10 +474,6 @@ void IRNormalizer::reorderInstructions(Function &F) const {
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
-    // Output order should be:
-    // 1 - Unused Instructions.
-    // 2 - Side effecting instructions .
-    // 3 - Instructions used outside of the basic block.
     LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName() 
                       << "\n");
     reorderBasedOnTopologicalSort(BB, UsedOutsideOfBBTopologicalSort);
@@ -493,14 +489,12 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
   Visited.insert(Definition);
 
   {
-    // TODO: Do some kind of ordering for instructions that come before the 
-    // result of getFirstNonPHIOrDbgOrAlloca().
     const auto *BasicBlock = Definition->getParent();
     const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
       return;
     else if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
-      return; 
+      return; // TODO: Do some kind of ordering for these instructions. 
   }
 
   for (auto &Operand : Definition->operands()) {

>From 47989eca6775a2fa8ab4dd97fc4a7e6ebf8086ee Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 18:22:17 -0800
Subject: [PATCH 38/70] Revert "Change the output ordering"

This reverts commit b1d6ef875221c1a32481592c3c1d92abc2dd1126.
---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 47 +++++++---------------
 1 file changed, 15 insertions(+), 32 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 045ef08c77ffe0..8220217cc6fe44 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -77,8 +77,6 @@ class IRNormalizer {
   void reorderDefinition(Instruction *Definition,
       std::stack<Instruction *> &TopologicalSort,
       SmallPtrSet<const Instruction *, 32> &Visited) const;
-  void reorderBasedOnTopologicalSort(BasicBlock &BB, 
-      std::stack<Instruction *> &TopologicalSort) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
   void reorderPHIIncomingValues(PHINode *PN) const;
   /// @}
@@ -449,35 +447,32 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     // We must iterate from the first to the last instruction otherwise side 
     // effecting instructions could be reordered. 
 
-    SmallPtrSet<const Instruction *, 32> Visited;
     std::stack<Instruction *> TopologicalSort;
+    SmallPtrSet<const Instruction *, 32> Visited;
     for (auto &I : BB) { 
       if (!isOutput(&I) && !I.isTerminator()) 
-        continue; // I is not side effecting. 
-      LLVM_DEBUG(dbgs() << "\tReordering from effecting source instruction: "; 
+        continue; // I is not a source node. 
+      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: "; 
                  I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
-    std::stack<Instruction *> UsedOutsideOfBBTopologicalSort;
-    for (auto &I : BB) { 
-      if (Visited.contains(&I) || !I.isUsedOutsideOfBlock(I.getParent())) 
-        continue;
-      LLVM_DEBUG(dbgs() << "\tReordering from source instruction that's used in another block: "; I.dump());
-      reorderDefinition(&I, UsedOutsideOfBBTopologicalSort, Visited);
-    }
-
     for (auto &I : BB) { 
       if (Visited.contains(&I)) 
-        continue;
-      LLVM_DEBUG(dbgs() << "\tReordering from dead source instruction: "; I.dump());
+        continue; // I is not a source node. 
+      LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
     LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName() 
                       << "\n");
-    reorderBasedOnTopologicalSort(BB, UsedOutsideOfBBTopologicalSort);
-    reorderBasedOnTopologicalSort(BB, TopologicalSort);
+    // Reorder based on the topological sort. 
+    while (!TopologicalSort.empty()) {
+      auto *Instruction = TopologicalSort.top();
+      auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
+      Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
+        TopologicalSort.pop();
+    }
   }
 }
 
@@ -493,7 +488,7 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
       return;
-    else if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
+    if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
       return; // TODO: Do some kind of ordering for these instructions. 
   }
 
@@ -505,7 +500,7 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     }
   }
 
-  // Don't reorder certain instructions. 
+  LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
   if (Definition->isTerminator())
     return;
   if (auto *Call = dyn_cast<CallInst>(Definition)) {
@@ -514,22 +509,10 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
       return;
   }
-
-  LLVM_DEBUG(dbgs() << "\t\tNext in topological sort: "; Definition->dump());
+  // TODO: return on llvm.experimental.deopt...
   TopologicalSort.emplace(Definition);
 }
 
-void IRNormalizer::reorderBasedOnTopologicalSort(BasicBlock &BB, 
-    std::stack<Instruction *> &TopologicalSort) const {
-  // Reorder based on the topological sort. 
-  while (!TopologicalSort.empty()) {
-    auto *Instruction = TopologicalSort.top();
-    auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
-    Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
-      TopologicalSort.pop();
-  }
-}
-
 /// Reorders instruction's operands alphabetically. This method assumes
 /// that passed instruction is commutative. Changing the operand order
 /// in other instructions may change the semantics.

>From 7d8a9ab0a0f94030c85db4e7297992f02ef1ec6a Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 18:30:35 -0800
Subject: [PATCH 39/70] clang-format

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 39 +++++++++++-----------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 8220217cc6fe44..8608e6ff1593e0 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -75,8 +75,8 @@ class IRNormalizer {
   /// @{
   void reorderInstructions(Function &F) const;
   void reorderDefinition(Instruction *Definition,
-      std::stack<Instruction *> &TopologicalSort,
-      SmallPtrSet<const Instruction *, 32> &Visited) const;
+                         std::stack<Instruction *> &TopologicalSort,
+                         SmallPtrSet<const Instruction *, 32> &Visited) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
   void reorderPHIIncomingValues(PHINode *PN) const;
   /// @}
@@ -441,43 +441,43 @@ void IRNormalizer::foldInstructionName(Instruction *I) const {
 /// \see reorderInstruction()
 void IRNormalizer::reorderInstructions(Function &F) const {
   for (auto &BB : F) {
-    LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: " 
+    LLVM_DEBUG(dbgs() << "Reordering instructions in basic block: "
                       << BB.getName() << "\n");
     // Find the source nodes of the DAG of instructions in this basic block.
-    // We must iterate from the first to the last instruction otherwise side 
-    // effecting instructions could be reordered. 
+    // 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) { 
-      if (!isOutput(&I) && !I.isTerminator()) 
-        continue; // I is not a source node. 
-      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: "; 
+    for (auto &I : BB) {
+      if (!isOutput(&I) && !I.isTerminator())
+        continue; // I is not a source node.
+      LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
                  I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
-    for (auto &I : BB) { 
-      if (Visited.contains(&I)) 
-        continue; // I is not a source node. 
+    for (auto &I : BB) {
+      if (Visited.contains(&I))
+        continue; // I is not a source node.
       LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
-    LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName() 
+    LLVM_DEBUG(dbgs() << "Inserting instructions into: " << BB.getName()
                       << "\n");
-    // Reorder based on the topological sort. 
+    // Reorder based on the topological sort.
     while (!TopologicalSort.empty()) {
       auto *Instruction = TopologicalSort.top();
       auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
       Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
-        TopologicalSort.pop();
+      TopologicalSort.pop();
     }
   }
 }
 
-void IRNormalizer::reorderDefinition(Instruction *Definition,
-    std::stack<Instruction *> &TopologicalSort,
+void IRNormalizer::reorderDefinition(
+    Instruction *Definition, std::stack<Instruction *> &TopologicalSort,
     SmallPtrSet<const Instruction *, 32> &Visited) const {
   if (Visited.contains(Definition))
     return;
@@ -485,11 +485,12 @@ void IRNormalizer::reorderDefinition(Instruction *Definition,
 
   {
     const auto *BasicBlock = Definition->getParent();
-    const auto FirstNonPHIOrDbgOrAlloca = BasicBlock->getFirstNonPHIOrDbgOrAlloca();
+    const auto FirstNonPHIOrDbgOrAlloca =
+        BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
       return;
     if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
-      return; // TODO: Do some kind of ordering for these instructions. 
+      return; // TODO: Do some kind of ordering for these instructions.
   }
 
   for (auto &Operand : Definition->operands()) {

>From 8a69c6d79ae64952769c3251f3efeac00ef03b99 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Sun, 19 Nov 2023 19:52:35 -0800
Subject: [PATCH 40/70] Don't reorder bitcasts the precede musttail

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 8608e6ff1593e0..6bbe4106a517fd 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -510,7 +510,13 @@ void IRNormalizer::reorderDefinition(
     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
       return;
   }
-  // TODO: return on llvm.experimental.deopt...
+  if (auto *BitCast = dyn_cast<BitCastInst>(Definition)) {
+    if (auto *Call = dyn_cast<CallInst>(BitCast->getOperand(0))) {
+      if (Call->isMustTailCall())
+        return;
+    }
+  }
+
   TopologicalSort.emplace(Definition);
 }
 

>From 871d69b44de6ec2c4275e34e3406ab4f2386cfa9 Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Wed, 13 Mar 2024 20:51:38 -0700
Subject: [PATCH 41/70] Fixup rebase

---
 llvm/docs/ReleaseNotes.md        |  2 ++
 llvm/lib/Passes/PassRegistry.def | 13 +------------
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 322e1ecfd3a9c3..7699c46668a881 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -47,6 +47,8 @@ for adding a new subsection. -->
   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
 subsection about it right here. You can copy the following boilerplate:
 
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index aa7e99c7fe1225..9511838cba6a0e 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -340,9 +340,6 @@ FUNCTION_PASS("bounds-checking", BoundsCheckingPass())
 FUNCTION_PASS("break-crit-edges", BreakCriticalEdgesPass())
 FUNCTION_PASS("callbr-prepare", CallBrPreparePass())
 FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass())
-FUNCTION_PASS("consthoist", ConstantHoistingPass())
-FUNCTION_PASS("count-visits", CountVisitsPass())
-FUNCTION_PASS("constraint-elimination", ConstraintEliminationPass())
 FUNCTION_PASS("chr", ControlHeightReductionPass())
 FUNCTION_PASS("codegenprepare", CodeGenPreparePass(TM))
 FUNCTION_PASS("complex-deinterleaving", ComplexDeinterleavingPass(TM))
@@ -417,16 +414,8 @@ FUNCTION_PASS("mergereturn", UnifyFunctionExitNodesPass())
 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("jump-threading", JumpThreadingPass())
-FUNCTION_PASS("partially-inline-libcalls", PartiallyInlineLibCallsPass())
-FUNCTION_PASS("kcfi", KCFIPass())
-FUNCTION_PASS("lcssa", LCSSAPass())
-FUNCTION_PASS("loop-data-prefetch", LoopDataPrefetchPass())
-FUNCTION_PASS("loop-load-elim", LoopLoadEliminationPass())
-FUNCTION_PASS("loop-fusion", LoopFusePass())
-FUNCTION_PASS("loop-distribute", LoopDistributePass())
-FUNCTION_PASS("loop-versioning", LoopVersioningPass())
 FUNCTION_PASS("objc-arc", ObjCARCOptPass())
 FUNCTION_PASS("objc-arc-contract", ObjCARCContractPass())
 FUNCTION_PASS("objc-arc-expand", ObjCARCExpandPass())

>From f69de53e5c079301d49e8112e258578c58452e1e Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Thu, 14 Mar 2024 19:25:00 -0700
Subject: [PATCH 42/70] Add regression tests

---
 .../IRNormalizer/regression-coro-elide-musttail.ll  | 13 +++++++++++++
 .../IRNormalizer/regression-deoptimize.ll           | 11 +++++++++++
 .../regression-dont-hoist-deoptimize.ll             | 13 +++++++++++++
 3 files changed, 37 insertions(+)
 create mode 100644 llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
 create mode 100644 llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
 create mode 100644 llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll

diff --git a/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll b/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
new file mode 100644
index 00000000000000..e24f4d8c5f5c57
--- /dev/null
+++ b/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
@@ -0,0 +1,13 @@
+; RUN: opt < %s -passes=normalize -verify-each
+
+define fastcc void @foo.resume_musttail(ptr %FramePtr) {
+entry:
+  %0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+  musttail call fastcc void undef(ptr null)
+  ret void
+}
+
+; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read)
+declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #0
+
+attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
diff --git a/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
new file mode 100644
index 00000000000000..b4bda7dd7d7674
--- /dev/null
+++ b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
@@ -0,0 +1,11 @@
+; RUN: opt < %s -passes=normalize -verify-each
+
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
+
+define void @test1() {
+  %1 = load i8, ptr null, align 1
+  call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+  ret void
+}
+
+declare void @llvm.experimental.deoptimize.isVoid(...)
diff --git a/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
new file mode 100644
index 00000000000000..9ec82f3a18690d
--- /dev/null
+++ b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
@@ -0,0 +1,13 @@
+; RUN: opt %s -passes=normalize -verify-each
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.experimental.deoptimize.isVoid(...)
+
+define void @widget() {
+bb:
+  %tmp3 = trunc i64 0 to i32
+  call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"() ]
+  ret void
+}
+

>From f1c89cd2964725a868577eff5a18f18c3dcb2b9d Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Thu, 14 Mar 2024 19:33:32 -0700
Subject: [PATCH 43/70] Add TODO for future work

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp                      | 2 ++
 .../Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 6bbe4106a517fd..26c46cde09b37f 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -122,6 +122,8 @@ bool IRNormalizer::runOnFunction(Function &F) {
   if (!PreserveOrder)
     reorderInstructions(F);
 
+  // TODO: Reorder basic blocks via a topological sort.
+
   for (auto &I : Outputs)
     nameInstruction(I);
 
diff --git a/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
index 9ec82f3a18690d..e218d8f67d8870 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
@@ -10,4 +10,3 @@ bb:
   call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"() ]
   ret void
 }
-

>From a602c25589104917ccf4d38f410f69141deeabcd Mon Sep 17 00:00:00 2001
From: justinfargnoli <justinfargnoli at gmail.com>
Date: Thu, 14 Mar 2024 20:12:54 -0700
Subject: [PATCH 44/70] Stash clang changes

---
 clang/lib/CodeGen/BackendUtil.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 70035a5e069a90..98662dede7e3d2 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -87,6 +87,7 @@
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
 #include "llvm/Transforms/Utils/Debugify.h"
+#include "llvm/Transforms/Utils/IRNormalizer.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <memory>
 #include <optional>
@@ -1084,6 +1085,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   if (CodeGenOpts.LinkBitcodePostopt)
     MPM.addPass(LinkInModulesPass(BC));
 
+  MPM.addPass(createModuleToFunctionPassAdaptor(IRNormalizerPass()));
+
   // Add a verifier pass if requested. We don't have to do this if the action
   // requires code generation because there will already be a verifier pass in
   // the code-generation pipeline.

>From 24fda639088da552cc8be379f5d9b8e5e58f6bdc Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 4 May 2024 18:08:16 -0700
Subject: [PATCH 45/70] Condense tests

---
 .../IRNormalizer/naming-basic-blocks.ll       |  8 --------
 .../{naming-instructions.ll => naming.ll}     |  7 +++++++
 ...phi-node-values.ll => reordering-basic.ll} | 20 +++++++++++++++++--
 .../IRNormalizer/reordering-instructions.ll   | 14 -------------
 .../Transforms/IRNormalizer/reordering.ll     |  5 +++++
 5 files changed, 30 insertions(+), 24 deletions(-)
 delete mode 100644 llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
 rename llvm/test/Transforms/IRNormalizer/{naming-instructions.ll => naming.ll} (77%)
 rename llvm/test/Transforms/IRNormalizer/{reordering-phi-node-values.ll => reordering-basic.ll} (60%)
 delete mode 100644 llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
 create mode 100644 llvm/test/Transforms/IRNormalizer/reordering.ll

diff --git a/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
deleted file mode 100644
index 9493b3f70ef763..00000000000000
--- a/llvm/test/Transforms/IRNormalizer/naming-basic-blocks.ll
+++ /dev/null
@@ -1,8 +0,0 @@
-; RUN: opt -S -passes=normalize -norm-rename-all < %s | FileCheck %s
-
-define i32 @foo(i32 %a0) {
-; CHECK: bb{{([0-9]{5})}}
-entry:
-  %a = add i32 %a0, 2
-  ret i32 %a
-}
diff --git a/llvm/test/Transforms/IRNormalizer/naming-instructions.ll b/llvm/test/Transforms/IRNormalizer/naming.ll
similarity index 77%
rename from llvm/test/Transforms/IRNormalizer/naming-instructions.ll
rename to llvm/test/Transforms/IRNormalizer/naming.ll
index c08ef18f948c83..9ef718a090f553 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-instructions.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming.ll
@@ -1,5 +1,12 @@
 ; RUN: opt -S -passes=normalize -norm-rename-all < %s | FileCheck %s
 
+define i32 @foo(i32 %a0) {
+; CHECK: bb{{([0-9]{5})}}
+entry:
+  %a = add i32 %a0, 2
+  ret i32 %a
+}
+
 define i32 @foo(i32 %a0) {
 entry:
 ; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
diff --git a/llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
similarity index 60%
rename from llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll
rename to llvm/test/Transforms/IRNormalizer/reordering-basic.ll
index cba92e8eaf9ac5..59cf3900a6a946 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering-phi-node-values.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
@@ -1,16 +1,31 @@
 ; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
-declare double @foo()
+define double @foo(double %a0, double %a1) {
+; CHECK-LABEL: foo(
+entry:
+; CHECK: %b
+; CHECK: %d
+; CHECK: %a
+; CHECK: %c
+  %a = fmul double %a0, %a1
+  %b = fmul double %a0, 2.000000e+00
+  %c = fmul double %a, 6.000000e+00
+  %d = fmul double %b, 6.000000e+00
+  ret double %d
+}
+
+declare double @bir()
 
 declare double @bar()
 
 define double @baz(double %x) {
+; CHECK-LABEL: baz(
 entry:
   %ifcond = fcmp one double %x, 0.000000e+00
   br i1 %ifcond, label %then, label %else
 
 then:       ; preds = %entry
-  %calltmp = call double @foo()
+  %calltmp = call double @bir()
   br label %ifcont
 
 else:       ; preds = %entry
@@ -22,3 +37,4 @@ ifcont:     ; preds = %else, %then
   %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
   ret double %iftmp
 }
+
diff --git a/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll b/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
deleted file mode 100644
index 338fbbe974cce7..00000000000000
--- a/llvm/test/Transforms/IRNormalizer/reordering-instructions.ll
+++ /dev/null
@@ -1,14 +0,0 @@
-; RUN: opt -S -passes=normalize < %s | FileCheck %s
-
-define double @foo(double %a0, double %a1) {
-entry:
-; CHECK: %b
-; CHECK: %d
-; CHECK: %a
-; CHECK: %c
-  %a = fmul double %a0, %a1
-  %b = fmul double %a0, 2.000000e+00
-  %c = fmul double %a, 6.000000e+00
-  %d = fmul double %b, 6.000000e+00
-  ret double %d
-}
diff --git a/llvm/test/Transforms/IRNormalizer/reordering.ll b/llvm/test/Transforms/IRNormalizer/reordering.ll
new file mode 100644
index 00000000000000..1cca67427b533d
--- /dev/null
+++ b/llvm/test/Transforms/IRNormalizer/reordering.ll
@@ -0,0 +1,5 @@
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
+
+define void @foo() {
+  ret void
+}
\ No newline at end of file

>From f858047948a86120e2dd1ddbc2516373f16692c4 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sun, 5 May 2024 12:24:59 -0700
Subject: [PATCH 46/70] Elaborate comment

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 26c46cde09b37f..ee28e2133bd08a 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -446,22 +446,27 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     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; // I is not a source node.
+        continue;
       LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
                  I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }
 
     for (auto &I : BB) {
+      // Process the remaining dead instructions.
       if (Visited.contains(&I))
-        continue; // I is not a source node.
+        continue;
       LLVM_DEBUG(dbgs() << "\tReordering from source instruction: "; I.dump());
       reorderDefinition(&I, TopologicalSort, Visited);
     }

>From b5896865e50caded6c3e055e2b4dda862a29b238 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sun, 5 May 2024 12:25:18 -0700
Subject: [PATCH 47/70] Fix naming.ll

---
 llvm/test/Transforms/IRNormalizer/naming.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/IRNormalizer/naming.ll b/llvm/test/Transforms/IRNormalizer/naming.ll
index 9ef718a090f553..9f9b033b6a5855 100644
--- a/llvm/test/Transforms/IRNormalizer/naming.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming.ll
@@ -7,7 +7,7 @@ entry:
   ret i32 %a
 }
 
-define i32 @foo(i32 %a0) {
+define i32 @bar(i32 %a0) {
 entry:
 ; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
   %a = add i32 %a0, 2

>From 9ff2593d3a6547738ce2ae235ae41714285dfdcb Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Mon, 6 May 2024 19:23:46 -0700
Subject: [PATCH 48/70] Add TODOs

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index ee28e2133bd08a..59686d7f8d06ba 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -45,7 +45,7 @@ class IRNormalizer {
   /// Preserves original order of instructions.
   static cl::opt<bool> PreserveOrder;
   /// Renames all instructions (including user-named).
-  static cl::opt<bool> RenameAll;
+  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.
@@ -464,7 +464,12 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     }
 
     for (auto &I : BB) {
-      // Process the remaining dead instructions.
+      // 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());
@@ -495,7 +500,7 @@ void IRNormalizer::reorderDefinition(
     const auto FirstNonPHIOrDbgOrAlloca =
         BasicBlock->getFirstNonPHIOrDbgOrAlloca();
     if (FirstNonPHIOrDbgOrAlloca == BasicBlock->end())
-      return;
+      return; // TODO: Is this necessary?
     if (Definition->comesBefore(&*FirstNonPHIOrDbgOrAlloca))
       return; // TODO: Do some kind of ordering for these instructions.
   }

>From 576e5edc10ad2b6147a38f882e3a0c6ea3b5194a Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Mon, 6 May 2024 19:24:04 -0700
Subject: [PATCH 49/70] Prefix infinite-loop.ll with regression

---
 .../{infinite-loop.ll => regression-infinite-loop.ll}             | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename llvm/test/Transforms/IRNormalizer/{infinite-loop.ll => regression-infinite-loop.ll} (100%)

diff --git a/llvm/test/Transforms/IRNormalizer/infinite-loop.ll b/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
similarity index 100%
rename from llvm/test/Transforms/IRNormalizer/infinite-loop.ll
rename to llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll

>From f8eb6cda49b64ea8cf27d2dbf22268eb26c96a03 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Mon, 6 May 2024 19:24:14 -0700
Subject: [PATCH 50/70] Add first set of reordering tests

---
 .../Transforms/IRNormalizer/reordering.ll     | 109 +++++++++++++++++-
 1 file changed, 107 insertions(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/IRNormalizer/reordering.ll b/llvm/test/Transforms/IRNormalizer/reordering.ll
index 1cca67427b533d..674c58ce3b2b80 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering.ll
@@ -1,5 +1,110 @@
-; RUN: opt -S -passes=normalize < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt -S -passes=normalize -verify-each < %s | FileCheck %s
 
 define void @foo() {
+; CHECK-LABEL: define void @foo() {
+; CHECK-NEXT:  bb17254:
+; CHECK-NEXT:    ret void
+;
   ret void
-}
\ No newline at end of file
+}
+
+define void @empty_basic_block() {
+; CHECK-LABEL: define void @empty_basic_block() {
+; CHECK-NEXT:  exit:
+; CHECK-NEXT:    ret void
+;
+exit:
+  ret void
+}
+
+declare void @effecting()
+
+; Place dead instruction(s) before the terminator
+define void @call_effecting() {
+; CHECK-LABEL: define void @call_effecting() {
+; CHECK-NEXT:  bb15160:
+; CHECK-NEXT:    call void @effecting()
+; CHECK-NEXT:    [[TMP0:%.*]] = add i32 0, 1
+; CHECK-NEXT:    ret void
+;
+  %1 = add i32 0, 1
+  call void @effecting()
+  ret void
+}
+
+define void @dont_move_above_phi() {
+; CHECK-LABEL: define void @dont_move_above_phi() {
+; CHECK-NEXT:  bb76951:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[BB76951:%.*]] ]
+; CHECK-NEXT:    call void @effecting()
+; CHECK-NEXT:    ret void
+;
+  br label %exit
+exit:
+  %1 = phi i32 [0, %0]
+  call void @effecting()
+  ret void
+}
+
+define void @dont_move_above_alloca() {
+; CHECK-LABEL: define void @dont_move_above_alloca() {
+; CHECK-NEXT:  bb15160:
+; CHECK-NEXT:    [[TMP0:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    call void @effecting()
+; CHECK-NEXT:    ret void
+;
+  %1 = alloca i32
+  call void @effecting()
+  ret void
+}
+
+declare void @effecting1()
+
+define void @dont_reorder_effecting() {
+; CHECK-LABEL: define void @dont_reorder_effecting() {
+; CHECK-NEXT:  bb10075:
+; CHECK-NEXT:    call void @effecting()
+; CHECK-NEXT:    call void @effecting1()
+; CHECK-NEXT:    ret void
+;
+  call void @effecting()
+  call void @effecting1()
+  ret void
+}
+
+declare void @effecting2(i32)
+
+define void @dont_reorder_effecting1() {
+; CHECK-LABEL: define void @dont_reorder_effecting1() {
+; CHECK-NEXT:  bb10075:
+; CHECK-NEXT:    [[ONE:%.*]] = add i32 1, 1
+; CHECK-NEXT:    call void @effecting2(i32 [[ONE]])
+; CHECK-NEXT:    [[TWO:%.*]] = add i32 2, 2
+; CHECK-NEXT:    call void @effecting2(i32 [[TWO]])
+; CHECK-NEXT:    ret void
+;
+  %one = add i32 1, 1
+  %two = add i32 2, 2
+  call void @effecting2(i32 %one)
+  call void @effecting2(i32 %two)
+  ret void
+}
+
+define void @dont_reorder_across_blocks() {
+; CHECK-LABEL: define void @dont_reorder_across_blocks() {
+; CHECK-NEXT:  bb76951:
+; CHECK-NEXT:    [[ONE:%.*]] = add i32 1, 1
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    call void @effecting2(i32 [[ONE]])
+; CHECK-NEXT:    ret void
+;
+  %one = add i32 1, 1
+  br label %exit
+exit:
+  call void @effecting2(i32 %one)
+  ret void
+}

>From 671c47fb690274657fd61ad5b692be82552ddef1 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 25 May 2024 13:08:12 -0700
Subject: [PATCH 51/70] clang-format changes

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 59686d7f8d06ba..ac67a8f5a2c119 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -446,7 +446,7 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     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 
+    // 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
@@ -467,9 +467,9 @@ void IRNormalizer::reorderInstructions(Function &F) const {
       // 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. 
+      // 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());

>From 0b9d91e078adb91d464364c844bde3c2d37de763 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Fri, 31 May 2024 19:00:52 -0700
Subject: [PATCH 52/70] Save work

---
 .../Transforms/IRNormalizer/reordering.ll     | 55 ++++++++++++++++++-
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/IRNormalizer/reordering.ll b/llvm/test/Transforms/IRNormalizer/reordering.ll
index 674c58ce3b2b80..313d44a88e3cb7 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
-; RUN: opt -S -passes=normalize -verify-each < %s | FileCheck %s
+; RUN: opt -S -passes=normalize -verify-each -norm-rename-all=false < %s | FileCheck %s
 
 define void @foo() {
 ; CHECK-LABEL: define void @foo() {
@@ -108,3 +108,56 @@ exit:
   call void @effecting2(i32 %one)
   ret void
 }
+
+define void @independentldst(ptr %a, ptr %b) {
+; CHECK-LABEL: define void @independentldst(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT:  bb10495:
+; CHECK-NEXT:    %"vl12961([[B]])" = load i32, ptr [[B]], align 4
+; CHECK-NEXT:    store i32 %"vl12961([[B]])", ptr [[A]], align 4
+; CHECK-NEXT:    %"vl89528([[A]])" = load i32, ptr [[A]], align 4
+; CHECK-NEXT:    store i32 %"vl89528([[A]])", ptr [[B]], align 4
+; CHECK-NEXT:    ret void
+;
+  %2 = load i32, ptr %a
+  %3 = load i32, ptr %b
+  store i32 %3, ptr %a
+  store i32 %2, ptr %b
+  ret void
+}
+
+define void @multiple_use_ld(ptr %a, ptr %b) {
+; CHECK-LABEL: define void @multiple_use_ld(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT:  bb14927:
+; CHECK-NEXT:    %"vl16793([[A]])" = load i32, ptr [[A]], align 4
+; CHECK-NEXT:    store i32 %"vl16793([[A]])", ptr [[A]], align 4
+; CHECK-NEXT:    %"vl89528([[B]])" = load i32, ptr [[B]], align 4
+; CHECK-NEXT:    store i32 %"vl89528([[B]])", ptr [[B]], align 4
+; CHECK-NEXT:    store i32 %"vl16793([[A]])", ptr [[A]], align 4
+; CHECK-NEXT:    ret void
+;
+  %2 = load i32, ptr %a
+  store i32 %2, ptr %a
+  %3 = load i32, ptr %b
+  store i32 %3, ptr %b
+  store i32 %2, ptr %a
+  ret void
+}
+
+; This is an incorrect transformation. Moving the store above the load could
+; change the loaded value. To do this, the pointers would need to be `noalias`.
+define void @undef_st(ptr %a, ptr %b) {
+; CHECK-LABEL: define void @undef_st(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT:  bb10495:
+; CHECK-NEXT:    store i32 undef, ptr [[B]], align 4
+; CHECK-NEXT:    %"vl16028([[A]])" = load i32, ptr [[A]], align 4
+; CHECK-NEXT:    store i32 %"vl16028([[A]])", ptr [[A]], align 4
+; CHECK-NEXT:    ret void
+;
+  %2 = load i32, ptr %a
+  store i32 undef, ptr %b
+  store i32 %2, ptr %a
+  ret void
+}

>From 4644d233db58393ef27dae6279af9022688b9f35 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 18:54:09 -0700
Subject: [PATCH 53/70] Revert "Stash clang changes"

This reverts commit bef6459c3c9b55e67e687392d92ce076cc9e780b.
---
 clang/lib/CodeGen/BackendUtil.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 98662dede7e3d2..a3b76fba06c55b 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -87,7 +87,7 @@
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
 #include "llvm/Transforms/Utils/Debugify.h"
-#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <memory>
 #include <optional>
@@ -1085,8 +1085,6 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   if (CodeGenOpts.LinkBitcodePostopt)
     MPM.addPass(LinkInModulesPass(BC));
 
-  MPM.addPass(createModuleToFunctionPassAdaptor(IRNormalizerPass()));
-
   // Add a verifier pass if requested. We don't have to do this if the action
   // requires code generation because there will already be a verifier pass in
   // the code-generation pipeline.

>From 05e011039bcedf8fc321c27c562175fd61275e78 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 18:55:38 -0700
Subject: [PATCH 54/70] [NFC] Change boolean logic for readability

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index ac67a8f5a2c119..db3e6a2147034f 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -456,7 +456,7 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     SmallPtrSet<const Instruction *, 32> Visited;
     for (auto &I : BB) {
       // First process side effecting and terminating instructions.
-      if (!isOutput(&I) && !I.isTerminator())
+      if (!(isOutput(&I) || I.isTerminator()))
         continue;
       LLVM_DEBUG(dbgs() << "\tReordering from source effecting instruction: ";
                  I.dump());

>From 8e12f8243eb4cab5b96ad1c05857a3dc9071cab3 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 18:58:13 -0700
Subject: [PATCH 55/70] Fixup revert - Delete #include

---
 clang/lib/CodeGen/BackendUtil.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index a3b76fba06c55b..70035a5e069a90 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -87,7 +87,6 @@
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
 #include "llvm/Transforms/Utils/Debugify.h"
-#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <memory>
 #include <optional>

>From 75fccb46d98a0b1df895cbd02bf072863cf1ae9a Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:33:58 -0700
Subject: [PATCH 56/70] Remove unnecessary sortCommutativeOperands | Rename
 vars

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 65 +++++++++-------------
 1 file changed, 27 insertions(+), 38 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index db3e6a2147034f..d92e6b5556de85 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -84,8 +84,6 @@ class IRNormalizer {
   /// \name Utility methods.
   /// @{
   template <typename T> void sortCommutativeOperands(T &Operands) const;
-  template <typename T, typename Compare>
-  void sortCommutativeOperands(T &Operands, Compare Comp) const;
   SmallVector<Instruction *, 16> collectOutputInstructions(Function &F) const;
   bool isOutput(const Instruction *I) const;
   bool isInitialInstruction(const Instruction *I) const;
@@ -205,15 +203,6 @@ void IRNormalizer::sortCommutativeOperands(T &Operands) const {
   llvm::sort(Operands.begin(), CommutativeEnd);
 }
 
-template <typename T, typename Compare>
-void IRNormalizer::sortCommutativeOperands(T &Operands, Compare Comp) const {
-  if (Operands.size() < 2)
-    return;
-  auto CommutativeEnd = Operands.begin();
-  std::advance(CommutativeEnd, 2);
-  llvm::sort(Operands.begin(), CommutativeEnd, Comp);
-}
-
 /// Names instruction following the scheme:
 /// vl00000Callee(Operands)
 ///
@@ -236,11 +225,11 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
   SmallVector<SmallString<64>, 4> Operands;
 
   // Collect operands.
-  for (auto &OP : I->operands()) {
-    if (!isa<Function>(OP)) {
+  for (auto &Op : I->operands()) {
+    if (!isa<Function>(Op)) {
       std::string TextRepresentation;
       raw_string_ostream Stream(TextRepresentation);
-      OP->printAsOperand(Stream, false);
+      Op->printAsOperand(Stream, false);
       Operands.push_back(StringRef(Stream.str()));
     }
   }
@@ -315,16 +304,16 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
   // walk.
 
   // Collect operands.
-  for (auto &OP : I->operands()) {
-    if (auto *IOP = dyn_cast<Instruction>(OP)) {
+  for (auto &Op : I->operands()) {
+    if (auto *I = dyn_cast<Instruction>(Op)) {
       // Walk down the use-def chain.
-      nameInstruction(IOP);
-      Operands.push_back(IOP->getName());
-    } else if (!isa<Function>(OP)) {
+      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);
+      Op->printAsOperand(Stream, false);
       Operands.push_back(StringRef(Stream.str()));
     }
   }
@@ -342,9 +331,9 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
   SmallVector<int, 4> OperandsOpcodes;
 
   // Collect operand opcodes for hashing.
-  for (auto &OP : I->operands())
-    if (auto *IOP = dyn_cast<Instruction>(OP))
-      OperandsOpcodes.push_back(IOP->getOpcode());
+  for (auto &Op : I->operands())
+    if (auto *I = dyn_cast<Instruction>(Op))
+      OperandsOpcodes.push_back(I->getOpcode());
 
   if (I->isCommutative())
     sortCommutativeOperands(OperandsOpcodes);
@@ -406,13 +395,13 @@ void IRNormalizer::foldInstructionName(Instruction *I) const {
   // Instruction operands.
   SmallVector<SmallString<64>, 4> Operands;
 
-  for (auto &OP : I->operands()) {
-    if (const auto *IOP = dyn_cast<Instruction>(OP)) {
+  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 ? IOP->getName().substr(0, 7)
-                                       : IOP->getName());
+      Operands.push_back(HasNormalName ? I->getName().substr(0, 7)
+                                       : I->getName());
     }
   }
 
@@ -546,28 +535,28 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
   SmallVector<std::pair<std::string, Value *>, 4> Operands;
 
   // Collect operands.
-  for (auto &OP : I->operands()) {
-    if (auto *VOP = dyn_cast<Value>(OP)) {
-      if (isa<Instruction>(VOP)) {
+  for (auto &Op : I->operands()) {
+    if (auto *V = dyn_cast<Value>(Op)) {
+      if (isa<Instruction>(V)) {
         // This is an an instruction.
         Operands.push_back(
-            std::pair<std::string, Value *>(VOP->getName(), VOP));
+            std::pair<std::string, Value *>(V->getName(), V));
       } else {
         std::string TextRepresentation;
         raw_string_ostream Stream(TextRepresentation);
-        OP->printAsOperand(Stream, false);
-        Operands.push_back(std::pair<std::string, Value *>(Stream.str(), VOP));
+        Op->printAsOperand(Stream, false);
+        Operands.push_back(std::pair<std::string, Value *>(Stream.str(), V));
       }
     }
   }
 
   // Sort operands.
-  sortCommutativeOperands(Operands, llvm::less_first());
+  sortCommutativeOperands(Operands);
 
   // Reorder operands.
   unsigned Position = 0;
-  for (auto &OP : I->operands()) {
-    OP.set(Operands[Position].second);
+  for (auto &Op : I->operands()) {
+    Op.set(Operands[Position].second);
     Position++;
   }
 }
@@ -643,8 +632,8 @@ bool IRNormalizer::isInitialInstruction(const Instruction *I) const {
 ///
 /// \param I Considered instruction.
 bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) const {
-  for (const auto &OP : I->operands())
-    if (isa<Instruction>(OP))
+  for (const auto &Op : I->operands())
+    if (isa<Instruction>(Op))
       return false; // Found non-immediate operand (instruction).
 
   return true;

>From 717fe442bfe645a659d685d79c36631eeb607c87 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:34:16 -0700
Subject: [PATCH 57/70] clang-format

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index d92e6b5556de85..f55013134fca92 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -539,8 +539,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
     if (auto *V = dyn_cast<Value>(Op)) {
       if (isa<Instruction>(V)) {
         // This is an an instruction.
-        Operands.push_back(
-            std::pair<std::string, Value *>(V->getName(), V));
+        Operands.push_back(std::pair<std::string, Value *>(V->getName(), V));
       } else {
         std::string TextRepresentation;
         raw_string_ostream Stream(TextRepresentation);

>From 6b1f18e93895ba5f14f82c9640f33dd02eafc464 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:35:35 -0700
Subject: [PATCH 58/70] Remove uses of ++

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index f55013134fca92..5e653859432aca 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -148,7 +148,7 @@ void IRNormalizer::nameFunctionArguments(Function &F) const {
   for (auto &A : F.args()) {
     if (RenameAll || A.getName().empty()) {
       A.setName("a" + Twine(ArgumentCounter));
-      ++ArgumentCounter;
+      ArgumentCounter += 1;
     }
   }
 }
@@ -556,7 +556,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
   unsigned Position = 0;
   for (auto &Op : I->operands()) {
     Op.set(Operands[Position].second);
-    Position++;
+    Position += 1;
   }
 }
 
@@ -634,7 +634,6 @@ bool IRNormalizer::hasOnlyImmediateOperands(const Instruction *I) const {
   for (const auto &Op : I->operands())
     if (isa<Instruction>(Op))
       return false; // Found non-immediate operand (instruction).
-
   return true;
 }
 
@@ -664,7 +663,7 @@ SetVector<int> IRNormalizer::getOutputFootprint(
         for (const auto &E : B) {
           if (&E == I)
             Outputs.insert(Count);
-          Count++;
+          Count += 1;
         }
       }
 

>From e3cd7392aa0135c3a4b8d47118a75724b5ec454c Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:36:27 -0700
Subject: [PATCH 59/70] Use int for iterators instead of unsigned long

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 5e653859432aca..7e54be7e220039 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -264,7 +264,7 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
   }
 
   Name.append("(");
-  for (unsigned long i = 0; i < Operands.size(); ++i) {
+  for (int i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)
@@ -352,7 +352,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
       Name.append(F->getName());
 
   Name.append("(");
-  for (unsigned long i = 0; i < Operands.size(); ++i) {
+  for (int i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)
@@ -412,7 +412,7 @@ void IRNormalizer::foldInstructionName(Instruction *I) const {
   Name.append(I->getName().substr(0, 7));
 
   Name.append("(");
-  for (unsigned long i = 0; i < Operands.size(); ++i) {
+  for (int i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)

>From a6d8df913e85272db61485aaa48a1259221caebc Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:42:34 -0700
Subject: [PATCH 60/70] [NFC] Remove newlines

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 7e54be7e220039..fb098d648d3bb4 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -597,11 +597,9 @@ IRNormalizer::collectOutputInstructions(Function &F) const {
   // Output instructions are collected top-down in each function,
   // any change may break the def-use chain in reordering methods.
   SmallVector<Instruction *, 16> Outputs;
-
   for (auto &I : instructions(F))
     if (isOutput(&I))
       Outputs.push_back(&I);
-
   return Outputs;
 }
 
@@ -611,10 +609,7 @@ IRNormalizer::collectOutputInstructions(Function &F) const {
 /// \param I Considered instruction.
 bool IRNormalizer::isOutput(const Instruction *I) const {
   // Outputs are such instructions which may have side effects or is ReturnInst.
-  if (I->mayHaveSideEffects() || isa<ReturnInst>(I))
-    return true;
-
-  return false;
+  return I->mayHaveSideEffects() || isa<ReturnInst>(I);
 }
 
 /// Helper method checking whether the instruction has users and only
@@ -675,7 +670,6 @@ SetVector<int> IRNormalizer::getOutputFootprint(
       if (auto *UI = dyn_cast<Instruction>(U)) {
         // Vector for outputs which use UI.
         SetVector<int> OutputsUsingUI = getOutputFootprint(UI, Visited);
-
         // Insert the indexes of outputs using UI.
         Outputs.insert(OutputsUsingUI.begin(), OutputsUsingUI.end());
       }

>From aafcbdccca970434b9840e3ed7d16609b88d0bf0 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:57:56 -0700
Subject: [PATCH 61/70] Refactor sortCommutativeOperands

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 47 ++++++++++------------
 1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index fb098d648d3bb4..afe3194ab8f47e 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -78,12 +78,12 @@ class IRNormalizer {
                          std::stack<Instruction *> &TopologicalSort,
                          SmallPtrSet<const Instruction *, 32> &Visited) const;
   void reorderInstructionOperandsByNames(Instruction *I) const;
-  void reorderPHIIncomingValues(PHINode *PN) const;
+  void reorderPHIIncomingValues(PHINode *Phi) const;
   /// @}
 
   /// \name Utility methods.
   /// @{
-  template <typename T> void sortCommutativeOperands(T &Operands) const;
+  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;
@@ -127,13 +127,12 @@ bool IRNormalizer::runOnFunction(Function &F) {
 
   for (auto &I : instructions(F)) {
     if (!PreserveOrder) {
-      if (ReorderOperands && I.isCommutative())
+      if (ReorderOperands)
         reorderInstructionOperandsByNames(&I);
 
-      if (auto *PN = dyn_cast<PHINode>(&I))
-        reorderPHIIncomingValues(PN);
+      if (auto *Phi = dyn_cast<PHINode>(&I))
+        reorderPHIIncomingValues(Phi);
     }
-
     foldInstructionName(&I);
   }
 
@@ -195,8 +194,8 @@ void IRNormalizer::nameInstruction(Instruction *I) {
 }
 
 template <typename T>
-void IRNormalizer::sortCommutativeOperands(T &Operands) const {
-  if (Operands.size() < 2)
+void IRNormalizer::sortCommutativeOperands(Instruction *I, T &Operands) const {
+  if (!(I->isCommutative() && Operands.size() >= 2))
     return;
   auto CommutativeEnd = Operands.begin();
   std::advance(CommutativeEnd, 2);
@@ -234,8 +233,7 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
     }
   }
 
-  if (I->isCommutative())
-    sortCommutativeOperands(Operands);
+  sortCommutativeOperands(I, Operands);
 
   // Initialize to a magic constant, so the state isn't zero.
   uint64_t Hash = MagicHashConstant;
@@ -264,7 +262,7 @@ void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
   }
 
   Name.append("(");
-  for (int i = 0; i < Operands.size(); ++i) {
+  for (size_t i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)
@@ -318,8 +316,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
     }
   }
 
-  if (I->isCommutative())
-    sortCommutativeOperands(Operands);
+  sortCommutativeOperands(I, Operands);
 
   // Initialize to a magic constant, so the state isn't zero.
   uint64_t Hash = MagicHashConstant;
@@ -335,8 +332,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
     if (auto *I = dyn_cast<Instruction>(Op))
       OperandsOpcodes.push_back(I->getOpcode());
 
-  if (I->isCommutative())
-    sortCommutativeOperands(OperandsOpcodes);
+  sortCommutativeOperands(I, OperandsOpcodes);
 
   // Consider operand opcodes in the hash.
   for (const int Code : OperandsOpcodes)
@@ -352,7 +348,7 @@ void IRNormalizer::nameAsRegularInstruction(Instruction *I) {
       Name.append(F->getName());
 
   Name.append("(");
-  for (int i = 0; i < Operands.size(); ++i) {
+  for (size_t i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)
@@ -405,14 +401,13 @@ void IRNormalizer::foldInstructionName(Instruction *I) const {
     }
   }
 
-  if (I->isCommutative())
-    sortCommutativeOperands(Operands);
+  sortCommutativeOperands(I, Operands);
 
   SmallString<256> Name;
   Name.append(I->getName().substr(0, 7));
 
   Name.append("(");
-  for (int i = 0; i < Operands.size(); ++i) {
+  for (size_t i = 0; i < Operands.size(); ++i) {
     Name.append(Operands[i]);
 
     if (i < Operands.size() - 1)
@@ -550,7 +545,7 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
   }
 
   // Sort operands.
-  sortCommutativeOperands(Operands);
+  sortCommutativeOperands(I, Operands);
 
   // Reorder operands.
   unsigned Position = 0;
@@ -563,14 +558,14 @@ void IRNormalizer::reorderInstructionOperandsByNames(Instruction *I) const {
 /// Reorders PHI node's values according to the names of corresponding basic
 /// blocks.
 ///
-/// \param PN PHI node to normalize.
-void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) const {
+/// \param Phi PHI node to normalize.
+void IRNormalizer::reorderPHIIncomingValues(PHINode *Phi) const {
   // Values for further sorting.
   SmallVector<std::pair<Value *, BasicBlock *>, 2> Values;
 
   // Collect blocks and corresponding values.
-  for (auto &BB : PN->blocks()) {
-    Value *V = PN->getIncomingValueForBlock(BB);
+  for (auto &BB : Phi->blocks()) {
+    Value *V = Phi->getIncomingValueForBlock(BB);
     Values.push_back(std::pair<Value *, BasicBlock *>(V, BB));
   }
 
@@ -582,8 +577,8 @@ void IRNormalizer::reorderPHIIncomingValues(PHINode *PN) const {
 
   // Swap.
   for (unsigned i = 0; i < Values.size(); ++i) {
-    PN->setIncomingBlock(i, Values[i].second);
-    PN->setIncomingValue(i, Values[i].first);
+    Phi->setIncomingBlock(i, Values[i].second);
+    Phi->setIncomingValue(i, Values[i].first);
   }
 }
 

>From aff753b5ef4be9a7036df2da9495050e6d8ff8dc Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 19:58:13 -0700
Subject: [PATCH 62/70] clang-format

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

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index afe3194ab8f47e..4650a54d24ee6b 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -83,7 +83,8 @@ class IRNormalizer {
 
   /// \name Utility methods.
   /// @{
-  template <typename T> void sortCommutativeOperands(Instruction *I, T &Operands) const;
+  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;

>From 291f53fef985767f8cf2a4b781a4cc30c83c0ec3 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 31 Aug 2024 20:16:00 -0700
Subject: [PATCH 63/70] [NFC] Refactor `if` for readability

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 4650a54d24ee6b..ee2363f8004cea 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -217,7 +217,9 @@ void IRNormalizer::sortCommutativeOperands(Instruction *I, T &Operands) const {
 /// \see getOutputFootprint()
 /// \param I Instruction to be renamed.
 void IRNormalizer::nameAsInitialInstruction(Instruction *I) const {
-  if (I->getType()->isVoidTy() || (!I->getName().empty() && !RenameAll))
+  if (I->getType()->isVoidTy())
+    return;
+  if (!(I->getName().empty() || RenameAll))
     return;
   LLVM_DEBUG(dbgs() << "Naming initial instruction: " << *I << "\n");
 

>From e9b3d29724486293a49da73ff9941bb1b6e63e56 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 7 Sep 2024 18:41:44 -0700
Subject: [PATCH 64/70] Auto generate tests

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp    |   8 +-
 .../IRNormalizer/naming-args-instr-blocks.ll  |  22 ++--
 .../IRNormalizer/naming-arguments.ll          |   8 +-
 llvm/test/Transforms/IRNormalizer/naming.ll   |  21 +++-
 .../regression-coro-elide-musttail.ll         |  10 +-
 .../IRNormalizer/regression-deoptimize.ll     |   3 +-
 .../regression-dont-hoist-deoptimize.ll       |  10 +-
 .../IRNormalizer/regression-infinite-loop.ll  | 100 +++++++++++++++++-
 .../IRNormalizer/reordering-basic.ll          |  32 ++++--
 9 files changed, 183 insertions(+), 31 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index ee2363f8004cea..c961ad2444b55f 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -97,16 +97,16 @@ class IRNormalizer {
 } // namespace
 
 cl::opt<bool> IRNormalizer::PreserveOrder(
-    "norm-preserve-order", cl::Hidden,
+    "norm-preserve-order", cl::Hidden, cl::init(false),
     cl::desc("Preserves original instruction order"));
 cl::opt<bool> IRNormalizer::RenameAll(
-    "norm-rename-all", cl::Hidden,
+    "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,
+    "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,
+    "norm-reorder-operands", cl::Hidden, cl::init(true),
     cl::desc("Sorts and reorders operands in commutative instructions"));
 
 /// Entry method to the IRNormalizer.
diff --git a/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
index 104ffc8dd6e39f..7845a22e3ae174 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-args-instr-blocks.ll
@@ -1,14 +1,18 @@
-; RUN: opt -S -passes=normalize -norm-rename-all -norm-preserve-order < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
-; CHECK: @foo(i32 %a0)
 define i32 @foo(i32) {
-; CHECK: bb{{([0-9]{5})}}
+; CHECK-LABEL: define i32 @foo(
+; CHECK-SAME: i32 [[A0:%.*]]) {
+; CHECK-NEXT:  [[BB17254:.*:]]
+; CHECK-NEXT:    %"vl24903([[A0]], 2)" = add i32 [[A0]], 2
+; CHECK-NEXT:    %"op10412(vl24903)" = add i32 6, %"vl24903([[A0]], 2)"
+; CHECK-NEXT:    ret i32 %"op10412(vl24903)"
+;
 entry:
-    ; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
-    %a = add i32 %0, 2
-    
-    ; CHECK: %"op{{([0-9]{5})}}(6, vl{{([0-9]{5})}}(%a0, 2))"
-    %b = add i32 %a, 6
+  %a = add i32 %0, 2
 
-    ret i32 %b
+  %b = add i32 %a, 6
+
+  ret i32 %b
 }
diff --git a/llvm/test/Transforms/IRNormalizer/naming-arguments.ll b/llvm/test/Transforms/IRNormalizer/naming-arguments.ll
index 3a1d435f76fdd0..a0066c97ca3db3 100644
--- a/llvm/test/Transforms/IRNormalizer/naming-arguments.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming-arguments.ll
@@ -1,7 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
-; CHECK: @foo(i32 %a0, i32 %a1)
 define i32 @foo(i32, i32) {
+; CHECK-LABEL: define i32 @foo(
+; CHECK-SAME: i32 [[A0:%.*]], i32 [[A1:%.*]]) {
+; CHECK-NEXT:  [[BB17254:.*:]]
+; CHECK-NEXT:    %"vl20416([[A0]], [[A1]])" = mul i32 [[A0]], [[A1]]
+; CHECK-NEXT:    ret i32 %"vl20416([[A0]], [[A1]])"
+;
   %tmp = mul i32 %0, %1
   ret i32 %tmp
 }
diff --git a/llvm/test/Transforms/IRNormalizer/naming.ll b/llvm/test/Transforms/IRNormalizer/naming.ll
index 9f9b033b6a5855..7c93a6213a4a9f 100644
--- a/llvm/test/Transforms/IRNormalizer/naming.ll
+++ b/llvm/test/Transforms/IRNormalizer/naming.ll
@@ -1,19 +1,30 @@
-; RUN: opt -S -passes=normalize -norm-rename-all < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 define i32 @foo(i32 %a0) {
-; CHECK: bb{{([0-9]{5})}}
+; CHECK-LABEL: define i32 @foo(
+; CHECK-SAME: i32 [[A0:%.*]]) {
+; CHECK-NEXT:  [[BB17254:.*:]]
+; CHECK-NEXT:    %"vl12603([[A0]], 2)" = add i32 [[A0]], 2
+; CHECK-NEXT:    ret i32 %"vl12603([[A0]], 2)"
+;
 entry:
   %a = add i32 %a0, 2
   ret i32 %a
 }
 
 define i32 @bar(i32 %a0) {
+; CHECK-LABEL: define i32 @bar(
+; CHECK-SAME: i32 [[A0:%.*]]) {
+; CHECK-NEXT:  [[BB17254:.*:]]
+; CHECK-NEXT:    %"vl76167([[A0]], 2)" = add i32 [[A0]], 2
+; CHECK-NEXT:    %"op10412(vl76167)" = add i32 6, %"vl76167([[A0]], 2)"
+; CHECK-NEXT:    %"op10412(op10412)" = add i32 8, %"op10412(vl76167)"
+; CHECK-NEXT:    ret i32 %"op10412(op10412)"
+;
 entry:
-; CHECK: %"vl{{([0-9]{5})}}(%a0, 2)"
   %a = add i32 %a0, 2
-; CHECK: %"op{{([0-9]{5})}}(vl{{([0-9]{5})}})"
   %b = add i32 %a, 6
-; CHECK: %"op{{([0-9]{5})}}(8, op{{([0-9]{5})}}(6, vl{{([0-9]{5})}}(%a0, 2)))"
   %c = add i32 %b, 8
   ret i32 %c
 }
diff --git a/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll b/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
index e24f4d8c5f5c57..891eae0954a7c1 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-coro-elide-musttail.ll
@@ -1,6 +1,14 @@
-; RUN: opt < %s -passes=normalize -verify-each
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 define fastcc void @foo.resume_musttail(ptr %FramePtr) {
+; CHECK-LABEL: define fastcc void @foo.resume_musttail(
+; CHECK-SAME: ptr [[A0:%.*]]) {
+; CHECK-NEXT:  [[BB15160:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+; CHECK-NEXT:    musttail call fastcc void undef(ptr null)
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
   musttail call fastcc void undef(ptr null)
diff --git a/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
index b4bda7dd7d7674..ceaceab9bf0822 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
@@ -1,4 +1,5 @@
-; RUN: opt < %s -passes=normalize -verify-each
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
 
diff --git a/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
index e218d8f67d8870..d3d3e33723f029 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-dont-hoist-deoptimize.ll
@@ -1,10 +1,18 @@
-; RUN: opt %s -passes=normalize -verify-each
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
+
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
 target triple = "x86_64-unknown-linux-gnu"
 
 declare void @llvm.experimental.deoptimize.isVoid(...)
 
 define void @widget() {
+; CHECK-LABEL: define void @widget() {
+; CHECK-NEXT:  [[BB15160:.*:]]
+; CHECK-NEXT:    [[TMP3:%.*]] = trunc i64 0 to i32
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"() ]
+; CHECK-NEXT:    ret void
+;
 bb:
   %tmp3 = trunc i64 0 to i32
   call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"() ]
diff --git a/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll b/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
index 109858e97fd36a..35ac0fd8c329a7 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-infinite-loop.ll
@@ -1,7 +1,103 @@
-; RUN: opt -passes=normalize -norm-preserve-order=true < %s
-; RUN: opt -passes=normalize -norm-preserve-order=false < %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 define void @test(ptr, i32) {
+; CHECK-LABEL: define void @test(
+; CHECK-SAME: ptr [[A0:%.*]], i32 [[A1:%.*]]) {
+; CHECK-NEXT:  [[BB76951:.*]]:
+; CHECK-NEXT:    %"vl72693([[A1]], 1)" = add i32 [[A1]], 1
+; CHECK-NEXT:    br label %[[BB16110:.*]]
+; CHECK:       [[BB16110]]:
+; CHECK-NEXT:    %"op10912(op18080, vl72693)" = phi i32 [ %"op18080(op10412, op17645)", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
+; CHECK-NEXT:    %"op10912(op17645, vl72693)" = phi i32 [ %"op17645(op10912)70", %[[BB16110]] ], [ %"vl72693([[A1]], 1)", %[[BB76951]] ]
+; CHECK-NEXT:    %"op15084(op10912)" = mul i32 %"op10912(op18080, vl72693)", undef
+; CHECK-NEXT:    %"op16562(op15084)" = xor i32 -1, %"op15084(op10912)"
+; CHECK-NEXT:    %"op44627(op10912, op16562)" = add i32 %"op10912(op18080, vl72693)", %"op16562(op15084)"
+; CHECK-NEXT:    %"op17645(op10912)" = add i32 -1, %"op10912(op17645, vl72693)"
+; CHECK-NEXT:    %"op18080(op17645, op44627)" = add i32 %"op17645(op10912)", %"op44627(op10912, op16562)"
+; CHECK-NEXT:    %"op17720(op15084, op18080)" = mul i32 %"op15084(op10912)", %"op18080(op17645, op44627)"
+; CHECK-NEXT:    %"op16562(op17720)" = xor i32 -1, %"op17720(op15084, op18080)"
+; CHECK-NEXT:    %"op17430(op16562, op18080)" = add i32 %"op16562(op17720)", %"op18080(op17645, op44627)"
+; CHECK-NEXT:    %"op10412(op17430)" = add i32 %"op17430(op16562, op18080)", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)" = mul i32 %"op10412(op17430)", %"op17720(op15084, op18080)"
+; CHECK-NEXT:    %"op16562(op17720)1" = xor i32 -1, %"op17720(op10412, op17720)"
+; CHECK-NEXT:    %"op17430(op10412, op16562)" = add i32 %"op10412(op17430)", %"op16562(op17720)1"
+; CHECK-NEXT:    %"op10412(op17430)2" = add i32 %"op17430(op10412, op16562)", undef
+; CHECK-NEXT:    %"op10412(op10412)" = add i32 %"op10412(op17430)2", undef
+; CHECK-NEXT:    %"op10412(op10412)3" = add i32 %"op10412(op10412)", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)4" = mul i32 %"op10412(op17430)2", %"op17720(op10412, op17720)"
+; CHECK-NEXT:    %"op17720(op10412, op17720)5" = mul i32 %"op10412(op10412)3", %"op17720(op10412, op17720)4"
+; CHECK-NEXT:    %"op16562(op17720)6" = xor i32 -1, %"op17720(op10412, op17720)5"
+; CHECK-NEXT:    %"op17430(op10412, op16562)7" = add i32 %"op10412(op10412)3", %"op16562(op17720)6"
+; CHECK-NEXT:    %"op10412(op17430)8" = add i32 %"op17430(op10412, op16562)7", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)9" = mul i32 %"op10412(op17430)8", %"op17720(op10412, op17720)5"
+; CHECK-NEXT:    %"op16562(op17720)10" = xor i32 -1, %"op17720(op10412, op17720)9"
+; CHECK-NEXT:    %"op17430(op10412, op16562)11" = add i32 %"op10412(op17430)8", %"op16562(op17720)10"
+; CHECK-NEXT:    %"op10412(op17430)12" = add i32 %"op17430(op10412, op16562)11", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)13" = mul i32 %"op10412(op17430)12", %"op17720(op10412, op17720)9"
+; CHECK-NEXT:    %"op16562(op17720)14" = xor i32 -1, %"op17720(op10412, op17720)13"
+; CHECK-NEXT:    %"op17430(op10412, op16562)15" = add i32 %"op10412(op17430)12", %"op16562(op17720)14"
+; CHECK-NEXT:    %"op10412(op17430)16" = add i32 %"op17430(op10412, op16562)15", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)17" = mul i32 %"op10412(op17430)16", %"op17720(op10412, op17720)13"
+; CHECK-NEXT:    %"op16562(op17720)18" = xor i32 -1, %"op17720(op10412, op17720)17"
+; CHECK-NEXT:    %"op17430(op10412, op16562)19" = add i32 %"op10412(op17430)16", %"op16562(op17720)18"
+; CHECK-NEXT:    %"op10412(op17430)20" = add i32 %"op17430(op10412, op16562)19", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)21" = mul i32 %"op10412(op17430)20", %"op17720(op10412, op17720)17"
+; CHECK-NEXT:    %"op16562(op17720)22" = xor i32 -1, %"op17720(op10412, op17720)21"
+; CHECK-NEXT:    %"op17430(op10412, op16562)23" = add i32 %"op10412(op17430)20", %"op16562(op17720)22"
+; CHECK-NEXT:    %"op17645(op10912)24" = add i32 -9, %"op10912(op17645, vl72693)"
+; CHECK-NEXT:    %"op18080(op17430, op17645)" = add i32 %"op17430(op10412, op16562)23", %"op17645(op10912)24"
+; CHECK-NEXT:    %"op17720(op17720, op18080)" = mul i32 %"op17720(op10412, op17720)21", %"op18080(op17430, op17645)"
+; CHECK-NEXT:    %"op16562(op17720)25" = xor i32 -1, %"op17720(op17720, op18080)"
+; CHECK-NEXT:    %"op17430(op16562, op18080)26" = add i32 %"op16562(op17720)25", %"op18080(op17430, op17645)"
+; CHECK-NEXT:    %"op10412(op17430)27" = add i32 %"op17430(op16562, op18080)26", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)28" = mul i32 %"op10412(op17430)27", %"op17720(op17720, op18080)"
+; CHECK-NEXT:    %"op16562(op17720)29" = xor i32 -1, %"op17720(op10412, op17720)28"
+; CHECK-NEXT:    %"op17430(op10412, op16562)30" = add i32 %"op10412(op17430)27", %"op16562(op17720)29"
+; CHECK-NEXT:    %"op10412(op17430)31" = add i32 %"op17430(op10412, op16562)30", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)32" = mul i32 %"op10412(op17430)31", %"op17720(op10412, op17720)28"
+; CHECK-NEXT:    %"op16562(op17720)33" = xor i32 -1, %"op17720(op10412, op17720)32"
+; CHECK-NEXT:    %"op17430(op10412, op16562)34" = add i32 %"op10412(op17430)31", %"op16562(op17720)33"
+; CHECK-NEXT:    %"op10412(op17430)35" = add i32 %"op17430(op10412, op16562)34", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)36" = mul i32 %"op10412(op17430)35", %"op17720(op10412, op17720)32"
+; CHECK-NEXT:    %"op16562(op17720)37" = xor i32 -1, %"op17720(op10412, op17720)36"
+; CHECK-NEXT:    %"op17430(op10412, op16562)38" = add i32 %"op10412(op17430)35", %"op16562(op17720)37"
+; CHECK-NEXT:    %"op10412(op17430)39" = add i32 %"op17430(op10412, op16562)38", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)40" = mul i32 %"op10412(op17430)39", %"op17720(op10412, op17720)36"
+; CHECK-NEXT:    %"op16562(op17720)41" = xor i32 -1, %"op17720(op10412, op17720)40"
+; CHECK-NEXT:    %"op17430(op10412, op16562)42" = add i32 %"op10412(op17430)39", %"op16562(op17720)41"
+; CHECK-NEXT:    %"op17645(op10912)43" = add i32 -14, %"op10912(op17645, vl72693)"
+; CHECK-NEXT:    %"op18080(op17430, op17645)44" = add i32 %"op17430(op10412, op16562)42", %"op17645(op10912)43"
+; CHECK-NEXT:    %"op17720(op17720, op18080)45" = mul i32 %"op17720(op10412, op17720)40", %"op18080(op17430, op17645)44"
+; CHECK-NEXT:    %"op16562(op17720)46" = xor i32 -1, %"op17720(op17720, op18080)45"
+; CHECK-NEXT:    %"op17430(op16562, op18080)47" = add i32 %"op16562(op17720)46", %"op18080(op17430, op17645)44"
+; CHECK-NEXT:    %"op10412(op17430)48" = add i32 %"op17430(op16562, op18080)47", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)49" = mul i32 %"op10412(op17430)48", %"op17720(op17720, op18080)45"
+; CHECK-NEXT:    %"op16562(op17720)50" = xor i32 -1, %"op17720(op10412, op17720)49"
+; CHECK-NEXT:    %"op17430(op10412, op16562)51" = add i32 %"op10412(op17430)48", %"op16562(op17720)50"
+; CHECK-NEXT:    %"op10412(op17430)52" = add i32 %"op17430(op10412, op16562)51", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)53" = mul i32 %"op10412(op17430)52", %"op17720(op10412, op17720)49"
+; CHECK-NEXT:    %"op16562(op17720)54" = xor i32 -1, %"op17720(op10412, op17720)53"
+; CHECK-NEXT:    %"op17430(op10412, op16562)55" = add i32 %"op10412(op17430)52", %"op16562(op17720)54"
+; CHECK-NEXT:    %"op10412(op17430)56" = add i32 %"op17430(op10412, op16562)55", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)57" = mul i32 %"op10412(op17430)56", %"op17720(op10412, op17720)53"
+; CHECK-NEXT:    %"op16562(op17720)58" = xor i32 -1, %"op17720(op10412, op17720)57"
+; CHECK-NEXT:    %"op17430(op10412, op16562)59" = add i32 %"op10412(op17430)56", %"op16562(op17720)58"
+; CHECK-NEXT:    %"op10412(op17430)60" = add i32 %"op17430(op10412, op16562)59", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)61" = mul i32 %"op10412(op17430)60", %"op17720(op10412, op17720)57"
+; CHECK-NEXT:    %"op16562(op17720)62" = xor i32 -1, %"op17720(op10412, op17720)61"
+; CHECK-NEXT:    %"op17430(op10412, op16562)63" = add i32 %"op10412(op17430)60", %"op16562(op17720)62"
+; CHECK-NEXT:    %"op10412(op17430)64" = add i32 %"op17430(op10412, op16562)63", undef
+; CHECK-NEXT:    %"op17720(op10412, op17720)65" = mul i32 %"op10412(op17430)64", %"op17720(op10412, op17720)61"
+; CHECK-NEXT:    %"op16562(op17720)66" = xor i32 -1, %"op17720(op10412, op17720)65"
+; CHECK-NEXT:    %"op17430(op10412, op16562)67" = add i32 %"op10412(op17430)64", %"op16562(op17720)66"
+; CHECK-NEXT:    %"op10412(op17430)68" = add i32 %"op17430(op10412, op16562)67", undef
+; CHECK-NEXT:    %"op10412(op10412)69" = add i32 %"op10412(op17430)68", undef
+; CHECK-NEXT:    %"op17645(op10912)70" = add i32 -21, %"op10912(op17645, vl72693)"
+; CHECK-NEXT:    %"op18080(op10412, op17645)" = add i32 %"op10412(op10412)69", %"op17645(op10912)70"
+; CHECK-NEXT:    store i32 %"op18080(op10412, op17645)", ptr [[A0]], align 4
+; CHECK-NEXT:    br label %[[BB16110]]
+;
 bb:
   %a = add i32 %1, 1
   br label %bb1
diff --git a/llvm/test/Transforms/IRNormalizer/reordering-basic.ll b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
index 59cf3900a6a946..fd09ce016addbc 100644
--- a/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
+++ b/llvm/test/Transforms/IRNormalizer/reordering-basic.ll
@@ -1,12 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -S -passes=normalize < %s | FileCheck %s
 
 define double @foo(double %a0, double %a1) {
-; CHECK-LABEL: foo(
+; CHECK-LABEL: define double @foo(
+; CHECK-SAME: double [[A0:%.*]], double [[A1:%.*]]) {
+; CHECK-NEXT:  [[BB17254:.*:]]
+; CHECK-NEXT:    %"vl93562([[A0]], 2.000000e+00)" = fmul double [[A0]], 2.000000e+00
+; CHECK-NEXT:    %"op95858(vl93562)" = fmul double 6.000000e+00, %"vl93562([[A0]], 2.000000e+00)"
+; CHECK-NEXT:    [[A:%.*]] = fmul double [[A0]], [[A1]]
+; CHECK-NEXT:    [[C:%.*]] = fmul double 6.000000e+00, [[A]]
+; CHECK-NEXT:    ret double %"op95858(vl93562)"
+;
 entry:
-; CHECK: %b
-; CHECK: %d
-; CHECK: %a
-; CHECK: %c
   %a = fmul double %a0, %a1
   %b = fmul double %a0, 2.000000e+00
   %c = fmul double %a, 6.000000e+00
@@ -19,7 +24,21 @@ declare double @bir()
 declare double @bar()
 
 define double @baz(double %x) {
-; CHECK-LABEL: baz(
+; CHECK-LABEL: define double @baz(
+; CHECK-SAME: double [[A0:%.*]]) {
+; CHECK-NEXT:  [[BB76951:.*:]]
+; CHECK-NEXT:    [[IFCOND:%.*]] = fcmp one double [[A0]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[IFCOND]], label %[[BB91455:.*]], label %[[BB914551:.*]]
+; CHECK:       [[BB91455]]:
+; CHECK-NEXT:    %"vl15001bir()" = call double @bir()
+; CHECK-NEXT:    br label %[[BB17254:.*]]
+; CHECK:       [[BB914551]]:
+; CHECK-NEXT:    %"vl69719bar()" = call double @bar()
+; CHECK-NEXT:    br label %[[BB17254]]
+; CHECK:       [[BB17254]]:
+; CHECK-NEXT:    %"op19734(vl15001, vl69719)" = phi double [ %"vl15001bir()", %[[BB91455]] ], [ %"vl69719bar()", %[[BB914551]] ]
+; CHECK-NEXT:    ret double %"op19734(vl15001, vl69719)"
+;
 entry:
   %ifcond = fcmp one double %x, 0.000000e+00
   br i1 %ifcond, label %then, label %else
@@ -33,7 +52,6 @@ else:       ; preds = %entry
   br label %ifcont
 
 ifcont:     ; preds = %else, %then
-; CHECK: %iftmp = phi double [ %calltmp1, %else ], [ %calltmp, %then ]
   %iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
   ret double %iftmp
 }

>From 876d6cf5b4894c3f704d84b5e6d65ea9279fa9ea Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 7 Sep 2024 19:56:01 -0700
Subject: [PATCH 65/70] Handle convergence intrinsics

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp    | 13 +++++++--
 .../regression-convergence-tokens.ll          | 27 +++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index c961ad2444b55f..83be9634dc35af 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -468,8 +468,13 @@ void IRNormalizer::reorderInstructions(Function &F) const {
     // Reorder based on the topological sort.
     while (!TopologicalSort.empty()) {
       auto *Instruction = TopologicalSort.top();
-      auto *FirstNonPHIOrDbgOrAlloca = &*BB.getFirstNonPHIOrDbgOrAlloca();
-      Instruction->moveBefore(FirstNonPHIOrDbgOrAlloca);
+      auto FirstNonPHIOrDbgOrAlloca = BB.getFirstNonPHIOrDbgOrAlloca();
+      if (auto *Call = dyn_cast<CallInst>(&*FirstNonPHIOrDbgOrAlloca)) {
+        if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_entry || 
+            Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
+          FirstNonPHIOrDbgOrAlloca++;
+      }
+      Instruction->moveBefore(&*FirstNonPHIOrDbgOrAlloca);
       TopologicalSort.pop();
     }
   }
@@ -508,6 +513,10 @@ void IRNormalizer::reorderDefinition(
       return;
     if (Call->getIntrinsicID() == Intrinsic::experimental_deoptimize)
       return;
+    if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_entry)
+      return;
+    if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
+      return;
   }
   if (auto *BitCast = dyn_cast<BitCastInst>(Definition)) {
     if (auto *Call = dyn_cast<CallInst>(BitCast->getOperand(0))) {
diff --git a/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll b/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll
new file mode 100644
index 00000000000000..633cf091da5085
--- /dev/null
+++ b/llvm/test/Transforms/IRNormalizer/regression-convergence-tokens.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=normalize < %s | FileCheck %s
+
+; Function Attrs: convergent nounwind readnone
+define i32 @nested(i32 %src) #0 {
+; CHECK-LABEL: define i32 @nested(
+; CHECK-SAME: i32 [[A0:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[BB15160:.*:]]
+; CHECK-NEXT:    [[T1:%.*]] = call token @llvm.experimental.convergence.entry()
+; CHECK-NEXT:    %"vl15001llvm.experimental.convergence.anchor()" = call token @llvm.experimental.convergence.anchor()
+; CHECK-NEXT:    %"op68297llvm.amdgcn.readfirstlane.i32([[A0]], vl15001llvm.experimental.convergence.anchor())" = call i32 @llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token %"vl15001llvm.experimental.convergence.anchor()") ]
+; CHECK-NEXT:    ret i32 undef
+;
+  %t1 = call token @llvm.experimental.convergence.entry()
+  %t2 = call token @llvm.experimental.convergence.anchor()
+  %r2 = call i32 @llvm.amdgcn.readfirstlane(i32 %src) [ "convergencectrl"(token %t2) ]
+  ret i32 undef
+}
+
+; Function Attrs: convergent nounwind readnone
+declare i32 @llvm.amdgcn.readfirstlane(i32) #0
+
+declare token @llvm.experimental.convergence.entry()
+
+declare token @llvm.experimental.convergence.anchor()
+
+attributes #0 = { convergent nounwind readnone }

>From 5a3c2263b46dc42206ca762f9c8259dafaee6299 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 7 Sep 2024 20:04:05 -0700
Subject: [PATCH 66/70] clang-format

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

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 83be9634dc35af..74c8fc26a0acd5 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -470,7 +470,8 @@ void IRNormalizer::reorderInstructions(Function &F) const {
       auto *Instruction = TopologicalSort.top();
       auto FirstNonPHIOrDbgOrAlloca = BB.getFirstNonPHIOrDbgOrAlloca();
       if (auto *Call = dyn_cast<CallInst>(&*FirstNonPHIOrDbgOrAlloca)) {
-        if (Call->getIntrinsicID() == Intrinsic::experimental_convergence_entry || 
+        if (Call->getIntrinsicID() ==
+                Intrinsic::experimental_convergence_entry ||
             Call->getIntrinsicID() == Intrinsic::experimental_convergence_loop)
           FirstNonPHIOrDbgOrAlloca++;
       }

>From 3cac781eff4b4927f36309e1aa1702d9856d94b8 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Sat, 7 Sep 2024 21:08:24 -0700
Subject: [PATCH 67/70] Add checks for regression-deoptimize.ll

---
 llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
index ceaceab9bf0822..594ea6109499a1 100644
--- a/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
+++ b/llvm/test/Transforms/IRNormalizer/regression-deoptimize.ll
@@ -4,6 +4,12 @@
 target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
 
 define void @test1() {
+; CHECK-LABEL: define void @test1() {
+; CHECK-NEXT:  [[BB15160:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr null, align 1
+; CHECK-NEXT:    call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
+; CHECK-NEXT:    ret void
+;
   %1 = load i8, ptr null, align 1
   call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
   ret void

>From ef6a751a794c3e2d266cac0242629043ddd0d2aa Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 12 Nov 2024 19:03:12 -0800
Subject: [PATCH 68/70] Port PreservedFunctionHashAnalysis and
 PreservedModuleHashAnalysis to Analysis

---
 llvm/include/llvm/Analysis/StructuralHash.h  | 33 +++++++++++++++++-
 llvm/lib/Analysis/StructuralHash.cpp         | 12 +++++--
 llvm/lib/Passes/StandardInstrumentations.cpp | 36 +-------------------
 3 files changed, 42 insertions(+), 39 deletions(-)

diff --git a/llvm/include/llvm/Analysis/StructuralHash.h b/llvm/include/llvm/Analysis/StructuralHash.h
index 4c9f063bc7d2c8..564f5b60b767ef 100644
--- a/llvm/include/llvm/Analysis/StructuralHash.h
+++ b/llvm/include/llvm/Analysis/StructuralHash.h
@@ -1,4 +1,4 @@
-//=- StructuralHash.h - Structural Hash Printing --*- C++ -*-----------------=//
+//=- StructuralHash.h - Structural Hash Printing and Analysis --*- C++ -*-----=//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -10,9 +10,40 @@
 #define LLVM_ANALYSIS_STRUCTURALHASH_H
 
 #include "llvm/IR/PassManager.h"
+#include "llvm/IR/StructuralHash.h"
 
 namespace llvm {
 
+struct PreservedFunctionHashAnalysis
+    : public AnalysisInfoMixin<PreservedFunctionHashAnalysis> {
+  static AnalysisKey Key;
+
+  struct FunctionHash {
+    uint64_t Hash;
+  };
+
+  using Result = FunctionHash;
+
+  Result run(Function &F, FunctionAnalysisManager &FAM) {
+    return Result{StructuralHash(F)};
+  }
+};
+
+struct PreservedModuleHashAnalysis
+    : public AnalysisInfoMixin<PreservedModuleHashAnalysis> {
+  static AnalysisKey Key;
+
+  struct ModuleHash {
+    uint64_t Hash;
+  };
+
+  using Result = ModuleHash;
+
+  Result run(Module &F, ModuleAnalysisManager &FAM) {
+    return Result{StructuralHash(F)};
+  }
+};
+
 enum class StructuralHashOptions {
   None,              /// Hash with opcode only.
   Detailed,          /// Hash with opcode and operands.
diff --git a/llvm/lib/Analysis/StructuralHash.cpp b/llvm/lib/Analysis/StructuralHash.cpp
index 4f2e003148b606..b18f391fe0be03 100644
--- a/llvm/lib/Analysis/StructuralHash.cpp
+++ b/llvm/lib/Analysis/StructuralHash.cpp
@@ -6,18 +6,24 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file defines the StructuralHashPrinterPass which is used to show
-// the structural hash of all functions in a module and the module itself.
+// This file defines the StructuralHashPrinterPass and the 
+// PreservedFunctionHashAnalysis and PreservedModuleHashAnalysis keys. 
+//
+// The StructuralHashPrinterPass is used to show the structural hash of all 
+// functions in a module and the module itself.
 //
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/StructuralHash.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/StructuralHash.h"
 #include "llvm/Support/Format.h"
 
 using namespace llvm;
 
+AnalysisKey PreservedFunctionHashAnalysis::Key;
+
+AnalysisKey PreservedModuleHashAnalysis::Key;
+
 PreservedAnalyses StructuralHashPrinterPass::run(Module &M,
                                                  ModuleAnalysisManager &MAM) {
   OS << "Module Hash: "
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index d4866a025c1b48..2d6aee0dab5f69 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Analysis/CallGraphSCCPass.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/StructuralHash.h"
 #include "llvm/CodeGen/MIRPrinter.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
@@ -30,7 +31,6 @@
 #include "llvm/IR/PassInstrumentation.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/PrintPasses.h"
-#include "llvm/IR/StructuralHash.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/CrashRecoveryContext.h"
@@ -1303,40 +1303,6 @@ struct PreservedCFGCheckerAnalysis
 
 AnalysisKey PreservedCFGCheckerAnalysis::Key;
 
-struct PreservedFunctionHashAnalysis
-    : public AnalysisInfoMixin<PreservedFunctionHashAnalysis> {
-  static AnalysisKey Key;
-
-  struct FunctionHash {
-    uint64_t Hash;
-  };
-
-  using Result = FunctionHash;
-
-  Result run(Function &F, FunctionAnalysisManager &FAM) {
-    return Result{StructuralHash(F)};
-  }
-};
-
-AnalysisKey PreservedFunctionHashAnalysis::Key;
-
-struct PreservedModuleHashAnalysis
-    : public AnalysisInfoMixin<PreservedModuleHashAnalysis> {
-  static AnalysisKey Key;
-
-  struct ModuleHash {
-    uint64_t Hash;
-  };
-
-  using Result = ModuleHash;
-
-  Result run(Module &F, ModuleAnalysisManager &FAM) {
-    return Result{StructuralHash(F)};
-  }
-};
-
-AnalysisKey PreservedModuleHashAnalysis::Key;
-
 bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
     Function &F, const PreservedAnalyses &PA,
     FunctionAnalysisManager::Invalidator &) {

>From 5dda94115b59df2a46e8d15a2770e8e49d6153e7 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 12 Nov 2024 19:03:31 -0800
Subject: [PATCH 69/70] Abandon PreservedFunctionHashAnalysis and
 PreservedModuleHashAnalysis in IRNormalizer

---
 llvm/lib/Transforms/Utils/IRNormalizer.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Utils/IRNormalizer.cpp b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
index 74c8fc26a0acd5..e04839e9e793de 100644
--- a/llvm/lib/Transforms/Utils/IRNormalizer.cpp
+++ b/llvm/lib/Transforms/Utils/IRNormalizer.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/StructuralHash.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
@@ -691,5 +692,8 @@ SetVector<int> IRNormalizer::getOutputFootprint(
 PreservedAnalyses IRNormalizerPass::run(Function &F,
                                         FunctionAnalysisManager &AM) const {
   IRNormalizer{}.runOnFunction(F);
-  return PreservedAnalyses::all();
+  auto PA = PreservedAnalyses::all();
+  PA.abandon<PreservedFunctionHashAnalysis>();
+  PA.abandon<PreservedModuleHashAnalysis>();
+  return PA;
 }

>From 3c33b5bac79b5769f9708f33b8d7e0e101fe9c62 Mon Sep 17 00:00:00 2001
From: Justin Fargnoli <jfargnoli at nvidia.com>
Date: Tue, 12 Nov 2024 19:12:08 -0800
Subject: [PATCH 70/70] clang-format

---
 llvm/include/llvm/Analysis/StructuralHash.h | 2 +-
 llvm/lib/Analysis/StructuralHash.cpp        | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Analysis/StructuralHash.h b/llvm/include/llvm/Analysis/StructuralHash.h
index 564f5b60b767ef..9ab13e43a3aa9d 100644
--- a/llvm/include/llvm/Analysis/StructuralHash.h
+++ b/llvm/include/llvm/Analysis/StructuralHash.h
@@ -1,4 +1,4 @@
-//=- StructuralHash.h - Structural Hash Printing and Analysis --*- C++ -*-----=//
+//=- StructuralHash.h - Structural Hash Printing and Analysis --*- C++ -*----=//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/llvm/lib/Analysis/StructuralHash.cpp b/llvm/lib/Analysis/StructuralHash.cpp
index b18f391fe0be03..f01d0064d2b619 100644
--- a/llvm/lib/Analysis/StructuralHash.cpp
+++ b/llvm/lib/Analysis/StructuralHash.cpp
@@ -6,10 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file defines the StructuralHashPrinterPass and the 
-// PreservedFunctionHashAnalysis and PreservedModuleHashAnalysis keys. 
+// This file defines the StructuralHashPrinterPass and the
+// PreservedFunctionHashAnalysis and PreservedModuleHashAnalysis keys.
 //
-// The StructuralHashPrinterPass is used to show the structural hash of all 
+// The StructuralHashPrinterPass is used to show the structural hash of all
 // functions in a module and the module itself.
 //
 //===----------------------------------------------------------------------===//



More information about the cfe-commits mailing list