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 @@ -2724,6 +2724,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 @@ -147,9 +139,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]] ; @@ -170,9 +160,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]] ; @@ -195,9 +183,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 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 @@ -46,15 +46,19 @@ ; Well, we could unroll this loop exactly twice, but that's ; a different transform. define void @test_mixed(ptr %p) { -; CHECK-LABEL: @test_mixed +; CHECK-LABEL: define void @test_mixed +; CHECK-SAME: (ptr [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP0:%.*]] = icmp eq ptr [[P]], null +; CHECK-NEXT: br i1 [[CMP0]], label [[EXIT:%.*]], label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void entry: %cmp0 = icmp eq ptr %p, null br i1 %cmp0, label %exit, label %loop loop: -; CHECK-LABEL: loop: -; CHECK-NEXT: phi -; CHECK-NEXT: %cmp1 = icmp -; CHECK-NEXT: br i1 %cmp1 %p1 = phi ptr [%p, %entry], [%p1, %loop] %cmp1 = icmp ne ptr %p1, null br i1 %cmp1, label %exit, label %loop