// Test whether two basic blocks have equivalent behaviour. int FunctionComparator::cmpBasicBlocks(const BasicBlock *BBL, const BasicBlock *BBR) const { BasicBlock::const_iterator InstL = BBL->begin(), InstLE = BBL->end(); BasicBlock::const_iterator InstR = BBR->begin(), InstRE = BBR->end(); do { bool needToCmpOperands = true; if (int Res = cmpOperations(&*InstL, &*InstR, needToCmpOperands)) return Res; if (needToCmpOperands) { assert(InstL->getNumOperands() == InstR->getNumOperands()); for (unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) { Value *OpL = InstL->getOperand(i); Value *OpR = InstR->getOperand(i); if (int Res = cmpValues(OpL, OpR)) return Res; // cmpValues should ensure this is true. assert(cmpTypes(OpL->getType(), OpR->getType()) == 0); } } ++InstL; ++InstR; } while (InstL != InstLE && InstR != InstRE); if (InstL != InstLE && InstR == InstRE) return 1; if (InstL == InstLE && InstR != InstRE) return -1; return 0; }
static bool equals(const BasicBlock *BB1, const BasicBlock *BB2, DenseMap<const Value *, const Value *> &ValueMap, DenseMap<const Value *, const Value *> &SpeculationMap) { // Specutively add it anyways. If it's false, we'll notice a difference later, and // this won't matter. ValueMap[BB1] = BB2; BasicBlock::const_iterator FI = BB1->begin(), FE = BB1->end(); BasicBlock::const_iterator GI = BB2->begin(), GE = BB2->end(); do { if (!FI->isSameOperationAs(const_cast<Instruction *>(&*GI))) return false; if (FI->getNumOperands() != GI->getNumOperands()) return false; if (ValueMap[FI] == GI) { ++FI, ++GI; continue; } if (ValueMap[FI] != NULL) return false; for (unsigned i = 0, e = FI->getNumOperands(); i != e; ++i) { Value *OpF = FI->getOperand(i); Value *OpG = GI->getOperand(i); if (ValueMap[OpF] == OpG) continue; if (ValueMap[OpF] != NULL) return false; assert(OpF->getType() == OpG->getType() && "Two of the same operation has operands of different type."); if (OpF->getValueID() != OpG->getValueID()) return false; if (isa<PHINode>(FI)) { if (SpeculationMap[OpF] == NULL) SpeculationMap[OpF] = OpG; else if (SpeculationMap[OpF] != OpG) return false; continue; } else if (isa<BasicBlock>(OpF)) { assert(isa<TerminatorInst>(FI) && "BasicBlock referenced by non-Terminator non-PHI"); // This call changes the ValueMap, hence we can't use // Value *& = ValueMap[...] if (!equals(cast<BasicBlock>(OpF), cast<BasicBlock>(OpG), ValueMap, SpeculationMap)) return false; } else { if (!compare(OpF, OpG)) return false; } ValueMap[OpF] = OpG; } ValueMap[FI] = GI; ++FI, ++GI; } while (FI != FE && GI != GE); return FI == FE && GI == GE; }
static bool equals(const BasicBlock *BB1, const BasicBlock *BB2, DenseMap<const Value *, const Value *> &ValueMap, DenseMap<const Value *, const Value *> &SpeculationMap) { // Speculatively add it anyways. If it's false, we'll notice a difference // later, and this won't matter. ValueMap[BB1] = BB2; BasicBlock::const_iterator FI = BB1->begin(), FE = BB1->end(); BasicBlock::const_iterator GI = BB2->begin(), GE = BB2->end(); do { if (isa<BitCastInst>(FI)) { ++FI; continue; } if (isa<BitCastInst>(GI)) { ++GI; continue; } if (!isEquivalentOperation(FI, GI)) return false; if (isa<GetElementPtrInst>(FI)) { const GetElementPtrInst *GEPF = cast<GetElementPtrInst>(FI); const GetElementPtrInst *GEPG = cast<GetElementPtrInst>(GI); if (GEPF->hasAllZeroIndices() && GEPG->hasAllZeroIndices()) { // It's effectively a bitcast. ++FI, ++GI; continue; } // TODO: we only really care about the elements before the index if (FI->getOperand(0)->getType() != GI->getOperand(0)->getType()) return false; } if (ValueMap[FI] == GI) { ++FI, ++GI; continue; } if (ValueMap[FI] != NULL) return false; for (unsigned i = 0, e = FI->getNumOperands(); i != e; ++i) { Value *OpF = IgnoreBitcasts(FI->getOperand(i)); Value *OpG = IgnoreBitcasts(GI->getOperand(i)); if (ValueMap[OpF] == OpG) continue; if (ValueMap[OpF] != NULL) return false; if (OpF->getValueID() != OpG->getValueID() || !isEquivalentType(OpF->getType(), OpG->getType())) return false; if (isa<PHINode>(FI)) { if (SpeculationMap[OpF] == NULL) SpeculationMap[OpF] = OpG; else if (SpeculationMap[OpF] != OpG) return false; continue; } else if (isa<BasicBlock>(OpF)) { assert(isa<TerminatorInst>(FI) && "BasicBlock referenced by non-Terminator non-PHI"); // This call changes the ValueMap, hence we can't use // Value *& = ValueMap[...] if (!equals(cast<BasicBlock>(OpF), cast<BasicBlock>(OpG), ValueMap, SpeculationMap)) return false; } else { if (!compare(OpF, OpG)) return false; } ValueMap[OpF] = OpG; } ValueMap[FI] = GI; ++FI, ++GI; } while (FI != FE && GI != GE); return FI == FE && GI == GE; }