[ValueTracking] Allow context-sensitive nullness check for non-pointers

Same as D60846 but with a fix for the problem encountered there which
was a missing context adjustment in the handling of PHI nodes.

The test that caused D60846 to be reverted was added in e15ab8f277.

Reviewers: nikic, nlopes, mkazantsev,spatel, dlrobertson, uabelho, hakzsam

Subscribers: hiraditya, bollu, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69571
This commit is contained in:
Johannes Doerfert
2019-10-29 11:49:57 -05:00
parent 04813ded98
commit 57dd4b03e4
5 changed files with 18 additions and 19 deletions

View File

@@ -543,10 +543,16 @@ static Value *ThreadCmpOverPHI(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
// Evaluate the BinOp on the incoming phi values.
Value *CommonValue = nullptr;
for (Value *Incoming : PI->incoming_values()) {
for (unsigned u = 0, e = PI->getNumIncomingValues(); u < e; ++u) {
Value *Incoming = PI->getIncomingValue(u);
Instruction *InTI = PI->getIncomingBlock(u)->getTerminator();
// If the incoming value is the phi node itself, it can safely be skipped.
if (Incoming == PI) continue;
Value *V = SimplifyCmpInst(Pred, Incoming, RHS, Q, MaxRecurse);
// Change the context instruction to the "edge" that flows into the phi.
// This is important because that is where incoming is actually "evaluated"
// even though it is used later somewhere else.
Value *V = SimplifyCmpInst(Pred, Incoming, RHS, Q.getWithInstruction(InTI),
MaxRecurse);
// If the operation failed to simplify, or simplified to a different value
// to previously, then give up.
if (!V || (CommonValue && V != CommonValue))

View File

@@ -1902,8 +1902,8 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
static bool isKnownNonNullFromDominatingCondition(const Value *V,
const Instruction *CtxI,
const DominatorTree *DT) {
assert(V->getType()->isPointerTy() && "V must be pointer type");
assert(!isa<ConstantData>(V) && "Did not expect ConstantPointerNull");
if (isa<Constant>(V))
return false;
if (!CtxI || !DT)
return false;
@@ -2078,12 +2078,11 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
}
}
if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
return true;
// Check for recursive pointer simplifications.
if (V->getType()->isPointerTy()) {
if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
return true;
// Look through bitcast operations, GEPs, and int2ptr instructions as they
// do not alter the value, or at least not the nullness property of the
// value, e.g., int2ptr is allowed to zero/sign extend the value.

View File

@@ -13,7 +13,7 @@ define i32 @test0(i64 %x) {
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
; CHECK: non_zero:
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 false), !range !0
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 true), !range !0
; CHECK-NEXT: [[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
@@ -40,7 +40,7 @@ define i32 @test1(i64 %x) {
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
; CHECK: non_zero:
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), !range !0
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 true), !range !0
; CHECK-NEXT: [[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:

View File

@@ -7,8 +7,7 @@ define i64 @test0(i64 %x) {
; CHECK-NEXT: [[A:%.*]] = icmp eq i64 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[A]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
; CHECK: non_zero:
; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X]], 0
; CHECK-NEXT: br i1 [[B]], label [[UNREACHABLE:%.*]], label [[EXIT]]
; CHECK-NEXT: br i1 false, label [[UNREACHABLE:%.*]], label [[EXIT]]
; CHECK: unreachable:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
@@ -37,8 +36,7 @@ define i64 @test1(i64 %x) {
; CHECK-NEXT: [[A:%.*]] = icmp eq i64 [[X:%.*]], 0
; CHECK-NEXT: br i1 [[A]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
; CHECK: non_zero:
; CHECK-NEXT: [[B:%.*]] = icmp ugt i64 [[X]], 0
; CHECK-NEXT: br i1 [[B]], label [[EXIT]], label [[UNREACHABLE:%.*]]
; CHECK-NEXT: br i1 true, label [[EXIT]], label [[UNREACHABLE:%.*]]
; CHECK: unreachable:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
@@ -73,11 +71,9 @@ define i1 @test2(i64 %x, i1 %y) {
; CHECK: two:
; CHECK-NEXT: br label [[MAINBLOCK]]
; CHECK: mainblock:
; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[X]], [[ONE]] ], [ 42, [[TWO]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P]], 0
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[RES:%.*]] = phi i1 [ [[CMP]], [[MAINBLOCK]] ], [ true, [[START:%.*]] ]
; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[MAINBLOCK]] ], [ true, [[START:%.*]] ]
; CHECK-NEXT: ret i1 [[RES]]
;
start:

View File

@@ -129,8 +129,6 @@ fail:
}
; requires fact length is non-zero
; TODO: IsKnownNonNullFromDominatingConditions is currently only be done for
; pointers; should handle integers too
define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable {
; CHECK-LABEL: @test4(
; CHECK-NEXT: entry:
@@ -138,6 +136,7 @@ define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable {
; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
; CHECK: preheader:
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[A]], align 4
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
@@ -145,7 +144,6 @@ define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable {
; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
; CHECK: continue:
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[A]], align 4
; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000