diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2674,6 +2674,23 @@ if (U.get() == PN) return true; RecQ.CxtI = PN->getIncomingBlock(U)->getTerminator(); + // Check if the branch on the phi excludes zero. + ICmpInst::Predicate Pred; + Value *X; + BasicBlock *TrueSucc, *FalseSucc; + if (match(RecQ.CxtI, + m_Br(m_c_ICmp(Pred, m_Specific(U.get()), m_Value(X)), + m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) { + // Check for cases of duplicate successors. + if ((TrueSucc == PN->getParent()) != (FalseSucc == PN->getParent())) { + // If we're using the false successor, invert the predicate. + if (FalseSucc == PN->getParent()) + Pred = CmpInst::getInversePredicate(Pred); + if (cmpExcludesZero(Pred, X)) + return true; + } + } + // Finally recurse on the edge and check it directly. return isKnownNonZero(U.get(), DemandedElts, NewDepth, RecQ); }); } diff --git a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll --- a/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll +++ b/llvm/test/Analysis/ValueTracking/phi-known-nonzero.ll @@ -7,9 +7,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -30,9 +28,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], 32 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -78,9 +74,7 @@ ; CHECK: T: ; CHECK-NEXT: br i1 true, label [[F]], label [[T]] ; CHECK: F: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[T]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; entry: %cmp = icmp ult i8 %x, 123 @@ -101,9 +95,7 @@ ; CHECK: T: ; CHECK-NEXT: br i1 true, label [[F]], label [[T]] ; CHECK: F: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[T]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; entry: %cmp = icmp ule i8 %x, 123 @@ -170,9 +162,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -193,9 +183,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 44 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; @@ -218,9 +206,7 @@ ; CHECK: T: ; CHECK-NEXT: br i1 true, label [[F]], label [[T]] ; CHECK: F: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[T]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; entry: %cmp = icmp eq i8 %x, 0 @@ -239,9 +225,7 @@ ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 1 ; CHECK-NEXT: br i1 [[CMP]], label [[T:%.*]], label [[F:%.*]] ; CHECK: T: -; CHECK-NEXT: [[V:%.*]] = phi i8 [ [[X]], [[ENTRY:%.*]] ], [ -1, [[F]] ] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; CHECK: F: ; CHECK-NEXT: br i1 true, label [[T]], label [[F]] ; diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll --- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll +++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll @@ -251,9 +251,8 @@ ; char* test11(char *p) { ; return p? p: nonnull(); ; } -; FIXME: missing nonnull define ptr @test11(ptr) local_unnamed_addr { -; FNATTRS-LABEL: define ptr @test11 +; FNATTRS-LABEL: define nonnull ptr @test11 ; FNATTRS-SAME: (ptr readnone [[TMP0:%.*]]) local_unnamed_addr { ; FNATTRS-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null ; FNATTRS-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] @@ -264,7 +263,7 @@ ; FNATTRS-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] ; FNATTRS-NEXT: ret ptr [[TMP6]] ; -; ATTRIBUTOR-LABEL: define ptr @test11 +; ATTRIBUTOR-LABEL: define nonnull ptr @test11 ; ATTRIBUTOR-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr { ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null ; ATTRIBUTOR-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] diff --git a/llvm/test/Transforms/JumpThreading/phi-known.ll b/llvm/test/Transforms/JumpThreading/phi-known.ll --- a/llvm/test/Transforms/JumpThreading/phi-known.ll +++ b/llvm/test/Transforms/JumpThreading/phi-known.ll @@ -66,9 +66,7 @@ ; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[P]], null ; CHECK-NEXT: br i1 [[CMP0]], label [[EXIT:%.*]], label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[P1:%.*]] = phi ptr [ [[P]], [[ENTRY:%.*]] ], [ [[P1]], [[LOOP]] ] -; CHECK-NEXT: [[CMP1:%.*]] = icmp ne ptr [[P1]], null -; CHECK-NEXT: br i1 [[CMP1]], label [[EXIT]], label [[LOOP]] +; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void ;