| subroutine if_then(a, l) | |
| integer :: a(4) | |
| logical :: l | |
| integer :: x | |
| if (l) x = 1 | |
| a = 11 | |
| end subroutine | |
| subroutine if_else(a, b, l) | |
| integer :: a(4), b(4) | |
| logical :: l | |
| integer :: x | |
| if (l) then | |
| x = 1 | |
| else | |
| x = 2 | |
| end if | |
| a = 11 | |
| b = a + x | |
| end subroutine | |
| subroutine computed_goto(a, k) | |
| integer :: a(4), k | |
| goto (10,20), k | |
| a = 33 | |
| return | |
| 10 a = 11 | |
| return | |
| 20 a = 22 | |
| end subroutine | |
| ! Expand assignments explicitly to exercise the O0 pipeline independently of | |
| ! which HLFIR expansions are enabled by default. | |
| ! RUN: %flang_fc1 -emit-hlfir -mmlir --mlir-print-debuginfo -o - %s | fir-opt --inline-elementals --inline-hlfir-assign --mlir-print-debuginfo -o %t.fir && %flang_fc1 -O0 -debug-info-kind=line-tables-only -emit-llvm %t.fir -o - | FileCheck %s | |
| ! Every path to an expanded assignment must go through its entry branch. | |
| ! In particular, keeping only the conditional edge is insufficient: the | |
| ! unconditional edge from the THEN arm must also go through the preheader. | |
| ! CHECK-LABEL: define void @if_then_( | |
| ! CHECK: br i1 {{.*}}, label %[[THEN:[0-9]+]], label %[[ENTRY:[0-9]+]] | |
| ! CHECK: [[THEN]]: | |
| ! CHECK: store i32 1, | |
| ! CHECK-NEXT: br label %[[ENTRY]], | |
| ! CHECK: [[ENTRY]]: | |
| ! CHECK-NEXT: br label %[[HEADER:[0-9]+]], !dbg ![[THEN_LOC:[0-9]+]] | |
| ! CHECK: [[HEADER]]: | |
| ! CHECK-NEXT: {{.*}} = phi i64 {{.*}}[ 1, %[[ENTRY]] ] | |
| ! Both arms must converge before initializing the loop PHIs. Merely finding | |
| ! one branch with the assignment location misses a breakpoint on the other arm. | |
| ! CHECK-LABEL: define void @if_else_( | |
| ! CHECK: br i1 {{.*}}, label %[[THEN:[0-9]+]], label %[[ELSE:[0-9]+]] | |
| ! CHECK: [[THEN]]: | |
| ! CHECK: store i32 1, | |
| ! CHECK-NEXT: br label %[[ENTRY:[0-9]+]], | |
| ! CHECK: [[ELSE]]: | |
| ! CHECK: store i32 2, | |
| ! CHECK-NEXT: br label %[[ENTRY]], | |
| ! CHECK: [[ENTRY]]: | |
| ! CHECK-NEXT: br label %[[HEADER:[0-9]+]], !dbg ![[ELSE_LOC:[0-9]+]] | |
| ! CHECK: [[HEADER]]: | |
| ! CHECK-NEXT: {{.*}} = phi i64 {{.*}}[ 1, %[[ENTRY]] ] | |
| ! A computed GOTO lowers to cf.switch. Check both case destinations and the | |
| ! default destination: none may skip the corresponding assignment preheader. | |
| ! CHECK-LABEL: define void @computed_goto_( | |
| ! CHECK: switch i64 {{.*}}, label %[[DEFAULT:[0-9]+]] [ | |
| ! CHECK-NEXT: i64 1, label %[[CASE1:[0-9]+]] | |
| ! CHECK-NEXT: i64 2, label %[[CASE2:[0-9]+]] | |
| ! CHECK: [[DEFAULT]]: | |
| ! CHECK-NEXT: br label %[[HEADER:[0-9]+]], !dbg ![[DEFAULT_LOC:[0-9]+]] | |
| ! CHECK: [[HEADER]]: | |
| ! CHECK-NEXT: {{.*}} = phi i64 {{.*}}[ 1, %[[DEFAULT]] ] | |
| ! CHECK: [[CASE1]]: | |
| ! CHECK-NEXT: br label %[[HEADER:[0-9]+]], !dbg ![[CASE1_LOC:[0-9]+]] | |
| ! CHECK: [[HEADER]]: | |
| ! CHECK-NEXT: {{.*}} = phi i64 {{.*}}[ 1, %[[CASE1]] ] | |
| ! CHECK: [[CASE2]]: | |
| ! CHECK-NEXT: br label %[[HEADER:[0-9]+]], !dbg ![[CASE2_LOC:[0-9]+]] | |
| ! CHECK: [[HEADER]]: | |
| ! CHECK-NEXT: {{.*}} = phi i64 {{.*}}[ 1, %[[CASE2]] ] | |
| ! CHECK-DAG: ![[THEN_LOC]] = !DILocation(line: 6, column: 3, | |
| ! CHECK-DAG: ![[ELSE_LOC]] = !DILocation(line: 18, column: 3, | |
| ! CHECK-DAG: ![[DEFAULT_LOC]] = !DILocation(line: 25, column: 3, | |
| ! CHECK-DAG: ![[CASE1_LOC]] = !DILocation(line: 27, column: 1, | |
| ! CHECK-DAG: ![[CASE2_LOC]] = !DILocation(line: 29, column: 1, |