[llvm] [llvm-diff] Add colorful output to diff (PR #131012)

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 12 11:52:28 PDT 2025


Albert =?utf-8?q?Havliček?= <albert.havlicek at fit.cvut.cz>
Message-ID: <llvm.org/llvm/llvm-project/pull/131012 at github.com>
In-Reply-To:


https://github.com/Bertik23 created https://github.com/llvm/llvm-project/pull/131012

Adds colorful output when when possible to the diff. Similar to GNU diff
like this 
![image](https://github.com/user-attachments/assets/8dc4e995-11c4-4060-8c46-60535d8608e3)

First commit formats all files of llvm-diff with clang-format

>From 799e1304f887a3d5191e9e286d7bd0b606c29d69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <albert.havlicek at fit.cvut.cz>
Date: Sun, 9 Mar 2025 10:55:42 +0100
Subject: [PATCH 1/2] (llvm-diff) autoformat using clang-format with llvm style

---
 llvm/tools/llvm-diff/lib/DiffConsumer.cpp     |  68 +++++----
 llvm/tools/llvm-diff/lib/DiffConsumer.h       | 124 ++++++++---------
 llvm/tools/llvm-diff/lib/DiffLog.cpp          |   3 +-
 llvm/tools/llvm-diff/lib/DiffLog.h            | 124 ++++++++---------
 llvm/tools/llvm-diff/lib/DifferenceEngine.cpp | 131 +++++++++++-------
 llvm/tools/llvm-diff/lib/DifferenceEngine.h   | 103 +++++++-------
 llvm/tools/llvm-diff/llvm-diff.cpp            |   8 +-
 7 files changed, 297 insertions(+), 264 deletions(-)

diff --git a/llvm/tools/llvm-diff/lib/DiffConsumer.cpp b/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
index b6eb71916acf9..c93e6af7a72cc 100644
--- a/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
+++ b/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
@@ -41,7 +41,7 @@ static void ComputeNumbering(const Function *F,
   assert(!Numbering.empty() && "asked for numbering but numbering was no-op");
 }
 
-void Consumer::anchor() { }
+void Consumer::anchor() {}
 
 void DiffConsumer::printValue(const Value *V, bool isL) {
   if (V->hasName()) {
@@ -72,7 +72,8 @@ void DiffConsumer::printValue(const Value *V, bool isL) {
   while (N > 0) {
     --N;
     DiffContext &ctxt = contexts[N];
-    if (!ctxt.IsFunction) continue;
+    if (!ctxt.IsFunction)
+      continue;
     if (isL) {
       if (ctxt.LNumbering.empty())
         ComputeNumbering(cast<Function>(ctxt.L), ctxt.LNumbering);
@@ -90,19 +91,22 @@ void DiffConsumer::printValue(const Value *V, bool isL) {
 }
 
 void DiffConsumer::header() {
-  if (contexts.empty()) return;
-  for (SmallVectorImpl<DiffContext>::iterator
-         I = contexts.begin(), E = contexts.end(); I != E; ++I) {
-    if (I->Differences) continue;
+  if (contexts.empty())
+    return;
+  for (SmallVectorImpl<DiffContext>::iterator I = contexts.begin(),
+                                              E = contexts.end();
+       I != E; ++I) {
+    if (I->Differences)
+      continue;
     if (isa<Function>(I->L)) {
       // Extra newline between functions.
-      if (Differences) out << "\n";
+      if (Differences)
+        out << "\n";
 
       const Function *L = cast<Function>(I->L);
       const Function *R = cast<Function>(I->R);
       if (L->getName() != R->getName())
-        out << "in function " << L->getName()
-            << " / " << R->getName() << ":\n";
+        out << "in function " << L->getName() << " / " << R->getName() << ":\n";
       else
         out << "in function " << L->getName() << ":\n";
     } else if (isa<BasicBlock>(I->L)) {
@@ -131,7 +135,8 @@ void DiffConsumer::header() {
 
 void DiffConsumer::indent() {
   unsigned N = Indent;
-  while (N--) out << ' ';
+  while (N--)
+    out << ' ';
 }
 
 void DiffConsumer::reset() {
@@ -140,9 +145,7 @@ void DiffConsumer::reset() {
   Indent = 0;
 }
 
-bool DiffConsumer::hadDifferences() const {
-  return Differences;
-}
+bool DiffConsumer::hadDifferences() const { return Differences; }
 
 void DiffConsumer::enterContext(const Value *L, const Value *R) {
   contexts.push_back(DiffContext(L, R));
@@ -176,16 +179,24 @@ void DiffConsumer::logf(const LogBuilder &Log) {
     }
     assert(format[percent] == '%');
 
-    if (percent > 0) out << format.substr(0, percent);
+    if (percent > 0)
+      out << format.substr(0, percent);
 
-    switch (format[percent+1]) {
-    case '%': out << '%'; break;
-    case 'l': printValue(Log.getArgument(arg++), true); break;
-    case 'r': printValue(Log.getArgument(arg++), false); break;
-    default: llvm_unreachable("unknown format character");
+    switch (format[percent + 1]) {
+    case '%':
+      out << '%';
+      break;
+    case 'l':
+      printValue(Log.getArgument(arg++), true);
+      break;
+    case 'r':
+      printValue(Log.getArgument(arg++), false);
+      break;
+    default:
+      llvm_unreachable("unknown format character");
     }
 
-    format = format.substr(percent+2);
+    format = format.substr(percent + 2);
   }
 
   out << '\n';
@@ -199,20 +210,23 @@ void DiffConsumer::logd(const DiffLogBuilder &Log) {
     switch (Log.getLineKind(I)) {
     case DC_match:
       out << "  ";
-      Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
-      //printValue(Log.getLeft(I), true);
+      Log.getLeft(I)->print(dbgs());
+      dbgs() << '\n';
+      // printValue(Log.getLeft(I), true);
       break;
     case DC_left:
       out << "< ";
-      Log.getLeft(I)->print(dbgs()); dbgs() << '\n';
-      //printValue(Log.getLeft(I), true);
+      Log.getLeft(I)->print(dbgs());
+      dbgs() << '\n';
+      // printValue(Log.getLeft(I), true);
       break;
     case DC_right:
       out << "> ";
-      Log.getRight(I)->print(dbgs()); dbgs() << '\n';
-      //printValue(Log.getRight(I), false);
+      Log.getRight(I)->print(dbgs());
+      dbgs() << '\n';
+      // printValue(Log.getRight(I), false);
       break;
     }
-    //out << "\n";
+    // out << "\n";
   }
 }
diff --git a/llvm/tools/llvm-diff/lib/DiffConsumer.h b/llvm/tools/llvm-diff/lib/DiffConsumer.h
index 08c3afcbe111e..2adf80cc2070d 100644
--- a/llvm/tools/llvm-diff/lib/DiffConsumer.h
+++ b/llvm/tools/llvm-diff/lib/DiffConsumer.h
@@ -22,70 +22,70 @@
 
 namespace llvm {
 class StringRef;
-  class Module;
-  class Value;
-  class Function;
-
-  /// The interface for consumers of difference data.
-  class Consumer {
-    virtual void anchor();
-  public:
-    /// Record that a local context has been entered.  Left and
-    /// Right are IR "containers" of some sort which are being
-    /// considered for structural equivalence: global variables,
-    /// functions, blocks, instructions, etc.
-    virtual void enterContext(const Value *Left, const Value *Right) = 0;
-
-    /// Record that a local context has been exited.
-    virtual void exitContext() = 0;
-
-    /// Record a difference within the current context.
-    virtual void log(StringRef Text) = 0;
-
-    /// Record a formatted difference within the current context.
-    virtual void logf(const LogBuilder &Log) = 0;
-
-    /// Record a line-by-line instruction diff.
-    virtual void logd(const DiffLogBuilder &Log) = 0;
-
-  protected:
-    virtual ~Consumer() {}
-  };
+class Module;
+class Value;
+class Function;
+
+/// The interface for consumers of difference data.
+class Consumer {
+  virtual void anchor();
+
+public:
+  /// Record that a local context has been entered.  Left and
+  /// Right are IR "containers" of some sort which are being
+  /// considered for structural equivalence: global variables,
+  /// functions, blocks, instructions, etc.
+  virtual void enterContext(const Value *Left, const Value *Right) = 0;
+
+  /// Record that a local context has been exited.
+  virtual void exitContext() = 0;
+
+  /// Record a difference within the current context.
+  virtual void log(StringRef Text) = 0;
+
+  /// Record a formatted difference within the current context.
+  virtual void logf(const LogBuilder &Log) = 0;
 
-  class DiffConsumer : public Consumer {
-  private:
-    struct DiffContext {
-      DiffContext(const Value *L, const Value *R)
-          : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
-      const Value *L;
-      const Value *R;
-      bool Differences;
-      bool IsFunction;
-      DenseMap<const Value *, unsigned> LNumbering;
-      DenseMap<const Value *, unsigned> RNumbering;
-    };
-
-    raw_ostream &out;
-    SmallVector<DiffContext, 5> contexts;
+  /// Record a line-by-line instruction diff.
+  virtual void logd(const DiffLogBuilder &Log) = 0;
+
+protected:
+  virtual ~Consumer() {}
+};
+
+class DiffConsumer : public Consumer {
+private:
+  struct DiffContext {
+    DiffContext(const Value *L, const Value *R)
+        : L(L), R(R), Differences(false), IsFunction(isa<Function>(L)) {}
+    const Value *L;
+    const Value *R;
     bool Differences;
-    unsigned Indent;
-
-    void printValue(const Value *V, bool isL);
-    void header();
-    void indent();
-
-  public:
-    DiffConsumer()
-      : out(errs()), Differences(false), Indent(0) {}
-
-    void reset();
-    bool hadDifferences() const;
-    void enterContext(const Value *L, const Value *R) override;
-    void exitContext() override;
-    void log(StringRef text) override;
-    void logf(const LogBuilder &Log) override;
-    void logd(const DiffLogBuilder &Log) override;
+    bool IsFunction;
+    DenseMap<const Value *, unsigned> LNumbering;
+    DenseMap<const Value *, unsigned> RNumbering;
   };
-}
+
+  raw_ostream &out;
+  SmallVector<DiffContext, 5> contexts;
+  bool Differences;
+  unsigned Indent;
+
+  void printValue(const Value *V, bool isL);
+  void header();
+  void indent();
+
+public:
+  DiffConsumer() : out(errs()), Differences(false), Indent(0) {}
+
+  void reset();
+  bool hadDifferences() const;
+  void enterContext(const Value *L, const Value *R) override;
+  void exitContext() override;
+  void log(StringRef text) override;
+  void logf(const LogBuilder &Log) override;
+  void logd(const DiffLogBuilder &Log) override;
+};
+} // namespace llvm
 
 #endif
diff --git a/llvm/tools/llvm-diff/lib/DiffLog.cpp b/llvm/tools/llvm-diff/lib/DiffLog.cpp
index d31a345d255c4..832ee060704a0 100644
--- a/llvm/tools/llvm-diff/lib/DiffLog.cpp
+++ b/llvm/tools/llvm-diff/lib/DiffLog.cpp
@@ -43,8 +43,7 @@ void DiffLogBuilder::addRight(const Instruction *R) {
 unsigned DiffLogBuilder::getNumLines() const { return Diff.size(); }
 
 DiffChange DiffLogBuilder::getLineKind(unsigned I) const {
-  return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left)
-                        : DC_right);
+  return (Diff[I].first ? (Diff[I].second ? DC_match : DC_left) : DC_right);
 }
 const Instruction *DiffLogBuilder::getLeft(unsigned I) const {
   return Diff[I].first;
diff --git a/llvm/tools/llvm-diff/lib/DiffLog.h b/llvm/tools/llvm-diff/lib/DiffLog.h
index d8b07b9711982..be7c1d133d4bd 100644
--- a/llvm/tools/llvm-diff/lib/DiffLog.h
+++ b/llvm/tools/llvm-diff/lib/DiffLog.h
@@ -17,67 +17,67 @@
 #include "llvm/ADT/StringRef.h"
 
 namespace llvm {
-  class Instruction;
-  class Value;
-  class Consumer;
-
-  /// Trichotomy assumption
-  enum DiffChange { DC_match, DC_left, DC_right };
-
-  /// A temporary-object class for building up log messages.
-  class LogBuilder {
-    Consumer *consumer;
-
-    /// The use of a stored StringRef here is okay because
-    /// LogBuilder should be used only as a temporary, and as a
-    /// temporary it will be destructed before whatever temporary
-    /// might be initializing this format.
-    StringRef Format;
-
-    SmallVector<const Value *, 4> Arguments;
-
-  public:
-    LogBuilder(Consumer &c, StringRef Format) : consumer(&c), Format(Format) {}
-    LogBuilder(LogBuilder &&L)
-        : consumer(L.consumer), Format(L.Format),
-          Arguments(std::move(L.Arguments)) {
-      L.consumer = nullptr;
-    }
-
-    LogBuilder &operator<<(const Value *V) {
-      Arguments.push_back(V);
-      return *this;
-    }
-
-    ~LogBuilder();
-
-    StringRef getFormat() const;
-    unsigned getNumArguments() const;
-    const Value *getArgument(unsigned I) const;
-  };
-
-  /// A temporary-object class for building up diff messages.
-  class DiffLogBuilder {
-    typedef std::pair<const Instruction *, const Instruction *> DiffRecord;
-    SmallVector<DiffRecord, 20> Diff;
-
-    Consumer &consumer;
-
-  public:
-    DiffLogBuilder(Consumer &c) : consumer(c) {}
-    ~DiffLogBuilder();
-
-    void addMatch(const Instruction *L, const Instruction *R);
-    // HACK: VS 2010 has a bug in the stdlib that requires this.
-    void addLeft(const Instruction *L);
-    void addRight(const Instruction *R);
-
-    unsigned getNumLines() const;
-    DiffChange getLineKind(unsigned I) const;
-    const Instruction *getLeft(unsigned I) const;
-    const Instruction *getRight(unsigned I) const;
-  };
-
-}
+class Instruction;
+class Value;
+class Consumer;
+
+/// Trichotomy assumption
+enum DiffChange { DC_match, DC_left, DC_right };
+
+/// A temporary-object class for building up log messages.
+class LogBuilder {
+  Consumer *consumer;
+
+  /// The use of a stored StringRef here is okay because
+  /// LogBuilder should be used only as a temporary, and as a
+  /// temporary it will be destructed before whatever temporary
+  /// might be initializing this format.
+  StringRef Format;
+
+  SmallVector<const Value *, 4> Arguments;
+
+public:
+  LogBuilder(Consumer &c, StringRef Format) : consumer(&c), Format(Format) {}
+  LogBuilder(LogBuilder &&L)
+      : consumer(L.consumer), Format(L.Format),
+        Arguments(std::move(L.Arguments)) {
+    L.consumer = nullptr;
+  }
+
+  LogBuilder &operator<<(const Value *V) {
+    Arguments.push_back(V);
+    return *this;
+  }
+
+  ~LogBuilder();
+
+  StringRef getFormat() const;
+  unsigned getNumArguments() const;
+  const Value *getArgument(unsigned I) const;
+};
+
+/// A temporary-object class for building up diff messages.
+class DiffLogBuilder {
+  typedef std::pair<const Instruction *, const Instruction *> DiffRecord;
+  SmallVector<DiffRecord, 20> Diff;
+
+  Consumer &consumer;
+
+public:
+  DiffLogBuilder(Consumer &c) : consumer(c) {}
+  ~DiffLogBuilder();
+
+  void addMatch(const Instruction *L, const Instruction *R);
+  // HACK: VS 2010 has a bug in the stdlib that requires this.
+  void addLeft(const Instruction *L);
+  void addRight(const Instruction *R);
+
+  unsigned getNumLines() const;
+  DiffChange getLineKind(unsigned I) const;
+  const Instruction *getLeft(unsigned I) const;
+  const Instruction *getRight(unsigned I) const;
+};
+
+} // namespace llvm
 
 #endif
diff --git a/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp b/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
index 9be0eec7b73f3..6bf1a7d6afba2 100644
--- a/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
+++ b/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
@@ -33,8 +33,7 @@ using namespace llvm;
 namespace {
 
 /// A priority queue, implemented as a heap.
-template <class T, class Sorter, unsigned InlineCapacity>
-class PriorityQueue {
+template <class T, class Sorter, unsigned InlineCapacity> class PriorityQueue {
   Sorter Precedes;
   llvm::SmallVector<T, InlineCapacity> Storage;
 
@@ -48,14 +47,17 @@ class PriorityQueue {
   void insert(const T &V) {
     unsigned Index = Storage.size();
     Storage.push_back(V);
-    if (Index == 0) return;
+    if (Index == 0)
+      return;
 
     T *data = Storage.data();
     while (true) {
       unsigned Target = (Index + 1) / 2 - 1;
-      if (!Precedes(data[Index], data[Target])) return;
+      if (!Precedes(data[Index], data[Target]))
+        return;
       std::swap(data[Index], data[Target]);
-      if (Target == 0) return;
+      if (Target == 0)
+        return;
       Index = Target;
     }
   }
@@ -64,7 +66,7 @@ class PriorityQueue {
   T remove_min() {
     assert(!empty());
     T tmp = Storage[0];
-    
+
     unsigned NewSize = Storage.size() - 1;
     if (NewSize) {
       // Move the slot at the end to the beginning.
@@ -83,7 +85,8 @@ class PriorityQueue {
         // If R is out of bounds, we're done after this in any case.
         if (R >= NewSize) {
           // If L is also out of bounds, we're done immediately.
-          if (L >= NewSize) break;
+          if (L >= NewSize)
+            break;
 
           // Otherwise, test whether we should swap L and Index.
           if (Precedes(Storage[L], Storage[Index]))
@@ -230,8 +233,8 @@ class FunctionDifferenceEngine {
     explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {}
 
     bool operator()(BlockPair &Old, BlockPair &New) {
-      return fde.getUnprocPredCount(Old.first)
-           < fde.getUnprocPredCount(New.first);
+      return fde.getUnprocPredCount(Old.first) <
+             fde.getUnprocPredCount(New.first);
     }
   };
 
@@ -246,11 +249,12 @@ class FunctionDifferenceEngine {
     const BasicBlock *&Ref = Blocks[L];
 
     if (Ref) {
-      if (Ref == R) return false;
+      if (Ref == R)
+        return false;
 
       Engine.logf("successor %l cannot be equivalent to %r; "
                   "it's already equivalent to %r")
-        << L << R << Ref;
+          << L << R << Ref;
       return true;
     }
 
@@ -266,7 +270,7 @@ class FunctionDifferenceEngine {
 
     bool Result = diff(L, R, true, true, true);
     assert(!Result && "structural differences second time around?");
-    (void) Result;
+    (void)Result;
     if (!L->use_empty())
       Values[L] = R;
   }
@@ -344,11 +348,13 @@ class FunctionDifferenceEngine {
     AssumptionContext AC = {L.getParent(), R.getParent()};
     if (!equivalentAsOperands(L.getCalledOperand(), R.getCalledOperand(),
                               &AC)) {
-      if (Complain) Engine.log("called functions differ");
+      if (Complain)
+        Engine.log("called functions differ");
       return true;
     }
     if (L.arg_size() != R.arg_size()) {
-      if (Complain) Engine.log("argument counts differ");
+      if (Complain)
+        Engine.log("argument counts differ");
       return true;
     }
     for (unsigned I = 0, E = L.arg_size(); I != E; ++I)
@@ -373,14 +379,16 @@ class FunctionDifferenceEngine {
 
     // Different opcodes always imply different operations.
     if (L->getOpcode() != R->getOpcode()) {
-      if (Complain) Engine.log("different instruction types");
+      if (Complain)
+        Engine.log("different instruction types");
       return true;
     }
 
     if (isa<CmpInst>(L)) {
-      if (cast<CmpInst>(L)->getPredicate()
-            != cast<CmpInst>(R)->getPredicate()) {
-        if (Complain) Engine.log("different predicates");
+      if (cast<CmpInst>(L)->getPredicate() !=
+          cast<CmpInst>(R)->getPredicate()) {
+        if (Complain)
+          Engine.log("different predicates");
         return true;
       }
     } else if (isa<CallInst>(L)) {
@@ -392,7 +400,8 @@ class FunctionDifferenceEngine {
       // This is really weird;  type uniquing is broken?
       if (LI.getType() != RI.getType()) {
         if (!LI.getType()->isPointerTy() || !RI.getType()->isPointerTy()) {
-          if (Complain) Engine.log("different phi types");
+          if (Complain)
+            Engine.log("different phi types");
           return true;
         }
       }
@@ -417,7 +426,7 @@ class FunctionDifferenceEngine {
 
       return false;
 
-    // Terminators.
+      // Terminators.
     } else if (isa<InvokeInst>(L)) {
       const InvokeInst &LI = cast<InvokeInst>(*L);
       const InvokeInst &RI = cast<InvokeInst>(*R);
@@ -455,30 +464,36 @@ class FunctionDifferenceEngine {
       const BranchInst *LI = cast<BranchInst>(L);
       const BranchInst *RI = cast<BranchInst>(R);
       if (LI->isConditional() != RI->isConditional()) {
-        if (Complain) Engine.log("branch conditionality differs");
+        if (Complain)
+          Engine.log("branch conditionality differs");
         return true;
       }
 
       if (LI->isConditional()) {
         if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) {
-          if (Complain) Engine.log("branch conditions differ");
+          if (Complain)
+            Engine.log("branch conditions differ");
           return true;
         }
-        if (TryUnify) tryUnify(LI->getSuccessor(1), RI->getSuccessor(1));
+        if (TryUnify)
+          tryUnify(LI->getSuccessor(1), RI->getSuccessor(1));
       }
-      if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
+      if (TryUnify)
+        tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
       return false;
 
     } else if (isa<IndirectBrInst>(L)) {
       const IndirectBrInst *LI = cast<IndirectBrInst>(L);
       const IndirectBrInst *RI = cast<IndirectBrInst>(R);
       if (LI->getNumDestinations() != RI->getNumDestinations()) {
-        if (Complain) Engine.log("indirectbr # of destinations differ");
+        if (Complain)
+          Engine.log("indirectbr # of destinations differ");
         return true;
       }
 
       if (!equivalentAsOperands(LI->getAddress(), RI->getAddress(), AC)) {
-        if (Complain) Engine.log("indirectbr addresses differ");
+        if (Complain)
+          Engine.log("indirectbr addresses differ");
         return true;
       }
 
@@ -493,10 +508,12 @@ class FunctionDifferenceEngine {
       const SwitchInst *LI = cast<SwitchInst>(L);
       const SwitchInst *RI = cast<SwitchInst>(R);
       if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) {
-        if (Complain) Engine.log("switch conditions differ");
+        if (Complain)
+          Engine.log("switch conditions differ");
         return true;
       }
-      if (TryUnify) tryUnify(LI->getDefaultDest(), RI->getDefaultDest());
+      if (TryUnify)
+        tryUnify(LI->getDefaultDest(), RI->getDefaultDest());
 
       bool Difference = false;
 
@@ -532,14 +549,16 @@ class FunctionDifferenceEngine {
     }
 
     if (L->getNumOperands() != R->getNumOperands()) {
-      if (Complain) Engine.log("instructions have different operand counts");
+      if (Complain)
+        Engine.log("instructions have different operand counts");
       return true;
     }
 
     for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) {
       Value *LO = L->getOperand(I), *RO = R->getOperand(I);
       if (!equivalentAsOperands(LO, RO, AC)) {
-        if (Complain) Engine.logf("operands %l and %r differ") << LO << RO;
+        if (Complain)
+          Engine.logf("operands %l and %r differ") << LO << RO;
         return true;
       }
     }
@@ -569,14 +588,15 @@ class FunctionDifferenceEngine {
 
     // Constants of the "same type" don't always actually have the same
     // type; I don't know why.  Just white-list them.
-    if (isa<ConstantPointerNull>(L) || isa<UndefValue>(L) || isa<ConstantAggregateZero>(L))
+    if (isa<ConstantPointerNull>(L) || isa<UndefValue>(L) ||
+        isa<ConstantAggregateZero>(L))
       return true;
 
     // Block addresses only match if we've already encountered the
     // block.  FIXME: tentative matches?
     if (isa<BlockAddress>(L))
-      return Blocks[cast<BlockAddress>(L)->getBasicBlock()]
-                 == cast<BlockAddress>(R)->getBasicBlock();
+      return Blocks[cast<BlockAddress>(L)->getBasicBlock()] ==
+             cast<BlockAddress>(R)->getBasicBlock();
 
     // If L and R are ConstantVectors, compare each element
     if (isa<ConstantVector>(L)) {
@@ -801,8 +821,8 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
 
   unsigned NL = std::distance(LStart, LE);
 
-  SmallVector<DiffEntry, 20> Paths1(NL+1);
-  SmallVector<DiffEntry, 20> Paths2(NL+1);
+  SmallVector<DiffEntry, 20> Paths1(NL + 1);
+  SmallVector<DiffEntry, 20> Paths2(NL + 1);
 
   DiffEntry *Cur = Paths1.data();
   DiffEntry *Next = Paths2.data();
@@ -814,7 +834,7 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
   assert(TentativeValues.empty());
 
   // Initialize the first column.
-  for (unsigned I = 0; I != NL+1; ++I) {
+  for (unsigned I = 0; I != NL + 1; ++I) {
     Cur[I].Cost = I * LeftCost;
     for (unsigned J = 0; J != I; ++J)
       Cur[I].Path.push_back(DC_left);
@@ -829,12 +849,12 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
     unsigned Index = 1;
     for (BasicBlock::const_iterator LI = LStart; LI != LE; ++LI, ++Index) {
       if (matchForBlockDiff(&*LI, &*RI)) {
-        Next[Index] = Cur[Index-1];
+        Next[Index] = Cur[Index - 1];
         Next[Index].Cost += MatchCost;
         Next[Index].Path.push_back(DC_match);
         TentativeValues.insert(std::make_pair(&*LI, &*RI));
-      } else if (Next[Index-1].Cost <= Cur[Index].Cost) {
-        Next[Index] = Next[Index-1];
+      } else if (Next[Index - 1].Cost <= Cur[Index].Cost) {
+        Next[Index] = Next[Index - 1];
         Next[Index].Cost += LeftCost;
         Next[Index].Path.push_back(DC_left);
       } else {
@@ -861,8 +881,7 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
     Path.pop_back();
 
   // Skip leading matches.
-  SmallVectorImpl<char>::iterator
-    PI = Path.begin(), PE = Path.end();
+  SmallVectorImpl<char>::iterator PI = Path.begin(), PE = Path.end();
   while (PI != PE && *PI == DC_match) {
     unify(&*LI, &*RI);
     ++PI;
@@ -879,7 +898,8 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
         unify(L, R);
         Diff.addMatch(L, R);
       }
-      ++LI; ++RI;
+      ++LI;
+      ++RI;
       break;
 
     case DC_left:
@@ -911,11 +931,14 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
   const Instruction *LTerm = LStart->getParent()->getTerminator();
   const Instruction *RTerm = RStart->getParent()->getTerminator();
   if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) {
-    if (cast<BranchInst>(LTerm)->isConditional()) return;
+    if (cast<BranchInst>(LTerm)->isConditional())
+      return;
     BasicBlock::const_iterator I = LTerm->getIterator();
-    if (I == LStart->getParent()->begin()) return;
+    if (I == LStart->getParent()->begin())
+      return;
     --I;
-    if (!isa<CallInst>(*I)) return;
+    if (!isa<CallInst>(*I))
+      return;
     const CallInst *LCall = cast<CallInst>(&*I);
     const InvokeInst *RInvoke = cast<InvokeInst>(RTerm);
     if (!equivalentAsOperands(LCall->getCalledOperand(),
@@ -925,11 +948,14 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
       Values[LCall] = RInvoke;
     tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest());
   } else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) {
-    if (cast<BranchInst>(RTerm)->isConditional()) return;
+    if (cast<BranchInst>(RTerm)->isConditional())
+      return;
     BasicBlock::const_iterator I = RTerm->getIterator();
-    if (I == RStart->getParent()->begin()) return;
+    if (I == RStart->getParent()->begin())
+      return;
     --I;
-    if (!isa<CallInst>(*I)) return;
+    if (!isa<CallInst>(*I))
+      return;
     const CallInst *RCall = cast<CallInst>(I);
     const InvokeInst *LInvoke = cast<InvokeInst>(LTerm);
     if (!equivalentAsOperands(LInvoke->getCalledOperand(),
@@ -940,9 +966,9 @@ void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
     tryUnify(LInvoke->getNormalDest(), RTerm->getSuccessor(0));
   }
 }
-}
+} // namespace
 
-void DifferenceEngine::Oracle::anchor() { }
+void DifferenceEngine::Oracle::anchor() {}
 
 void DifferenceEngine::diff(const Function *L, const Function *R) {
   Context C(*this, L, R);
@@ -950,7 +976,7 @@ void DifferenceEngine::diff(const Function *L, const Function *R) {
   // FIXME: types
   // FIXME: attributes and CC
   // FIXME: parameter attributes
-  
+
   // If both are declarations, we're done.
   if (L->empty() && R->empty())
     return;
@@ -1014,7 +1040,8 @@ void DifferenceEngine::diff(const Module *L, const Module *R) {
 
 bool DifferenceEngine::equivalentAsOperands(const GlobalValue *L,
                                             const GlobalValue *R) {
-  if (globalValueOracle) return (*globalValueOracle)(L, R);
+  if (globalValueOracle)
+    return (*globalValueOracle)(L, R);
 
   if (isa<GlobalVariable>(L) && isa<GlobalVariable>(R)) {
     const GlobalVariable *GVL = cast<GlobalVariable>(L);
diff --git a/llvm/tools/llvm-diff/lib/DifferenceEngine.h b/llvm/tools/llvm-diff/lib/DifferenceEngine.h
index 436a35566360f..4d79cdff6c994 100644
--- a/llvm/tools/llvm-diff/lib/DifferenceEngine.h
+++ b/llvm/tools/llvm-diff/lib/DifferenceEngine.h
@@ -20,71 +20,64 @@
 #include <utility>
 
 namespace llvm {
-  class Function;
-  class GlobalValue;
-  class Instruction;
-  class LLVMContext;
-  class Module;
-  class Twine;
-  class Value;
+class Function;
+class GlobalValue;
+class Instruction;
+class LLVMContext;
+class Module;
+class Twine;
+class Value;
 
-  /// A class for performing structural comparisons of LLVM assembly.
-  class DifferenceEngine {
-  public:
-    /// A RAII object for recording the current context.
-    struct Context {
-      Context(DifferenceEngine &Engine, const Value *L, const Value *R)
-          : Engine(Engine) {
-        Engine.consumer.enterContext(L, R);
-      }
+/// A class for performing structural comparisons of LLVM assembly.
+class DifferenceEngine {
+public:
+  /// A RAII object for recording the current context.
+  struct Context {
+    Context(DifferenceEngine &Engine, const Value *L, const Value *R)
+        : Engine(Engine) {
+      Engine.consumer.enterContext(L, R);
+    }
+
+    ~Context() { Engine.consumer.exitContext(); }
 
-      ~Context() {
-        Engine.consumer.exitContext();
-      }
+  private:
+    DifferenceEngine &Engine;
+  };
 
-    private:
-      DifferenceEngine &Engine;
-    };
+  /// An oracle for answering whether two values are equivalent as
+  /// operands.
+  class Oracle {
+    virtual void anchor();
 
-    /// An oracle for answering whether two values are equivalent as
-    /// operands.
-    class Oracle {
-      virtual void anchor();
-    public:
-      virtual bool operator()(const Value *L, const Value *R) = 0;
+  public:
+    virtual bool operator()(const Value *L, const Value *R) = 0;
 
-    protected:
-      virtual ~Oracle() {}
-    };
+  protected:
+    virtual ~Oracle() {}
+  };
 
-    DifferenceEngine(Consumer &consumer)
+  DifferenceEngine(Consumer &consumer)
       : consumer(consumer), globalValueOracle(nullptr) {}
 
-    void diff(const Module *L, const Module *R);
-    void diff(const Function *L, const Function *R);
-    void log(StringRef text) {
-      consumer.log(text);
-    }
-    LogBuilder logf(StringRef text) {
-      return LogBuilder(consumer, text);
-    }
-    Consumer& getConsumer() const { return consumer; }
+  void diff(const Module *L, const Module *R);
+  void diff(const Function *L, const Function *R);
+  void log(StringRef text) { consumer.log(text); }
+  LogBuilder logf(StringRef text) { return LogBuilder(consumer, text); }
+  Consumer &getConsumer() const { return consumer; }
 
-    /// Installs an oracle to decide whether two global values are
-    /// equivalent as operands.  Without an oracle, global values are
-    /// considered equivalent as operands precisely when they have the
-    /// same name.
-    void setGlobalValueOracle(Oracle *oracle) {
-      globalValueOracle = oracle;
-    }
+  /// Installs an oracle to decide whether two global values are
+  /// equivalent as operands.  Without an oracle, global values are
+  /// considered equivalent as operands precisely when they have the
+  /// same name.
+  void setGlobalValueOracle(Oracle *oracle) { globalValueOracle = oracle; }
 
-    /// Determines whether two global values are equivalent.
-    bool equivalentAsOperands(const GlobalValue *L, const GlobalValue *R);
+  /// Determines whether two global values are equivalent.
+  bool equivalentAsOperands(const GlobalValue *L, const GlobalValue *R);
 
-  private:
-    Consumer &consumer;
-    Oracle *globalValueOracle;
-  };
-}
+private:
+  Consumer &consumer;
+  Oracle *globalValueOracle;
+};
+} // namespace llvm
 
 #endif
diff --git a/llvm/tools/llvm-diff/llvm-diff.cpp b/llvm/tools/llvm-diff/llvm-diff.cpp
index 2126b91f75ae1..6574ed3a6216f 100644
--- a/llvm/tools/llvm-diff/llvm-diff.cpp
+++ b/llvm/tools/llvm-diff/llvm-diff.cpp
@@ -20,12 +20,11 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
 #include <string>
 #include <utility>
 
-
 using namespace llvm;
 
 /// Reads a module from a file.  On error, messages are written to stderr
@@ -77,7 +76,8 @@ int main(int argc, char **argv) {
   // Load both modules.  Die if that fails.
   std::unique_ptr<Module> LModule = readModule(Context, LeftFilename);
   std::unique_ptr<Module> RModule = readModule(Context, RightFilename);
-  if (!LModule || !RModule) return 1;
+  if (!LModule || !RModule)
+    return 1;
 
   DiffConsumer Consumer;
   DifferenceEngine Engine(Consumer);
@@ -87,7 +87,7 @@ int main(int argc, char **argv) {
     for (unsigned I = 0, E = GlobalsToCompare.size(); I != E; ++I)
       diffGlobal(Engine, *LModule, *RModule, GlobalsToCompare[I]);
 
-  // Otherwise, diff everything in the module.
+    // Otherwise, diff everything in the module.
   } else {
     Engine.diff(LModule.get(), RModule.get());
   }

>From e168c80d97cae525ea5bb4181d4e8a59b65c03be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <albert.havlicek at fit.cvut.cz>
Date: Sun, 9 Mar 2025 13:24:18 +0100
Subject: [PATCH 2/2] [llvm-diff] Color for differences between left and right

---
 llvm/tools/llvm-diff/lib/DiffConsumer.cpp | 26 ++++++++++++-----------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/llvm/tools/llvm-diff/lib/DiffConsumer.cpp b/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
index c93e6af7a72cc..ba8fad789017a 100644
--- a/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
+++ b/llvm/tools/llvm-diff/lib/DiffConsumer.cpp
@@ -14,6 +14,8 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 
@@ -212,21 +214,21 @@ void DiffConsumer::logd(const DiffLogBuilder &Log) {
       out << "  ";
       Log.getLeft(I)->print(dbgs());
       dbgs() << '\n';
-      // printValue(Log.getLeft(I), true);
       break;
-    case DC_left:
-      out << "< ";
-      Log.getLeft(I)->print(dbgs());
-      dbgs() << '\n';
-      // printValue(Log.getLeft(I), true);
+    case DC_left: {
+      auto LeftColor = llvm::WithColor(out, raw_ostream::RED);
+      LeftColor << "< ";
+      Log.getLeft(I)->print(LeftColor);
+      LeftColor << '\n';
       break;
-    case DC_right:
-      out << "> ";
-      Log.getRight(I)->print(dbgs());
-      dbgs() << '\n';
-      // printValue(Log.getRight(I), false);
+    }
+    case DC_right: {
+      auto RightColor = llvm::WithColor(out, raw_ostream::GREEN);
+      RightColor << "> ";
+      Log.getRight(I)->print(RightColor);
+      RightColor << '\n';
       break;
     }
-    // out << "\n";
+    }
   }
 }



More information about the llvm-commits mailing list