14d293f21SBill Wendling //===-- DifferenceEngine.cpp - Structural function/module comparison ------===// 24d293f21SBill Wendling // 34d293f21SBill Wendling // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44d293f21SBill Wendling // See https://llvm.org/LICENSE.txt for license information. 54d293f21SBill Wendling // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64d293f21SBill Wendling // 74d293f21SBill Wendling //===----------------------------------------------------------------------===// 84d293f21SBill Wendling // 94d293f21SBill Wendling // This header defines the implementation of the LLVM difference 104d293f21SBill Wendling // engine, which structurally compares global values within a module. 114d293f21SBill Wendling // 124d293f21SBill Wendling //===----------------------------------------------------------------------===// 134d293f21SBill Wendling 144d293f21SBill Wendling #include "DifferenceEngine.h" 154d293f21SBill Wendling #include "llvm/ADT/DenseMap.h" 164d293f21SBill Wendling #include "llvm/ADT/DenseSet.h" 174d293f21SBill Wendling #include "llvm/ADT/SmallString.h" 184d293f21SBill Wendling #include "llvm/ADT/SmallVector.h" 194d293f21SBill Wendling #include "llvm/ADT/StringSet.h" 20e0447961SJannik Silvanus #include "llvm/IR/BasicBlock.h" 214d293f21SBill Wendling #include "llvm/IR/CFG.h" 224d293f21SBill Wendling #include "llvm/IR/Constants.h" 234d293f21SBill Wendling #include "llvm/IR/Function.h" 244d293f21SBill Wendling #include "llvm/IR/Instructions.h" 254d293f21SBill Wendling #include "llvm/IR/Module.h" 264d293f21SBill Wendling #include "llvm/Support/ErrorHandling.h" 274d293f21SBill Wendling #include "llvm/Support/raw_ostream.h" 284d293f21SBill Wendling #include "llvm/Support/type_traits.h" 294d293f21SBill Wendling #include <utility> 304d293f21SBill Wendling 314d293f21SBill Wendling using namespace llvm; 324d293f21SBill Wendling 334d293f21SBill Wendling namespace { 344d293f21SBill Wendling 354d293f21SBill Wendling /// A priority queue, implemented as a heap. 364d293f21SBill Wendling template <class T, class Sorter, unsigned InlineCapacity> 374d293f21SBill Wendling class PriorityQueue { 384d293f21SBill Wendling Sorter Precedes; 394d293f21SBill Wendling llvm::SmallVector<T, InlineCapacity> Storage; 404d293f21SBill Wendling 414d293f21SBill Wendling public: 424d293f21SBill Wendling PriorityQueue(const Sorter &Precedes) : Precedes(Precedes) {} 434d293f21SBill Wendling 444d293f21SBill Wendling /// Checks whether the heap is empty. 454d293f21SBill Wendling bool empty() const { return Storage.empty(); } 464d293f21SBill Wendling 474d293f21SBill Wendling /// Insert a new value on the heap. 484d293f21SBill Wendling void insert(const T &V) { 494d293f21SBill Wendling unsigned Index = Storage.size(); 504d293f21SBill Wendling Storage.push_back(V); 514d293f21SBill Wendling if (Index == 0) return; 524d293f21SBill Wendling 534d293f21SBill Wendling T *data = Storage.data(); 544d293f21SBill Wendling while (true) { 554d293f21SBill Wendling unsigned Target = (Index + 1) / 2 - 1; 564d293f21SBill Wendling if (!Precedes(data[Index], data[Target])) return; 574d293f21SBill Wendling std::swap(data[Index], data[Target]); 584d293f21SBill Wendling if (Target == 0) return; 594d293f21SBill Wendling Index = Target; 604d293f21SBill Wendling } 614d293f21SBill Wendling } 624d293f21SBill Wendling 634d293f21SBill Wendling /// Remove the minimum value in the heap. Only valid on a non-empty heap. 644d293f21SBill Wendling T remove_min() { 654d293f21SBill Wendling assert(!empty()); 664d293f21SBill Wendling T tmp = Storage[0]; 674d293f21SBill Wendling 684d293f21SBill Wendling unsigned NewSize = Storage.size() - 1; 694d293f21SBill Wendling if (NewSize) { 704d293f21SBill Wendling // Move the slot at the end to the beginning. 714d293f21SBill Wendling if (std::is_trivially_copyable<T>::value) 724d293f21SBill Wendling Storage[0] = Storage[NewSize]; 734d293f21SBill Wendling else 744d293f21SBill Wendling std::swap(Storage[0], Storage[NewSize]); 754d293f21SBill Wendling 764d293f21SBill Wendling // Bubble the root up as necessary. 774d293f21SBill Wendling unsigned Index = 0; 784d293f21SBill Wendling while (true) { 794d293f21SBill Wendling // With a 1-based index, the children would be Index*2 and Index*2+1. 804d293f21SBill Wendling unsigned R = (Index + 1) * 2; 814d293f21SBill Wendling unsigned L = R - 1; 824d293f21SBill Wendling 834d293f21SBill Wendling // If R is out of bounds, we're done after this in any case. 844d293f21SBill Wendling if (R >= NewSize) { 854d293f21SBill Wendling // If L is also out of bounds, we're done immediately. 864d293f21SBill Wendling if (L >= NewSize) break; 874d293f21SBill Wendling 884d293f21SBill Wendling // Otherwise, test whether we should swap L and Index. 894d293f21SBill Wendling if (Precedes(Storage[L], Storage[Index])) 904d293f21SBill Wendling std::swap(Storage[L], Storage[Index]); 914d293f21SBill Wendling break; 924d293f21SBill Wendling } 934d293f21SBill Wendling 944d293f21SBill Wendling // Otherwise, we need to compare with the smaller of L and R. 954d293f21SBill Wendling // Prefer R because it's closer to the end of the array. 964d293f21SBill Wendling unsigned IndexToTest = (Precedes(Storage[L], Storage[R]) ? L : R); 974d293f21SBill Wendling 984d293f21SBill Wendling // If Index is >= the min of L and R, then heap ordering is restored. 994d293f21SBill Wendling if (!Precedes(Storage[IndexToTest], Storage[Index])) 1004d293f21SBill Wendling break; 1014d293f21SBill Wendling 1024d293f21SBill Wendling // Otherwise, keep bubbling up. 1034d293f21SBill Wendling std::swap(Storage[IndexToTest], Storage[Index]); 1044d293f21SBill Wendling Index = IndexToTest; 1054d293f21SBill Wendling } 1064d293f21SBill Wendling } 1074d293f21SBill Wendling Storage.pop_back(); 1084d293f21SBill Wendling 1094d293f21SBill Wendling return tmp; 1104d293f21SBill Wendling } 1114d293f21SBill Wendling }; 1124d293f21SBill Wendling 1134d293f21SBill Wendling /// A function-scope difference engine. 1144d293f21SBill Wendling class FunctionDifferenceEngine { 1154d293f21SBill Wendling DifferenceEngine &Engine; 1164d293f21SBill Wendling 1174d293f21SBill Wendling // Some initializers may reference the variable we're currently checking. This 1184d293f21SBill Wendling // can cause an infinite loop. The Saved[LR]HS ivars can be checked to prevent 1194d293f21SBill Wendling // recursing. 1204d293f21SBill Wendling const Value *SavedLHS; 1214d293f21SBill Wendling const Value *SavedRHS; 1224d293f21SBill Wendling 123e0447961SJannik Silvanus // The current mapping from old local values to new local values. 1244d293f21SBill Wendling DenseMap<const Value *, const Value *> Values; 1254d293f21SBill Wendling 126e0447961SJannik Silvanus // The current mapping from old blocks to new blocks. 1274d293f21SBill Wendling DenseMap<const BasicBlock *, const BasicBlock *> Blocks; 1284d293f21SBill Wendling 129e0447961SJannik Silvanus // The tentative mapping from old local values while comparing a pair of 130e0447961SJannik Silvanus // basic blocks. Once the pair has been processed, the tentative mapping is 131e0447961SJannik Silvanus // committed to the Values map. 1324d293f21SBill Wendling DenseSet<std::pair<const Value *, const Value *>> TentativeValues; 1334d293f21SBill Wendling 134e0447961SJannik Silvanus // Equivalence Assumptions 135e0447961SJannik Silvanus // 136e0447961SJannik Silvanus // For basic blocks in loops, some values in phi nodes may depend on 137e0447961SJannik Silvanus // values from not yet processed basic blocks in the loop. When encountering 138e0447961SJannik Silvanus // such values, we optimistically asssume their equivalence and store this 139e0447961SJannik Silvanus // assumption in a BlockDiffCandidate for the pair of compared BBs. 140e0447961SJannik Silvanus // 141e0447961SJannik Silvanus // Once we have diffed all BBs, for every BlockDiffCandidate, we check all 142e0447961SJannik Silvanus // stored assumptions using the Values map that stores proven equivalences 143e0447961SJannik Silvanus // between the old and new values, and report a diff if an assumption cannot 144e0447961SJannik Silvanus // be proven to be true. 145e0447961SJannik Silvanus // 146e0447961SJannik Silvanus // Note that after having made an assumption, all further determined 147e0447961SJannik Silvanus // equivalences implicitly depend on that assumption. These will not be 148e0447961SJannik Silvanus // reverted or reported if the assumption proves to be false, because these 149e0447961SJannik Silvanus // are considered indirect diffs caused by earlier direct diffs. 150e0447961SJannik Silvanus // 151e0447961SJannik Silvanus // We aim to avoid false negatives in llvm-diff, that is, ensure that 152e0447961SJannik Silvanus // whenever no diff is reported, the functions are indeed equal. If 153e0447961SJannik Silvanus // assumptions were made, this is not entirely clear, because in principle we 154e0447961SJannik Silvanus // could end up with a circular proof where the proof of equivalence of two 155e0447961SJannik Silvanus // nodes is depending on the assumption of their equivalence. 156e0447961SJannik Silvanus // 157e0447961SJannik Silvanus // To see that assumptions do not add false negatives, note that if we do not 158e0447961SJannik Silvanus // report a diff, this means that there is an equivalence mapping between old 159e0447961SJannik Silvanus // and new values that is consistent with all assumptions made. The circular 160e0447961SJannik Silvanus // dependency that exists on an IR value level does not exist at run time, 161e0447961SJannik Silvanus // because the values selected by the phi nodes must always already have been 162e0447961SJannik Silvanus // computed. Hence, we can prove equivalence of the old and new functions by 163e0447961SJannik Silvanus // considering step-wise parallel execution, and incrementally proving 164e0447961SJannik Silvanus // equivalence of every new computed value. Another way to think about it is 165e0447961SJannik Silvanus // to imagine cloning the loop BBs for every iteration, turning the loops 166e0447961SJannik Silvanus // into (possibly infinite) DAGs, and proving equivalence by induction on the 167e0447961SJannik Silvanus // iteration, using the computed value mapping. 168e0447961SJannik Silvanus 169e0447961SJannik Silvanus // The class BlockDiffCandidate stores pairs which either have already been 170e0447961SJannik Silvanus // proven to differ, or pairs whose equivalence depends on assumptions to be 171e0447961SJannik Silvanus // verified later. 172e0447961SJannik Silvanus struct BlockDiffCandidate { 173e0447961SJannik Silvanus const BasicBlock *LBB; 174e0447961SJannik Silvanus const BasicBlock *RBB; 175e0447961SJannik Silvanus // Maps old values to assumed-to-be-equivalent new values 176e0447961SJannik Silvanus SmallDenseMap<const Value *, const Value *> EquivalenceAssumptions; 177e0447961SJannik Silvanus // If set, we already know the blocks differ. 178e0447961SJannik Silvanus bool KnownToDiffer; 179e0447961SJannik Silvanus }; 180e0447961SJannik Silvanus 181e0447961SJannik Silvanus // List of block diff candidates in the order found by processing. 182e0447961SJannik Silvanus // We generate reports in this order. 183e0447961SJannik Silvanus // For every LBB, there may only be one corresponding RBB. 184e0447961SJannik Silvanus SmallVector<BlockDiffCandidate> BlockDiffCandidates; 185e0447961SJannik Silvanus // Maps LBB to the index of its BlockDiffCandidate, if existing. 186e0447961SJannik Silvanus DenseMap<const BasicBlock *, uint64_t> BlockDiffCandidateIndices; 187e0447961SJannik Silvanus 188e0447961SJannik Silvanus // Note: Every LBB must always be queried together with the same RBB. 189e0447961SJannik Silvanus // The returned reference is not permanently valid and should not be stored. 190e0447961SJannik Silvanus BlockDiffCandidate &getOrCreateBlockDiffCandidate(const BasicBlock *LBB, 191e0447961SJannik Silvanus const BasicBlock *RBB) { 192*f4136b32SKazu Hirata auto [It, Inserted] = 193*f4136b32SKazu Hirata BlockDiffCandidateIndices.try_emplace(LBB, BlockDiffCandidates.size()); 194e0447961SJannik Silvanus // Check if LBB already has a diff candidate 195*f4136b32SKazu Hirata if (Inserted) { 196e0447961SJannik Silvanus // Add new one 197e0447961SJannik Silvanus BlockDiffCandidates.push_back( 198e0447961SJannik Silvanus {LBB, RBB, SmallDenseMap<const Value *, const Value *>(), false}); 199e0447961SJannik Silvanus return BlockDiffCandidates.back(); 200e0447961SJannik Silvanus } 201e0447961SJannik Silvanus // Use existing one 202e0447961SJannik Silvanus BlockDiffCandidate &Result = BlockDiffCandidates[It->second]; 203e0447961SJannik Silvanus assert(Result.RBB == RBB && "Inconsistent basic block pairing!"); 204e0447961SJannik Silvanus return Result; 205e0447961SJannik Silvanus } 206e0447961SJannik Silvanus 207e0447961SJannik Silvanus // Optionally passed to equivalence checker functions, so these can add 208e0447961SJannik Silvanus // assumptions in BlockDiffCandidates. Its presence controls whether 209e0447961SJannik Silvanus // assumptions are generated. 210e0447961SJannik Silvanus struct AssumptionContext { 211e0447961SJannik Silvanus // The two basic blocks that need the two compared values to be equivalent. 212e0447961SJannik Silvanus const BasicBlock *LBB; 213e0447961SJannik Silvanus const BasicBlock *RBB; 214e0447961SJannik Silvanus }; 215e0447961SJannik Silvanus 2164d293f21SBill Wendling unsigned getUnprocPredCount(const BasicBlock *Block) const { 2178c330445SKazu Hirata return llvm::count_if(predecessors(Block), [&](const BasicBlock *Pred) { 2188c330445SKazu Hirata return !Blocks.contains(Pred); 2198c330445SKazu Hirata }); 2204d293f21SBill Wendling } 2214d293f21SBill Wendling 2224d293f21SBill Wendling typedef std::pair<const BasicBlock *, const BasicBlock *> BlockPair; 2234d293f21SBill Wendling 2244d293f21SBill Wendling /// A type which sorts a priority queue by the number of unprocessed 2254d293f21SBill Wendling /// predecessor blocks it has remaining. 2264d293f21SBill Wendling /// 2274d293f21SBill Wendling /// This is actually really expensive to calculate. 2284d293f21SBill Wendling struct QueueSorter { 2294d293f21SBill Wendling const FunctionDifferenceEngine &fde; 2304d293f21SBill Wendling explicit QueueSorter(const FunctionDifferenceEngine &fde) : fde(fde) {} 2314d293f21SBill Wendling 2324d293f21SBill Wendling bool operator()(BlockPair &Old, BlockPair &New) { 2334d293f21SBill Wendling return fde.getUnprocPredCount(Old.first) 2344d293f21SBill Wendling < fde.getUnprocPredCount(New.first); 2354d293f21SBill Wendling } 2364d293f21SBill Wendling }; 2374d293f21SBill Wendling 2384d293f21SBill Wendling /// A queue of unified blocks to process. 2394d293f21SBill Wendling PriorityQueue<BlockPair, QueueSorter, 20> Queue; 2404d293f21SBill Wendling 2414d293f21SBill Wendling /// Try to unify the given two blocks. Enqueues them for processing 2424d293f21SBill Wendling /// if they haven't already been processed. 2434d293f21SBill Wendling /// 2444d293f21SBill Wendling /// Returns true if there was a problem unifying them. 2454d293f21SBill Wendling bool tryUnify(const BasicBlock *L, const BasicBlock *R) { 2464d293f21SBill Wendling const BasicBlock *&Ref = Blocks[L]; 2474d293f21SBill Wendling 2484d293f21SBill Wendling if (Ref) { 2494d293f21SBill Wendling if (Ref == R) return false; 2504d293f21SBill Wendling 2514d293f21SBill Wendling Engine.logf("successor %l cannot be equivalent to %r; " 2524d293f21SBill Wendling "it's already equivalent to %r") 2534d293f21SBill Wendling << L << R << Ref; 2544d293f21SBill Wendling return true; 2554d293f21SBill Wendling } 2564d293f21SBill Wendling 2574d293f21SBill Wendling Ref = R; 2584d293f21SBill Wendling Queue.insert(BlockPair(L, R)); 2594d293f21SBill Wendling return false; 2604d293f21SBill Wendling } 2614d293f21SBill Wendling 2624d293f21SBill Wendling /// Unifies two instructions, given that they're known not to have 2634d293f21SBill Wendling /// structural differences. 2644d293f21SBill Wendling void unify(const Instruction *L, const Instruction *R) { 2654d293f21SBill Wendling DifferenceEngine::Context C(Engine, L, R); 2664d293f21SBill Wendling 267e0447961SJannik Silvanus bool Result = diff(L, R, true, true, true); 2684d293f21SBill Wendling assert(!Result && "structural differences second time around?"); 2694d293f21SBill Wendling (void) Result; 2704d293f21SBill Wendling if (!L->use_empty()) 2714d293f21SBill Wendling Values[L] = R; 2724d293f21SBill Wendling } 2734d293f21SBill Wendling 2744d293f21SBill Wendling void processQueue() { 2754d293f21SBill Wendling while (!Queue.empty()) { 2764d293f21SBill Wendling BlockPair Pair = Queue.remove_min(); 2774d293f21SBill Wendling diff(Pair.first, Pair.second); 2784d293f21SBill Wendling } 2794d293f21SBill Wendling } 2804d293f21SBill Wendling 281e0447961SJannik Silvanus void checkAndReportDiffCandidates() { 282e0447961SJannik Silvanus for (BlockDiffCandidate &BDC : BlockDiffCandidates) { 283e0447961SJannik Silvanus 284e0447961SJannik Silvanus // Check assumptions 285e0447961SJannik Silvanus for (const auto &[L, R] : BDC.EquivalenceAssumptions) { 286e0447961SJannik Silvanus auto It = Values.find(L); 287e0447961SJannik Silvanus if (It == Values.end() || It->second != R) { 288e0447961SJannik Silvanus BDC.KnownToDiffer = true; 289e0447961SJannik Silvanus break; 290e0447961SJannik Silvanus } 291e0447961SJannik Silvanus } 292e0447961SJannik Silvanus 293e0447961SJannik Silvanus // Run block diff if the BBs differ 294e0447961SJannik Silvanus if (BDC.KnownToDiffer) { 295e0447961SJannik Silvanus DifferenceEngine::Context C(Engine, BDC.LBB, BDC.RBB); 296e0447961SJannik Silvanus runBlockDiff(BDC.LBB->begin(), BDC.RBB->begin()); 297e0447961SJannik Silvanus } 298e0447961SJannik Silvanus } 299e0447961SJannik Silvanus } 300e0447961SJannik Silvanus 3014d293f21SBill Wendling void diff(const BasicBlock *L, const BasicBlock *R) { 3024d293f21SBill Wendling DifferenceEngine::Context C(Engine, L, R); 3034d293f21SBill Wendling 3044d293f21SBill Wendling BasicBlock::const_iterator LI = L->begin(), LE = L->end(); 3054d293f21SBill Wendling BasicBlock::const_iterator RI = R->begin(); 3064d293f21SBill Wendling 3074d293f21SBill Wendling do { 3084d293f21SBill Wendling assert(LI != LE && RI != R->end()); 3094d293f21SBill Wendling const Instruction *LeftI = &*LI, *RightI = &*RI; 3104d293f21SBill Wendling 3114d293f21SBill Wendling // If the instructions differ, start the more sophisticated diff 3124d293f21SBill Wendling // algorithm at the start of the block. 313e0447961SJannik Silvanus if (diff(LeftI, RightI, false, false, true)) { 3144d293f21SBill Wendling TentativeValues.clear(); 315e0447961SJannik Silvanus // Register (L, R) as diffing pair. Note that we could directly emit a 316e0447961SJannik Silvanus // block diff here, but this way we ensure all diffs are emitted in one 317e0447961SJannik Silvanus // consistent order, independent of whether the diffs were detected 318e0447961SJannik Silvanus // immediately or via invalid assumptions. 319e0447961SJannik Silvanus getOrCreateBlockDiffCandidate(L, R).KnownToDiffer = true; 320e0447961SJannik Silvanus return; 3214d293f21SBill Wendling } 3224d293f21SBill Wendling 3234d293f21SBill Wendling // Otherwise, tentatively unify them. 3244d293f21SBill Wendling if (!LeftI->use_empty()) 3254d293f21SBill Wendling TentativeValues.insert(std::make_pair(LeftI, RightI)); 3264d293f21SBill Wendling 3274d293f21SBill Wendling ++LI; 3284d293f21SBill Wendling ++RI; 3294d293f21SBill Wendling } while (LI != LE); // This is sufficient: we can't get equality of 3304d293f21SBill Wendling // terminators if there are residual instructions. 3314d293f21SBill Wendling 3324d293f21SBill Wendling // Unify everything in the block, non-tentatively this time. 3334d293f21SBill Wendling TentativeValues.clear(); 3344d293f21SBill Wendling for (LI = L->begin(), RI = R->begin(); LI != LE; ++LI, ++RI) 3354d293f21SBill Wendling unify(&*LI, &*RI); 3364d293f21SBill Wendling } 3374d293f21SBill Wendling 3384d293f21SBill Wendling bool matchForBlockDiff(const Instruction *L, const Instruction *R); 3394d293f21SBill Wendling void runBlockDiff(BasicBlock::const_iterator LI, 3404d293f21SBill Wendling BasicBlock::const_iterator RI); 3414d293f21SBill Wendling 3424d293f21SBill Wendling bool diffCallSites(const CallBase &L, const CallBase &R, bool Complain) { 3434d293f21SBill Wendling // FIXME: call attributes 344e0447961SJannik Silvanus AssumptionContext AC = {L.getParent(), R.getParent()}; 345e0447961SJannik Silvanus if (!equivalentAsOperands(L.getCalledOperand(), R.getCalledOperand(), 346e0447961SJannik Silvanus &AC)) { 3474d293f21SBill Wendling if (Complain) Engine.log("called functions differ"); 3484d293f21SBill Wendling return true; 3494d293f21SBill Wendling } 3504d293f21SBill Wendling if (L.arg_size() != R.arg_size()) { 3514d293f21SBill Wendling if (Complain) Engine.log("argument counts differ"); 3524d293f21SBill Wendling return true; 3534d293f21SBill Wendling } 3544d293f21SBill Wendling for (unsigned I = 0, E = L.arg_size(); I != E; ++I) 355e0447961SJannik Silvanus if (!equivalentAsOperands(L.getArgOperand(I), R.getArgOperand(I), &AC)) { 3564d293f21SBill Wendling if (Complain) 3574d293f21SBill Wendling Engine.logf("arguments %l and %r differ") 3584d293f21SBill Wendling << L.getArgOperand(I) << R.getArgOperand(I); 3594d293f21SBill Wendling return true; 3604d293f21SBill Wendling } 3614d293f21SBill Wendling return false; 3624d293f21SBill Wendling } 3634d293f21SBill Wendling 364e0447961SJannik Silvanus // If AllowAssumptions is enabled, whenever we encounter a pair of values 365e0447961SJannik Silvanus // that we cannot prove to be equivalent, we assume equivalence and store that 366e0447961SJannik Silvanus // assumption to be checked later in BlockDiffCandidates. 3674d293f21SBill Wendling bool diff(const Instruction *L, const Instruction *R, bool Complain, 368e0447961SJannik Silvanus bool TryUnify, bool AllowAssumptions) { 3694d293f21SBill Wendling // FIXME: metadata (if Complain is set) 370e0447961SJannik Silvanus AssumptionContext ACValue = {L->getParent(), R->getParent()}; 371e0447961SJannik Silvanus // nullptr AssumptionContext disables assumption generation. 372e0447961SJannik Silvanus const AssumptionContext *AC = AllowAssumptions ? &ACValue : nullptr; 3734d293f21SBill Wendling 3744d293f21SBill Wendling // Different opcodes always imply different operations. 3754d293f21SBill Wendling if (L->getOpcode() != R->getOpcode()) { 3764d293f21SBill Wendling if (Complain) Engine.log("different instruction types"); 3774d293f21SBill Wendling return true; 3784d293f21SBill Wendling } 3794d293f21SBill Wendling 3804d293f21SBill Wendling if (isa<CmpInst>(L)) { 3814d293f21SBill Wendling if (cast<CmpInst>(L)->getPredicate() 3824d293f21SBill Wendling != cast<CmpInst>(R)->getPredicate()) { 3834d293f21SBill Wendling if (Complain) Engine.log("different predicates"); 3844d293f21SBill Wendling return true; 3854d293f21SBill Wendling } 3864d293f21SBill Wendling } else if (isa<CallInst>(L)) { 3874d293f21SBill Wendling return diffCallSites(cast<CallInst>(*L), cast<CallInst>(*R), Complain); 3884d293f21SBill Wendling } else if (isa<PHINode>(L)) { 3892975f37dSBill Wendling const PHINode &LI = cast<PHINode>(*L); 3902975f37dSBill Wendling const PHINode &RI = cast<PHINode>(*R); 3914d293f21SBill Wendling 3924d293f21SBill Wendling // This is really weird; type uniquing is broken? 3932975f37dSBill Wendling if (LI.getType() != RI.getType()) { 3942975f37dSBill Wendling if (!LI.getType()->isPointerTy() || !RI.getType()->isPointerTy()) { 3954d293f21SBill Wendling if (Complain) Engine.log("different phi types"); 3964d293f21SBill Wendling return true; 3974d293f21SBill Wendling } 3984d293f21SBill Wendling } 3992975f37dSBill Wendling 4002975f37dSBill Wendling if (LI.getNumIncomingValues() != RI.getNumIncomingValues()) { 4012975f37dSBill Wendling if (Complain) 4022975f37dSBill Wendling Engine.log("PHI node # of incoming values differ"); 4032975f37dSBill Wendling return true; 4042975f37dSBill Wendling } 4052975f37dSBill Wendling 4062975f37dSBill Wendling for (unsigned I = 0; I < LI.getNumIncomingValues(); ++I) { 4072975f37dSBill Wendling if (TryUnify) 4082975f37dSBill Wendling tryUnify(LI.getIncomingBlock(I), RI.getIncomingBlock(I)); 4092975f37dSBill Wendling 4102975f37dSBill Wendling if (!equivalentAsOperands(LI.getIncomingValue(I), 411e0447961SJannik Silvanus RI.getIncomingValue(I), AC)) { 4122975f37dSBill Wendling if (Complain) 4132975f37dSBill Wendling Engine.log("PHI node incoming values differ"); 4142975f37dSBill Wendling return true; 4152975f37dSBill Wendling } 4162975f37dSBill Wendling } 4172975f37dSBill Wendling 4184d293f21SBill Wendling return false; 4194d293f21SBill Wendling 4204d293f21SBill Wendling // Terminators. 4214d293f21SBill Wendling } else if (isa<InvokeInst>(L)) { 4224d293f21SBill Wendling const InvokeInst &LI = cast<InvokeInst>(*L); 4234d293f21SBill Wendling const InvokeInst &RI = cast<InvokeInst>(*R); 4244d293f21SBill Wendling if (diffCallSites(LI, RI, Complain)) 4254d293f21SBill Wendling return true; 4264d293f21SBill Wendling 4274d293f21SBill Wendling if (TryUnify) { 4284d293f21SBill Wendling tryUnify(LI.getNormalDest(), RI.getNormalDest()); 4294d293f21SBill Wendling tryUnify(LI.getUnwindDest(), RI.getUnwindDest()); 4304d293f21SBill Wendling } 4314d293f21SBill Wendling return false; 4324d293f21SBill Wendling 4334d293f21SBill Wendling } else if (isa<CallBrInst>(L)) { 4344d293f21SBill Wendling const CallBrInst &LI = cast<CallBrInst>(*L); 4354d293f21SBill Wendling const CallBrInst &RI = cast<CallBrInst>(*R); 4364d293f21SBill Wendling if (LI.getNumIndirectDests() != RI.getNumIndirectDests()) { 4374d293f21SBill Wendling if (Complain) 4384d293f21SBill Wendling Engine.log("callbr # of indirect destinations differ"); 4394d293f21SBill Wendling return true; 4404d293f21SBill Wendling } 4414d293f21SBill Wendling 4424d293f21SBill Wendling // Perform the "try unify" step so that we can equate the indirect 4434d293f21SBill Wendling // destinations before checking the call site. 4444d293f21SBill Wendling for (unsigned I = 0; I < LI.getNumIndirectDests(); I++) 4454d293f21SBill Wendling tryUnify(LI.getIndirectDest(I), RI.getIndirectDest(I)); 4464d293f21SBill Wendling 4474d293f21SBill Wendling if (diffCallSites(LI, RI, Complain)) 4484d293f21SBill Wendling return true; 4494d293f21SBill Wendling 4504d293f21SBill Wendling if (TryUnify) 4514d293f21SBill Wendling tryUnify(LI.getDefaultDest(), RI.getDefaultDest()); 4524d293f21SBill Wendling return false; 4534d293f21SBill Wendling 4544d293f21SBill Wendling } else if (isa<BranchInst>(L)) { 4554d293f21SBill Wendling const BranchInst *LI = cast<BranchInst>(L); 4564d293f21SBill Wendling const BranchInst *RI = cast<BranchInst>(R); 4574d293f21SBill Wendling if (LI->isConditional() != RI->isConditional()) { 4584d293f21SBill Wendling if (Complain) Engine.log("branch conditionality differs"); 4594d293f21SBill Wendling return true; 4604d293f21SBill Wendling } 4614d293f21SBill Wendling 4624d293f21SBill Wendling if (LI->isConditional()) { 463e0447961SJannik Silvanus if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) { 4644d293f21SBill Wendling if (Complain) Engine.log("branch conditions differ"); 4654d293f21SBill Wendling return true; 4664d293f21SBill Wendling } 4674d293f21SBill Wendling if (TryUnify) tryUnify(LI->getSuccessor(1), RI->getSuccessor(1)); 4684d293f21SBill Wendling } 4694d293f21SBill Wendling if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0)); 4704d293f21SBill Wendling return false; 4714d293f21SBill Wendling 4724d293f21SBill Wendling } else if (isa<IndirectBrInst>(L)) { 4734d293f21SBill Wendling const IndirectBrInst *LI = cast<IndirectBrInst>(L); 4744d293f21SBill Wendling const IndirectBrInst *RI = cast<IndirectBrInst>(R); 4754d293f21SBill Wendling if (LI->getNumDestinations() != RI->getNumDestinations()) { 4764d293f21SBill Wendling if (Complain) Engine.log("indirectbr # of destinations differ"); 4774d293f21SBill Wendling return true; 4784d293f21SBill Wendling } 4794d293f21SBill Wendling 480e0447961SJannik Silvanus if (!equivalentAsOperands(LI->getAddress(), RI->getAddress(), AC)) { 4814d293f21SBill Wendling if (Complain) Engine.log("indirectbr addresses differ"); 4824d293f21SBill Wendling return true; 4834d293f21SBill Wendling } 4844d293f21SBill Wendling 4854d293f21SBill Wendling if (TryUnify) { 4864d293f21SBill Wendling for (unsigned i = 0; i < LI->getNumDestinations(); i++) { 4874d293f21SBill Wendling tryUnify(LI->getDestination(i), RI->getDestination(i)); 4884d293f21SBill Wendling } 4894d293f21SBill Wendling } 4904d293f21SBill Wendling return false; 4914d293f21SBill Wendling 4924d293f21SBill Wendling } else if (isa<SwitchInst>(L)) { 4934d293f21SBill Wendling const SwitchInst *LI = cast<SwitchInst>(L); 4944d293f21SBill Wendling const SwitchInst *RI = cast<SwitchInst>(R); 495e0447961SJannik Silvanus if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) { 4964d293f21SBill Wendling if (Complain) Engine.log("switch conditions differ"); 4974d293f21SBill Wendling return true; 4984d293f21SBill Wendling } 4994d293f21SBill Wendling if (TryUnify) tryUnify(LI->getDefaultDest(), RI->getDefaultDest()); 5004d293f21SBill Wendling 5014d293f21SBill Wendling bool Difference = false; 5024d293f21SBill Wendling 5034d293f21SBill Wendling DenseMap<const ConstantInt *, const BasicBlock *> LCases; 5044d293f21SBill Wendling for (auto Case : LI->cases()) 5054d293f21SBill Wendling LCases[Case.getCaseValue()] = Case.getCaseSuccessor(); 5064d293f21SBill Wendling 5074d293f21SBill Wendling for (auto Case : RI->cases()) { 5084d293f21SBill Wendling const ConstantInt *CaseValue = Case.getCaseValue(); 5094d293f21SBill Wendling const BasicBlock *LCase = LCases[CaseValue]; 5104d293f21SBill Wendling if (LCase) { 5114d293f21SBill Wendling if (TryUnify) 5124d293f21SBill Wendling tryUnify(LCase, Case.getCaseSuccessor()); 5134d293f21SBill Wendling LCases.erase(CaseValue); 5144d293f21SBill Wendling } else if (Complain || !Difference) { 5154d293f21SBill Wendling if (Complain) 5164d293f21SBill Wendling Engine.logf("right switch has extra case %r") << CaseValue; 5174d293f21SBill Wendling Difference = true; 5184d293f21SBill Wendling } 5194d293f21SBill Wendling } 5204d293f21SBill Wendling if (!Difference) 5214d293f21SBill Wendling for (DenseMap<const ConstantInt *, const BasicBlock *>::iterator 5224d293f21SBill Wendling I = LCases.begin(), 5234d293f21SBill Wendling E = LCases.end(); 5244d293f21SBill Wendling I != E; ++I) { 5254d293f21SBill Wendling if (Complain) 5264d293f21SBill Wendling Engine.logf("left switch has extra case %l") << I->first; 5274d293f21SBill Wendling Difference = true; 5284d293f21SBill Wendling } 5294d293f21SBill Wendling return Difference; 5304d293f21SBill Wendling } else if (isa<UnreachableInst>(L)) { 5314d293f21SBill Wendling return false; 5324d293f21SBill Wendling } 5334d293f21SBill Wendling 5344d293f21SBill Wendling if (L->getNumOperands() != R->getNumOperands()) { 5354d293f21SBill Wendling if (Complain) Engine.log("instructions have different operand counts"); 5364d293f21SBill Wendling return true; 5374d293f21SBill Wendling } 5384d293f21SBill Wendling 5394d293f21SBill Wendling for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) { 5404d293f21SBill Wendling Value *LO = L->getOperand(I), *RO = R->getOperand(I); 541e0447961SJannik Silvanus if (!equivalentAsOperands(LO, RO, AC)) { 5424d293f21SBill Wendling if (Complain) Engine.logf("operands %l and %r differ") << LO << RO; 5434d293f21SBill Wendling return true; 5444d293f21SBill Wendling } 5454d293f21SBill Wendling } 5464d293f21SBill Wendling 5474d293f21SBill Wendling return false; 5484d293f21SBill Wendling } 5494d293f21SBill Wendling 5504d293f21SBill Wendling public: 551e0447961SJannik Silvanus bool equivalentAsOperands(const Constant *L, const Constant *R, 552e0447961SJannik Silvanus const AssumptionContext *AC) { 5534d293f21SBill Wendling // Use equality as a preliminary filter. 5544d293f21SBill Wendling if (L == R) 5554d293f21SBill Wendling return true; 5564d293f21SBill Wendling 5574d293f21SBill Wendling if (L->getValueID() != R->getValueID()) 5584d293f21SBill Wendling return false; 5594d293f21SBill Wendling 5604d293f21SBill Wendling // Ask the engine about global values. 5614d293f21SBill Wendling if (isa<GlobalValue>(L)) 5624d293f21SBill Wendling return Engine.equivalentAsOperands(cast<GlobalValue>(L), 5634d293f21SBill Wendling cast<GlobalValue>(R)); 5644d293f21SBill Wendling 5654d293f21SBill Wendling // Compare constant expressions structurally. 5664d293f21SBill Wendling if (isa<ConstantExpr>(L)) 567e0447961SJannik Silvanus return equivalentAsOperands(cast<ConstantExpr>(L), cast<ConstantExpr>(R), 568e0447961SJannik Silvanus AC); 5694d293f21SBill Wendling 5704d293f21SBill Wendling // Constants of the "same type" don't always actually have the same 5714d293f21SBill Wendling // type; I don't know why. Just white-list them. 5724d293f21SBill Wendling if (isa<ConstantPointerNull>(L) || isa<UndefValue>(L) || isa<ConstantAggregateZero>(L)) 5734d293f21SBill Wendling return true; 5744d293f21SBill Wendling 5754d293f21SBill Wendling // Block addresses only match if we've already encountered the 5764d293f21SBill Wendling // block. FIXME: tentative matches? 5774d293f21SBill Wendling if (isa<BlockAddress>(L)) 5784d293f21SBill Wendling return Blocks[cast<BlockAddress>(L)->getBasicBlock()] 5794d293f21SBill Wendling == cast<BlockAddress>(R)->getBasicBlock(); 5804d293f21SBill Wendling 5814d293f21SBill Wendling // If L and R are ConstantVectors, compare each element 5824d293f21SBill Wendling if (isa<ConstantVector>(L)) { 5834d293f21SBill Wendling const ConstantVector *CVL = cast<ConstantVector>(L); 5844d293f21SBill Wendling const ConstantVector *CVR = cast<ConstantVector>(R); 5854d293f21SBill Wendling if (CVL->getType()->getNumElements() != CVR->getType()->getNumElements()) 5864d293f21SBill Wendling return false; 5874d293f21SBill Wendling for (unsigned i = 0; i < CVL->getType()->getNumElements(); i++) { 588e0447961SJannik Silvanus if (!equivalentAsOperands(CVL->getOperand(i), CVR->getOperand(i), AC)) 5894d293f21SBill Wendling return false; 5904d293f21SBill Wendling } 5914d293f21SBill Wendling return true; 5924d293f21SBill Wendling } 5934d293f21SBill Wendling 5944d293f21SBill Wendling // If L and R are ConstantArrays, compare the element count and types. 5954d293f21SBill Wendling if (isa<ConstantArray>(L)) { 5964d293f21SBill Wendling const ConstantArray *CAL = cast<ConstantArray>(L); 5974d293f21SBill Wendling const ConstantArray *CAR = cast<ConstantArray>(R); 5984d293f21SBill Wendling // Sometimes a type may be equivalent, but not uniquified---e.g. it may 5994d293f21SBill Wendling // contain a GEP instruction. Do a deeper comparison of the types. 6004d293f21SBill Wendling if (CAL->getType()->getNumElements() != CAR->getType()->getNumElements()) 6014d293f21SBill Wendling return false; 6024d293f21SBill Wendling 6034d293f21SBill Wendling for (unsigned I = 0; I < CAL->getType()->getNumElements(); ++I) { 6044d293f21SBill Wendling if (!equivalentAsOperands(CAL->getAggregateElement(I), 605e0447961SJannik Silvanus CAR->getAggregateElement(I), AC)) 6064d293f21SBill Wendling return false; 6074d293f21SBill Wendling } 6084d293f21SBill Wendling 6094d293f21SBill Wendling return true; 6104d293f21SBill Wendling } 6114d293f21SBill Wendling 6124d293f21SBill Wendling // If L and R are ConstantStructs, compare each field and type. 6134d293f21SBill Wendling if (isa<ConstantStruct>(L)) { 6144d293f21SBill Wendling const ConstantStruct *CSL = cast<ConstantStruct>(L); 6154d293f21SBill Wendling const ConstantStruct *CSR = cast<ConstantStruct>(R); 6164d293f21SBill Wendling 6174d293f21SBill Wendling const StructType *LTy = cast<StructType>(CSL->getType()); 6184d293f21SBill Wendling const StructType *RTy = cast<StructType>(CSR->getType()); 6194d293f21SBill Wendling 6204d293f21SBill Wendling // The StructTypes should have the same attributes. Don't use 6214d293f21SBill Wendling // isLayoutIdentical(), because that just checks the element pointers, 6224d293f21SBill Wendling // which may not work here. 6234d293f21SBill Wendling if (LTy->getNumElements() != RTy->getNumElements() || 6244d293f21SBill Wendling LTy->isPacked() != RTy->isPacked()) 6254d293f21SBill Wendling return false; 6264d293f21SBill Wendling 6274d293f21SBill Wendling for (unsigned I = 0; I < LTy->getNumElements(); I++) { 6284d293f21SBill Wendling const Value *LAgg = CSL->getAggregateElement(I); 6294d293f21SBill Wendling const Value *RAgg = CSR->getAggregateElement(I); 6304d293f21SBill Wendling 6314d293f21SBill Wendling if (LAgg == SavedLHS || RAgg == SavedRHS) { 6324d293f21SBill Wendling if (LAgg != SavedLHS || RAgg != SavedRHS) 6334d293f21SBill Wendling // If the left and right operands aren't both re-analyzing the 6344d293f21SBill Wendling // variable, then the initialiers don't match, so report "false". 6354d293f21SBill Wendling // Otherwise, we skip these operands.. 6364d293f21SBill Wendling return false; 6374d293f21SBill Wendling 6384d293f21SBill Wendling continue; 6394d293f21SBill Wendling } 6404d293f21SBill Wendling 641e0447961SJannik Silvanus if (!equivalentAsOperands(LAgg, RAgg, AC)) { 6424d293f21SBill Wendling return false; 6434d293f21SBill Wendling } 6444d293f21SBill Wendling } 6454d293f21SBill Wendling 6464d293f21SBill Wendling return true; 6474d293f21SBill Wendling } 6484d293f21SBill Wendling 6494d293f21SBill Wendling return false; 6504d293f21SBill Wendling } 6514d293f21SBill Wendling 652e0447961SJannik Silvanus bool equivalentAsOperands(const ConstantExpr *L, const ConstantExpr *R, 653e0447961SJannik Silvanus const AssumptionContext *AC) { 6544d293f21SBill Wendling if (L == R) 6554d293f21SBill Wendling return true; 6564d293f21SBill Wendling 6574d293f21SBill Wendling if (L->getOpcode() != R->getOpcode()) 6584d293f21SBill Wendling return false; 6594d293f21SBill Wendling 6604d293f21SBill Wendling switch (L->getOpcode()) { 6614d293f21SBill Wendling case Instruction::GetElementPtr: 6624d293f21SBill Wendling // FIXME: inbounds? 6634d293f21SBill Wendling break; 6644d293f21SBill Wendling 6654d293f21SBill Wendling default: 6664d293f21SBill Wendling break; 6674d293f21SBill Wendling } 6684d293f21SBill Wendling 6694d293f21SBill Wendling if (L->getNumOperands() != R->getNumOperands()) 6704d293f21SBill Wendling return false; 6714d293f21SBill Wendling 6724d293f21SBill Wendling for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) { 6734d293f21SBill Wendling const auto *LOp = L->getOperand(I); 6744d293f21SBill Wendling const auto *ROp = R->getOperand(I); 6754d293f21SBill Wendling 6764d293f21SBill Wendling if (LOp == SavedLHS || ROp == SavedRHS) { 6774d293f21SBill Wendling if (LOp != SavedLHS || ROp != SavedRHS) 6784d293f21SBill Wendling // If the left and right operands aren't both re-analyzing the 6794d293f21SBill Wendling // variable, then the initialiers don't match, so report "false". 6804d293f21SBill Wendling // Otherwise, we skip these operands.. 6814d293f21SBill Wendling return false; 6824d293f21SBill Wendling 6834d293f21SBill Wendling continue; 6844d293f21SBill Wendling } 6854d293f21SBill Wendling 686e0447961SJannik Silvanus if (!equivalentAsOperands(LOp, ROp, AC)) 6874d293f21SBill Wendling return false; 6884d293f21SBill Wendling } 6894d293f21SBill Wendling 6904d293f21SBill Wendling return true; 6914d293f21SBill Wendling } 6924d293f21SBill Wendling 693e0447961SJannik Silvanus // There are cases where we cannot determine whether two values are 694e0447961SJannik Silvanus // equivalent, because it depends on not yet processed basic blocks -- see the 695e0447961SJannik Silvanus // documentation on assumptions. 696e0447961SJannik Silvanus // 697e0447961SJannik Silvanus // AC is the context in which we are currently performing a diff. 698e0447961SJannik Silvanus // When we encounter a pair of values for which we can neither prove 699e0447961SJannik Silvanus // equivalence nor the opposite, we do the following: 700e0447961SJannik Silvanus // * If AC is nullptr, we treat the pair as non-equivalent. 701e0447961SJannik Silvanus // * If AC is set, we add an assumption for the basic blocks given by AC, 702e0447961SJannik Silvanus // and treat the pair as equivalent. The assumption is checked later. 703e0447961SJannik Silvanus bool equivalentAsOperands(const Value *L, const Value *R, 704e0447961SJannik Silvanus const AssumptionContext *AC) { 7054d293f21SBill Wendling // Fall out if the values have different kind. 7064d293f21SBill Wendling // This possibly shouldn't take priority over oracles. 7074d293f21SBill Wendling if (L->getValueID() != R->getValueID()) 7084d293f21SBill Wendling return false; 7094d293f21SBill Wendling 7104d293f21SBill Wendling // Value subtypes: Argument, Constant, Instruction, BasicBlock, 7114d293f21SBill Wendling // InlineAsm, MDNode, MDString, PseudoSourceValue 7124d293f21SBill Wendling 7134d293f21SBill Wendling if (isa<Constant>(L)) 714e0447961SJannik Silvanus return equivalentAsOperands(cast<Constant>(L), cast<Constant>(R), AC); 7154d293f21SBill Wendling 716e0447961SJannik Silvanus if (isa<Instruction>(L)) { 717e0447961SJannik Silvanus auto It = Values.find(L); 718e0447961SJannik Silvanus if (It != Values.end()) 719e0447961SJannik Silvanus return It->second == R; 720e0447961SJannik Silvanus 721e0447961SJannik Silvanus if (TentativeValues.count(std::make_pair(L, R))) 722e0447961SJannik Silvanus return true; 723e0447961SJannik Silvanus 724e0447961SJannik Silvanus // L and R might be equivalent, this could depend on not yet processed 725e0447961SJannik Silvanus // basic blocks, so we cannot decide here. 726e0447961SJannik Silvanus if (AC) { 727e0447961SJannik Silvanus // Add an assumption, unless there is a conflict with an existing one 728e0447961SJannik Silvanus BlockDiffCandidate &BDC = 729e0447961SJannik Silvanus getOrCreateBlockDiffCandidate(AC->LBB, AC->RBB); 730e0447961SJannik Silvanus auto InsertionResult = BDC.EquivalenceAssumptions.insert({L, R}); 731e0447961SJannik Silvanus if (!InsertionResult.second && InsertionResult.first->second != R) { 732e0447961SJannik Silvanus // We already have a conflicting equivalence assumption for L, so at 733e0447961SJannik Silvanus // least one must be wrong, and we know that there is a diff. 734e0447961SJannik Silvanus BDC.KnownToDiffer = true; 735e0447961SJannik Silvanus BDC.EquivalenceAssumptions.clear(); 736e0447961SJannik Silvanus return false; 737e0447961SJannik Silvanus } 738e0447961SJannik Silvanus // Optimistically assume equivalence, and check later once all BBs 739e0447961SJannik Silvanus // have been processed. 740e0447961SJannik Silvanus return true; 741e0447961SJannik Silvanus } 742e0447961SJannik Silvanus 743e0447961SJannik Silvanus // Assumptions disabled, so pessimistically assume non-equivalence. 744e0447961SJannik Silvanus return false; 745e0447961SJannik Silvanus } 7464d293f21SBill Wendling 7474d293f21SBill Wendling if (isa<Argument>(L)) 7484d293f21SBill Wendling return Values[L] == R; 7494d293f21SBill Wendling 7504d293f21SBill Wendling if (isa<BasicBlock>(L)) 7514d293f21SBill Wendling return Blocks[cast<BasicBlock>(L)] != R; 7524d293f21SBill Wendling 7534d293f21SBill Wendling // Pretend everything else is identical. 7544d293f21SBill Wendling return true; 7554d293f21SBill Wendling } 7564d293f21SBill Wendling 7574d293f21SBill Wendling // Avoid a gcc warning about accessing 'this' in an initializer. 7584d293f21SBill Wendling FunctionDifferenceEngine *this_() { return this; } 7594d293f21SBill Wendling 7604d293f21SBill Wendling public: 7614d293f21SBill Wendling FunctionDifferenceEngine(DifferenceEngine &Engine, 7624d293f21SBill Wendling const Value *SavedLHS = nullptr, 7634d293f21SBill Wendling const Value *SavedRHS = nullptr) 7644d293f21SBill Wendling : Engine(Engine), SavedLHS(SavedLHS), SavedRHS(SavedRHS), 7654d293f21SBill Wendling Queue(QueueSorter(*this_())) {} 7664d293f21SBill Wendling 7674d293f21SBill Wendling void diff(const Function *L, const Function *R) { 768e0447961SJannik Silvanus assert(Values.empty() && "Multiple diffs per engine are not supported!"); 769e0447961SJannik Silvanus 7704d293f21SBill Wendling if (L->arg_size() != R->arg_size()) 7714d293f21SBill Wendling Engine.log("different argument counts"); 7724d293f21SBill Wendling 7734d293f21SBill Wendling // Map the arguments. 7744d293f21SBill Wendling for (Function::const_arg_iterator LI = L->arg_begin(), LE = L->arg_end(), 7754d293f21SBill Wendling RI = R->arg_begin(), RE = R->arg_end(); 7764d293f21SBill Wendling LI != LE && RI != RE; ++LI, ++RI) 7774d293f21SBill Wendling Values[&*LI] = &*RI; 7784d293f21SBill Wendling 7794d293f21SBill Wendling tryUnify(&*L->begin(), &*R->begin()); 7804d293f21SBill Wendling processQueue(); 781e0447961SJannik Silvanus checkAndReportDiffCandidates(); 7824d293f21SBill Wendling } 7834d293f21SBill Wendling }; 7844d293f21SBill Wendling 7854d293f21SBill Wendling struct DiffEntry { 7865fcecea8SKazu Hirata DiffEntry() = default; 7874d293f21SBill Wendling 7885fcecea8SKazu Hirata unsigned Cost = 0; 7894d293f21SBill Wendling llvm::SmallVector<char, 8> Path; // actually of DifferenceEngine::DiffChange 7904d293f21SBill Wendling }; 7914d293f21SBill Wendling 7924d293f21SBill Wendling bool FunctionDifferenceEngine::matchForBlockDiff(const Instruction *L, 7934d293f21SBill Wendling const Instruction *R) { 794e0447961SJannik Silvanus return !diff(L, R, false, false, false); 7954d293f21SBill Wendling } 7964d293f21SBill Wendling 7974d293f21SBill Wendling void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart, 7984d293f21SBill Wendling BasicBlock::const_iterator RStart) { 7994d293f21SBill Wendling BasicBlock::const_iterator LE = LStart->getParent()->end(); 8004d293f21SBill Wendling BasicBlock::const_iterator RE = RStart->getParent()->end(); 8014d293f21SBill Wendling 8024d293f21SBill Wendling unsigned NL = std::distance(LStart, LE); 8034d293f21SBill Wendling 8044d293f21SBill Wendling SmallVector<DiffEntry, 20> Paths1(NL+1); 8054d293f21SBill Wendling SmallVector<DiffEntry, 20> Paths2(NL+1); 8064d293f21SBill Wendling 8074d293f21SBill Wendling DiffEntry *Cur = Paths1.data(); 8084d293f21SBill Wendling DiffEntry *Next = Paths2.data(); 8094d293f21SBill Wendling 8104d293f21SBill Wendling const unsigned LeftCost = 2; 8114d293f21SBill Wendling const unsigned RightCost = 2; 8124d293f21SBill Wendling const unsigned MatchCost = 0; 8134d293f21SBill Wendling 8144d293f21SBill Wendling assert(TentativeValues.empty()); 8154d293f21SBill Wendling 8164d293f21SBill Wendling // Initialize the first column. 8174d293f21SBill Wendling for (unsigned I = 0; I != NL+1; ++I) { 8184d293f21SBill Wendling Cur[I].Cost = I * LeftCost; 8194d293f21SBill Wendling for (unsigned J = 0; J != I; ++J) 8204d293f21SBill Wendling Cur[I].Path.push_back(DC_left); 8214d293f21SBill Wendling } 8224d293f21SBill Wendling 8234d293f21SBill Wendling for (BasicBlock::const_iterator RI = RStart; RI != RE; ++RI) { 8244d293f21SBill Wendling // Initialize the first row. 8254d293f21SBill Wendling Next[0] = Cur[0]; 8264d293f21SBill Wendling Next[0].Cost += RightCost; 8274d293f21SBill Wendling Next[0].Path.push_back(DC_right); 8284d293f21SBill Wendling 8294d293f21SBill Wendling unsigned Index = 1; 8304d293f21SBill Wendling for (BasicBlock::const_iterator LI = LStart; LI != LE; ++LI, ++Index) { 8314d293f21SBill Wendling if (matchForBlockDiff(&*LI, &*RI)) { 8324d293f21SBill Wendling Next[Index] = Cur[Index-1]; 8334d293f21SBill Wendling Next[Index].Cost += MatchCost; 8344d293f21SBill Wendling Next[Index].Path.push_back(DC_match); 8354d293f21SBill Wendling TentativeValues.insert(std::make_pair(&*LI, &*RI)); 8364d293f21SBill Wendling } else if (Next[Index-1].Cost <= Cur[Index].Cost) { 8374d293f21SBill Wendling Next[Index] = Next[Index-1]; 8384d293f21SBill Wendling Next[Index].Cost += LeftCost; 8394d293f21SBill Wendling Next[Index].Path.push_back(DC_left); 8404d293f21SBill Wendling } else { 8414d293f21SBill Wendling Next[Index] = Cur[Index]; 8424d293f21SBill Wendling Next[Index].Cost += RightCost; 8434d293f21SBill Wendling Next[Index].Path.push_back(DC_right); 8444d293f21SBill Wendling } 8454d293f21SBill Wendling } 8464d293f21SBill Wendling 8474d293f21SBill Wendling std::swap(Cur, Next); 8484d293f21SBill Wendling } 8494d293f21SBill Wendling 8504d293f21SBill Wendling // We don't need the tentative values anymore; everything from here 8514d293f21SBill Wendling // on out should be non-tentative. 8524d293f21SBill Wendling TentativeValues.clear(); 8534d293f21SBill Wendling 8544d293f21SBill Wendling SmallVectorImpl<char> &Path = Cur[NL].Path; 8554d293f21SBill Wendling BasicBlock::const_iterator LI = LStart, RI = RStart; 8564d293f21SBill Wendling 8574d293f21SBill Wendling DiffLogBuilder Diff(Engine.getConsumer()); 8584d293f21SBill Wendling 8594d293f21SBill Wendling // Drop trailing matches. 8604d293f21SBill Wendling while (Path.size() && Path.back() == DC_match) 8614d293f21SBill Wendling Path.pop_back(); 8624d293f21SBill Wendling 8634d293f21SBill Wendling // Skip leading matches. 8644d293f21SBill Wendling SmallVectorImpl<char>::iterator 8654d293f21SBill Wendling PI = Path.begin(), PE = Path.end(); 8664d293f21SBill Wendling while (PI != PE && *PI == DC_match) { 8674d293f21SBill Wendling unify(&*LI, &*RI); 8684d293f21SBill Wendling ++PI; 8694d293f21SBill Wendling ++LI; 8704d293f21SBill Wendling ++RI; 8714d293f21SBill Wendling } 8724d293f21SBill Wendling 8734d293f21SBill Wendling for (; PI != PE; ++PI) { 8744d293f21SBill Wendling switch (static_cast<DiffChange>(*PI)) { 8754d293f21SBill Wendling case DC_match: 8764d293f21SBill Wendling assert(LI != LE && RI != RE); 8774d293f21SBill Wendling { 8784d293f21SBill Wendling const Instruction *L = &*LI, *R = &*RI; 8794d293f21SBill Wendling unify(L, R); 8804d293f21SBill Wendling Diff.addMatch(L, R); 8814d293f21SBill Wendling } 8824d293f21SBill Wendling ++LI; ++RI; 8834d293f21SBill Wendling break; 8844d293f21SBill Wendling 8854d293f21SBill Wendling case DC_left: 8864d293f21SBill Wendling assert(LI != LE); 8874d293f21SBill Wendling Diff.addLeft(&*LI); 8884d293f21SBill Wendling ++LI; 8894d293f21SBill Wendling break; 8904d293f21SBill Wendling 8914d293f21SBill Wendling case DC_right: 8924d293f21SBill Wendling assert(RI != RE); 8934d293f21SBill Wendling Diff.addRight(&*RI); 8944d293f21SBill Wendling ++RI; 8954d293f21SBill Wendling break; 8964d293f21SBill Wendling } 8974d293f21SBill Wendling } 8984d293f21SBill Wendling 8994d293f21SBill Wendling // Finishing unifying and complaining about the tails of the block, 9004d293f21SBill Wendling // which should be matches all the way through. 9014d293f21SBill Wendling while (LI != LE) { 9024d293f21SBill Wendling assert(RI != RE); 9034d293f21SBill Wendling unify(&*LI, &*RI); 9044d293f21SBill Wendling ++LI; 9054d293f21SBill Wendling ++RI; 9064d293f21SBill Wendling } 9074d293f21SBill Wendling 9084d293f21SBill Wendling // If the terminators have different kinds, but one is an invoke and the 9094d293f21SBill Wendling // other is an unconditional branch immediately following a call, unify 9104d293f21SBill Wendling // the results and the destinations. 9114d293f21SBill Wendling const Instruction *LTerm = LStart->getParent()->getTerminator(); 9124d293f21SBill Wendling const Instruction *RTerm = RStart->getParent()->getTerminator(); 9134d293f21SBill Wendling if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) { 9144d293f21SBill Wendling if (cast<BranchInst>(LTerm)->isConditional()) return; 9154d293f21SBill Wendling BasicBlock::const_iterator I = LTerm->getIterator(); 9164d293f21SBill Wendling if (I == LStart->getParent()->begin()) return; 9174d293f21SBill Wendling --I; 9184d293f21SBill Wendling if (!isa<CallInst>(*I)) return; 9194d293f21SBill Wendling const CallInst *LCall = cast<CallInst>(&*I); 9204d293f21SBill Wendling const InvokeInst *RInvoke = cast<InvokeInst>(RTerm); 9214d293f21SBill Wendling if (!equivalentAsOperands(LCall->getCalledOperand(), 922e0447961SJannik Silvanus RInvoke->getCalledOperand(), nullptr)) 9234d293f21SBill Wendling return; 9244d293f21SBill Wendling if (!LCall->use_empty()) 9254d293f21SBill Wendling Values[LCall] = RInvoke; 9264d293f21SBill Wendling tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest()); 9274d293f21SBill Wendling } else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) { 9284d293f21SBill Wendling if (cast<BranchInst>(RTerm)->isConditional()) return; 9294d293f21SBill Wendling BasicBlock::const_iterator I = RTerm->getIterator(); 9304d293f21SBill Wendling if (I == RStart->getParent()->begin()) return; 9314d293f21SBill Wendling --I; 9324d293f21SBill Wendling if (!isa<CallInst>(*I)) return; 9334d293f21SBill Wendling const CallInst *RCall = cast<CallInst>(I); 9344d293f21SBill Wendling const InvokeInst *LInvoke = cast<InvokeInst>(LTerm); 9354d293f21SBill Wendling if (!equivalentAsOperands(LInvoke->getCalledOperand(), 936e0447961SJannik Silvanus RCall->getCalledOperand(), nullptr)) 9374d293f21SBill Wendling return; 9384d293f21SBill Wendling if (!LInvoke->use_empty()) 9394d293f21SBill Wendling Values[LInvoke] = RCall; 9404d293f21SBill Wendling tryUnify(LInvoke->getNormalDest(), RTerm->getSuccessor(0)); 9414d293f21SBill Wendling } 9424d293f21SBill Wendling } 9434d293f21SBill Wendling } 9444d293f21SBill Wendling 9454d293f21SBill Wendling void DifferenceEngine::Oracle::anchor() { } 9464d293f21SBill Wendling 9474d293f21SBill Wendling void DifferenceEngine::diff(const Function *L, const Function *R) { 9484d293f21SBill Wendling Context C(*this, L, R); 9494d293f21SBill Wendling 9504d293f21SBill Wendling // FIXME: types 9514d293f21SBill Wendling // FIXME: attributes and CC 9524d293f21SBill Wendling // FIXME: parameter attributes 9534d293f21SBill Wendling 9544d293f21SBill Wendling // If both are declarations, we're done. 9554d293f21SBill Wendling if (L->empty() && R->empty()) 9564d293f21SBill Wendling return; 9574d293f21SBill Wendling else if (L->empty()) 9584d293f21SBill Wendling log("left function is declaration, right function is definition"); 9594d293f21SBill Wendling else if (R->empty()) 9604d293f21SBill Wendling log("right function is declaration, left function is definition"); 9614d293f21SBill Wendling else 9624d293f21SBill Wendling FunctionDifferenceEngine(*this).diff(L, R); 9634d293f21SBill Wendling } 9644d293f21SBill Wendling 9654d293f21SBill Wendling void DifferenceEngine::diff(const Module *L, const Module *R) { 9664d293f21SBill Wendling StringSet<> LNames; 9674d293f21SBill Wendling SmallVector<std::pair<const Function *, const Function *>, 20> Queue; 9684d293f21SBill Wendling 9694d293f21SBill Wendling unsigned LeftAnonCount = 0; 9704d293f21SBill Wendling unsigned RightAnonCount = 0; 9714d293f21SBill Wendling 9724d293f21SBill Wendling for (Module::const_iterator I = L->begin(), E = L->end(); I != E; ++I) { 9734d293f21SBill Wendling const Function *LFn = &*I; 9744d293f21SBill Wendling StringRef Name = LFn->getName(); 9754d293f21SBill Wendling if (Name.empty()) { 9764d293f21SBill Wendling ++LeftAnonCount; 9774d293f21SBill Wendling continue; 9784d293f21SBill Wendling } 9794d293f21SBill Wendling 9804d293f21SBill Wendling LNames.insert(Name); 9814d293f21SBill Wendling 9824d293f21SBill Wendling if (Function *RFn = R->getFunction(LFn->getName())) 9834d293f21SBill Wendling Queue.push_back(std::make_pair(LFn, RFn)); 9844d293f21SBill Wendling else 9854d293f21SBill Wendling logf("function %l exists only in left module") << LFn; 9864d293f21SBill Wendling } 9874d293f21SBill Wendling 9884d293f21SBill Wendling for (Module::const_iterator I = R->begin(), E = R->end(); I != E; ++I) { 9894d293f21SBill Wendling const Function *RFn = &*I; 9904d293f21SBill Wendling StringRef Name = RFn->getName(); 9914d293f21SBill Wendling if (Name.empty()) { 9924d293f21SBill Wendling ++RightAnonCount; 9934d293f21SBill Wendling continue; 9944d293f21SBill Wendling } 9954d293f21SBill Wendling 9964d293f21SBill Wendling if (!LNames.count(Name)) 9974d293f21SBill Wendling logf("function %r exists only in right module") << RFn; 9984d293f21SBill Wendling } 9994d293f21SBill Wendling 10004d293f21SBill Wendling if (LeftAnonCount != 0 || RightAnonCount != 0) { 10014d293f21SBill Wendling SmallString<32> Tmp; 10024d293f21SBill Wendling logf(("not comparing " + Twine(LeftAnonCount) + 10034d293f21SBill Wendling " anonymous functions in the left module and " + 10044d293f21SBill Wendling Twine(RightAnonCount) + " in the right module") 10054d293f21SBill Wendling .toStringRef(Tmp)); 10064d293f21SBill Wendling } 10074d293f21SBill Wendling 10084d293f21SBill Wendling for (SmallVectorImpl<std::pair<const Function *, const Function *>>::iterator 10094d293f21SBill Wendling I = Queue.begin(), 10104d293f21SBill Wendling E = Queue.end(); 10114d293f21SBill Wendling I != E; ++I) 10124d293f21SBill Wendling diff(I->first, I->second); 10134d293f21SBill Wendling } 10144d293f21SBill Wendling 10154d293f21SBill Wendling bool DifferenceEngine::equivalentAsOperands(const GlobalValue *L, 10164d293f21SBill Wendling const GlobalValue *R) { 10174d293f21SBill Wendling if (globalValueOracle) return (*globalValueOracle)(L, R); 10184d293f21SBill Wendling 10194d293f21SBill Wendling if (isa<GlobalVariable>(L) && isa<GlobalVariable>(R)) { 10204d293f21SBill Wendling const GlobalVariable *GVL = cast<GlobalVariable>(L); 10214d293f21SBill Wendling const GlobalVariable *GVR = cast<GlobalVariable>(R); 10224d293f21SBill Wendling if (GVL->hasLocalLinkage() && GVL->hasUniqueInitializer() && 10234d293f21SBill Wendling GVR->hasLocalLinkage() && GVR->hasUniqueInitializer()) 10244d293f21SBill Wendling return FunctionDifferenceEngine(*this, GVL, GVR) 1025e0447961SJannik Silvanus .equivalentAsOperands(GVL->getInitializer(), GVR->getInitializer(), 1026e0447961SJannik Silvanus nullptr); 10274d293f21SBill Wendling } 10284d293f21SBill Wendling 10294d293f21SBill Wendling return L->getName() == R->getName(); 10304d293f21SBill Wendling } 1031