summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-04-10 20:42:39 +0000
committerSanjay Patel <spatel@rotateright.com>2018-04-10 20:42:39 +0000
commit3b6d46761f139e7ee3057758698efa4487323829 (patch)
treec5120140dcb3fb41e319c1d78a36c4fc4cbd4f39 /llvm/lib
parentd88041672269603f858ba24c1266bb743feb09d9 (diff)
downloadbcm5719-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.cpp60
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;
OpenPOWER on IntegriCloud