mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-30 23:21:04 +00:00
[SCEV] Strengthen variance condition in calculateLoopDisposition
Given loops `L1` and `L2` with AddRecs `AR1` and `AR2` varying in them respectively. When identifying loop disposition of `AR2` w.r.t. `L1`, we only say that it is varying if `L1` contains `L2`. But there is also a possible situation where `L1` and `L2` are consecutive sibling loops within the parent loop. In this case, `AR2` is also varying w.r.t. `L1`, but we don't correctly identify it. It can lead, for exaple, to attempt of incorrect folding. Consider: AR1 = {a,+,b}<L1> AR2 = {c,+,d}<L2> EXAR2 = sext(AR1) MUL = mul AR1, EXAR2 If we incorrectly assume that `EXAR2` is invariant w.r.t. `L1`, we can end up trying to construct something like: `{a * {c,+,d}<L2>,+,b * {c,+,d}<L2>}<L1>`, which is incorrect because `AR2` is not available on entrance of `L1`. Both situations "`L1` contains `L2`" and "`L1` preceeds sibling loop `L2`" can be handled with one check: "header of `L1` dominates header of `L2`". This patch replaces the old insufficient check with this one. Differential Revision: https://reviews.llvm.org/D39453 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318819 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
882fbe3d4c
commit
f66b47b328
@ -10927,9 +10927,11 @@ ScalarEvolution::computeLoopDisposition(const SCEV *S, const Loop *L) {
|
||||
if (!L)
|
||||
return LoopVariant;
|
||||
|
||||
// This recurrence is variant w.r.t. L if L contains AR's loop.
|
||||
if (L->contains(AR->getLoop()))
|
||||
// Everything that is not defined at loop entry is variant.
|
||||
if (DT.dominates(L->getHeader(), AR->getLoop()->getHeader()))
|
||||
return LoopVariant;
|
||||
assert(!L->contains(AR->getLoop()) && "Containing loop's header does not"
|
||||
" dominate the contained loop's header?");
|
||||
|
||||
// This recurrence is invariant w.r.t. L if AR's loop contains L.
|
||||
if (AR->getLoop()->contains(L))
|
||||
|
@ -510,3 +510,122 @@ exit:
|
||||
%tmp10 = add i32 %iv.1.2, 3
|
||||
ret void
|
||||
}
|
||||
|
||||
define i64 @test_09(i32 %param) {
|
||||
|
||||
; CHECK-LABEL: Classifying expressions for: @test_09
|
||||
; CHECK: %iv1 = phi i64 [ %iv1.next, %guarded ], [ 0, %outer.loop ]
|
||||
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop1>
|
||||
; CHECK: %iv1.trunc = trunc i64 %iv1 to i32
|
||||
; CHECK-NEXT: --> {0,+,1}<%loop1>
|
||||
; CHECK: %iv1.next = add nuw nsw i64 %iv1, 1
|
||||
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop1>
|
||||
; CHECK: %iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
|
||||
; CHECK-NEXT: --> {%param,+,1}<%loop2>
|
||||
; CHECK: %iv2.next = add i32 %iv2, 1
|
||||
; CHECK-NEXT: --> {(1 + %param),+,1}<%loop2>
|
||||
; CHECK: %iv2.ext = sext i32 %iv2.next to i64
|
||||
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<%loop2> to i64)
|
||||
; CHECK: %ret = mul i64 %iv1, %iv2.ext
|
||||
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>)
|
||||
|
||||
entry:
|
||||
br label %outer.loop
|
||||
|
||||
outer.loop: ; preds = %loop2.exit, %entry
|
||||
br label %loop1
|
||||
|
||||
loop1: ; preds = %guarded, %outer.loop
|
||||
%iv1 = phi i64 [ %iv1.next, %guarded ], [ 0, %outer.loop ]
|
||||
%iv1.trunc = trunc i64 %iv1 to i32
|
||||
%cond1 = icmp ult i64 %iv1, 100
|
||||
br i1 %cond1, label %guarded, label %deopt
|
||||
|
||||
guarded: ; preds = %loop1
|
||||
%iv1.next = add nuw nsw i64 %iv1, 1
|
||||
%tmp16 = icmp slt i32 %iv1.trunc, 2
|
||||
br i1 %tmp16, label %loop1, label %loop2.preheader
|
||||
|
||||
deopt: ; preds = %loop1
|
||||
unreachable
|
||||
|
||||
loop2.preheader: ; preds = %guarded
|
||||
br label %loop2
|
||||
|
||||
loop2: ; preds = %loop2, %loop2.preheader
|
||||
%iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
|
||||
%iv2.next = add i32 %iv2, 1
|
||||
%cond2 = icmp slt i32 %iv2, %iv1.trunc
|
||||
br i1 %cond2, label %loop2, label %exit
|
||||
|
||||
exit: ; preds = %loop2.exit
|
||||
%iv2.ext = sext i32 %iv2.next to i64
|
||||
%ret = mul i64 %iv1, %iv2.ext
|
||||
ret i64 %ret
|
||||
}
|
||||
|
||||
define i64 @test_10(i32 %param) {
|
||||
|
||||
; CHECK-LABEL: Classifying expressions for: @test_10
|
||||
; CHECK: %uncle = phi i64 [ %uncle.outer.next, %uncle.loop.backedge ], [ 0, %outer.loop ]
|
||||
; CHECK-NEXT: --> {0,+,1}<%uncle.loop>
|
||||
; CHECK: %iv1 = phi i64 [ %iv1.next, %guarded ], [ 0, %uncle.loop ]
|
||||
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop1>
|
||||
; CHECK: %iv1.trunc = trunc i64 %iv1 to i32
|
||||
; CHECK-NEXT: --> {0,+,1}<%loop1>
|
||||
; CHECK: %iv1.next = add nuw nsw i64 %iv1, 1
|
||||
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop1>
|
||||
; CHECK: %uncle.outer.next = add i64 %uncle, 1
|
||||
; CHECK-NEXT: --> {1,+,1}<%uncle.loop>
|
||||
; CHECK: %iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
|
||||
; CHECK-NEXT: --> {%param,+,1}<%loop2>
|
||||
; CHECK: %iv2.next = add i32 %iv2, 1
|
||||
; CHECK-NEXT: --> {(1 + %param),+,1}<%loop2>
|
||||
; CHECK: %iv2.ext = sext i32 %iv2.next to i64
|
||||
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<%loop2> to i64)
|
||||
; CHECK: %ret = mul i64 %iv1, %iv2.ext
|
||||
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>)
|
||||
|
||||
entry:
|
||||
br label %outer.loop
|
||||
|
||||
outer.loop: ; preds = %entry
|
||||
br label %uncle.loop
|
||||
|
||||
uncle.loop: ; preds = %uncle.loop.backedge, %outer.loop
|
||||
%uncle = phi i64 [ %uncle.outer.next, %uncle.loop.backedge ], [ 0, %outer.loop ]
|
||||
br label %loop1
|
||||
|
||||
loop1: ; preds = %guarded, %uncle.loop
|
||||
%iv1 = phi i64 [ %iv1.next, %guarded ], [ 0, %uncle.loop ]
|
||||
%iv1.trunc = trunc i64 %iv1 to i32
|
||||
%cond1 = icmp ult i64 %iv1, 100
|
||||
br i1 %cond1, label %guarded, label %deopt
|
||||
|
||||
guarded: ; preds = %loop1
|
||||
%iv1.next = add nuw nsw i64 %iv1, 1
|
||||
%tmp16 = icmp slt i32 %iv1.trunc, 2
|
||||
br i1 %tmp16, label %loop1, label %uncle.loop.backedge
|
||||
|
||||
uncle.loop.backedge: ; preds = %guarded
|
||||
%uncle.outer.next = add i64 %uncle, 1
|
||||
%cond.uncle = icmp ult i64 %uncle, 120
|
||||
br i1 %cond.uncle, label %loop2.preheader, label %uncle.loop
|
||||
|
||||
deopt: ; preds = %loop1
|
||||
unreachable
|
||||
|
||||
loop2.preheader: ; preds = %uncle.loop.backedge
|
||||
br label %loop2
|
||||
|
||||
loop2: ; preds = %loop2, %loop2.preheader
|
||||
%iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
|
||||
%iv2.next = add i32 %iv2, 1
|
||||
%cond2 = icmp slt i32 %iv2, %iv1.trunc
|
||||
br i1 %cond2, label %loop2, label %exit
|
||||
|
||||
exit: ; preds = %loop2
|
||||
%iv2.ext = sext i32 %iv2.next to i64
|
||||
%ret = mul i64 %iv1, %iv2.ext
|
||||
ret i64 %ret
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user