diff options
author | Jun Bum Lim <junbuml@codeaurora.org> | 2016-02-11 15:50:07 +0000 |
---|---|---|
committer | Jun Bum Lim <junbuml@codeaurora.org> | 2016-02-11 15:50:07 +0000 |
commit | 339e9723c12dfc046b1493bb75891515127ff0ff (patch) | |
tree | dc9b7432e371db8ea8acbd7066171b8157ee7790 /llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp | |
parent | e3b963d5eea70d510e5ad5d852ce74a2642886e1 (diff) | |
download | bcm5719-llvm-339e9723c12dfc046b1493bb75891515127ff0ff.tar.gz bcm5719-llvm-339e9723c12dfc046b1493bb75891515127ff0ff.zip |
[InstCombine] Simplify a known nonzero incoming value of PHI
Summary:
When a PHI is used only to be compared with zero, it is possible to replace an
incoming value with any non-zero constant if the incoming value can be proved as
a known nonzero value. For example, in below code, we can replace the incoming value %v 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] ...
%c = icmp eq, %p, 0
Reviewers: mcrosier, jmolloy, sanjoy
Subscribers: hfinkel, mcrosier, majnemer, llvm-commits, haicheng, bmakam, mssimpso, gberry
Differential Revision: http://reviews.llvm.org/D16240
llvm-svn: 260530
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp index f8c6fa534fd..138a95cb7c8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -15,8 +15,11 @@ #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; +using namespace llvm::PatternMatch; #define DEBUG_TYPE "instcombine" @@ -641,6 +644,16 @@ static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal, return true; } +/// Return an existing non-zero constant if this phi node has, otherwise ruturn +/// constant 1. +static ConstantInt *GetAnyNonZeroConstInt(PHINode &PN) { + assert(isa<IntegerType>(PN.getType()) && "Expect only intger type phi"); + for (Value *V : PN.operands()) + if (auto *ConstVA = dyn_cast<ConstantInt>(V)) + if (!ConstVA->isZeroValue()) + return ConstVA; + return ConstantInt::get(cast<IntegerType>(PN.getType()), 1); +} namespace { struct PHIUsageRecord { @@ -919,6 +932,29 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) { 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 + auto *CmpInst = dyn_cast<ICmpInst>(PHIUser); + // FIXME: To be simple, handle only integer type for now. + if (CmpInst && isa<IntegerType>(PN.getType()) && CmpInst->isEquality() && + match(CmpInst->getOperand(1), m_Zero())) { + ConstantInt *NonZeroConst = nullptr; + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + Instruction *CtxI = PN.getIncomingBlock(i)->getTerminator(); + Value *VA = PN.getIncomingValue(i); + if (isKnownNonZero(VA, DL, 0, AC, CtxI, DT)) { + if (!NonZeroConst) + NonZeroConst = GetAnyNonZeroConstInt(PN); + PN.setIncomingValue(i, NonZeroConst); + } + } + } } // We sometimes end up with phi cycles that non-obviously end up being the |