//===-- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
#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/IR/CFG.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/type_traits.h"
unsigned NewSize = Storage.size() - 1;
if (NewSize) {
// Move the slot at the end to the beginning.
- if (isPodLike<T>::value)
+ if (is_trivially_copyable<T>::value)
Storage[0] = Storage[NewSize];
else
std::swap(Storage[0], Storage[NewSize]);
if (!LeftI->use_empty())
TentativeValues.insert(std::make_pair(LeftI, RightI));
- ++LI, ++RI;
+ ++LI;
+ ++RI;
} while (LI != LE); // This is sufficient: we can't get equality of
// terminators if there are residual instructions.
if (TryUnify) tryUnify(LI->getSuccessor(0), RI->getSuccessor(0));
return false;
+ } else if (isa<IndirectBrInst>(L)) {
+ IndirectBrInst *LI = cast<IndirectBrInst>(L);
+ IndirectBrInst *RI = cast<IndirectBrInst>(R);
+ if (LI->getNumDestinations() != RI->getNumDestinations()) {
+ if (Complain) Engine.log("indirectbr # of destinations differ");
+ return true;
+ }
+
+ if (!equivalentAsOperands(LI->getAddress(), RI->getAddress())) {
+ if (Complain) Engine.log("indirectbr addresses differ");
+ return true;
+ }
+
+ if (TryUnify) {
+ for (unsigned i = 0; i < LI->getNumDestinations(); i++) {
+ tryUnify(LI->getDestination(i), RI->getDestination(i));
+ }
+ }
+ return false;
+
} else if (isa<SwitchInst>(L)) {
SwitchInst *LI = cast<SwitchInst>(L);
SwitchInst *RI = cast<SwitchInst>(R);
bool Difference = false;
DenseMap<ConstantInt*,BasicBlock*> LCases;
-
- for (SwitchInst::CaseIt I = LI->case_begin(), E = LI->case_end();
- I != E; ++I)
- LCases[I.getCaseValue()] = I.getCaseSuccessor();
-
- for (SwitchInst::CaseIt I = RI->case_begin(), E = RI->case_end();
- I != E; ++I) {
- ConstantInt *CaseValue = I.getCaseValue();
+ for (auto Case : LI->cases())
+ LCases[Case.getCaseValue()] = Case.getCaseSuccessor();
+
+ for (auto Case : RI->cases()) {
+ ConstantInt *CaseValue = Case.getCaseValue();
BasicBlock *LCase = LCases[CaseValue];
if (LCase) {
- if (TryUnify) tryUnify(LCase, I.getCaseSuccessor());
+ if (TryUnify)
+ tryUnify(LCase, Case.getCaseSuccessor());
LCases.erase(CaseValue);
} else if (Complain || !Difference) {
if (Complain)
return equivalentAsOperands(cast<ConstantExpr>(L),
cast<ConstantExpr>(R));
- // Nulls of the "same type" don't always actually have the same
+ // 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))
+ if (isa<ConstantPointerNull>(L) || isa<UndefValue>(L) || isa<ConstantAggregateZero>(L))
return true;
// Block addresses only match if we've already encountered the
return Blocks[cast<BlockAddress>(L)->getBasicBlock()]
== cast<BlockAddress>(R)->getBasicBlock();
+ // If L and R are ConstantVectors, compare each element
+ if (isa<ConstantVector>(L)) {
+ ConstantVector *CVL = cast<ConstantVector>(L);
+ ConstantVector *CVR = cast<ConstantVector>(R);
+ if (CVL->getType()->getNumElements() != CVR->getType()->getNumElements())
+ return false;
+ for (unsigned i = 0; i < CVL->getType()->getNumElements(); i++) {
+ if (!equivalentAsOperands(CVL->getOperand(i), CVR->getOperand(i)))
+ return false;
+ }
+ return true;
+ }
+
return false;
}
PI = Path.begin(), PE = Path.end();
while (PI != PE && *PI == DC_match) {
unify(&*LI, &*RI);
- ++PI, ++LI, ++RI;
+ ++PI;
+ ++LI;
+ ++RI;
}
for (; PI != PE; ++PI) {
while (LI != LE) {
assert(RI != RE);
unify(&*LI, &*RI);
- ++LI, ++RI;
+ ++LI;
+ ++RI;
}
// If the terminators have different kinds, but one is an invoke and the
// other is an unconditional branch immediately following a call, unify
// the results and the destinations.
- TerminatorInst *LTerm = LStart->getParent()->getTerminator();
- TerminatorInst *RTerm = RStart->getParent()->getTerminator();
+ Instruction *LTerm = LStart->getParent()->getTerminator();
+ Instruction *RTerm = RStart->getParent()->getTerminator();
if (isa<BranchInst>(LTerm) && isa<InvokeInst>(RTerm)) {
if (cast<BranchInst>(LTerm)->isConditional()) return;
- BasicBlock::iterator I = LTerm;
+ BasicBlock::iterator I = LTerm->getIterator();
if (I == LStart->getParent()->begin()) return;
--I;
if (!isa<CallInst>(*I)) return;
tryUnify(LTerm->getSuccessor(0), RInvoke->getNormalDest());
} else if (isa<InvokeInst>(LTerm) && isa<BranchInst>(RTerm)) {
if (cast<BranchInst>(RTerm)->isConditional()) return;
- BasicBlock::iterator I = RTerm;
+ BasicBlock::iterator I = RTerm->getIterator();
if (I == RStart->getParent()->begin()) return;
--I;
if (!isa<CallInst>(*I)) return;
StringSet<> LNames;
SmallVector<std::pair<Function*,Function*>, 20> Queue;
+ unsigned LeftAnonCount = 0;
+ unsigned RightAnonCount = 0;
+
for (Module::iterator I = L->begin(), E = L->end(); I != E; ++I) {
Function *LFn = &*I;
- LNames.insert(LFn->getName());
+ StringRef Name = LFn->getName();
+ if (Name.empty()) {
+ ++LeftAnonCount;
+ continue;
+ }
+
+ LNames.insert(Name);
if (Function *RFn = R->getFunction(LFn->getName()))
Queue.push_back(std::make_pair(LFn, RFn));
for (Module::iterator I = R->begin(), E = R->end(); I != E; ++I) {
Function *RFn = &*I;
- if (!LNames.count(RFn->getName()))
+ StringRef Name = RFn->getName();
+ if (Name.empty()) {
+ ++RightAnonCount;
+ continue;
+ }
+
+ if (!LNames.count(Name))
logf("function %r exists only in right module") << RFn;
}
+
+ if (LeftAnonCount != 0 || RightAnonCount != 0) {
+ SmallString<32> Tmp;
+ logf(("not comparing " + Twine(LeftAnonCount) +
+ " anonymous functions in the left module and " +
+ Twine(RightAnonCount) + " in the right module")
+ .toStringRef(Tmp));
+ }
+
for (SmallVectorImpl<std::pair<Function*,Function*> >::iterator
I = Queue.begin(), E = Queue.end(); I != E; ++I)
diff(I->first, I->second);