diff options
Diffstat (limited to 'flang/test')
-rw-r--r-- | flang/test/Examples/omp-atomic.f90 | 6 | ||||
-rw-r--r-- | flang/test/Examples/omp-sections.f90 | 4 | ||||
-rw-r--r-- | flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 | 91 | ||||
-rw-r--r-- | flang/test/Lower/OpenACC/acc-atomic-capture.f90 | 28 | ||||
-rw-r--r-- | flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 | 267 | ||||
-rw-r--r-- | flang/test/Lower/OpenMP/unroll-heuristic01.f90 | 63 | ||||
-rw-r--r-- | flang/test/Lower/OpenMP/unroll-heuristic02.f90 | 98 | ||||
-rw-r--r-- | flang/test/Lower/OpenMP/unroll-heuristic03.f90 | 61 | ||||
-rw-r--r-- | flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 | 6 | ||||
-rw-r--r-- | flang/test/Parser/OpenMP/enter-automap-modifier.f90 | 16 | ||||
-rw-r--r-- | flang/test/Parser/OpenMP/sections.f90 | 144 | ||||
-rw-r--r-- | flang/test/Semantics/OpenACC/acc-atomic-validity.f90 | 69 | ||||
-rw-r--r-- | flang/test/Semantics/OpenACC/acc-default-none-function.f90 | 20 | ||||
-rw-r--r-- | flang/test/Semantics/assign02.f90 | 2 | ||||
-rw-r--r-- | flang/test/Semantics/bug1214.cuf | 49 | ||||
-rw-r--r-- | flang/test/Semantics/cuf11.cuf | 2 |
16 files changed, 791 insertions, 135 deletions
diff --git a/flang/test/Examples/omp-atomic.f90 b/flang/test/Examples/omp-atomic.f90 index 934f84f..5695b62 100644 --- a/flang/test/Examples/omp-atomic.f90 +++ b/flang/test/Examples/omp-atomic.f90 @@ -31,13 +31,13 @@ end ! CHECK-NEXT: - clause: read ! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: seq_cst -! CHECK-NEXT: details: 'name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' ! CHECK-NEXT: line: 12 ! CHECK-NEXT: construct: atomic ! CHECK-NEXT: clauses: ! CHECK-NEXT: - clause: seq_cst -! CHECK-NEXT: details: 'name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: write ! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' @@ -45,7 +45,7 @@ end ! CHECK-NEXT: construct: atomic ! CHECK-NEXT: clauses: ! CHECK-NEXT: - clause: capture -! CHECK-NEXT: details: 'name_modifier=atomic;name_modifier=atomic;' +! CHECK-NEXT: details: '' ! CHECK-NEXT: - clause: seq_cst ! CHECK-NEXT: details: '' ! CHECK-NEXT:- file: '{{[^"]*}}omp-atomic.f90' diff --git a/flang/test/Examples/omp-sections.f90 b/flang/test/Examples/omp-sections.f90 index 41e6e8f..a6d2806 100644 --- a/flang/test/Examples/omp-sections.f90 +++ b/flang/test/Examples/omp-sections.f90 @@ -13,11 +13,11 @@ subroutine omp_sections() end subroutine omp_sections !CHECK: - file: {{.*}} -!CHECK: line: 9 +!CHECK: line: 8 !CHECK: construct: section !CHECK: clauses: [] !CHECK: - file: {{.*}} -!CHECK: line: 11 +!CHECK: line: 10 !CHECK: construct: section !CHECK: clauses: [] !CHECK: - file: {{.*}} diff --git a/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 b/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 new file mode 100644 index 0000000..aa1d443 --- /dev/null +++ b/flang/test/Lower/OpenACC/Todo/do-loops-to-acc-loops-todo.f90 @@ -0,0 +1,91 @@ +! RUN: split-file %s %t +! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/do_loop_with_stop.f90 -o - 2>&1 | FileCheck %s --check-prefix=CHECK1 +! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/do_loop_with_cycle_goto.f90 -o - 2>&1 | FileCheck %s --check-prefix=CHECK2 +! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/nested_goto_loop.f90 -o - 2>&1 | FileCheck %s --check-prefix=CHECK3 +! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/nested_loop_with_inner_goto.f90 -o - 2>&1 | FileCheck %s --check-prefix=CHECK4 + +//--- do_loop_with_stop.f90 + +subroutine do_loop_with_stop() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + !$acc kernels + do i = 1, n + a(i) = b(i) + 1.0 + if (i == 5) stop + end do + !$acc end kernels + +! CHECK1: not yet implemented: unstructured do loop in acc kernels + +end subroutine + +//--- do_loop_with_cycle_goto.f90 + +subroutine do_loop_with_cycle_goto() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Do loop with cycle and goto - unstructured control flow is not converted. + !$acc kernels + do i = 1, n + if (i == 3) cycle + a(i) = b(i) + 1.0 + if (i == 7) goto 200 + a(i) = a(i) * 2.0 + end do +200 continue + !$acc end kernels + +! CHECK2: not yet implemented: unstructured do loop in acc kernels + +end subroutine + +//--- nested_goto_loop.f90 + +subroutine nested_goto_loop() + integer :: i, j + integer, parameter :: n = 10, m = 5 + real, dimension(n,m) :: a, b + + ! Nested loop with goto from inner to outer - should NOT convert to acc.loop + !$acc kernels + do i = 1, n + do j = 1, m + a(i,j) = b(i,j) + 1.0 + if (i * j > 20) goto 300 ! Exit both loops + end do + end do +300 continue + !$acc end kernels + +! CHECK3: not yet implemented: unstructured do loop in acc kernels + +end subroutine + +//--- nested_loop_with_inner_goto.f90 + +subroutine nested_loop_with_inner_goto() + integer :: ii = 0, jj = 0 + integer, parameter :: nn = 3 + real, dimension(nn, nn) :: aa + + aa = -1 + + ! Nested loop with goto from inner loop - unstructured control flow is not converted. + !$acc kernels + do ii = 1, nn + do jj = 1, nn + if (jj > 1) goto 300 + aa(jj, ii) = 1337 + end do + 300 continue + end do + !$acc end kernels + +! CHECK4: not yet implemented: unstructured do loop in acc kernels + +end subroutine
\ No newline at end of file diff --git a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 index ee38ab6..30e60e3 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-capture.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-capture.f90 @@ -123,17 +123,20 @@ end subroutine ! CHECK: } subroutine capture_with_convert_i32_to_f64() - real(8) :: x - integer :: v + real(8) :: x + integer :: v, u x = 1.0 v = 0 + u = 1 !$acc atomic capture v = x - x = v + x = u !$acc end atomic end subroutine capture_with_convert_i32_to_f64 ! CHECK-LABEL: func.func @_QPcapture_with_convert_i32_to_f64() +! CHECK: %[[U:.*]] = fir.alloca i32 {bindc_name = "u", uniq_name = "_QFcapture_with_convert_i32_to_f64Eu"} +! CHECK: %[[U_DECL:.*]]:2 = hlfir.declare %[[U]] {uniq_name = "_QFcapture_with_convert_i32_to_f64Eu"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[V:.*]] = fir.alloca i32 {bindc_name = "v", uniq_name = "_QFcapture_with_convert_i32_to_f64Ev"} ! CHECK: %[[V_DECL:.*]]:2 = hlfir.declare %[[V]] {uniq_name = "_QFcapture_with_convert_i32_to_f64Ev"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[X:.*]] = fir.alloca f64 {bindc_name = "x", uniq_name = "_QFcapture_with_convert_i32_to_f64Ex"} @@ -142,7 +145,9 @@ end subroutine capture_with_convert_i32_to_f64 ! CHECK: hlfir.assign %[[CST]] to %[[X_DECL]]#0 : f64, !fir.ref<f64> ! CHECK: %c0_i32 = arith.constant 0 : i32 ! CHECK: hlfir.assign %c0_i32 to %[[V_DECL]]#0 : i32, !fir.ref<i32> -! CHECK: %[[LOAD:.*]] = fir.load %[[V_DECL]]#0 : !fir.ref<i32> +! CHECK: %c1_i32 = arith.constant 1 : i32 +! CHECK: hlfir.assign %c1_i32 to %[[U_DECL]]#0 : i32, !fir.ref<i32> +! CHECK: %[[LOAD:.*]] = fir.load %[[U_DECL]]#0 : !fir.ref<i32> ! CHECK: %[[CONV:.*]] = fir.convert %[[LOAD]] : (i32) -> f64 ! CHECK: acc.atomic.capture { ! CHECK: acc.atomic.read %[[V_DECL]]#0 = %[[X_DECL]]#0 : !fir.ref<i32>, !fir.ref<f64>, f64 @@ -155,7 +160,7 @@ subroutine capture_with_convert_f64_to_i32() x = 1 v = 0 !$acc atomic capture - x = v * v + x = x * 2.0_8 v = x !$acc end atomic end subroutine capture_with_convert_f64_to_i32 @@ -167,15 +172,14 @@ end subroutine capture_with_convert_f64_to_i32 ! CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFcapture_with_convert_f64_to_i32Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %c1_i32 = arith.constant 1 : i32 ! CHECK: hlfir.assign %c1_i32 to %[[X_DECL]]#0 : i32, !fir.ref<i32> -! CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f64 -! CHECK: hlfir.assign %[[CST]] to %[[V_DECL]]#0 : f64, !fir.ref<f64> -! CHECK: %[[LOAD:.*]] = fir.load %[[V_DECL]]#0 : !fir.ref<f64> +! CHECK: %[[CST:.*]] = arith.constant 2.000000e+00 : f64 ! CHECK: acc.atomic.capture { ! CHECK: acc.atomic.update %[[X_DECL]]#0 : !fir.ref<i32> { -! CHECK: ^bb0(%arg0: i32): -! CHECK: %[[MUL:.*]] = arith.mulf %[[LOAD]], %[[LOAD]] fastmath<contract> : f64 -! CHECK: %[[CONV:.*]] = fir.convert %[[MUL]] : (f64) -> i32 -! CHECK: acc.yield %[[CONV]] : i32 +! CHECK: ^bb0(%[[ARG:.*]]: i32): +! CHECK: %[[CONV_ARG:.*]] = fir.convert %[[ARG]] : (i32) -> f64 +! CHECK: %[[MUL:.*]] = arith.mulf %[[CONV_ARG]], %[[CST]] fastmath<contract> : f64 +! CHECK: %[[CONV_MUL:.*]] = fir.convert %[[MUL]] : (f64) -> i32 +! CHECK: acc.yield %[[CONV_MUL]] : i32 ! CHECK: } ! CHECK: acc.atomic.read %[[V_DECL]]#0 = %[[X_DECL]]#0 : !fir.ref<f64>, !fir.ref<i32>, i32 ! CHECK: } diff --git a/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 b/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 new file mode 100644 index 0000000..5f8ea03 --- /dev/null +++ b/flang/test/Lower/OpenACC/do-loops-to-acc-loops.f90 @@ -0,0 +1,267 @@ +! This test checks lowering of Fortran do loops and do concurrent loops to OpenACC loop constructs. +! Tests the new functionality that converts Fortran iteration constructs to acc.loop with proper IV handling. + +! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPbasic_do_loop +subroutine basic_do_loop() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do loop that should be converted to acc.loop + !$acc kernels + do i = 1, n + a(i) = b(i) + 1.0 + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} + +end subroutine + +! CHECK-LABEL: func.func @_QPbasic_do_concurrent +subroutine basic_do_concurrent() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do concurrent loop + !$acc kernels + do concurrent (i = 1:n) + a(i) = b(i) + 1.0 + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} + +end subroutine + +! CHECK-LABEL: func.func @_QPbasic_do_loop_parallel +subroutine basic_do_loop_parallel() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do loop with acc parallel that should be converted to acc.loop + !$acc parallel + do i = 1, n + a(i) = b(i) + 1.0 + end do + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} + +end subroutine + +! CHECK-LABEL: func.func @_QPbasic_do_loop_serial +subroutine basic_do_loop_serial() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do loop with acc serial that should be converted to acc.loop + !$acc serial + do i = 1, n + a(i) = b(i) + 1.0 + end do + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} + +end subroutine + +! CHECK-LABEL: func.func @_QPbasic_do_concurrent_parallel +subroutine basic_do_concurrent_parallel() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do concurrent loop with acc parallel + !$acc parallel + do concurrent (i = 1:n) + a(i) = b(i) + 1.0 + end do + !$acc end parallel + +! CHECK: acc.parallel { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} + +end subroutine + +! CHECK-LABEL: func.func @_QPbasic_do_concurrent_serial +subroutine basic_do_concurrent_serial() + integer :: i + integer, parameter :: n = 10 + real, dimension(n) :: a, b + + ! Basic do concurrent loop with acc serial + !$acc serial + do concurrent (i = 1:n) + a(i) = b(i) + 1.0 + end do + !$acc end serial + +! CHECK: acc.serial { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} + +end subroutine + +! CHECK-LABEL: func.func @_QPmulti_dimension_do_concurrent +subroutine multi_dimension_do_concurrent() + integer :: i, j, k + integer, parameter :: n = 10, m = 20, l = 5 + real, dimension(n,m,l) :: a, b + + ! Multi-dimensional do concurrent with multiple iteration variables + !$acc kernels + do concurrent (i = 1:n, j = 1:m, k = 1:l) + a(i,j,k) = b(i,j,k) * 2.0 + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%{{.*}}, %{{.*}}, %{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true, true, true>} +end subroutine + + +! CHECK-LABEL: func.func @_QPnested_do_loops +subroutine nested_do_loops() + integer :: i, j + integer, parameter :: n = 10, m = 20 + real, dimension(n,m) :: a, b + + ! Nested do loops + !$acc kernels + do i = 1, n + do j = 1, m + a(i,j) = b(i,j) + i + j + end do + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} + +end subroutine + +! CHECK-LABEL: func.func @_QPvariable_bounds_and_step +subroutine variable_bounds_and_step(n, start_val, step_val) + integer, intent(in) :: n, start_val, step_val + integer :: i + real, dimension(n) :: a, b + + ! Do loop with variable bounds and step + !$acc kernels + do i = start_val, n, step_val + a(i) = b(i) * 2.0 + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.yield +! CHECK: attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} + +end subroutine + +! CHECK-LABEL: func.func @_QPdifferent_iv_types +subroutine different_iv_types() + integer(kind=8) :: i8 + integer(kind=4) :: i4 + integer(kind=2) :: i2 + integer, parameter :: n = 10 + real, dimension(n) :: a, b, c, d + + ! Test different iteration variable types + !$acc kernels + do i8 = 1_8, int(n,8) + a(i8) = b(i8) + 1.0 + end do + !$acc end kernels + + !$acc kernels + do i4 = 1, n + b(i4) = c(i4) + 1.0 + end do + !$acc end kernels + + !$acc kernels + do i2 = 1_2, int(n,2) + c(i2) = d(i2) + 1.0 + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i64) = (%{{.*}} : i64) to (%{{.*}} : i64) step (%{{.*}} : i64) +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) +! CHECK: acc.kernels { +! CHECK: acc.loop {{.*}} control(%{{.*}} : i16) = (%{{.*}} : i16) to (%{{.*}} : i16) step (%{{.*}} : i16) + +end subroutine + +! ----------------------------------------------------------------------------------------- +! Tests for loops that should NOT be converted to acc.loop due to unstructured control flow + +! CHECK-LABEL: func.func @_QPinfinite_loop_no_iv +subroutine infinite_loop_no_iv() + integer :: i + logical :: condition + + ! Infinite loop with no induction variable - should NOT convert to acc.loop + !$acc kernels + do + i = i + 1 + if (i > 100) exit + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK-NOT: acc.loop + +end subroutine + +! CHECK-LABEL: func.func @_QPwhile_like_loop +subroutine while_like_loop() + integer :: i + logical :: condition + + i = 1 + condition = .true. + + ! While-like infinite loop - should NOT convert to acc.loop + !$acc kernels + do while (condition) + i = i + 1 + if (i > 100) condition = .false. + end do + !$acc end kernels + +! CHECK: acc.kernels { +! CHECK-NOT: acc.loop + +end subroutine diff --git a/flang/test/Lower/OpenMP/unroll-heuristic01.f90 b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 index a5f5c00..34020eb 100644 --- a/flang/test/Lower/OpenMP/unroll-heuristic01.f90 +++ b/flang/test/Lower/OpenMP/unroll-heuristic01.f90 @@ -13,27 +13,42 @@ subroutine omp_unroll_heuristic01(lb, ub, inc) end subroutine omp_unroll_heuristic01 -!CHECK-LABEL: func.func @_QPomp_unroll_heuristic01( -!CHECK: %c0_i32 = arith.constant 0 : i32 -!CHECK-NEXT: %c1_i32 = arith.constant 1 : i32 -!CHECK-NEXT: %13 = arith.cmpi slt, %12, %c0_i32 : i32 -!CHECK-NEXT: %14 = arith.subi %c0_i32, %12 : i32 -!CHECK-NEXT: %15 = arith.select %13, %14, %12 : i32 -!CHECK-NEXT: %16 = arith.select %13, %11, %10 : i32 -!CHECK-NEXT: %17 = arith.select %13, %10, %11 : i32 -!CHECK-NEXT: %18 = arith.subi %17, %16 overflow<nuw> : i32 -!CHECK-NEXT: %19 = arith.divui %18, %15 : i32 -!CHECK-NEXT: %20 = arith.addi %19, %c1_i32 overflow<nuw> : i32 -!CHECK-NEXT: %21 = arith.cmpi slt, %17, %16 : i32 -!CHECK-NEXT: %22 = arith.select %21, %c0_i32, %20 : i32 -!CHECK-NEXT: %canonloop_s0 = omp.new_cli -!CHECK-NEXT: omp.canonical_loop(%canonloop_s0) %iv : i32 in range(%22) { -!CHECK-NEXT: %23 = arith.muli %iv, %12 : i32 -!CHECK-NEXT: %24 = arith.addi %10, %23 : i32 -!CHECK-NEXT: hlfir.assign %24 to %9#0 : i32, !fir.ref<i32> -!CHECK-NEXT: %25 = fir.load %9#0 : !fir.ref<i32> -!CHECK-NEXT: hlfir.assign %25 to %6#0 : i32, !fir.ref<i32> -!CHECK-NEXT: omp.terminator -!CHECK-NEXT: } -!CHECK-NEXT: omp.unroll_heuristic(%canonloop_s0) -!CHECK-NEXT: return +! CHECK-LABEL: func.func @_QPomp_unroll_heuristic01( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "lb"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "ub"}, +! CHECK-SAME: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "inc"}) { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic01Ei"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic01Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic01Eres"} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_unroll_heuristic01Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic01Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.cmpi slt, %[[VAL_10]], %[[VAL_11]] : i32 +! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_11]], %[[VAL_10]] : i32 +! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_13]], %[[VAL_14]], %[[VAL_10]] : i32 +! CHECK: %[[VAL_16:.*]] = arith.select %[[VAL_13]], %[[VAL_9]], %[[VAL_8]] : i32 +! CHECK: %[[VAL_17:.*]] = arith.select %[[VAL_13]], %[[VAL_8]], %[[VAL_9]] : i32 +! CHECK: %[[VAL_18:.*]] = arith.subi %[[VAL_17]], %[[VAL_16]] overflow<nuw> : i32 +! CHECK: %[[VAL_19:.*]] = arith.divui %[[VAL_18]], %[[VAL_15]] : i32 +! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_19]], %[[VAL_12]] overflow<nuw> : i32 +! CHECK: %[[VAL_21:.*]] = arith.cmpi slt, %[[VAL_17]], %[[VAL_16]] : i32 +! CHECK: %[[VAL_22:.*]] = arith.select %[[VAL_21]], %[[VAL_11]], %[[VAL_20]] : i32 +! CHECK: %[[VAL_23:.*]] = omp.new_cli +! CHECK: omp.canonical_loop(%[[VAL_23]]) %[[VAL_24:.*]] : i32 in range(%[[VAL_22]]) { +! CHECK: %[[VAL_25:.*]] = arith.muli %[[VAL_24]], %[[VAL_10]] : i32 +! CHECK: %[[VAL_26:.*]] = arith.addi %[[VAL_8]], %[[VAL_25]] : i32 +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_2]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_27]] to %[[VAL_6]]#0 : i32, !fir.ref<i32> +! CHECK: omp.terminator +! CHECK: } +! CHECK: omp.unroll_heuristic(%[[VAL_23]]) +! CHECK: return +! CHECK: }
\ No newline at end of file diff --git a/flang/test/Lower/OpenMP/unroll-heuristic02.f90 b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 index 14f694d..fdb1366 100644 --- a/flang/test/Lower/OpenMP/unroll-heuristic02.f90 +++ b/flang/test/Lower/OpenMP/unroll-heuristic02.f90 @@ -37,61 +37,55 @@ end subroutine omp_unroll_heuristic_nested02 !CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eouter_ub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[VAL_11:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} !CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFomp_unroll_heuristic_nested02Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_13:.*]] = fir.alloca i32 {bindc_name = "i", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} -!CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_15:.*]] = fir.alloca i32 {bindc_name = "j", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} -!CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_20:.*]] = arith.constant 0 : i32 -!CHECK: %[[VAL_21:.*]] = arith.constant 1 : i32 -!CHECK: %[[VAL_22:.*]] = arith.cmpi slt, %[[VAL_19]], %[[VAL_20]] : i32 -!CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_20]], %[[VAL_19]] : i32 -!CHECK: %[[VAL_24:.*]] = arith.select %[[VAL_22]], %[[VAL_23]], %[[VAL_19]] : i32 -!CHECK: %[[VAL_25:.*]] = arith.select %[[VAL_22]], %[[VAL_18]], %[[VAL_17]] : i32 -!CHECK: %[[VAL_26:.*]] = arith.select %[[VAL_22]], %[[VAL_17]], %[[VAL_18]] : i32 -!CHECK: %[[VAL_27:.*]] = arith.subi %[[VAL_26]], %[[VAL_25]] overflow<nuw> : i32 -!CHECK: %[[VAL_28:.*]] = arith.divui %[[VAL_27]], %[[VAL_24]] : i32 -!CHECK: %[[VAL_29:.*]] = arith.addi %[[VAL_28]], %[[VAL_21]] overflow<nuw> : i32 -!CHECK: %[[VAL_30:.*]] = arith.cmpi slt, %[[VAL_26]], %[[VAL_25]] : i32 -!CHECK: %[[VAL_31:.*]] = arith.select %[[VAL_30]], %[[VAL_20]], %[[VAL_29]] : i32 -!CHECK: %[[VAL_32:.*]] = omp.new_cli -!CHECK: omp.canonical_loop(%[[VAL_32]]) %[[VAL_33:.*]] : i32 in range(%[[VAL_31]]) { -!CHECK: %[[VAL_34:.*]] = arith.muli %[[VAL_33]], %[[VAL_19]] : i32 -!CHECK: %[[VAL_35:.*]] = arith.addi %[[VAL_17]], %[[VAL_34]] : i32 -!CHECK: hlfir.assign %[[VAL_35]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> -!CHECK: %[[VAL_36:.*]] = fir.alloca i32 {bindc_name = "j", pinned, uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} -!CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_36]] {uniq_name = "_QFomp_unroll_heuristic_nested02Ej"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_41:.*]] = arith.constant 0 : i32 -!CHECK: %[[VAL_42:.*]] = arith.constant 1 : i32 -!CHECK: %[[VAL_43:.*]] = arith.cmpi slt, %[[VAL_40]], %[[VAL_41]] : i32 -!CHECK: %[[VAL_44:.*]] = arith.subi %[[VAL_41]], %[[VAL_40]] : i32 -!CHECK: %[[VAL_45:.*]] = arith.select %[[VAL_43]], %[[VAL_44]], %[[VAL_40]] : i32 -!CHECK: %[[VAL_46:.*]] = arith.select %[[VAL_43]], %[[VAL_39]], %[[VAL_38]] : i32 -!CHECK: %[[VAL_47:.*]] = arith.select %[[VAL_43]], %[[VAL_38]], %[[VAL_39]] : i32 -!CHECK: %[[VAL_48:.*]] = arith.subi %[[VAL_47]], %[[VAL_46]] overflow<nuw> : i32 -!CHECK: %[[VAL_49:.*]] = arith.divui %[[VAL_48]], %[[VAL_45]] : i32 -!CHECK: %[[VAL_50:.*]] = arith.addi %[[VAL_49]], %[[VAL_42]] overflow<nuw> : i32 -!CHECK: %[[VAL_51:.*]] = arith.cmpi slt, %[[VAL_47]], %[[VAL_46]] : i32 -!CHECK: %[[VAL_52:.*]] = arith.select %[[VAL_51]], %[[VAL_41]], %[[VAL_50]] : i32 -!CHECK: %[[VAL_53:.*]] = omp.new_cli -!CHECK: omp.canonical_loop(%[[VAL_53]]) %[[VAL_54:.*]] : i32 in range(%[[VAL_52]]) { -!CHECK: %[[VAL_55:.*]] = arith.muli %[[VAL_54]], %[[VAL_40]] : i32 -!CHECK: %[[VAL_56:.*]] = arith.addi %[[VAL_38]], %[[VAL_55]] : i32 -!CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_37]]#0 : i32, !fir.ref<i32> -!CHECK: %[[VAL_57:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_58:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref<i32> -!CHECK: %[[VAL_59:.*]] = arith.addi %[[VAL_57]], %[[VAL_58]] : i32 -!CHECK: hlfir.assign %[[VAL_59]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +!CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_16:.*]] = arith.constant 0 : i32 +!CHECK: %[[VAL_17:.*]] = arith.constant 1 : i32 +!CHECK: %[[VAL_18:.*]] = arith.cmpi slt, %[[VAL_15]], %[[VAL_16]] : i32 +!CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_16]], %[[VAL_15]] : i32 +!CHECK: %[[VAL_20:.*]] = arith.select %[[VAL_18]], %[[VAL_19]], %[[VAL_15]] : i32 +!CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_18]], %[[VAL_14]], %[[VAL_13]] : i32 +!CHECK: %[[VAL_22:.*]] = arith.select %[[VAL_18]], %[[VAL_13]], %[[VAL_14]] : i32 +!CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_22]], %[[VAL_21]] overflow<nuw> : i32 +!CHECK: %[[VAL_24:.*]] = arith.divui %[[VAL_23]], %[[VAL_20]] : i32 +!CHECK: %[[VAL_25:.*]] = arith.addi %[[VAL_24]], %[[VAL_17]] overflow<nuw> : i32 +!CHECK: %[[VAL_26:.*]] = arith.cmpi slt, %[[VAL_22]], %[[VAL_21]] : i32 +!CHECK: %[[VAL_27:.*]] = arith.select %[[VAL_26]], %[[VAL_16]], %[[VAL_25]] : i32 +!CHECK: %[[VAL_28:.*]] = omp.new_cli +!CHECK: omp.canonical_loop(%[[VAL_28]]) %[[VAL_29:.*]] : i32 in range(%[[VAL_27]]) { +!CHECK: %[[VAL_30:.*]] = arith.muli %[[VAL_29]], %[[VAL_15]] : i32 +!CHECK: %[[VAL_31:.*]] = arith.addi %[[VAL_13]], %[[VAL_30]] : i32 +!CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_2]]#0 : i32, !fir.ref<i32> +!CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_33:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_35:.*]] = arith.constant 0 : i32 +!CHECK: %[[VAL_36:.*]] = arith.constant 1 : i32 +!CHECK: %[[VAL_37:.*]] = arith.cmpi slt, %[[VAL_34]], %[[VAL_35]] : i32 +!CHECK: %[[VAL_38:.*]] = arith.subi %[[VAL_35]], %[[VAL_34]] : i32 +!CHECK: %[[VAL_39:.*]] = arith.select %[[VAL_37]], %[[VAL_38]], %[[VAL_34]] : i32 +!CHECK: %[[VAL_40:.*]] = arith.select %[[VAL_37]], %[[VAL_33]], %[[VAL_32]] : i32 +!CHECK: %[[VAL_41:.*]] = arith.select %[[VAL_37]], %[[VAL_32]], %[[VAL_33]] : i32 +!CHECK: %[[VAL_42:.*]] = arith.subi %[[VAL_41]], %[[VAL_40]] overflow<nuw> : i32 +!CHECK: %[[VAL_43:.*]] = arith.divui %[[VAL_42]], %[[VAL_39]] : i32 +!CHECK: %[[VAL_44:.*]] = arith.addi %[[VAL_43]], %[[VAL_36]] overflow<nuw> : i32 +!CHECK: %[[VAL_45:.*]] = arith.cmpi slt, %[[VAL_41]], %[[VAL_40]] : i32 +!CHECK: %[[VAL_46:.*]] = arith.select %[[VAL_45]], %[[VAL_35]], %[[VAL_44]] : i32 +!CHECK: %[[VAL_47:.*]] = omp.new_cli +!CHECK: omp.canonical_loop(%[[VAL_47]]) %[[VAL_48:.*]] : i32 in range(%[[VAL_46]]) { +!CHECK: %[[VAL_49:.*]] = arith.muli %[[VAL_48]], %[[VAL_34]] : i32 +!CHECK: %[[VAL_50:.*]] = arith.addi %[[VAL_32]], %[[VAL_49]] : i32 +!CHECK: hlfir.assign %[[VAL_50]] to %[[VAL_7]]#0 : i32, !fir.ref<i32> +!CHECK: %[[VAL_51:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +!CHECK: %[[VAL_53:.*]] = arith.addi %[[VAL_51]], %[[VAL_52]] : i32 +!CHECK: hlfir.assign %[[VAL_53]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> !CHECK: omp.terminator !CHECK: } -!CHECK: omp.unroll_heuristic(%[[VAL_53]]) +!CHECK: omp.unroll_heuristic(%[[VAL_47]]) !CHECK: omp.terminator !CHECK: } -!CHECK: omp.unroll_heuristic(%[[VAL_32]]) +!CHECK: omp.unroll_heuristic(%[[VAL_28]]) !CHECK: return !CHECK: } diff --git a/flang/test/Lower/OpenMP/unroll-heuristic03.f90 b/flang/test/Lower/OpenMP/unroll-heuristic03.f90 new file mode 100644 index 0000000..308c149 --- /dev/null +++ b/flang/test/Lower/OpenMP/unroll-heuristic03.f90 @@ -0,0 +1,61 @@ +! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s + +! Test implicitly privatized loop variable that is affected by unrolling. + +subroutine omp_unroll_heuristic03(lb, ub, inc) + integer res, i, lb, ub, inc + + !$omp parallel + !$omp unroll + do i = lb, ub, inc + res = i + end do + !$omp end unroll + !$omp end parallel + +end subroutine omp_unroll_heuristic03 + + +! CHECK-LABEL: func.func @_QPomp_unroll_heuristic03( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<i32> {fir.bindc_name = "lb"}, +! CHECK-SAME: %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "ub"}, +! CHECK-SAME: %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "inc"}) { +! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_unroll_heuristic03Ei"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFomp_unroll_heuristic03Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Einc"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Elb"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFomp_unroll_heuristic03Eres"} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFomp_unroll_heuristic03Eres"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %[[VAL_0]] {uniq_name = "_QFomp_unroll_heuristic03Eub"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: omp.parallel private(@_QFomp_unroll_heuristic03Ei_private_i32 %[[VAL_2]]#0 -> %[[VAL_8:.*]] : !fir.ref<i32>) { +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFomp_unroll_heuristic03Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_15:.*]] = arith.cmpi slt, %[[VAL_12]], %[[VAL_13]] : i32 +! CHECK: %[[VAL_16:.*]] = arith.subi %[[VAL_13]], %[[VAL_12]] : i32 +! CHECK: %[[VAL_17:.*]] = arith.select %[[VAL_15]], %[[VAL_16]], %[[VAL_12]] : i32 +! CHECK: %[[VAL_18:.*]] = arith.select %[[VAL_15]], %[[VAL_11]], %[[VAL_10]] : i32 +! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_15]], %[[VAL_10]], %[[VAL_11]] : i32 +! CHECK: %[[VAL_20:.*]] = arith.subi %[[VAL_19]], %[[VAL_18]] overflow<nuw> : i32 +! CHECK: %[[VAL_21:.*]] = arith.divui %[[VAL_20]], %[[VAL_17]] : i32 +! CHECK: %[[VAL_22:.*]] = arith.addi %[[VAL_21]], %[[VAL_14]] overflow<nuw> : i32 +! CHECK: %[[VAL_23:.*]] = arith.cmpi slt, %[[VAL_19]], %[[VAL_18]] : i32 +! CHECK: %[[VAL_24:.*]] = arith.select %[[VAL_23]], %[[VAL_13]], %[[VAL_22]] : i32 +! CHECK: %[[VAL_25:.*]] = omp.new_cli +! CHECK: omp.canonical_loop(%[[VAL_25]]) %[[VAL_26:.*]] : i32 in range(%[[VAL_24]]) { +! CHECK: %[[VAL_27:.*]] = arith.muli %[[VAL_26]], %[[VAL_12]] : i32 +! CHECK: %[[VAL_28:.*]] = arith.addi %[[VAL_10]], %[[VAL_27]] : i32 +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_9]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_29]] to %[[VAL_6]]#0 : i32, !fir.ref<i32> +! CHECK: omp.terminator +! CHECK: } +! CHECK: omp.unroll_heuristic(%[[VAL_25]]) +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: }
\ No newline at end of file diff --git a/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 index df85942..916bd66 100644 --- a/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 +++ b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 @@ -15,7 +15,8 @@ module functions contains function func1() result(i) !$omp declare target enter(func1) indirect(.true.) - !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func1' + !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpEnterClause + !CHECK-NEXT: | | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func1' !CHECK-NEXT: | | | | | OmpClause -> Indirect -> OmpIndirectClause -> Scalar -> Logical -> Expr = '.true._4' !CHECK-NEXT: | | | | | | LiteralConstant -> LogicalLiteralConstant !CHECK-NEXT: | | | | | | | bool = 'true' @@ -26,7 +27,8 @@ contains function func2() result(i) !$omp declare target enter(func2) indirect - !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func2' + !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpEnterClause + !CHECK-NEXT: | | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func2' !CHECK-NEXT: | | | | | OmpClause -> Indirect -> OmpIndirectClause -> character(1) :: i i = 'b' diff --git a/flang/test/Parser/OpenMP/enter-automap-modifier.f90 b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 new file mode 100644 index 0000000..1f361ca5 --- /dev/null +++ b/flang/test/Parser/OpenMP/enter-automap-modifier.f90 @@ -0,0 +1,16 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck %s --check-prefix=UNPARSE +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck %s --check-prefix=PARSE-TREE + +program automap + integer :: x + !$omp declare target enter(automap: x) +end program + +!UNPARSE: PROGRAM AUTOMAP +!UNPARSE: INTEGER x +!UNPARSE: !$OMP DECLARE TARGET ENTER(AUTOMAP: x) +!UNPARSE: END PROGRAM + +!PARSE-TREE: OmpClauseList -> OmpClause -> Enter -> OmpEnterClause +!PARSE-TREE-NEXT: | Modifier -> OmpAutomapModifier -> Value = Automap +!PARSE-TREE-NEXT: | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' diff --git a/flang/test/Parser/OpenMP/sections.f90 b/flang/test/Parser/OpenMP/sections.f90 index 3752cef..8ba2294 100644 --- a/flang/test/Parser/OpenMP/sections.f90 +++ b/flang/test/Parser/OpenMP/sections.f90 @@ -10,32 +10,41 @@ subroutine openmp_sections(x, y) !============================================================================== !CHECK: !$omp sections !$omp sections - !CHECK: !$omp section !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | Block +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! single section, without `!$omp section` !============================================================================== !CHECK: !$omp sections !$omp sections - !CHECK: !$omp section !CHECK: CALL call F1() !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! single section with `!$omp section` @@ -49,12 +58,22 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! multiple sections @@ -76,16 +95,40 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections !$omp end sections -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> !============================================================================== ! multiple sections with clauses @@ -107,15 +150,40 @@ subroutine openmp_sections(x, y) !CHECK: !$omp end sections NOWAIT !$omp end sections NOWAIT -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct -!PARSE-TREE: OmpBeginSectionsDirective -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block -!PARSE-TREE: CallStmt -!PARSE-TREE-NOT: ExecutionPartConstruct -!PARSE-TREE: OmpEndSectionsDirective +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: | OmpBeginSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | OmpClause -> Firstprivate -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2' +!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: | | | Flags = None +!PARSE-TREE: | | Block +!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()' +!PARSE-TREE: | | | | Call +!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3' +!PARSE-TREE: | OmpEndSectionsDirective +!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait END subroutine openmp_sections diff --git a/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 index 07fb864..5c8d33f 100644 --- a/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-atomic-validity.f90 @@ -54,11 +54,38 @@ program openacc_atomic_validity i = c(i) !$acc end atomic + !TODO: Should error because c(i) references i which is the atomic update variable. !$acc atomic capture c(i) = i i = i + 1 !$acc end atomic + !ERROR: The variables assigned in this atomic capture construct must be distinct + !$acc atomic capture + c(1) = c(2) + c(1) = c(3) + !$acc end atomic + + !ERROR: The assignments in this atomic capture construct do not update a variable and capture either its initial or final value + !$acc atomic capture + c(1) = c(2) + c(2) = c(2) + !$acc end atomic + + !ERROR: The assignments in this atomic capture construct do not update a variable and capture either its initial or final value + !$acc atomic capture + c(1) = c(2) + c(2) = c(1) + !$acc end atomic + + !ERROR: The assignments in this atomic capture construct do not update a variable and capture either its initial or final value + !$acc atomic capture + c(1) = c(2) + c(3) = c(2) + !$acc end atomic + + + !$acc atomic capture if(l .EQV. .false.) c(i) = i i = i + 1 @@ -79,3 +106,45 @@ program openacc_atomic_validity !$acc end parallel end program openacc_atomic_validity + +subroutine capture_with_convert_f64_to_i32() + integer :: x + real(8) :: v, w + x = 1 + v = 0 + w = 2 + + !$acc atomic capture + x = x * 2.5_8 + v = x + !$acc end atomic + + !$acc atomic capture + !TODO: The rhs side of this update statement cannot reference v. + x = x * v + v = x + !$acc end atomic + + !$acc atomic capture + !TODO: The rhs side of this update statement cannot reference v. + x = v * x + v = x + !$acc end atomic + + !$acc atomic capture + !ERROR: The RHS of this atomic update statement must reference the updated variable: x + x = v * v + v = x + !$acc end atomic + + !$acc atomic capture + x = v + !ERROR: The updated variable, v, cannot appear more than once in the atomic update operation + v = v * v + !$acc end atomic + + !$acc atomic capture + v = x + x = w * w + !$acc end atomic +end subroutine capture_with_convert_f64_to_i32
\ No newline at end of file diff --git a/flang/test/Semantics/OpenACC/acc-default-none-function.f90 b/flang/test/Semantics/OpenACC/acc-default-none-function.f90 new file mode 100644 index 0000000..f0a697f --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-default-none-function.f90 @@ -0,0 +1,20 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc -pedantic + +module mm_acc_rout_function +contains + integer function dosomething(res) + !$acc routine seq + integer :: res + dosomething = res + 1 + end function +end module + +program main + use mm_acc_rout_function + implicit none + integer :: res = 1 + !$acc serial default(none) copy(res) + res = dosomething(res) + !$acc end serial +end program + diff --git a/flang/test/Semantics/assign02.f90 b/flang/test/Semantics/assign02.f90 index f998197..c447078 100644 --- a/flang/test/Semantics/assign02.f90 +++ b/flang/test/Semantics/assign02.f90 @@ -139,7 +139,7 @@ contains real, target :: x real, pointer :: p p => f1() - !ERROR: pointer 'p' is associated with the result of a reference to function 'f2' that is a not a pointer + !ERROR: pointer 'p' is associated with the result of a reference to function 'f2' that is not a pointer p => f2() contains function f1() diff --git a/flang/test/Semantics/bug1214.cuf b/flang/test/Semantics/bug1214.cuf new file mode 100644 index 0000000..114fad1 --- /dev/null +++ b/flang/test/Semantics/bug1214.cuf @@ -0,0 +1,49 @@ +! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +module overrides + type realResult + real a + end type + interface operator(*) + procedure :: multHostDevice, multDeviceHost + end interface + interface assignment(=) + procedure :: assignHostResult, assignDeviceResult + end interface + contains + elemental function multHostDevice(x, y) result(result) + real, intent(in) :: x + real, intent(in), device :: y + type(realResult) result + result%a = x * y + end + elemental function multDeviceHost(x, y) result(result) + real, intent(in), device :: x + real, intent(in) :: y + type(realResult) result + result%a = x * y + end + elemental subroutine assignHostResult(lhs, rhs) + real, intent(out) :: lhs + type(realResult), intent(in) :: rhs + lhs = rhs%a + end + elemental subroutine assignDeviceResult(lhs, rhs) + real, intent(out), device :: lhs + type(realResult), intent(in) :: rhs + lhs = rhs%a + end +end + +program p + use overrides + real, device :: da, db + real :: ha, hb +!CHECK: CALL assigndeviceresult(db,multhostdevice(2._4,da)) + db = 2. * da +!CHECK: CALL assigndeviceresult(db,multdevicehost(da,2._4)) + db = da * 2. +!CHECK: CALL assignhostresult(ha,multhostdevice(2._4,da)) + ha = 2. * da +!CHECK: CALL assignhostresult(ha,multdevicehost(da,2._4)) + ha = da * 2. +end diff --git a/flang/test/Semantics/cuf11.cuf b/flang/test/Semantics/cuf11.cuf index 554ac25..1f5beb0 100644 --- a/flang/test/Semantics/cuf11.cuf +++ b/flang/test/Semantics/cuf11.cuf @@ -16,7 +16,7 @@ subroutine sub1() real, device :: adev(10), bdev(10) real :: ahost(10) -!ERROR: More than one reference to a CUDA object on the right hand side of the assigment +!ERROR: More than one reference to a CUDA object on the right hand side of the assignment ahost = adev + bdev ahost = adev + adev |