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