llvm.org GIT mirror llvm / b71ba51
[ValueTracking] Teach isKnownNonNullFromDominatingCondition about AND `isKnownNonNullFromDominatingCondition` is able to prove non-null basing on `br` or `guard` by `%p != null` condition, but is unable to do so basing on `(%p != null) && %other_cond`. This patch allows it to do so. Differential Revision: https://reviews.llvm.org/D50172 Reviewed By: reames git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338990 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 1 year, 3 months ago
2 changed file(s) with 111 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
18601860 continue;
18611861
18621862 for (auto *CmpU : U->users()) {
1863 if (const BranchInst *BI = dyn_cast(CmpU)) {
1864 assert(BI->isConditional() && "uses a comparison!");
1865
1866 BasicBlock *NonNullSuccessor =
1867 BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
1868 BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
1869 if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
1863 SmallVector WorkList;
1864 SmallPtrSet Visited;
1865 Visited.insert(CmpU);
1866 WorkList.push_back(CmpU);
1867
1868 while (!WorkList.empty()) {
1869 auto *Curr = WorkList.pop_back_val();
1870
1871 // If a user is an AND, add all its users to the work list.
1872 if (auto *BO = dyn_cast(Curr))
1873 if (BO->getOpcode() == Instruction::And) {
1874 for (auto *BOU : BO->users())
1875 if (Visited.insert(BOU).second)
1876 WorkList.push_back(BOU);
1877 continue;
1878 }
1879
1880 if (const BranchInst *BI = dyn_cast(Curr)) {
1881 assert(BI->isConditional() && "uses a comparison!");
1882
1883 BasicBlock *NonNullSuccessor =
1884 BI->getSuccessor(Pred == ICmpInst::ICMP_EQ ? 1 : 0);
1885 BasicBlockEdge Edge(BI->getParent(), NonNullSuccessor);
1886 if (Edge.isSingleEdge() && DT->dominates(Edge, CtxI->getParent()))
1887 return true;
1888 } else if (Pred == ICmpInst::ICMP_NE &&
1889 match(Curr, m_Intrinsic()) &&
1890 DT->dominates(cast(Curr), CtxI)) {
18701891 return true;
1871 } else if (Pred == ICmpInst::ICMP_NE &&
1872 match(CmpU, m_Intrinsic()) &&
1873 DT->dominates(cast(CmpU), CtxI)) {
1874 return true;
1892 }
18751893 }
18761894 }
18771895 }
555555 ret void
556556 }
557557
558 ; Check that branch by condition "null check AND something" allows to hoist the
559 ; load.
560 define void @test14(i32* noalias %a, i32* %b, i32* dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {
561
562 ; CHECK-LABEL: @test14
563 ; CHECK: load i32, i32* %c, align 4
564 ; CHECK: for.body:
565
566 entry:
567 %not_null = icmp ne i32* %c, null
568 %dummy_and = and i1 %not_null, %dummy_cond
569 br i1 %dummy_and, label %not.null, label %for.end
570
571 not.null:
572 %cmp11 = icmp sgt i32 %n, 0
573 br i1 %cmp11, label %for.body, label %for.end
574
575 for.body: ; preds = %not.null, %for.inc
576 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]
577 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
578 %0 = load i32, i32* %arrayidx, align 4
579 %cmp1 = icmp sgt i32 %0, 0
580 br i1 %cmp1, label %if.then, label %for.inc
581
582 if.then: ; preds = %for.body
583 %1 = load i32, i32* %c, align 4
584 %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
585 %2 = load i32, i32* %arrayidx3, align 4
586 %mul = mul nsw i32 %2, %1
587 store i32 %mul, i32* %arrayidx, align 4
588 br label %for.inc
589
590 for.inc: ; preds = %for.body, %if.then
591 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
592 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
593 %exitcond = icmp eq i32 %lftr.wideiv, %n
594 br i1 %exitcond, label %for.end, label %for.body
595
596 for.end: ; preds = %for.inc, %entry, %not.null
597 ret void
598 }
599
600 ; Check that guard by condition "null check AND something" allows to hoist the
601 ; load.
602 define void @test15(i32* noalias %a, i32* %b, i32* dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {
603
604 ; CHECK-LABEL: @test15
605 ; CHECK: load i32, i32* %c, align 4
606 ; CHECK: for.body:
607
608 entry:
609 %not_null = icmp ne i32* %c, null
610 %dummy_and = and i1 %not_null, %dummy_cond
611 call void(i1, ...) @llvm.experimental.guard(i1 %dummy_and) [ "deopt"() ]
612 %cmp11 = icmp sgt i32 %n, 0
613 br i1 %cmp11, label %for.body, label %for.end
614
615 for.body: ; preds = %entry, %for.inc
616 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
617 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
618 %0 = load i32, i32* %arrayidx, align 4
619 %cmp1 = icmp sgt i32 %0, 0
620 br i1 %cmp1, label %if.then, label %for.inc
621
622 if.then: ; preds = %for.body
623 %1 = load i32, i32* %c, align 4
624 %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %indvars.iv
625 %2 = load i32, i32* %arrayidx3, align 4
626 %mul = mul nsw i32 %2, %1
627 store i32 %mul, i32* %arrayidx, align 4
628 br label %for.inc
629
630 for.inc: ; preds = %for.body, %if.then
631 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
632 %lftr.wideiv = trunc i64 %indvars.iv.next to i32
633 %exitcond = icmp eq i32 %lftr.wideiv, %n
634 br i1 %exitcond, label %for.end, label %for.body
635
636 for.end: ; preds = %for.inc, %entry
637 ret void
638 }
639
558640 attributes #0 = { nounwind uwtable }
559641 !0 = !{i64 4}