Index: lib/Transforms/InstCombine/InstCombine.h =================================================================== --- lib/Transforms/InstCombine/InstCombine.h +++ lib/Transforms/InstCombine/InstCombine.h @@ -14,6 +14,7 @@ #include "llvm/Analysis/AssumptionTracker.h" #include "llvm/Analysis/TargetFolder.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" @@ -97,8 +98,8 @@ public InstVisitor { AssumptionTracker *AT; const DataLayout *DL; - TargetLibraryInfo *TLI; DominatorTree *DT; // not required + TargetLibraryInfo *TLI; bool MadeIRChange; LibCallSimplifier *Simplifier; bool MinimizeSize; @@ -113,7 +114,8 @@ BuilderTy *Builder; static char ID; // Pass identification, replacement for typeid - InstCombiner() : FunctionPass(ID), DL(nullptr), Builder(nullptr) { + InstCombiner() + : FunctionPass(ID), DL(nullptr), DT(nullptr), Builder(nullptr) { MinimizeSize = false; initializeInstCombinerPass(*PassRegistry::getPassRegistry()); } @@ -242,6 +244,8 @@ // visitInstruction - Specify what to return for unhandled instructions... Instruction *visitInstruction(Instruction &I) { return nullptr; } + bool dominatesAllUses(Instruction *DEF, Instruction *USE, BasicBlock *D); + bool isChainSelectCmpBranch(SelectInst *SI); private: bool ShouldChangeType(Type *From, Type *To) const; Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2425,6 +2425,42 @@ return GlobalSwapBenefits > 0; } +// +// true when \param USE is the only use of \param DEF in the parent block and +// all other uses of \param DEF in in blocks dominated by block \param D. +// +bool InstCombiner::dominatesAllUses(Instruction *DEF, Instruction *USE, + BasicBlock *D) { + assert(DEF && DEF->getParent() == USE->getParent() && + "select and cmp must be in the same block"); + bool DominatesAll = true; + for (auto I = DEF->use_begin(), E = DEF->use_end(); I != E; ++I) { + Use &U = *I; + auto *User = cast(U.getUser()); + if (User == USE || (DT && DT->dominates(D, User->getParent()))) + continue; + DominatesAll = false; + break; + } + return DominatesAll; +} + +// +// true when the instruction sequence within a block is select-cmp-br. +// +bool InstCombiner::isChainSelectCmpBranch(SelectInst *SI) { + BasicBlock *BB = SI->getParent(); + if (!BB) + return false; + auto *BI = dyn_cast_or_null(BB->getTerminator()); + if (!BI || BI->getNumSuccessors() != 2) + return false; + auto *IC = dyn_cast(BI->getCondition()); + if (!IC || IC->getOperand(0) != SI) + return false; + return true; +} + Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { bool Changed = false; Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -2881,8 +2917,72 @@ // fold to a constant (in which case the icmp is replaced with a select // which will usually simplify) or this is the only user of the // select (in which case we are trading a select+icmp for a simpler - // select+icmp). - if ((Op1 && Op2) || (LHSI->hasOneUse() && (Op1 || Op2))) { + // select+icmp) or all uses of the select can be replaced based on + // dominance information ("global case"). + // + // Example for global case: + // + // entry: + // %4 = select i1 %3, %C* %0, %C* null + // %5 = icmp eq %C* %4, null + // br i1 %5, label %9, label %7 + // ... + // ;