Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions llvm/test/Transforms/LoopUnrollAndJam/dependencies.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; fore_aft_less SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Aft block: A[i-1] = sum (write in outer loop after inner)
; No dependency conflict: The fore block write A[i] and aft block write A[i-1]
; access different array elements, so unrolling the outer loop and jamming the
; inner loop is safe. The backward dependency (i-1) doesn't create conflicts
; between different unrolled iterations.
define void @fore_aft_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -48,6 +57,15 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; fore_aft_eq SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Aft block: A[i] = sum (write in outer loop after inner)
; Dependency conflict: Both fore and aft blocks write to A[i], creating a
; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam
; because the aft block write always happens after the fore block write in
; the same iteration, preserving the original execution order.
define void @fore_aft_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -86,6 +104,15 @@ cleanup:
; CHECK-LABEL: fore_aft_more
; CHECK: %j = phi
; CHECK-NOT: %j.1 = phi
;
; fore_aft_more should NOT be unroll-and-jammed due to a dependency violation.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Aft block: A[i+1] = sum (write in outer loop after inner)
; Dependency conflict: The fore block writes A[i] and aft block writes A[i+1].
; When unroll-and-jamming, iteration i's aft block writes A[i+1] which conflicts
; with iteration i+1's fore block write to A[i+1], creating a write-after-write
; race condition that violates the original sequential semantics.
define void @fore_aft_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -126,6 +153,14 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; fore_sub_less SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Sub block: A[i-1] = sum (write inside inner loop)
; No dependency conflict: The fore block writes A[i] and sub block writes A[i-1].
; These access different array elements, so unroll-and-jam is safe. The backward
; dependency pattern doesn't create conflicts between unrolled iterations.
define void @fore_sub_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -166,6 +201,15 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; fore_sub_eq SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Sub block: A[i] = sum (write inside inner loop)
; Dependency conflict: Both fore and sub blocks write to A[i], creating a
; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam
; because the execution order is preserved: fore block executes first, then
; the entire inner loop (sub block) executes, maintaining the original semantics.
define void @fore_sub_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -204,6 +248,15 @@ cleanup:
; CHECK-LABEL: fore_sub_more
; CHECK: %j = phi
; CHECK-NOT: %j.1 = phi
;
; fore_sub_more should NOT be unroll-and-jammed due to a dependency violation.
; Memory accesses:
; - Fore block: A[i] = 1 (write in outer loop before inner)
; - Sub block: A[i+1] = sum (write inside inner loop)
; Dependency conflict: The fore block writes A[i] and sub block writes A[i+1].
; When unroll-and-jamming, iteration i's fore block writes A[i] but iteration i's
; sub block writes A[i+1]. This conflicts with iteration i+1's fore block write
; to A[i+1], creating a write-after-write race condition.
define void @fore_sub_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -244,6 +297,14 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; sub_aft_less SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Aft block: A[i-1] = sum (write in outer loop after inner)
; No dependency conflict: The sub block writes A[i] and aft block writes A[i-1].
; These access different array elements, so unroll-and-jam is safe. The backward
; dependency pattern doesn't create conflicts between unrolled iterations.
define void @sub_aft_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -284,6 +345,15 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; sub_aft_eq SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Aft block: A[i] = sum (write in outer loop after inner)
; Dependency conflict: Both sub and aft blocks write to A[i], creating a
; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam
; because the execution order is preserved: the entire inner loop (sub block)
; executes first, then the aft block executes, maintaining original semantics.
define void @sub_aft_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -322,6 +392,15 @@ cleanup:
; CHECK-LABEL: sub_aft_more
; CHECK: %j = phi
; CHECK-NOT: %j.1 = phi
;
; sub_aft_more should NOT be unroll-and-jammed due to a dependency violation.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Aft block: A[i+1] = sum (write in outer loop after inner)
; Dependency conflict: The sub block writes A[i] and aft block writes A[i+1].
; When unroll-and-jamming, iteration i's aft block writes A[i+1] which conflicts
; with iteration i+1's sub block write to A[i+1], creating a write-after-write
; race condition that violates the original sequential semantics.
define void @sub_aft_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -360,6 +439,15 @@ cleanup:
; CHECK-LABEL: sub_sub_less
; CHECK: %j = phi
; CHECK-NOT: %j.1 = phi
;
; sub_sub_less should NOT be unroll-and-jammed due to a dependency violation.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Sub block: A[i-1] = sum (write inside inner loop)
; Dependency conflict: Both writes are in the sub block (inner loop), accessing
; A[i] and A[i-1]. When unroll-and-jamming, the inner loop is jammed, meaning
; iterations of the inner loop from different outer iterations execute together.
; This creates a backward dependency that can cause race conditions.
define void @sub_sub_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -400,6 +488,15 @@ cleanup:
; CHECK: %j.1 = phi
; CHECK: %j.2 = phi
; CHECK: %j.3 = phi
;
; sub_sub_eq SHOULD be unroll-and-jammed (count=4) as it's safe.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Sub block: A[i] = sum (write inside inner loop)
; Dependency conflict: Both writes are to A[i] within the sub block, creating a
; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam
; because both writes are in the same basic block and maintain their relative
; order: A[i] = 1 always executes before A[i] = sum in each iteration.
define void @sub_sub_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down Expand Up @@ -438,6 +535,15 @@ cleanup:
; CHECK-LABEL: sub_sub_more
; CHECK: %j = phi
; CHECK-NOT: %j.1 = phi
;
; sub_sub_more should NOT be unroll-and-jammed due to a dependency violation.
; Memory accesses:
; - Sub block: A[i] = 1 (write inside inner loop)
; - Sub block: A[i+1] = sum (write inside inner loop)
; Dependency conflict: Both writes are in the sub block, accessing A[i] and A[i+1].
; When unroll-and-jamming, iteration i's sub block writes A[i+1] which conflicts
; with iteration i+1's sub block write to A[i+1]. This creates a forward
; dependency that causes write-after-write race conditions.
define void @sub_sub_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {
entry:
%cmp = icmp sgt i32 %N, 0
Expand Down
Loading