diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-04-10 20:42:39 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-04-10 20:42:39 +0000 |
commit | 3b6d46761f139e7ee3057758698efa4487323829 (patch) | |
tree | c5120140dcb3fb41e319c1d78a36c4fc4cbd4f39 /llvm/lib | |
parent | d88041672269603f858ba24c1266bb743feb09d9 (diff) | |
download | bcm5719-llvm-3b6d46761f139e7ee3057758698efa4487323829.tar.gz bcm5719-llvm-3b6d46761f139e7ee3057758698efa4487323829.zip |
[CVP] simplify phi with constant incoming values that match common variable edge values
This is based on an example that was recently posted on llvm-dev:
void *propagate_null(void* b, int* g) {
if (!b) {
return 0;
}
(*g)++;
return b;
}
https://godbolt.org/g/xYk3qG
The original code or constant propagation in other passes has obscured the fact
that the phi can be removed completely.
Differential Revision: https://reviews.llvm.org/D45448
llvm-svn: 329755
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 417f482c1d9..a85daaa0780 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -52,6 +52,7 @@ using namespace llvm; #define DEBUG_TYPE "correlated-value-propagation" STATISTIC(NumPhis, "Number of phis propagated"); +STATISTIC(NumPhiCommon, "Number of phis deleted via common incoming value"); STATISTIC(NumSelects, "Number of selects propagated"); STATISTIC(NumMemAccess, "Number of memory access targets propagated"); STATISTIC(NumCmps, "Number of comparisons propagated"); @@ -123,6 +124,62 @@ static bool processSelect(SelectInst *S, LazyValueInfo *LVI) { return true; } +/// Try to simplify a phi with constant incoming values that match the edge +/// values of a non-constant value on all other edges: +/// bb0: +/// %isnull = icmp eq i8* %x, null +/// br i1 %isnull, label %bb2, label %bb1 +/// bb1: +/// br label %bb2 +/// bb2: +/// %r = phi i8* [ %x, %bb1 ], [ null, %bb0 ] +/// --> +/// %r = %x +static bool simplifyCommonValuePhi(PHINode *P, LazyValueInfo *LVI, + const SimplifyQuery &SQ) { + // Collect incoming constants and initialize possible common value. + SmallVector<std::pair<Constant *, unsigned>, 4> IncomingConstants; + Value *CommonValue = nullptr; + for (unsigned i = 0, e = P->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = P->getIncomingValue(i); + if (auto *IncomingConstant = dyn_cast<Constant>(Incoming)) { + IncomingConstants.push_back(std::make_pair(IncomingConstant, i)); + } else if (!CommonValue) { + // The potential common value is initialized to the first non-constant. + CommonValue = Incoming; + } else if (Incoming != CommonValue) { + // There can be only one non-constant common value. + return false; + } + } + + if (!CommonValue || IncomingConstants.empty()) + return false; + + // The common value must be valid in all incoming blocks. + BasicBlock *ToBB = P->getParent(); + if (auto *CommonInst = dyn_cast<Instruction>(CommonValue)) + if (!SQ.DT->dominates(CommonInst, ToBB)) + return false; + + // We have a phi with exactly 1 variable incoming value and 1 or more constant + // incoming values. See if all constant incoming values can be mapped back to + // the same incoming variable value. + for (auto &IncomingConstant : IncomingConstants) { + Constant *C = IncomingConstant.first; + BasicBlock *IncomingBB = P->getIncomingBlock(IncomingConstant.second); + if (C != LVI->getConstantOnEdge(CommonValue, IncomingBB, ToBB, P)) + return false; + } + + // All constant incoming values map to the same variable along the incoming + // edges of the phi. The phi is unnecessary. + P->replaceAllUsesWith(CommonValue); + P->eraseFromParent(); + ++NumPhiCommon; + return true; +} + static bool processPHI(PHINode *P, LazyValueInfo *LVI, const SimplifyQuery &SQ) { bool Changed = false; @@ -184,6 +241,9 @@ static bool processPHI(PHINode *P, LazyValueInfo *LVI, Changed = true; } + if (!Changed) + Changed = simplifyCommonValuePhi(P, LVI, SQ); + if (Changed) ++NumPhis; |