1 //===- MergeICmps.cpp - Optimize chains of integer comparisons ------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass turns chains of integer comparisons into memcmp (the memcmp is 11 // later typically inlined as a chain of efficient hardware comparisons). This 12 // typically benefits c++ member or nonmember operator==(). 13 // 14 // The basic idea is to replace a larger chain of integer comparisons loaded 15 // from contiguous memory locations into a smaller chain of such integer 16 // comparisons. Benefits are double: 17 // - There are less jumps, and therefore less opportunities for mispredictions 18 // and I-cache misses. 19 // - Code size is smaller, both because jumps are removed and because the 20 // encoding of a 2*n byte compare is smaller than that of two n-byte 21 // compares. 22 23 //===----------------------------------------------------------------------===// 24 25 #include "llvm/ADT/APSInt.h" 26 #include "llvm/Analysis/Loads.h" 27 #include "llvm/IR/Function.h" 28 #include "llvm/IR/IRBuilder.h" 29 #include "llvm/IR/IntrinsicInst.h" 30 #include "llvm/Pass.h" 31 #include "llvm/Transforms/Scalar.h" 32 #include "llvm/Transforms/Utils/BuildLibCalls.h" 33 #include <algorithm> 34 #include <numeric> 35 #include <utility> 36 #include <vector> 37 38 using namespace llvm; 39 40 namespace { 41 42 #define DEBUG_TYPE "mergeicmps" 43 44 #define MERGEICMPS_DOT_ON 45 46 // A BCE atom. 47 struct BCEAtom { 48 BCEAtom() : GEP(nullptr), LoadI(nullptr), Offset() {} 49 50 const Value *Base() const { return GEP ? GEP->getPointerOperand() : nullptr; } 51 52 bool operator<(const BCEAtom &O) const { 53 return Base() == O.Base() ? Offset.slt(O.Offset) : Base() < O.Base(); 54 } 55 56 GetElementPtrInst *GEP; 57 LoadInst *LoadI; 58 APInt Offset; 59 }; 60 61 // If this value is a load from a constant offset w.r.t. a base address, and 62 // there are no othe rusers of the load or address, returns the base address and 63 // the offset. 64 BCEAtom visitICmpLoadOperand(Value *const Val) { 65 BCEAtom Result; 66 if (auto *const LoadI = dyn_cast<LoadInst>(Val)) { 67 DEBUG(dbgs() << "load\n"); 68 if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { 69 DEBUG(dbgs() << "used outside of block\n"); 70 return {}; 71 } 72 if (LoadI->isVolatile()) { 73 DEBUG(dbgs() << "volatile\n"); 74 return {}; 75 } 76 Value *const Addr = LoadI->getOperand(0); 77 if (auto *const GEP = dyn_cast<GetElementPtrInst>(Addr)) { 78 DEBUG(dbgs() << "GEP\n"); 79 if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { 80 DEBUG(dbgs() << "used outside of block\n"); 81 return {}; 82 } 83 const auto &DL = GEP->getModule()->getDataLayout(); 84 if (!isDereferenceablePointer(GEP, DL)) { 85 DEBUG(dbgs() << "not dereferenceable\n"); 86 // We need to make sure that we can do comparison in any order, so we 87 // require memory to be unconditionnally dereferencable. 88 return {}; 89 } 90 Result.Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); 91 if (GEP->accumulateConstantOffset(DL, Result.Offset)) { 92 Result.GEP = GEP; 93 Result.LoadI = LoadI; 94 } 95 } 96 } 97 return Result; 98 } 99 100 // A basic block with a comparison between two BCE atoms. 101 // Note: the terminology is misleading: the comparison is symmetric, so there 102 // is no real {l/r}hs. To break the symmetry, we use the smallest atom as Lhs. 103 class BCECmpBlock { 104 public: 105 BCECmpBlock() {} 106 107 BCECmpBlock(BCEAtom L, BCEAtom R, int SizeBits) 108 : Lhs_(L), Rhs_(R), SizeBits_(SizeBits) { 109 if (Rhs_ < Lhs_) 110 std::swap(Rhs_, Lhs_); 111 } 112 113 bool IsValid() const { 114 return Lhs_.Base() != nullptr && Rhs_.Base() != nullptr; 115 } 116 117 // Assert the the block is consistent: If valid, it should also have 118 // non-null members besides Lhs_ and Rhs_. 119 void AssertConsistent() const { 120 if (IsValid()) { 121 assert(BB); 122 assert(CmpI); 123 assert(BranchI); 124 } 125 } 126 127 const BCEAtom &Lhs() const { return Lhs_; } 128 const BCEAtom &Rhs() const { return Rhs_; } 129 int SizeBits() const { return SizeBits_; } 130 131 // Returns true if the block does other works besides comparison. 132 bool doesOtherWork() const; 133 134 // The basic block where this comparison happens. 135 BasicBlock *BB = nullptr; 136 // The ICMP for this comparison. 137 ICmpInst *CmpI = nullptr; 138 // The terminating branch. 139 BranchInst *BranchI = nullptr; 140 141 private: 142 BCEAtom Lhs_; 143 BCEAtom Rhs_; 144 int SizeBits_ = 0; 145 }; 146 147 bool BCECmpBlock::doesOtherWork() const { 148 AssertConsistent(); 149 // TODO(courbet): Can we allow some other things ? This is very conservative. 150 // We might be able to get away with anything does does not have any side 151 // effects outside of the basic block. 152 // Note: The GEPs and/or loads are not necessarily in the same block. 153 for (const Instruction &Inst : *BB) { 154 if (const auto *const GEP = dyn_cast<GetElementPtrInst>(&Inst)) { 155 if (!(Lhs_.GEP == GEP || Rhs_.GEP == GEP)) 156 return true; 157 } else if (const auto *const L = dyn_cast<LoadInst>(&Inst)) { 158 if (!(Lhs_.LoadI == L || Rhs_.LoadI == L)) 159 return true; 160 } else if (const auto *const C = dyn_cast<ICmpInst>(&Inst)) { 161 if (C != CmpI) 162 return true; 163 } else if (const auto *const Br = dyn_cast<BranchInst>(&Inst)) { 164 if (Br != BranchI) 165 return true; 166 } else { 167 return true; 168 } 169 } 170 return false; 171 } 172 173 // Visit the given comparison. If this is a comparison between two valid 174 // BCE atoms, returns the comparison. 175 BCECmpBlock visitICmp(const ICmpInst *const CmpI, 176 const ICmpInst::Predicate ExpectedPredicate) { 177 if (CmpI->getPredicate() == ExpectedPredicate) { 178 DEBUG(dbgs() << "cmp " 179 << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") 180 << "\n"); 181 auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0)); 182 if (!Lhs.Base()) 183 return {}; 184 auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1)); 185 if (!Rhs.Base()) 186 return {}; 187 return BCECmpBlock(std::move(Lhs), std::move(Rhs), 188 CmpI->getOperand(0)->getType()->getScalarSizeInBits()); 189 } 190 return {}; 191 } 192 193 // Visit the given comparison block. If this is a comparison between two valid 194 // BCE atoms, returns the comparison. 195 BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, 196 const BasicBlock *const PhiBlock) { 197 if (Block->empty()) 198 return {}; 199 auto *const BranchI = dyn_cast<BranchInst>(Block->getTerminator()); 200 if (!BranchI) 201 return {}; 202 DEBUG(dbgs() << "branch\n"); 203 if (BranchI->isUnconditional()) { 204 // In this case, we expect an incoming value which is the result of the 205 // comparison. This is the last link in the chain of comparisons (note 206 // that this does not mean that this is the last incoming value, blocks 207 // can be reordered). 208 auto *const CmpI = dyn_cast<ICmpInst>(Val); 209 if (!CmpI) 210 return {}; 211 DEBUG(dbgs() << "icmp\n"); 212 auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ); 213 Result.CmpI = CmpI; 214 Result.BranchI = BranchI; 215 return Result; 216 } else { 217 // In this case, we expect a constant incoming value (the comparison is 218 // chained). 219 const auto *const Const = dyn_cast<ConstantInt>(Val); 220 DEBUG(dbgs() << "const\n"); 221 if (!Const->isZero()) 222 return {}; 223 DEBUG(dbgs() << "false\n"); 224 auto *const CmpI = dyn_cast<ICmpInst>(BranchI->getCondition()); 225 if (!CmpI) 226 return {}; 227 DEBUG(dbgs() << "icmp\n"); 228 assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch"); 229 BasicBlock *const FalseBlock = BranchI->getSuccessor(1); 230 auto Result = visitICmp( 231 CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE); 232 Result.CmpI = CmpI; 233 Result.BranchI = BranchI; 234 return Result; 235 } 236 return {}; 237 } 238 239 // A chain of comparisons. 240 class BCECmpChain { 241 public: 242 BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi); 243 244 int size() const { return Comparisons_.size(); } 245 246 #ifdef MERGEICMPS_DOT_ON 247 void dump() const; 248 #endif // MERGEICMPS_DOT_ON 249 250 bool simplify(const TargetLibraryInfo *const TLI); 251 252 private: 253 static bool IsContiguous(const BCECmpBlock &First, 254 const BCECmpBlock &Second) { 255 return First.Lhs().Base() == Second.Lhs().Base() && 256 First.Rhs().Base() == Second.Rhs().Base() && 257 First.Lhs().Offset + First.SizeBits() / 8 == Second.Lhs().Offset && 258 First.Rhs().Offset + First.SizeBits() / 8 == Second.Rhs().Offset; 259 } 260 261 // Merges the given comparison blocks into one memcmp block and update 262 // branches. Comparisons are assumed to be continguous. If NextBBInChain is 263 // null, the merged block will link to the phi block. 264 static void mergeComparisons(ArrayRef<BCECmpBlock> Comparisons, 265 BasicBlock *const NextBBInChain, PHINode &Phi, 266 const TargetLibraryInfo *const TLI); 267 268 PHINode &Phi_; 269 std::vector<BCECmpBlock> Comparisons_; 270 // The original entry block (before sorting); 271 BasicBlock *EntryBlock_; 272 }; 273 274 BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi) 275 : Phi_(Phi) { 276 // Now look inside blocks to check for BCE comparisons. 277 std::vector<BCECmpBlock> Comparisons; 278 for (BasicBlock *Block : Blocks) { 279 BCECmpBlock Comparison = visitCmpBlock(Phi.getIncomingValueForBlock(Block), 280 Block, Phi.getParent()); 281 Comparison.BB = Block; 282 if (!Comparison.IsValid()) { 283 DEBUG(dbgs() << "skip: not a valid BCECmpBlock\n"); 284 return; 285 } 286 if (Comparison.doesOtherWork()) { 287 DEBUG(dbgs() << "block does extra work besides compare\n"); 288 if (Comparisons.empty()) { // First block. 289 // TODO(courbet): The first block can do other things, and we should 290 // split them apart in a separate block before the comparison chain. 291 // Right now we just discard it and make the chain shorter. 292 DEBUG(dbgs() 293 << "ignoring first block that does extra work besides compare\n"); 294 continue; 295 } 296 // TODO(courbet): Right now we abort the whole chain. We could be 297 // merging only the blocks that don't do other work and resume the 298 // chain from there. For example: 299 // if (a[0] == b[0]) { // bb1 300 // if (a[1] == b[1]) { // bb2 301 // some_value = 3; //bb3 302 // if (a[2] == b[2]) { //bb3 303 // do a ton of stuff //bb4 304 // } 305 // } 306 // } 307 // 308 // This is: 309 // 310 // bb1 --eq--> bb2 --eq--> bb3* -eq--> bb4 --+ 311 // \ \ \ \ 312 // ne ne ne \ 313 // \ \ \ v 314 // +------------+-----------+----------> bb_phi 315 // 316 // We can only merge the first two comparisons, because bb3* does 317 // "other work" (setting some_value to 3). 318 // We could still merge bb1 and bb2 though. 319 return; 320 } 321 DEBUG(dbgs() << "*Found cmp of " << Comparison.SizeBits() 322 << " bits between " << Comparison.Lhs().Base() << " + " 323 << Comparison.Lhs().Offset << " and " 324 << Comparison.Rhs().Base() << " + " << Comparison.Rhs().Offset 325 << "\n"); 326 DEBUG(dbgs() << "\n"); 327 Comparisons.push_back(Comparison); 328 } 329 EntryBlock_ = Comparisons[0].BB; 330 Comparisons_ = std::move(Comparisons); 331 #ifdef MERGEICMPS_DOT_ON 332 errs() << "BEFORE REORDERING:\n\n"; 333 dump(); 334 #endif // MERGEICMPS_DOT_ON 335 // Reorder blocks by LHS. We can do that without changing the 336 // semantics because we are only accessing dereferencable memory. 337 std::sort(Comparisons_.begin(), Comparisons_.end(), 338 [](const BCECmpBlock &a, const BCECmpBlock &b) { 339 return a.Lhs() < b.Lhs(); 340 }); 341 #ifdef MERGEICMPS_DOT_ON 342 errs() << "AFTER REORDERING:\n\n"; 343 dump(); 344 #endif // MERGEICMPS_DOT_ON 345 } 346 347 #ifdef MERGEICMPS_DOT_ON 348 void BCECmpChain::dump() const { 349 errs() << "digraph dag {\n"; 350 errs() << " graph [bgcolor=transparent];\n"; 351 errs() << " node [color=black,style=filled,fillcolor=lightyellow];\n"; 352 errs() << " edge [color=black];\n"; 353 for (size_t I = 0; I < Comparisons_.size(); ++I) { 354 const auto &Comparison = Comparisons_[I]; 355 errs() << " \"" << I << "\" [label=\"%" 356 << Comparison.Lhs().Base()->getName() << " + " 357 << Comparison.Lhs().Offset << " == %" 358 << Comparison.Rhs().Base()->getName() << " + " 359 << Comparison.Rhs().Offset << " (" << (Comparison.SizeBits() / 8) 360 << " bytes)\"];\n"; 361 const Value *const Val = Phi_.getIncomingValueForBlock(Comparison.BB); 362 if (I > 0) 363 errs() << " \"" << (I - 1) << "\" -> \"" << I << "\";\n"; 364 errs() << " \"" << I << "\" -> \"Phi\" [label=\"" << *Val << "\"];\n"; 365 } 366 errs() << " \"Phi\" [label=\"Phi\"];\n"; 367 errs() << "}\n\n"; 368 } 369 #endif // MERGEICMPS_DOT_ON 370 371 bool BCECmpChain::simplify(const TargetLibraryInfo *const TLI) { 372 // First pass to check if there is at least one merge. If not, we don't do 373 // anything and we keep analysis passes intact. 374 { 375 bool AtLeastOneMerged = false; 376 for (size_t I = 1; I < Comparisons_.size(); ++I) { 377 if (IsContiguous(Comparisons_[I - 1], Comparisons_[I])) { 378 AtLeastOneMerged = true; 379 break; 380 } 381 } 382 if (!AtLeastOneMerged) 383 return false; 384 } 385 386 // Remove phi references to comparison blocks, they will be rebuilt as we 387 // merge the blocks. 388 for (const auto &Comparison : Comparisons_) { 389 Phi_.removeIncomingValue(Comparison.BB, false); 390 } 391 392 // Point the predecessors of the chain to the first comparison block (which is 393 // the new entry point). 394 if (EntryBlock_ != Comparisons_[0].BB) 395 EntryBlock_->replaceAllUsesWith(Comparisons_[0].BB); 396 397 // Effectively merge blocks. 398 int NumMerged = 1; 399 for (size_t I = 1; I < Comparisons_.size(); ++I) { 400 if (IsContiguous(Comparisons_[I - 1], Comparisons_[I])) { 401 ++NumMerged; 402 } else { 403 // Merge all previous comparisons and start a new merge block. 404 mergeComparisons( 405 makeArrayRef(Comparisons_).slice(I - NumMerged, NumMerged), 406 Comparisons_[I].BB, Phi_, TLI); 407 NumMerged = 1; 408 } 409 } 410 mergeComparisons(makeArrayRef(Comparisons_) 411 .slice(Comparisons_.size() - NumMerged, NumMerged), 412 nullptr, Phi_, TLI); 413 414 return true; 415 } 416 417 void BCECmpChain::mergeComparisons(ArrayRef<BCECmpBlock> Comparisons, 418 BasicBlock *const NextBBInChain, 419 PHINode &Phi, 420 const TargetLibraryInfo *const TLI) { 421 assert(!Comparisons.empty()); 422 const auto &FirstComparison = *Comparisons.begin(); 423 BasicBlock *const BB = FirstComparison.BB; 424 LLVMContext &Context = BB->getContext(); 425 426 if (Comparisons.size() >= 2) { 427 DEBUG(dbgs() << "Merging " << Comparisons.size() << " comparisons\n"); 428 const auto TotalSize = 429 std::accumulate(Comparisons.begin(), Comparisons.end(), 0, 430 [](int Size, const BCECmpBlock &C) { 431 return Size + C.SizeBits(); 432 }) / 433 8; 434 435 // Incoming edges do not need to be updated, and both GEPs are already 436 // computing the right address, we just need to: 437 // - replace the two loads and the icmp with the memcmp 438 // - update the branch 439 // - update the incoming values in the phi. 440 FirstComparison.BranchI->eraseFromParent(); 441 FirstComparison.CmpI->eraseFromParent(); 442 FirstComparison.Lhs().LoadI->eraseFromParent(); 443 FirstComparison.Rhs().LoadI->eraseFromParent(); 444 445 IRBuilder<> Builder(BB); 446 const auto &DL = Phi.getModule()->getDataLayout(); 447 Value *const MemCmpCall = 448 emitMemCmp(FirstComparison.Lhs().GEP, FirstComparison.Rhs().GEP, 449 ConstantInt::get(DL.getIntPtrType(Context), TotalSize), 450 Builder, DL, TLI); 451 Value *const MemCmpIsZero = Builder.CreateICmpEQ( 452 MemCmpCall, ConstantInt::get(Type::getInt32Ty(Context), 0)); 453 454 // Add a branch to the next basic block in the chain. 455 if (NextBBInChain) { 456 Builder.CreateCondBr(MemCmpIsZero, NextBBInChain, Phi.getParent()); 457 Phi.addIncoming(ConstantInt::getFalse(Context), BB); 458 } else { 459 Builder.CreateBr(Phi.getParent()); 460 Phi.addIncoming(MemCmpIsZero, BB); 461 } 462 463 // Delete merged blocks. 464 for (size_t I = 1; I < Comparisons.size(); ++I) { 465 BasicBlock *CBB = Comparisons[I].BB; 466 CBB->replaceAllUsesWith(BB); 467 CBB->eraseFromParent(); 468 } 469 } else { 470 assert(Comparisons.size() == 1); 471 // There are no blocks to merge, but we still need to update the branches. 472 DEBUG(dbgs() << "Only one comparison, updating branches\n"); 473 if (NextBBInChain) { 474 if (FirstComparison.BranchI->isConditional()) { 475 DEBUG(dbgs() << "conditional -> conditional\n"); 476 // Just update the "true" target, the "false" target should already be 477 // the phi block. 478 assert(FirstComparison.BranchI->getSuccessor(1) == Phi.getParent()); 479 FirstComparison.BranchI->setSuccessor(0, NextBBInChain); 480 Phi.addIncoming(ConstantInt::getFalse(Context), BB); 481 } else { 482 DEBUG(dbgs() << "unconditional -> conditional\n"); 483 // Replace the unconditional branch by a conditional one. 484 FirstComparison.BranchI->eraseFromParent(); 485 IRBuilder<> Builder(BB); 486 Builder.CreateCondBr(FirstComparison.CmpI, NextBBInChain, 487 Phi.getParent()); 488 Phi.addIncoming(FirstComparison.CmpI, BB); 489 } 490 } else { 491 if (FirstComparison.BranchI->isConditional()) { 492 DEBUG(dbgs() << "conditional -> unconditional\n"); 493 // Replace the conditional branch by an unconditional one. 494 FirstComparison.BranchI->eraseFromParent(); 495 IRBuilder<> Builder(BB); 496 Builder.CreateBr(Phi.getParent()); 497 Phi.addIncoming(FirstComparison.CmpI, BB); 498 } else { 499 DEBUG(dbgs() << "unconditional -> unconditional\n"); 500 Phi.addIncoming(FirstComparison.CmpI, BB); 501 } 502 } 503 } 504 } 505 506 std::vector<BasicBlock *> getOrderedBlocks(PHINode &Phi, 507 BasicBlock *const LastBlock, 508 int NumBlocks) { 509 // Walk up from the last block to find other blocks. 510 std::vector<BasicBlock *> Blocks(NumBlocks); 511 BasicBlock *CurBlock = LastBlock; 512 for (int BlockIndex = NumBlocks - 1; BlockIndex > 0; --BlockIndex) { 513 if (CurBlock->hasAddressTaken()) { 514 // Somebody is jumping to the block through an address, all bets are 515 // off. 516 DEBUG(dbgs() << "skip: block " << BlockIndex 517 << " has its address taken\n"); 518 return {}; 519 } 520 Blocks[BlockIndex] = CurBlock; 521 auto *SinglePredecessor = CurBlock->getSinglePredecessor(); 522 if (!SinglePredecessor) { 523 // The block has two or more predecessors. 524 DEBUG(dbgs() << "skip: block " << BlockIndex 525 << " has two or more predecessors\n"); 526 return {}; 527 } 528 if (Phi.getBasicBlockIndex(SinglePredecessor) < 0) { 529 // The block does not link back to the phi. 530 DEBUG(dbgs() << "skip: block " << BlockIndex 531 << " does not link back to the phi\n"); 532 return {}; 533 } 534 CurBlock = SinglePredecessor; 535 } 536 Blocks[0] = CurBlock; 537 return Blocks; 538 } 539 540 bool processPhi(PHINode &Phi, const TargetLibraryInfo *const TLI) { 541 DEBUG(dbgs() << "processPhi()\n"); 542 if (Phi.getNumIncomingValues() <= 1) { 543 DEBUG(dbgs() << "skip: only one incoming value in phi\n"); 544 return false; 545 } 546 // We are looking for something that has the following structure: 547 // bb1 --eq--> bb2 --eq--> bb3 --eq--> bb4 --+ 548 // \ \ \ \ 549 // ne ne ne \ 550 // \ \ \ v 551 // +------------+-----------+----------> bb_phi 552 // 553 // - The last basic block (bb4 here) must branch unconditionally to bb_phi. 554 // It's the only block that contributes a non-constant value to the Phi. 555 // - All other blocks (b1, b2, b3) must have exactly two successors, one of 556 // them being the the phi block. 557 // - All intermediate blocks (bb2, bb3) must have only one predecessor. 558 // - Blocks cannot do other work besides the comparison, see doesOtherWork() 559 560 // The blocks are not necessarily ordered in the phi, so we start from the 561 // last block and reconstruct the order. 562 BasicBlock *LastBlock = nullptr; 563 for (unsigned I = 0; I < Phi.getNumIncomingValues(); ++I) { 564 if (isa<ConstantInt>(Phi.getIncomingValue(I))) 565 continue; 566 if (LastBlock) { 567 // There are several non-constant values. 568 DEBUG(dbgs() << "skip: several non-constant values\n"); 569 return false; 570 } 571 LastBlock = Phi.getIncomingBlock(I); 572 } 573 if (!LastBlock) { 574 // There is no non-constant block. 575 DEBUG(dbgs() << "skip: no non-constant block\n"); 576 return false; 577 } 578 if (LastBlock->getSingleSuccessor() != Phi.getParent()) { 579 DEBUG(dbgs() << "skip: last block non-phi successor\n"); 580 return false; 581 } 582 583 const auto Blocks = 584 getOrderedBlocks(Phi, LastBlock, Phi.getNumIncomingValues()); 585 if (Blocks.empty()) 586 return false; 587 BCECmpChain CmpChain(Blocks, Phi); 588 589 if (CmpChain.size() < 2) { 590 DEBUG(dbgs() << "skip: only one compare block\n"); 591 return false; 592 } 593 594 return CmpChain.simplify(TLI); 595 } 596 597 class MergeICmps : public FunctionPass { 598 public: 599 static char ID; 600 601 MergeICmps() : FunctionPass(ID) { 602 initializeMergeICmpsPass(*PassRegistry::getPassRegistry()); 603 } 604 605 bool runOnFunction(Function &F) override { 606 if (skipFunction(F)) return false; 607 const auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); 608 auto PA = runImpl(F, &TLI); 609 return !PA.areAllPreserved(); 610 } 611 612 private: 613 void getAnalysisUsage(AnalysisUsage &AU) const override { 614 AU.addRequired<TargetLibraryInfoWrapperPass>(); 615 } 616 617 PreservedAnalyses runImpl(Function &F, const TargetLibraryInfo *TLI); 618 }; 619 620 PreservedAnalyses MergeICmps::runImpl(Function &F, 621 const TargetLibraryInfo *TLI) { 622 DEBUG(dbgs() << "MergeICmpsPass: " << F.getName() << "\n"); 623 624 bool MadeChange = false; 625 626 for (auto BBIt = ++F.begin(); BBIt != F.end(); ++BBIt) { 627 // A Phi operation is always first in a basic block. 628 if (auto *const Phi = dyn_cast<PHINode>(&*BBIt->begin())) 629 MadeChange |= processPhi(*Phi, TLI); 630 } 631 632 if (MadeChange) 633 return PreservedAnalyses::none(); 634 return PreservedAnalyses::all(); 635 } 636 637 } // namespace 638 639 char MergeICmps::ID = 0; 640 INITIALIZE_PASS_BEGIN(MergeICmps, "mergeicmps", 641 "Merge contiguous icmps into a memcmp", false, false) 642 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 643 INITIALIZE_PASS_END(MergeICmps, "mergeicmps", 644 "Merge contiguous icmps into a memcmp", false, false) 645 646 Pass *llvm::createMergeICmpsPass() { return new MergeICmps(); } 647 648