Skip to content

Commit 9d42c75

Browse files
committed
[LAA] Fix picking context instr in evaluatePtrAddRec for multiple preds.
A loop may have more than one predecessor out of the loop. In that case, just pick the first non-phi instruction in the loop header.
1 parent 67141c7 commit 9d42c75

File tree

2 files changed

+139
-2
lines changed

2 files changed

+139
-2
lines changed

llvm/lib/Analysis/LoopAccessAnalysis.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,14 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
234234

235235
// Check if we have a suitable dereferencable assumption we can use.
236236
if (!StartPtrV->canBeFreed()) {
237+
Instruction *CtxI = &*L->getHeader()->getFirstNonPHIIt();
238+
if (BasicBlock *LoopPred = L->getLoopPredecessor()) {
239+
if (isa<BranchInst>(LoopPred->getTerminator()))
240+
CtxI = LoopPred->getTerminator();
241+
}
242+
237243
RetainedKnowledge DerefRK = getKnowledgeValidInContext(
238-
StartPtrV, {Attribute::Dereferenceable}, *AC,
239-
L->getLoopPredecessor()->getTerminator(), DT);
244+
StartPtrV, {Attribute::Dereferenceable}, *AC, CtxI, DT);
240245
if (DerefRK) {
241246
DerefBytesSCEV =
242247
SE.getUMaxExpr(DerefBytesSCEV, SE.getSCEV(DerefRK.IRArgValue));

llvm/test/Analysis/LoopAccessAnalysis/early-exit-runtime-checks.ll

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,138 @@ e.2:
565565
ret void
566566
}
567567

568+
define void @all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref_via_assumption_multiple_predecessors(ptr %A, ptr %B, i1 %c) nosync nofree {
569+
; CHECK-LABEL: 'all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref_via_assumption_multiple_predecessors'
570+
; CHECK-NEXT: loop.header:
571+
; CHECK-NEXT: Memory dependences are safe with run-time checks
572+
; CHECK-NEXT: Dependences:
573+
; CHECK-NEXT: Run-time memory checks:
574+
; CHECK-NEXT: Check 0:
575+
; CHECK-NEXT: Comparing group GRP0:
576+
; CHECK-NEXT: %gep.B = getelementptr inbounds i32, ptr %B, i64 %iv
577+
; CHECK-NEXT: Against group GRP1:
578+
; CHECK-NEXT: %gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
579+
; CHECK-NEXT: Grouped accesses:
580+
; CHECK-NEXT: Group GRP0:
581+
; CHECK-NEXT: (Low: %B High: (2000 + %B))
582+
; CHECK-NEXT: Member: {%B,+,4}<nuw><%loop.header>
583+
; CHECK-NEXT: Group GRP1:
584+
; CHECK-NEXT: (Low: %A High: (2000 + %A))
585+
; CHECK-NEXT: Member: {%A,+,4}<nuw><%loop.header>
586+
; CHECK-EMPTY:
587+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
588+
; CHECK-NEXT: SCEV assumptions:
589+
; CHECK-EMPTY:
590+
; CHECK-NEXT: Expressions re-written:
591+
;
592+
entry:
593+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %A, i64 2000) ]
594+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %B, i64 2000) ]
595+
br i1 %c, label %then, label %else
596+
597+
then:
598+
br label %loop.header
599+
600+
else:
601+
br label %loop.header
602+
603+
loop.header:
604+
%iv = phi i64 [ 0, %then ], [ 0, %else ], [ %iv.next, %latch ]
605+
%gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
606+
%gep.B = getelementptr inbounds i32, ptr %B, i64 %iv
607+
%l = load i32, ptr %gep.A, align 4
608+
store i32 0, ptr %gep.B, align 4
609+
%cntable.c.1 = icmp ult i64 %iv, 1000
610+
%iv.next = add nuw nsw i64 %iv, 1
611+
br i1 %cntable.c.1, label %b2, label %e.1
612+
613+
b2:
614+
%uncntable.c.0 = icmp eq i32 %l, 0
615+
br i1 %uncntable.c.0, label %e.2, label %b3
616+
617+
b3:
618+
%cntable.c.2 = icmp eq i64 %iv.next, 500
619+
br i1 %cntable.c.2, label %cleanup4, label %latch
620+
621+
latch:
622+
br label %loop.header
623+
624+
cleanup4:
625+
ret void
626+
627+
e.1:
628+
ret void
629+
630+
e.2:
631+
ret void
632+
}
633+
634+
define void @all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref_via_assumption_multiple_predecessors_no_valid(ptr %A, ptr %B, i1 %c) nosync nofree {
635+
; CHECK-LABEL: 'all_exits_dominate_latch_countable_exits_at_most_500_iterations_known_deref_via_assumption_multiple_predecessors_no_valid'
636+
; CHECK-NEXT: loop.header:
637+
; CHECK-NEXT: Memory dependences are safe with run-time checks
638+
; CHECK-NEXT: Dependences:
639+
; CHECK-NEXT: Run-time memory checks:
640+
; CHECK-NEXT: Check 0:
641+
; CHECK-NEXT: Comparing group GRP0:
642+
; CHECK-NEXT: %gep.B = getelementptr inbounds i32, ptr %B, i64 %iv
643+
; CHECK-NEXT: Against group GRP1:
644+
; CHECK-NEXT: %gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
645+
; CHECK-NEXT: Grouped accesses:
646+
; CHECK-NEXT: Group GRP0:
647+
; CHECK-NEXT: (Low: %B High: inttoptr (i64 -1 to ptr))
648+
; CHECK-NEXT: Member: {%B,+,4}<nuw><%loop.header>
649+
; CHECK-NEXT: Group GRP1:
650+
; CHECK-NEXT: (Low: %A High: (2000 + %A))
651+
; CHECK-NEXT: Member: {%A,+,4}<nuw><%loop.header>
652+
; CHECK-EMPTY:
653+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
654+
; CHECK-NEXT: SCEV assumptions:
655+
; CHECK-EMPTY:
656+
; CHECK-NEXT: Expressions re-written:
657+
;
658+
entry:
659+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %A, i64 2000) ]
660+
br i1 %c, label %then, label %else
661+
662+
then:
663+
call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %B, i64 2000) ]
664+
br label %loop.header
665+
666+
else:
667+
br label %loop.header
668+
669+
loop.header:
670+
%iv = phi i64 [ 0, %then ], [ 0, %else ], [ %iv.next, %latch ]
671+
%gep.A = getelementptr inbounds i32, ptr %A, i64 %iv
672+
%gep.B = getelementptr inbounds i32, ptr %B, i64 %iv
673+
%l = load i32, ptr %gep.A, align 4
674+
store i32 0, ptr %gep.B, align 4
675+
%cntable.c.1 = icmp ult i64 %iv, 1000
676+
%iv.next = add nuw nsw i64 %iv, 1
677+
br i1 %cntable.c.1, label %b2, label %e.1
678+
679+
b2:
680+
%uncntable.c.0 = icmp eq i32 %l, 0
681+
br i1 %uncntable.c.0, label %e.2, label %b3
682+
683+
b3:
684+
%cntable.c.2 = icmp eq i64 %iv.next, 500
685+
br i1 %cntable.c.2, label %cleanup4, label %latch
686+
687+
latch:
688+
br label %loop.header
689+
690+
cleanup4:
691+
ret void
692+
693+
e.1:
694+
ret void
695+
696+
e.2:
697+
ret void
698+
}
699+
568700
define void @all_exits_dominate_latch_countable_exits_at_most_500_iterations_deref_via_assumption_too_small(ptr %A, ptr %B) nosync nofree {
569701
; CHECK-LABEL: 'all_exits_dominate_latch_countable_exits_at_most_500_iterations_deref_via_assumption_too_small'
570702
; CHECK-NEXT: loop.header:

0 commit comments

Comments
 (0)