Index: lib/Transforms/InstCombine/InstCombine.h =================================================================== --- lib/Transforms/InstCombine/InstCombine.h +++ lib/Transforms/InstCombine/InstCombine.h @@ -13,6 +13,7 @@ #include "InstCombineWorklist.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" @@ -87,6 +88,7 @@ : public FunctionPass, public InstVisitor { const DataLayout *DL; + const DominatorTree *DT; TargetLibraryInfo *TLI; bool MadeIRChange; LibCallSimplifier *Simplifier; @@ -102,7 +104,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()); } @@ -226,6 +229,8 @@ // visitInstruction - Specify what to return for unhandled instructions... Instruction *visitInstruction(Instruction &I) { return nullptr; } + bool dominatesAllUses(SelectInst *SI, ICmpInst &ICmp, 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,41 @@ return GlobalSwapBenefits > 0; } +// +// true when \param SI dominates all of its uses or \param ICmp. +// +bool InstCombiner::dominatesAllUses(SelectInst *SI, ICmpInst &ICmp, + BasicBlock *D) { + bool dominates_all_uses = true; + for (auto I = SI->use_begin(), E = SI->use_end(); I != E; ++I) { + Use &U = *I; + auto *User = cast(U.getUser()); + if (User == &ICmp || DT->dominates(D, User->getParent())) + continue; + dominates_all_uses = false; + break; + } + return dominates_all_uses; +} + +// +// 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; + if (!isa(BB->getTerminator())) + return false; + BranchInst *BI = cast(BB->getTerminator()); + if (BI->getNumSuccessors() != 2) + return false; + ICmpInst *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 +2916,75 @@ // 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 + // ... + // ;