diff --git a/llvm/tools/llvm-diff/DifferenceEngine.cpp b/llvm/tools/llvm-diff/DifferenceEngine.cpp
new file mode 100644
index 0000000..400ab9f
--- /dev/null
+++ b/llvm/tools/llvm-diff/DifferenceEngine.cpp
@@ -0,0 +1,600 @@
+//===-- DifferenceEngine.cpp - Structural function/module comparison ------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the interface to the LLVM difference engine,
+// which structurally compares functions within a module.
+//
+//===----------------------------------------------------------------------===//
+
+#include <utility>
+
+#include <llvm/ADT/DenseMap.h>
+#include <llvm/ADT/DenseSet.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/StringSet.h>
+
+#include <llvm/Module.h>
+#include <llvm/Function.h>
+#include <llvm/Instructions.h>
+#include <llvm/Support/CFG.h>
+
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/type_traits.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/CallSite.h>
+
+#include "DifferenceEngine.h"
+
+using namespace llvm;
+
+namespace {
+
+/// A priority queue, implemented as a heap.
+template <class T, class Sorter, unsigned InlineCapacity>
+class PriorityQueue {
+  Sorter Precedes;
+  llvm::SmallVector<T, InlineCapacity> Storage;
+
+public:
+  PriorityQueue(const Sorter &Precedes) : Precedes(Precedes) {}
+
+  /// Checks whether the heap is empty.
+  bool empty() const { return Storage.empty(); }
+
+  /// Insert a new value on the heap.
+  void insert(const T &V) {
+    unsigned Index = Storage.size();
+    Storage.push_back(V);
+    if (Index == 0) return;
+
+    T *data = Storage.data();
+    while (true) {
+      unsigned Target = (Index + 1) / 2 - 1;
+      if (!Precedes(data[Index], data[Target])) return;
+      std::swap(data[Index], data[Target]);
+      if (Target == 0) return;
+      Index = Target;
+    }
+  }
+
+  /// Remove the minimum value in the heap.  Only valid on a non-empty heap.
+  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.
+      if (isPodLike<T>::value)
+        Storage[0] = Storage[NewSize];
+      else
+        std::swap(Storage[0], Storage[NewSize]);
+
+      // Bubble the root up as necessary.
+      unsigned Index = 0;
+      while (true) {
+        // With a 1-based index, the children would be Index*2 and Index*2+1.
+        unsigned R = (Index + 1) * 2;
+        unsigned L = R - 1;
+
+        // 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;
+
+          // Otherwise, test whether we should swap L and Index.
+          if (Precedes(Storage[L], Storage[Index]))
+            std::swap(Storage[L], Storage[Index]);
+          break;
+        }
+
+        // Otherwise, we need to compare with the smaller of L and R.
+        // Prefer R because it's closer to the end of the array.
+        unsigned IndexToTest = (Precedes(Storage[L], Storage[R]) ? L : R);
+
+        // If Index is >= the min of L and R, then heap ordering is restored.
+        if (!Precedes(Storage[IndexToTest], Storage[Index]))
+          break;
+
+        // Otherwise, keep bubbling up.
+        std::swap(Storage[IndexToTest], Storage[Index]);
+        Index = IndexToTest;
+      }
+    }
+    Storage.pop_back();
+
+    return tmp;
+  }
+};
+
+/// A function-scope difference engine.
+class FunctionDifferenceEngine {
+  DifferenceEngine &Engine;
+
+  /// The current mapping from old local values to new local values.
+  DenseMap<Value*, Value*> Values;
+
+  /// The current mapping from old blocks to new blocks.
+  DenseMap<BasicBlock*, BasicBlock*> Blocks;
+
+  DenseSet<std::pair<Value*, Value*> > TentativeValuePairs;
+
+  unsigned getUnprocPredCount(BasicBlock *Block) const {
+    unsigned Count = 0;
+    for (pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E; ++I)
+      if (!Blocks.count(*I)) Count++;
+    return Count;
+  }
+
+  typedef std::pair<BasicBlock*, BasicBlock*> BlockPair;
+
+  /// A type which sorts a priority queue by the number of unprocessed
+  /// predecessor blocks it has remaining.
+  ///
+  /// This is actually really expensive to calculate.
+  struct QueueSorter {
+    const FunctionDifferenceEngine &fde;
+    explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {}
+
+    bool operator()(const BlockPair &Old, const BlockPair &New) {
+      return fde.getUnprocPredCount(Old.first)
+           < fde.getUnprocPredCount(New.first);
+    }
+  };
+
+  /// A queue of unified blocks to process.
+  PriorityQueue<BlockPair, QueueSorter, 20> Queue;
+
+  /// Try to unify the given two blocks.  Enqueues them for processing
+  /// if they haven't already been processed.
+  ///
+  /// Returns true if there was a problem unifying them.
+  bool tryUnify(BasicBlock *L, BasicBlock *R) {
+    BasicBlock *&Ref = Blocks[L];
+
+    if (Ref) {
+      if (Ref == R) return false;
+
+      Engine.logf("successor %s cannot be equivalent to %s; "
+                  "it's already equivalent to %s")
+        << L << R << Ref;
+      return true;
+    }
+
+    Ref = R;
+    Queue.insert(BlockPair(L, R));
+    return false;
+  }
+
+  void processQueue() {
+    while (!Queue.empty()) {
+      BlockPair Pair = Queue.remove_min();
+      diff(Pair.first, Pair.second);
+    }
+  }
+
+  void diff(BasicBlock *L, BasicBlock *R) {
+    DifferenceEngine::Context C(Engine, L, R);
+
+    BasicBlock::iterator LI = L->begin(), LE = L->end();
+    BasicBlock::iterator RI = R->begin(), RE = R->end();
+
+    do {
+      assert(LI != LE && RI != RE);
+      Instruction *LeftI = &*LI, *RightI = &*RI;
+
+      // If the instructions differ, start the more sophisticated diff
+      // algorithm here.
+      if (diff(LeftI, RightI, false, true))
+        return runBlockDiff(LI, RI);
+
+      // Otherwise, unify them.
+      if (!LeftI->use_empty())
+        Values[LeftI] = RightI;
+
+      ++LI, ++RI;
+    } while (LI != LE); // This is sufficient: we can't get equality of
+                        // terminators if there are residual instructions.
+  }
+
+  bool matchForBlockDiff(Instruction *L, Instruction *R);
+  void runBlockDiff(BasicBlock::iterator LI, BasicBlock::iterator RI);
+
+  bool diffCallSites(CallSite L, CallSite R, bool Complain) {
+    // FIXME: call attributes
+    if (!equivalentAsOperands(L.getCalledValue(), R.getCalledValue())) {
+      if (Complain) Engine.log("called functions differ");
+      return true;
+    }
+    if (L.arg_size() != R.arg_size()) {
+      if (Complain) Engine.log("argument counts differ");
+      return true;
+    }
+    for (unsigned I = 0, E = L.arg_size(); I != E; ++I)
+      if (!equivalentAsOperands(L.getArgument(I), R.getArgument(I))) {
+        if (Complain)
+          Engine.logf("arguments %s and %s differ")
+            << L.getArgument(I) << R.getArgument(I);
+        return true;
+      }
+    return false;
+  }
+
+  bool diff(Instruction *L, Instruction *R, bool Complain, bool TryUnify) {
+    // FIXME: metadata (if Complain is set)
+
+    // Different opcodes always imply different operations.
+    if (L->getOpcode() != R->getOpcode()) {
+      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");
+        return true;
+      }
+    } else if (isa<CallInst>(L)) {
+      return diffCallSites(CallSite(L), CallSite(R), Complain);
+    } else if (isa<PHINode>(L)) {
+      // FIXME: implement.
+
+      // This is really wierd;  type uniquing is broken?
+      if (L->getType() != R->getType()) {
+        if (!L->getType()->isPointerTy() || !R->getType()->isPointerTy()) {
+          if (Complain) Engine.log("different phi types");
+          return true;
+        }
+      }
+      return false;
+
+    // Terminators.
+    } else if (isa<InvokeInst>(L)) {
+      InvokeInst *LI = cast<InvokeInst>(L);
+      InvokeInst *RI = cast<InvokeInst>(R);
+      if (diffCallSites(CallSite(LI), CallSite(RI), Complain))
+        return true;
+
+      if (TryUnify) {
+        tryUnify(LI->getNormalDest(), RI->getNormalDest());
+        tryUnify(LI->getUnwindDest(), RI->getUnwindDest());
+      }
+      return false;
+
+    } else if (isa<BranchInst>(L)) {
+      BranchInst *LI = cast<BranchInst>(L);
+      BranchInst *RI = cast<BranchInst>(R);
+      if (LI->isConditional() != RI->isConditional()) {
+        if (Complain) Engine.log("branch conditionality differs");
+        return true;
+      }
+
+      if (LI->isConditional()) {
+        if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+          if (Complain) Engine.log("branch conditions differ");
+          return true;
+        }
+        if (TryUnify) tryUnify(LI->getSuccessor(1), RI->getSuccessor(1));
+      }
+      if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
+      return false;
+
+    } else if (isa<SwitchInst>(L)) {
+      SwitchInst *LI = cast<SwitchInst>(L);
+      SwitchInst *RI = cast<SwitchInst>(R);
+      if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+        if (Complain) Engine.log("switch conditions differ");
+        return true;
+      }
+      if (TryUnify) tryUnify(LI->getDefaultDest(), RI->getDefaultDest());
+
+      bool Difference = false;
+
+      DenseMap<ConstantInt*,BasicBlock*> LCases;
+      for (unsigned I = 1, E = LI->getNumCases(); I != E; ++I)
+        LCases[LI->getCaseValue(I)] = LI->getSuccessor(I);
+      for (unsigned I = 1, E = RI->getNumCases(); I != E; ++I) {
+        ConstantInt *CaseValue = RI->getCaseValue(I);
+        BasicBlock *LCase = LCases[CaseValue];
+        if (LCase) {
+          if (TryUnify) tryUnify(LCase, RI->getSuccessor(I));
+          LCases.erase(CaseValue);
+        } else if (!Difference) {
+          if (Complain)
+            Engine.logf("right switch has extra case %s") << CaseValue;
+          Difference = true;
+        }
+      }
+      if (!Difference)
+        for (DenseMap<ConstantInt*,BasicBlock*>::iterator
+               I = LCases.begin(), E = LCases.end(); I != E; ++I) {
+          if (Complain)
+            Engine.logf("left switch has extra case %s") << I->first;
+          Difference = true;
+        }
+      return Difference;
+    } else if (isa<UnreachableInst>(L)) {
+      return false;
+    }
+
+    if (L->getNumOperands() != R->getNumOperands()) {
+      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)) {
+        if (Complain) Engine.logf("operands %s and %s differ") << LO << RO;
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  bool equivalentAsOperands(Constant *L, Constant *R) {
+    // Use equality as a preliminary filter.
+    if (L == R)
+      return true;
+
+    if (L->getValueID() != R->getValueID())
+      return false;
+    
+    // Ask the engine about global values.
+    if (isa<GlobalValue>(L))
+      return Engine.equivalentAsOperands(cast<GlobalValue>(L),
+                                         cast<GlobalValue>(R));
+
+    // Compare constant expressions structurally.
+    if (isa<ConstantExpr>(L))
+      return equivalentAsOperands(cast<ConstantExpr>(L),
+                                  cast<ConstantExpr>(R));
+
+    // Nulls 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))
+      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 false;
+  }
+
+  bool equivalentAsOperands(ConstantExpr *L, ConstantExpr *R) {
+    if (L == R)
+      return true;
+    if (L->getOpcode() != R->getOpcode())
+      return false;
+
+    switch (L->getOpcode()) {
+    case Instruction::ICmp:
+    case Instruction::FCmp:
+      if (L->getPredicate() != R->getPredicate())
+        return false;
+      break;
+
+    case Instruction::GetElementPtr:
+      // FIXME: inbounds?
+      break;
+
+    default:
+      break;
+    }
+
+    if (L->getNumOperands() != R->getNumOperands())
+      return false;
+
+    for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I)
+      if (!equivalentAsOperands(L->getOperand(I), R->getOperand(I)))
+        return false;
+
+    return true;
+  }
+
+  bool equivalentAsOperands(Value *L, Value *R) {
+    // Fall out if the values have different kind.
+    // This possibly shouldn't take priority over oracles.
+    if (L->getValueID() != R->getValueID())
+      return false;
+
+    // Value subtypes:  Argument, Constant, Instruction, BasicBlock,
+    //                  InlineAsm, MDNode, MDString, PseudoSourceValue
+
+    if (isa<Constant>(L))
+      return equivalentAsOperands(cast<Constant>(L), cast<Constant>(R));
+
+    if (isa<Instruction>(L))
+      return Values[L] == R || TentativeValuePairs.count(std::make_pair(L, R));
+
+    if (isa<Argument>(L))
+      return Values[L] == R;
+
+    if (isa<BasicBlock>(L))
+      return Blocks[cast<BasicBlock>(L)] != R;
+
+    // Pretend everything else is identical.
+    return true;
+  }
+
+  // Avoid a gcc warning about accessing 'this' in an initializer.
+  FunctionDifferenceEngine *this_() { return this; }
+
+public:
+  FunctionDifferenceEngine(DifferenceEngine &Engine) :
+    Engine(Engine), Queue(QueueSorter(*this_())) {}
+
+  void diff(Function *L, Function *R) {
+    if (L->arg_size() != R->arg_size())
+      Engine.log("different argument counts");
+
+    // Map the arguments.
+    for (Function::arg_iterator
+           LI = L->arg_begin(), LE = L->arg_end(),
+           RI = R->arg_begin(), RE = R->arg_end();
+         LI != LE && RI != RE; ++LI, ++RI)
+      Values[&*LI] = &*RI;
+
+    tryUnify(&*L->begin(), &*R->begin());
+    processQueue();
+  }
+};
+
+struct DiffEntry {
+  DiffEntry() : Cost(0) {}
+
+  unsigned Cost;
+  llvm::SmallVector<char, 8> Path; // actually of DifferenceEngine::DiffChange
+};
+
+bool FunctionDifferenceEngine::matchForBlockDiff(Instruction *L,
+                                                 Instruction *R) {
+  return !diff(L, R, false, false);
+}
+
+void FunctionDifferenceEngine::runBlockDiff(BasicBlock::iterator LStart,
+                                            BasicBlock::iterator RStart) {
+  BasicBlock::iterator LE = LStart->getParent()->end();
+  BasicBlock::iterator RE = RStart->getParent()->end();
+
+  unsigned NL = std::distance(LStart, LE);
+
+  SmallVector<DiffEntry, 20> Paths1(NL+1);
+  SmallVector<DiffEntry, 20> Paths2(NL+1);
+
+  DiffEntry *Cur = Paths1.data();
+  DiffEntry *Next = Paths2.data();
+
+  assert(TentativeValuePairs.empty());
+
+  // Initialize the first column.
+  for (unsigned I = 0; I != NL+1; ++I) {
+    Cur[I].Cost = I;
+    for (unsigned J = 0; J != I; ++J)
+      Cur[I].Path.push_back(DifferenceEngine::DC_left);
+  }
+
+  for (BasicBlock::iterator RI = RStart; RI != RE; ++RI) {
+    // Initialize the first row.
+    Next[0] = Cur[0];
+    Next[0].Path.push_back(DifferenceEngine::DC_right);
+
+    unsigned Index = 1;
+    for (BasicBlock::iterator LI = LStart; LI != LE; ++LI, ++Index) {
+      if (matchForBlockDiff(&*LI, &*RI)) {
+        Next[Index] = Cur[Index-1];
+        Next[Index].Path.push_back(DifferenceEngine::DC_match);
+        TentativeValuePairs.insert(std::make_pair(&*LI, &*RI));
+      } else if (Next[Index-1].Cost <= Cur[Index].Cost) {
+        Next[Index] = Next[Index-1];
+        Next[Index].Path.push_back(DifferenceEngine::DC_left);
+      } else {
+        Next[Index] = Cur[Index];
+        Next[Index].Path.push_back(DifferenceEngine::DC_right);
+      }
+    }
+
+    std::swap(Cur, Next);
+  }
+
+  SmallVectorImpl<char> &Path = Cur[NL].Path;
+  BasicBlock::iterator LI = LStart, RI = RStart;
+
+  DifferenceEngine::DiffLogBuilder Diff(Engine);
+
+  // Drop trailing matches.
+  while (Path.back() == DifferenceEngine::DC_match)
+    Path.pop_back();
+
+  for (SmallVectorImpl<char>::iterator
+         PI = Path.begin(), PE = Path.end(); PI != PE; ++PI) {
+    switch (static_cast<DifferenceEngine::DiffChange>(*PI)) {
+    case DifferenceEngine::DC_match:
+      assert(LI != LE && RI != RE);
+      {
+        Instruction *L = &*LI, *R = &*RI;
+        DifferenceEngine::Context C(Engine, L, R);
+        diff(L, R, false, true);
+        Diff.addMatch(L, R);
+      }
+      ++LI; ++RI;
+      break;
+
+    case DifferenceEngine::DC_left:
+      assert(LI != LE);
+      Diff.addLeft(&*LI);
+      ++LI;
+      break;
+
+    case DifferenceEngine::DC_right:
+      assert(RI != RE);
+      Diff.addRight(&*RI);
+      ++RI;
+      break;
+    }
+  }
+
+  TentativeValuePairs.clear();
+}
+
+}
+
+void DifferenceEngine::diff(Function *L, Function *R) {
+  Context C(*this, L, R);
+
+  // FIXME: types
+  // FIXME: attributes and CC
+  // FIXME: parameter attributes
+  
+  // If both are declarations, we're done.
+  if (L->empty() && R->empty())
+    return;
+  else if (L->empty())
+    log("left function is declaration, right function is definition");
+  else if (R->empty())
+    log("right function is declaration, left function is definition");
+  else
+    FunctionDifferenceEngine(*this).diff(L, R);
+}
+
+void DifferenceEngine::diff(Module *L, Module *R) {
+  StringSet<> LNames;
+  SmallVector<std::pair<Function*,Function*>, 20> Queue;
+
+  for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) {
+    Function *LFn = &*I;
+    LNames.insert(LFn->getName());
+
+    if (Function *RFn = R->getFunction(LFn->getName()))
+      Queue.push_back(std::make_pair(LFn, RFn));
+    else
+      logf("function %s exists only in left module") << LFn;
+  }
+
+  for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) {
+    Function *RFn = &*I;
+    if (!LNames.count(RFn->getName()))
+      logf("function %s exists only in right module") << RFn;
+  }
+
+  for (SmallVectorImpl<std::pair<Function*,Function*> >::iterator
+         I = Queue.begin(), E = Queue.end(); I != E; ++I)
+    diff(I->first, I->second);
+}
+
+bool DifferenceEngine::equivalentAsOperands(GlobalValue *L, GlobalValue *R) {
+  if (globalValueOracle) return (*globalValueOracle)(L, R);
+  return L->getName() == R->getName();
+}
