[llvm] r329755 - [CVP] simplify phi with constant incoming values that match common variable edge values
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 10 13:42:39 PDT 2018
Author: spatel
Date: Tue Apr 10 13:42:39 2018
New Revision: 329755
URL: http://llvm.org/viewvc/llvm-project?rev=329755&view=rev
Log:
[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
Added:
llvm/trunk/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=329755&r1=329754&r2=329755&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp Tue Apr 10 13:42:39 2018
@@ -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,
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, LazyV
Changed = true;
}
+ if (!Changed)
+ Changed = simplifyCommonValuePhi(P, LVI, SQ);
+
if (Changed)
++NumPhis;
Added: llvm/trunk/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll?rev=329755&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll (added)
+++ llvm/trunk/test/Transforms/CorrelatedValuePropagation/phi-common-val.ll Tue Apr 10 13:42:39 2018
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -correlated-propagation -S | FileCheck %s
+
+define i8* @simplify_phi_common_value_op0(i8* %ptr, i32* %b) {
+; CHECK-LABEL: @simplify_phi_common_value_op0(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i8* [[PTR:%.*]], null
+; CHECK-NEXT: br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[LB:%.*]] = load i32, i32* [[B:%.*]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LB]], 1
+; CHECK-NEXT: store i32 [[ADD]], i32* [[B]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: ret i8* [[PTR]]
+;
+entry:
+ %isnull = icmp eq i8* %ptr, null
+ br i1 %isnull, label %return, label %else
+
+else:
+ %lb = load i32, i32* %b
+ %add = add nsw i32 %lb, 1
+ store i32 %add, i32* %b
+ br label %return
+
+return:
+ %r = phi i8* [ %ptr, %else ], [ null, %entry ]
+ ret i8* %r
+}
+
+define i8* @simplify_phi_common_value_op1(i8* %ptr, i32* %b) {
+; CHECK-LABEL: @simplify_phi_common_value_op1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq i8* [[PTR:%.*]], null
+; CHECK-NEXT: br i1 [[ISNULL]], label [[RETURN:%.*]], label [[ELSE:%.*]]
+; CHECK: else:
+; CHECK-NEXT: [[LB:%.*]] = load i32, i32* [[B:%.*]]
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LB]], 1
+; CHECK-NEXT: store i32 [[ADD]], i32* [[B]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: ret i8* [[PTR]]
+;
+entry:
+ %isnull = icmp eq i8* %ptr, null
+ br i1 %isnull, label %return, label %else
+
+else:
+ %lb = load i32, i32* %b
+ %add = add i32 %lb, 1
+ store i32 %add, i32* %b
+ br label %return
+
+return:
+ %r = phi i8* [ null, %entry], [ %ptr, %else ]
+ ret i8* %r
+}
+
+define i8 @simplify_phi_multiple_constants(i8 %x, i32* %b) {
+; CHECK-LABEL: @simplify_phi_multiple_constants(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[IS0:%.*]] = icmp eq i8 [[X:%.*]], 0
+; CHECK-NEXT: br i1 [[IS0]], label [[RETURN:%.*]], label [[ELSE1:%.*]]
+; CHECK: else1:
+; CHECK-NEXT: [[IS42:%.*]] = icmp eq i8 [[X]], 42
+; CHECK-NEXT: br i1 [[IS42]], label [[RETURN]], label [[ELSE2:%.*]]
+; CHECK: else2:
+; CHECK-NEXT: [[LB:%.*]] = load i32, i32* [[B:%.*]]
+; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LB]], 1
+; CHECK-NEXT: store i32 [[ADD]], i32* [[B]]
+; CHECK-NEXT: br label [[RETURN]]
+; CHECK: return:
+; CHECK-NEXT: ret i8 [[X]]
+;
+entry:
+ %is0 = icmp eq i8 %x, 0
+ br i1 %is0, label %return, label %else1
+
+else1:
+ %is42 = icmp eq i8 %x, 42
+ br i1 %is42, label %return, label %else2
+
+else2:
+ %lb = load i32, i32* %b
+ %add = add i32 %lb, 1
+ store i32 %add, i32* %b
+ br label %return
+
+return:
+ %r = phi i8 [ 0, %entry], [ %x, %else2 ], [ 42, %else1 ]
+ ret i8 %r
+}
+
More information about the llvm-commits
mailing list