summaryrefslogtreecommitdiff
path: root/flang/test/HLFIR/order_assignments/forall-scheduling.f90
blob: f5cb53bb8284f89db0224ac8563c1b5d83ae115e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
! Test forall scheduling analysis from lower-hlfir-ordered-assignments pass.
! The printed output is done via LLVM_DEBUG, hence the "asserts" requirement.
! This test test that conflicting actions are not scheduled to be evaluated
! in the same loops (same run id).

! RUN: bbc -hlfir -o - -pass-pipeline="builtin.module(lower-hlfir-ordered-assignments)" --debug-only=flang-ordered-assignment -flang-dbg-order-assignment-schedule-only %s 2>&1 | FileCheck %s
! REQUIRES: asserts

subroutine no_conflict(x)
  real :: x(:)
  forall(i=1:10) x(i) = i
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPno_conflict ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1

subroutine rhs_lhs_overlap(x)
  real :: x(:)
  forall(i=1:10) x(i) = x(11-i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPrhs_lhs_overlap ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?xf32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?xf32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/rhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine no_rhs_lhs_overlap(x, y)
  real :: x(:), y(:)
  forall(i=1:10) x(i) = y(i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPno_rhs_lhs_overlap ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1

subroutine no_rhs_lhs_overlap_2(x)
  real :: x(:), y(10)
  forall(i=1:10) x(i) = y(i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPno_rhs_lhs_overlap_2 ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1

subroutine no_rhs_lhs_overlap_3()
  real :: x(10), y(10)
  forall(i=1:10) x(i) = y(i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPno_rhs_lhs_overlap_3 ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1

subroutine array_expr_rhs_lhs_overlap(x)
  real :: x(:, :)
  forall(i=1:10) x(i, :) = x(:, i)*2
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QParray_expr_rhs_lhs_overlap ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xf32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?x?xf32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/rhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine array_expr_no_rhs_lhs_overlap(x, y, z)
  real :: x(:, :), y(:, :), z(:, :)
  forall(i=1:10) x(i, :) = y(:, i) + z(i, :)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QParray_expr_no_rhs_lhs_overlap ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1

subroutine rhs_lhs_overlap_2(x, y)
  real, target :: x(:), y(:)
  forall(i=1:10) x(i) = y(i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPrhs_lhs_overlap_2 ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?xf32>>' at index: 1 W:<block argument> of type '!fir.box<!fir.array<?xf32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/rhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine lhs_lhs_overlap(x)
  integer :: x(10)
  forall(i=1:10) x(x(i)) = i
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPlhs_lhs_overlap ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.ref<!fir.array<10xi32>>' at index: 0 W:<block argument> of type '!fir.ref<!fir.array<10xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/lhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine unknown_function_call(x)
  interface
    pure real function foo(x, i)
      integer, intent(in) :: i
      real, intent(in) :: x(10)
    end function
  end interface
  real :: x(10)
  forall(i=1:10) x(i) = foo(x, i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPunknown_function_call ------------
!CHECK-NEXT: unknown effect: {{.*}} fir.call @_QPfoo
!CHECK-NEXT: conflict: R/W: <unknown> W:<block argument> of type '!fir.ref<!fir.array<10xf32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/rhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine unknown_function_call2(x)
  interface
    pure real function foo2(i)
      integer, value :: i
    end function
  end interface
  ! foo2 may read x since it is a target, even if it is pure,
  ! if the actual argument of x is a module variable accessible
  ! to foo via host association.
  real, target :: x(:)
  forall(i=1:10) x(i) = foo2(i)
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPunknown_function_call2 ------------
!CHECK-NEXT: unknown effect: {{.*}} fir.call @_QPfoo2(
!CHECK-NEXT: conflict: R/W: <unknown> W:<block argument> of type '!fir.box<!fir.array<?xf32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/region_assign1/rhs
!CHECK-NEXT: run 2 evaluate: forall/region_assign1

subroutine forall_mask_conflict(x)
  integer :: x(:)
  forall(i=1:10, x(11-i)>0) x(i) = 42
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPforall_mask_conflict ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?xi32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/forall_mask1/mask
!CHECK-NEXT: run 2 evaluate: forall/forall_mask1/region_assign1

subroutine forall_ub_conflict(x, y)
  integer :: x(:, :)
  forall(i=1:10)
    forall(j=1:x(i,i))
      x(i, j) = 42
    end forall
  end forall
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPforall_ub_conflict ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/forall1/ub
!CHECK-NEXT: run 2 evaluate: forall/forall1/region_assign1

subroutine sequential_assign(x, y)
  integer :: x(:), y(:)
  forall(i=1:10)
    x(i) = y(i)
    y(2*i) = x(i)
  end forall
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPsequential_assign ------------
!CHECK-NEXT: run 1 evaluate: forall/region_assign1
!CHECK-NEXT: run 2 evaluate: forall/region_assign2

subroutine loads_of_conlficts(x, y)
  integer, target :: x(:, :), y(:, :)
  forall(i=1:10)
    forall (j=1:y(i,i)) x(x(i, j), j) = y(i, j)
    forall (j=1:x(i,i), y(i,i)>0) y(x(i, j), j) = 0
  end forall
end subroutine
!CHECK-LABEL: ------------ scheduling forall in _QPloads_of_conlficts ------------
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/forall1/ub
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/forall1/region_assign1/rhs
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0
!CHECK-NEXT: run 1 save    : forall/forall1/region_assign1/lhs
!CHECK-NEXT: run 2 evaluate: forall/forall1/region_assign1
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1
!CHECK-NEXT: run 3 save    : forall/forall2/ub
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1
!CHECK-NEXT: run 3 save    : forall/forall2/forall_mask1/mask
!CHECK-NEXT: conflict: R/W: <block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 0 W:<block argument> of type '!fir.box<!fir.array<?x?xi32>>' at index: 1
!CHECK-NEXT: run 3 save    : forall/forall2/forall_mask1/region_assign1/lhs
!CHECK-NEXT: run 4 evaluate: forall/forall2/forall_mask1/region_assign1