Index: lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombinePHI.cpp +++ lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -15,6 +15,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -919,6 +921,30 @@ PHIUser->user_back() == &PN) { return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType())); } + + // When a PHI is used only to be compared with zero, it is safe to replace + // an incoming value proved as known nonzero with any non-zero constant. + // For example, in below code, the incoming value %v can be replaced with + // any non-zero constant based on the fact that the PHI is only used to be + // compared with zero and %v is a known non-zero value: + // %v = select %cond, 1, 2 + // %p = phi [%v, BB] ... + // icmp eq, %p, 0 + ICmpInst *CmpInst = dyn_cast(PHIUser); + // FIXME: To be simple, handle only integer type for now. + if (CmpInst && isa(PN.getType()) && CmpInst->isEquality() && + (match(CmpInst->getOperand(1), PatternMatch::m_Zero()) || + match(CmpInst->getOperand(0), PatternMatch::m_Zero()))) { + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + BasicBlock *InBB = PN.getIncomingBlock(i); + Instruction *CtxI = (InBB && InBB->getTerminator()) + ? (Instruction *)InBB->getTerminator() + : (Instruction *)&PN; + Value *VA = PN.getIncomingValue(i); + if (!isa(VA) && isKnownNonZero(VA, DL, 0, AC, CtxI, DT)) + PN.setIncomingValue(i, ConstantInt::get(PN.getType(), 1)); + } + } } // We sometimes end up with phi cycles that non-obviously end up being the Index: test/Transforms/InstCombine/phi.ll =================================================================== --- test/Transforms/InstCombine/phi.ll +++ test/Transforms/InstCombine/phi.ll @@ -760,3 +760,27 @@ ; CHECK-NEXT: ret i1 %[[RES]] } +; CHECK-LABEL: @phi_knownnonzero +; CHECK-LABEL: if.then: +; CHECK-NOT: select +; CHECK-LABEL: if.end: +; CHECK: phi i32 [ 1, %if.then ] + + +define i1 @phi_knownnonzero(i32 %n, i32 %s, i32* nocapture readonly %P) { +entry: + %tobool = icmp slt i32 %n, %s + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + %0 = load i32, i32* %P + %cmp = icmp eq i32 %n, %0 + %1 = select i1 %cmp, i32 1, i32 2 + br label %if.end + +if.end: ; preds = %entry, %if.then + %a.0 = phi i32 [ %1, %if.then ], [ %n, %entry ] + %cmp1 = icmp eq i32 %a.0, 0 + ret i1 %cmp1 +} +