[flang-commits] [flang] a3c05df - [flang] Fix invalid branch optimization

V Donaldson via flang-commits flang-commits at lists.llvm.org
Sun Sep 11 19:38:10 PDT 2022


Author: V Donaldson
Date: 2022-09-11T19:37:32-07:00
New Revision: a3c05df16bc66d8ac84c1b10a74f59b12eb25a94

URL: https://github.com/llvm/llvm-project/commit/a3c05df16bc66d8ac84c1b10a74f59b12eb25a94
DIFF: https://github.com/llvm/llvm-project/commit/a3c05df16bc66d8ac84c1b10a74f59b12eb25a94.diff

LOG: [flang] Fix invalid branch optimization

Branch optimization in function rewriteIfGotos attempts to rewrite code
such as

    <<IfConstruct>>
      1 If[Then]Stmt: if(cond) goto L
      2 GotoStmt: goto L
      3 EndIfStmt
    <<End IfConstruct>>
    4 Statement: ...
    5 Statement: ...
    6 Statement: L ...

to eliminate a branch and a trivial basic block to get:

    <<IfConstruct>>
      1 If[Then]Stmt [negate]: if(cond) goto L
      4 Statement: ...
      5 Statement: ...
      3 EndIfStmt
    <<End IfConstruct>>
    6 Statement: L ...

Among other requirements, this is invalid if any statement between the
GOTO and its target is an intermediate construct statement such as a
CASE or ELSE IF statement, like the CASE DEFAULT statement in:

  select case(i)
  case (:2)
    n = i * 10
  case (5:)
    n = i * 1000
    if (i <= 6) goto 9 ! exit over 'case default'; may not be rewritten
    n = i * 10000
  case default
    n = i * 100
9 end select

Added: 
    

Modified: 
    flang/lib/Lower/PFTBuilder.cpp
    flang/test/Lower/select-case-statement.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 16cfde1e02145..59a9b2cdcb67c 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -503,7 +503,7 @@ class PFTBuilder {
     for (auto it = evaluationList.begin(), end = evaluationList.end();
          it != end; ++it) {
       auto &eval = *it;
-      if (eval.isA<parser::EntryStmt>()) {
+      if (eval.isA<parser::EntryStmt>() || eval.isIntermediateConstructStmt()) {
         ifCandidateStack.clear();
         continue;
       }

diff  --git a/flang/test/Lower/select-case-statement.f90 b/flang/test/Lower/select-case-statement.f90
index 5eaff33dc89d0..d62e9e2d05f4d 100644
--- a/flang/test/Lower/select-case-statement.f90
+++ b/flang/test/Lower/select-case-statement.f90
@@ -252,7 +252,6 @@ subroutine scharacter1(s)
     print*, n
   end subroutine
 
-
   ! CHECK-LABEL: func @_QPscharacter2
   subroutine scharacter2(s)
     ! CHECK-DAG: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
@@ -337,6 +336,47 @@ subroutine sempty(n)
     ! CHECK:   return
   end subroutine
 
+  ! CHECK-LABEL: func @_QPsgoto
+  ! select case with goto exit
+  subroutine sgoto
+    n = 0
+    do i=1,8
+      ! CHECK:   %[[i:[0-9]+]] = fir.alloca {{.*}} "_QFsgotoEi"
+      ! CHECK: ^bb2:  // pred: ^bb1
+      ! CHECK:   %[[selector:[0-9]+]] = fir.load %[[i]] : !fir.ref<i32>
+      ! CHECK:   fir.select_case %[[selector]] : i32 [#fir.upper, %c2{{.*}}, ^bb3, #fir.lower, %c5{{.*}}, ^bb4, unit, ^bb7]
+      ! CHECK: ^bb3:  // pred: ^bb2
+      ! CHECK:   arith.muli %c10{{[^0]}}
+      ! CHECK:   br ^bb9
+      ! CHECK: ^bb4:  // pred: ^bb2
+      ! CHECK:   arith.muli %c1000{{[^0]}}
+      ! CHECK:   cond_br {{.*}}, ^bb5, ^bb6
+      ! CHECK: ^bb5:  // pred: ^bb4
+      ! CHECK:   br ^bb8
+      ! CHECK: ^bb6:  // pred: ^bb4
+      ! CHECK:   arith.muli %c10000{{[^0]}}
+      ! CHECK:   br ^bb9
+      ! CHECK: ^bb7:  // pred: ^bb2
+      ! CHECK:   arith.muli %c100{{[^0]}}
+      ! CHECK:   br ^bb8
+      ! CHECK: ^bb8:  // 2 preds: ^bb5, ^bb7
+      ! CHECK:   br ^bb9
+      ! CHECK: ^bb9:  // 3 preds: ^bb3, ^bb6, ^bb8
+      ! CHECK:   fir.call @_FortranAioBeginExternalListOutput
+      select case(i)
+      case (:2)
+        n = i * 10
+      case (5:)
+        n = i * 1000
+        if (i <= 6) goto 9
+        n = i * 10000
+      case default
+        n = i * 100
+  9   end select
+      print*, n
+    enddo
+    ! CHECK:   return
+  end
 
   ! CHECK-LABEL: func @_QPswhere
   subroutine swhere(num)
@@ -452,6 +492,9 @@ program p
     call sempty(2)            ! no output
     call sempty(3)            ! expected output: 3 i:case default; 3 c:case default
 
+    print*
+    call sgoto                ! expected output:  10 20 300 400 5000 6000 70000 80000 
+
     print*
     call swhere(1)            ! expected output: 42.
     call sforall(1)           ! expected output: 42.


        


More information about the flang-commits mailing list