[flang] Make EndProgramStmt a NOP + early return
authorValentin Clement <clementval@gmail.com>
Wed, 1 Feb 2023 14:53:52 +0000 (15:53 +0100)
committerValentin Clement <clementval@gmail.com>
Wed, 1 Feb 2023 14:55:23 +0000 (15:55 +0100)
Fix done in D143055 can be simpler by making EndProgramStmt a NOP
and dealing with the exit in `endNewFunction` in a centralize way.
Also add finalization when there is an early exit in the main
program.

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D143065

flang/lib/Lower/Bridge.cpp
flang/test/Lower/derived-type-finalization.f90

index 492176f..9033ab8 100644 (file)
@@ -950,7 +950,6 @@ private:
     if (blockIsUnterminated())
       builder->create<mlir::func::ReturnOp>(toLocation());
   }
-  void genFIR(const Fortran::parser::EndProgramStmt &) { genExitRoutine(); }
 
   /// END of procedure-like constructs
   ///
@@ -3059,6 +3058,7 @@ private:
         getEval().getOwningProcedure();
     assert(funit && "not inside main program, function or subroutine");
     if (funit->isMainProgram()) {
+      bridge.fctCtx().finalizeAndKeep();
       genExitRoutine();
       return;
     }
@@ -3114,6 +3114,7 @@ private:
   void genFIR(const Fortran::parser::EndFunctionStmt &) {}     // nop
   void genFIR(const Fortran::parser::EndIfStmt &) {}           // nop
   void genFIR(const Fortran::parser::EndMpSubprogramStmt &) {} // nop
+  void genFIR(const Fortran::parser::EndProgramStmt &) {}      // nop
   void genFIR(const Fortran::parser::EndSelectStmt &) {}       // nop
   void genFIR(const Fortran::parser::EndSubroutineStmt &) {}   // nop
   void genFIR(const Fortran::parser::EntryStmt &) {}           // nop
@@ -3438,16 +3439,8 @@ private:
   void endNewFunction(Fortran::lower::pft::FunctionLikeUnit &funit) {
     setCurrentPosition(Fortran::lower::pft::stmtSourceLoc(funit.endStmt));
     if (funit.isMainProgram()) {
-      if (!blockIsUnterminated()) {
-        auto insertPt = builder->saveInsertionPoint();
-        mlir::Block *currentBlock = builder->getBlock();
-        builder->setInsertionPoint(&currentBlock->back());
-        bridge.fctCtx().finalizeAndPop();
-        builder->restoreInsertionPoint(insertPt);
-      } else {
-        bridge.fctCtx().finalizeAndPop();
-        genExitRoutine();
-      }
+      bridge.fctCtx().finalizeAndPop();
+      genExitRoutine();
     } else {
       genFIRProcedureExit(funit, funit.getSubprogramSymbol());
     }
index 6dcf7cf..fae1cdc 100644 (file)
@@ -153,12 +153,20 @@ end module
 program p
   use derived_type_finalization
   type(t1) :: t
+  if (t%a == 10) return
   print *, 'end of program'
 end program
 
 ! CHECK-LABEL: func.func @_QQmain() {
 ! CHECK: %[[T:.*]] = fir.alloca !fir.type<_QMderived_type_finalizationTt1{a:i32}> {bindc_name = "t", uniq_name = "_QFEt"}
-! CHECK: %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
-! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
-! CHECK: %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
-! CHECK: return
+! CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
+! CHECK: ^bb1:
+! CHECK:  %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK:  %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK:  %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
+! CHECK:  return
+! CHECK: ^bb2:
+! CHECK:  %[[EMBOX:.*]] = fir.embox %[[T]] : (!fir.ref<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>
+! CHECK:  %[[BOX_NONE:.*]] = fir.convert %[[EMBOX]] : (!fir.box<!fir.type<_QMderived_type_finalizationTt1{a:i32}>>) -> !fir.box<none>
+! CHECK:  %{{.*}} = fir.call @_FortranADestroy(%[[BOX_NONE]]) {{.*}} : (!fir.box<none>) -> none
+! CHECK:  return