https://github.com/NimishMishra updated 
https://github.com/llvm/llvm-project/pull/159788

>From 80000310c58c79c9081eb64e00c40c9e4d3ffe73 Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Tue, 21 Jul 2026 19:16:00 +0530
Subject: [PATCH 1/7] Address review comments

---
 clang/include/clang/Options/FlangOptions.td   |  4 +-
 clang/lib/Driver/ToolChains/Flang.cpp         |  2 +-
 flang/include/flang/Lower/LoweringOptions.def |  3 +
 flang/lib/Frontend/CompilerInvocation.cpp     |  5 +
 flang/lib/Lower/ConvertVariable.cpp           | 91 +++++++++++++++++++
 flang/test/Driver/finit-local-zero.f90        |  8 ++
 flang/test/Lower/init-local-zero.f90          | 66 ++++++++++++++
 7 files changed, 177 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Driver/finit-local-zero.f90
 create mode 100644 flang/test/Lower/init-local-zero.f90

diff --git a/clang/include/clang/Options/FlangOptions.td 
b/clang/include/clang/Options/FlangOptions.td
index bafc063663fe2..79cabe35e9406 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -59,7 +59,9 @@ defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, 
Group<gfortran_Group>;
 defm external_blas : BooleanFFlag<"external-blas">, Group<gfortran_Group>;
 defm f2c : BooleanFFlag<"f2c">, Group<gfortran_Group>;
 defm frontend_optimize : BooleanFFlag<"frontend-optimize">, 
Group<gfortran_Group>;
-defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>;
+defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>,
+        Visibility<[FlangOption, FC1Option]>, HelpText<"Initialize real, 
integer, character, logical, and complex variables "
+               "to zero.">;
 defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, 
Group<gfortran_Group>;
 defm max_identifier_length : BooleanFFlag<"max-identifier-length">, 
Group<gfortran_Group>;
 defm module_private : BooleanFFlag<"module-private">, Group<gfortran_Group>;
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index d900037230f20..34452206ed6db 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -263,7 +263,7 @@ void Flang::addCodegenOptions(const ArgList &Args,
        options::OPT_fno_ppc_native_vec_elem_order,
        options::OPT_fppc_native_vec_elem_order, options::OPT_finit_global_zero,
        options::OPT_fno_init_global_zero, options::OPT_frepack_arrays,
-       options::OPT_fno_repack_arrays,
+       options::OPT_fno_repack_arrays, options::OPT_finit_local_zero,
        options::OPT_frepack_arrays_contiguity_EQ,
        options::OPT_fstack_repack_arrays, options::OPT_fno_stack_repack_arrays,
        options::OPT_ftime_report, options::OPT_ftime_report_EQ,
diff --git a/flang/include/flang/Lower/LoweringOptions.def 
b/flang/include/flang/Lower/LoweringOptions.def
index 0b02ffd5a3b22..2b75d579c021e 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -93,5 +93,8 @@ ENUM_LOWERINGOPT(PreserveUseDebugInfo, unsigned, 1, 0)
 /// Portable, Extremum, ExtremeNum). Default: Legacy.
 ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
+/// When true, it enables semantics for -finit-local-zero during codegen.
+ENUM_LOWERINGOPT(InitLocalZeroDef, unsigned, 1, 0)
+
 #undef LOWERINGOPT
 #undef ENUM_LOWERINGOPT
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 79ad08353b64c..32f03215f3469 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1684,6 +1684,11 @@ bool CompilerInvocation::createFromArgs(
   else
     invoc.loweringOpts.setInitGlobalZero(false);
 
+  // -finit-local-zero
+  if (args.hasArg(clang::options::OPT_finit_local_zero)) {
+    invoc.loweringOpts.setInitLocalZeroDef(1);
+  }
+
   // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
   // -Rpass-analysis. This will be used later when processing and outputting 
the
   // remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
diff --git a/flang/lib/Lower/ConvertVariable.cpp 
b/flang/lib/Lower/ConvertVariable.cpp
index 007b536d97098..607f40e48e133 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -31,6 +31,7 @@
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Builder/IntrinsicCall.h"
+#include "flang/Optimizer/Builder/Runtime/Assign.h"
 #include "flang/Optimizer/Builder/Runtime/Derived.h"
 #include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Optimizer/Dialect/CUF/CUFOps.h"
@@ -1225,6 +1226,54 @@ getSafeRepackAttrs(Fortran::lower::AbstractConverter 
&converter) {
   return attrs.empty() ? mlir::ArrayAttr{} : builder.getArrayAttr(attrs);
 }
 
+// Helper class to encapsulate utilities related to emission of implicit
+// assignments. `Implicit` here implies the assignment does not
+// exist in the Fortran source, but is implicit through definition
+// of one or more flagsets (like -finit-* family of flags).
+// General purpose usage of these utilities outside the
+// scope detailed here is discouraged, and is probably wrong.
+class ImplicitAssignmentGenerator {
+private:
+  bool isInitLocalZeroFlagDefined;
+
+public:
+  ImplicitAssignmentGenerator(bool isInitLocalZeroFlagDefined)
+      : isInitLocalZeroFlagDefined(isInitLocalZeroFlagDefined) {}
+
+  void emitAssignment(Fortran::lower::AbstractConverter &converter,
+                      mlir::Location loc, const Fortran::semantics::Symbol 
&sym,
+                      Fortran::lower::SymMap &symMap) {
+    if (isInitLocalZeroFlagDefined) {
+      mlir::Type eleTy = hlfir::getFortranElementType(converter.genType(sym));
+      auto *builder = &converter.getFirOpBuilder();
+
+      if (mlir::isa<fir::CharacterType>(eleTy)) {
+        fir::factory::CharacterExprHelper helper{*builder, loc};
+        fir::CharacterType::KindTy kind =
+            helper.getCharacterType(eleTy).getFKind();
+        mlir::Value zeroCode =
+            builder->createIntegerConstant(loc, builder->getI32Type(), 0);
+        mlir::Value zero = helper.createSingletonFromCode(zeroCode, kind);
+        hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
+        lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
+        mlir::Value rhsTmp = builder->createTemporary(loc, zero.getType());
+        builder->create<fir::StoreOp>(loc, zero, rhsTmp);
+        builder->create<hlfir::AssignOp>(loc, rhsTmp, lhs);
+      }
+
+      else if (fir::isa_integer(eleTy) || fir::isa_real(eleTy) ||
+               fir::isa_complex(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) {
+        mlir::Value zero = fir::factory::createZeroValue(*builder, loc, eleTy);
+        hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
+        lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
+        mlir::Value rhsTmp = builder->createTemporary(loc, zero.getType());
+        builder->create<fir::StoreOp>(loc, zero, rhsTmp);
+        builder->create<hlfir::AssignOp>(loc, rhsTmp, lhs);
+      }
+    }
+  }
+};
+
 /// Instantiate a local variable. Precondition: Each variable will be visited
 /// such that if its properties depend on other variables, the variables upon
 /// which its properties depend will already have been visited.
@@ -1317,6 +1366,48 @@ static void 
instantiateLocal(Fortran::lower::AbstractConverter &converter,
       Fortran::lower::genUnpackArray(*converterPtr, loc, *varDef, *sym);
     });
   }
+
+  /// These options do not initialize:
+  ///   1) Any variable already initialized
+  ///   2) objects with the POINTER attribute
+  ///   3) allocatable arrays
+  ///   4) variables that appear in an EQUIVALENCE statement
+
+  auto isEligibleForImplicitAssignment = [&var]() -> bool {
+    if (!var.hasSymbol())
+      return false;
+
+    const Fortran::semantics::Symbol &sym = var.getSymbol();
+    if (const auto *details =
+            sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
+      if (details->init())
+        return false;
+    }
+
+    if (sym.attrs().test(Fortran::semantics::Attr::POINTER))
+      return false;
+
+    if (sym.Rank() > 0 &&
+        sym.attrs().test(Fortran::semantics::Attr::ALLOCATABLE))
+      return false;
+
+    if (Fortran::lower::pft::getDependentVariableList(sym).size() > 1)
+      return false;
+
+    return true;
+  };
+
+  if (isEligibleForImplicitAssignment()) {
+    // Internal state of this class holds only the -finit-* flagsets. Hence
+    // can be reused for different symbols. Also minimizes the number of
+    // calls to `getLoweringOptions()`.
+    static ImplicitAssignmentGenerator implicitAssignmentGenerator{
+        /*isInitLocalZeroFlagDefined=*/converter.getLoweringOptions()
+            .getInitLocalZeroDef() == 1};
+
+    implicitAssignmentGenerator.emitAssignment(
+        converter, converter.getCurrentLocation(), var.getSymbol(), symMap);
+  }
 }
 
 //===----------------------------------------------------------------===//
diff --git a/flang/test/Driver/finit-local-zero.f90 
b/flang/test/Driver/finit-local-zero.f90
new file mode 100644
index 0000000000000..7dd2612e624ad
--- /dev/null
+++ b/flang/test/Driver/finit-local-zero.f90
@@ -0,0 +1,8 @@
+! Check that the driver passes through -finit-global-zero:
+! RUN: %flang -### -S -finit-local-zero %s -o - 2>&1 | FileCheck %s
+
+! Check that the compiler accepts -finit-local-zero:
+! RUN: %flang_fc1 -emit-hlfir -finit-local-zero %s -o -
+
+
+! CHECK: "-fc1"{{.*}}"-finit-local-zero"
diff --git a/flang/test/Lower/init-local-zero.f90 
b/flang/test/Lower/init-local-zero.f90
new file mode 100644
index 0000000000000..61a4d70ad788d
--- /dev/null
+++ b/flang/test/Lower/init-local-zero.f90
@@ -0,0 +1,66 @@
+! RUN: %flang_fc1 -emit-hlfir -finit-local-zero -o - %s | FileCheck %s
+
+
+!CHECK-LABEL: func.func @_QPuninitialized_integer() {
+!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca i32
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = 
"_QFuninitialized_integerEx"}
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_integerEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, 
!fir.ref<i32>)
+!CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
+!CHECK: fir.store %[[ZERO]] to %[[ZERO_ALLOCA]] : !fir.ref<i32>
+!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<i32>, 
!fir.ref<i32>
+subroutine uninitialized_integer
+  integer :: x
+end subroutine
+
+!CHECK-LABEL: func.func @_QPuninitialized_real() {
+!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca f32
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = 
"_QFuninitialized_realEx"}
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+!CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32
+!CHECK: fir.store %[[ZERO]] to %[[ZERO_ALLOCA]] : !fir.ref<f32>
+!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<f32>, 
!fir.ref<f32>
+subroutine uninitialized_real
+   real :: x
+end subroutine
+
+!CHECK-LABEL: func.func @_QPuninitialized_logical() {
+!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca !fir.logical<4>
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", 
uniq_name = "_QFuninitialized_logicalEx"}
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_logicalEx"} : (!fir.ref<!fir.logical<4>>) -> 
(!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+!CHECK: %false = arith.constant false
+!CHECK: %[[CVT:.*]] = fir.convert %false : (i1) -> !fir.logical<4>
+!CHECK: fir.store %[[CVT]] to %[[ZERO_ALLOCA]] : !fir.ref<!fir.logical<4>>
+!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<!fir.logical<4>>, 
!fir.ref<!fir.logical<4>>
+subroutine uninitialized_logical
+   logical :: x
+end subroutine
+
+
+!CHECK-LABEL: func.func @_QPuninitialized_complex() {
+!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca complex<f32>
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca complex<f32> {bindc_name = "x", 
uniq_name = "_QFuninitialized_complexEx"}
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_complexEx"} : (!fir.ref<complex<f32>>) -> 
(!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
+!CHECK: %[[CONST:.*]] = arith.constant 0.000000e+00 : f32
+!CHECK: %[[UNDEF:.*]] = fir.undefined complex<f32>
+!CHECK: %[[IDX0:.*]] = fir.insert_value %[[UNDEF]], %[[CONST]], [0 : index] : 
(complex<f32>, f32) -> complex<f32>
+!CHECK: %[[IDX1:.*]] = fir.insert_value %[[IDX0]], %[[CONST]], [1 : index] : 
(complex<f32>, f32) -> complex<f32>
+!CHECK: fir.store %[[IDX1]] to %[[ZERO_ALLOCA]] : !fir.ref<complex<f32>>
+!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<complex<f32>>, 
!fir.ref<complex<f32>>
+subroutine uninitialized_complex
+   complex :: x
+end subroutine
+
+!CHECK-LABEL: func.func @_QPuninitialized_character() {
+!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca !fir.char<1>
+!CHECK: %[[ONE:.*]] = arith.constant 1 : index
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.char<1> {bindc_name = "x", 
uniq_name = "_QFuninitialized_characterEx"}
+!CHECK: %3:2 = hlfir.declare %[[X_ALLOCA]] typeparams %[[ONE]] {uniq_name = 
"_QFuninitialized_characterEx"} : (!fir.ref<!fir.char<1>>, index) -> 
(!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+!CHECK: %[[CONST:.*]] = arith.constant 0 : i32
+!CHECK: %[[CVT:.*]] = fir.convert %[[CONST]] : (i32) -> i8
+!CHECK: %[[UNDEF:.*]] = fir.undefined !fir.char<1>
+!CHECK: %[[VAL:.*]] = fir.insert_value %[[UNDEF]], %[[CVT]], [0 : index] : 
(!fir.char<1>, i8) -> !fir.char<1>
+!CHECK: fir.store %[[VAL]] to %[[ZERO_ALLOCA]] : !fir.ref<!fir.char<1>>
+!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<!fir.char<1>>, 
!fir.ref<!fir.char<1>>
+subroutine uninitialized_character
+   character :: x
+end subroutine

>From a5f6b3cde11ec8ee5c1ae53b7629f91b784ceede Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Tue, 21 Jul 2026 19:19:51 +0530
Subject: [PATCH 2/7] fix test

---
 flang/test/Driver/finit-local-zero.f90 | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/flang/test/Driver/finit-local-zero.f90 
b/flang/test/Driver/finit-local-zero.f90
index 7dd2612e624ad..8cfadc9372edc 100644
--- a/flang/test/Driver/finit-local-zero.f90
+++ b/flang/test/Driver/finit-local-zero.f90
@@ -1,8 +1,7 @@
-! Check that the driver passes through -finit-global-zero:
+! Check that the driver passes through -finit-local-zero:
 ! RUN: %flang -### -S -finit-local-zero %s -o - 2>&1 | FileCheck %s
 
 ! Check that the compiler accepts -finit-local-zero:
-! RUN: %flang_fc1 -emit-hlfir -finit-local-zero %s -o -
-
+! RUN: %flang_fc1 -emit-hlfir -finit-local-zero %s -o /dev/null
 
 ! CHECK: "-fc1"{{.*}}"-finit-local-zero"

>From 1ad6500f8025ebcb4109469a38f95a83537ce0a5 Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Tue, 21 Jul 2026 19:28:04 +0530
Subject: [PATCH 3/7] Update LoweringOptions.def

---
 flang/include/flang/Lower/LoweringOptions.def | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/include/flang/Lower/LoweringOptions.def 
b/flang/include/flang/Lower/LoweringOptions.def
index 2b75d579c021e..3155cf7878608 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -93,7 +93,7 @@ ENUM_LOWERINGOPT(PreserveUseDebugInfo, unsigned, 1, 0)
 /// Portable, Extremum, ExtremeNum). Default: Legacy.
 ENUM_LOWERINGOPT(FPMaxminBehavior, Fortran::common::FPMaxminBehavior, 2, 0)
 
-/// When true, it enables semantics for -finit-local-zero during codegen.
+/// When true, enables semantics for -finit-local-zero during codegen.
 ENUM_LOWERINGOPT(InitLocalZeroDef, unsigned, 1, 0)
 
 #undef LOWERINGOPT

>From 02e4431915267f05fa6b988d10a3c05c20503f0d Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Tue, 21 Jul 2026 19:29:30 +0530
Subject: [PATCH 4/7] Update CompilerInvocation.cpp

---
 flang/lib/Frontend/CompilerInvocation.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index 32f03215f3469..903818824a266 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1685,9 +1685,8 @@ bool CompilerInvocation::createFromArgs(
     invoc.loweringOpts.setInitGlobalZero(false);
 
   // -finit-local-zero
-  if (args.hasArg(clang::options::OPT_finit_local_zero)) {
+  if (args.hasArg(clang::options::OPT_finit_local_zero))
     invoc.loweringOpts.setInitLocalZeroDef(1);
-  }
 
   // Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
   // -Rpass-analysis. This will be used later when processing and outputting 
the

>From ec112fef380534224585cdb88d1fb9d230960e69 Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Sun, 26 Jul 2026 18:33:53 +0530
Subject: [PATCH 5/7] Address review comments

---
 flang/lib/Lower/ConvertVariable.cpp    | 115 ++++++++++++++-----------
 flang/test/Driver/finit-local-zero.f90 |   4 +-
 flang/test/Lower/init-local-zero.f90   |  45 +++++-----
 3 files changed, 93 insertions(+), 71 deletions(-)

diff --git a/flang/lib/Lower/ConvertVariable.cpp 
b/flang/lib/Lower/ConvertVariable.cpp
index 607f40e48e133..8278340f3b7d2 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1226,53 +1226,68 @@ getSafeRepackAttrs(Fortran::lower::AbstractConverter 
&converter) {
   return attrs.empty() ? mlir::ArrayAttr{} : builder.getArrayAttr(attrs);
 }
 
-// Helper class to encapsulate utilities related to emission of implicit
+// Helper function to related to emission of implicit
 // assignments. `Implicit` here implies the assignment does not
 // exist in the Fortran source, but is implicit through definition
 // of one or more flagsets (like -finit-* family of flags).
-// General purpose usage of these utilities outside the
+// General purpose usage of this function outside the
 // scope detailed here is discouraged, and is probably wrong.
-class ImplicitAssignmentGenerator {
-private:
-  bool isInitLocalZeroFlagDefined;
-
-public:
-  ImplicitAssignmentGenerator(bool isInitLocalZeroFlagDefined)
-      : isInitLocalZeroFlagDefined(isInitLocalZeroFlagDefined) {}
-
-  void emitAssignment(Fortran::lower::AbstractConverter &converter,
-                      mlir::Location loc, const Fortran::semantics::Symbol 
&sym,
-                      Fortran::lower::SymMap &symMap) {
-    if (isInitLocalZeroFlagDefined) {
-      mlir::Type eleTy = hlfir::getFortranElementType(converter.genType(sym));
-      auto *builder = &converter.getFirOpBuilder();
-
-      if (mlir::isa<fir::CharacterType>(eleTy)) {
-        fir::factory::CharacterExprHelper helper{*builder, loc};
-        fir::CharacterType::KindTy kind =
-            helper.getCharacterType(eleTy).getFKind();
-        mlir::Value zeroCode =
-            builder->createIntegerConstant(loc, builder->getI32Type(), 0);
-        mlir::Value zero = helper.createSingletonFromCode(zeroCode, kind);
-        hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
-        lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
-        mlir::Value rhsTmp = builder->createTemporary(loc, zero.getType());
-        builder->create<fir::StoreOp>(loc, zero, rhsTmp);
-        builder->create<hlfir::AssignOp>(loc, rhsTmp, lhs);
-      }
+static void emitImplicitAssignment(Fortran::lower::AbstractConverter 
&converter,
+                                   mlir::Location loc,
+                                   const Fortran::semantics::Symbol &sym,
+                                   Fortran::lower::SymMap &symMap) {
+  if (converter.getLoweringOptions().getInitLocalZeroDef()) {
+    mlir::Type eleTy = hlfir::getFortranElementType(converter.genType(sym));
+    auto *builder = &converter.getFirOpBuilder();
+
+    if (mlir::isa<fir::CharacterType>(eleTy)) {
+      fir::ExtendedValue ext = converter.getSymbolExtendedValue(sym);
+      const auto *charBox = ext.getCharBox();
+      mlir::Value buffer = charBox->getBuffer();
+      assert(buffer && "CharBox buffer is null");
+      auto eleTy = fir::unwrapRefType(buffer.getType());
+      auto charTy =
+          mlir::cast<fir::CharacterType>(fir::unwrapSequenceType(eleTy));
+      unsigned kindBytes =
+          builder->getKindMap().getCharacterBitsize(charTy.getFKind()) / 8;
+      auto lenVal = charBox->getLen();
+      mlir::Value byteLen;
+      if (lenVal) {
+
+        mlir::Value lenI64 =
+            builder->createConvert(loc, builder->getI64Type(), lenVal);
+        mlir::Value kind = builder->createIntegerConstant(
+            loc, builder->getI64Type(), kindBytes);
+        byteLen = mlir::arith::MulIOp::create(*builder, loc, lenI64, kind);
+        byteLen = builder->createConvert(loc, builder->getI64Type(), byteLen);
+      } else {
 
-      else if (fir::isa_integer(eleTy) || fir::isa_real(eleTy) ||
-               fir::isa_complex(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) {
-        mlir::Value zero = fir::factory::createZeroValue(*builder, loc, eleTy);
-        hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
-        lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
-        mlir::Value rhsTmp = builder->createTemporary(loc, zero.getType());
-        builder->create<fir::StoreOp>(loc, zero, rhsTmp);
-        builder->create<hlfir::AssignOp>(loc, rhsTmp, lhs);
+        assert(charTy.hasConstantLen() && "expected constant character 
length");
+        byteLen = builder->createIntegerConstant(loc, builder->getI64Type(),
+                                                 charTy.getLen() * kindBytes);
       }
+
+      auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder->getContext());
+      mlir::Value ptr = builder->createConvert(loc, ptrTy, buffer);
+      mlir::Value zero =
+          builder->createIntegerConstant(loc, builder->getI8Type(), 0);
+      mlir::ModuleOp mod = builder->getModule();
+      mlir::OpBuilder modBuilder(mod.getBodyRegion());
+      modBuilder.setInsertionPointToEnd(zero.getParentBlock());
+      mlir::LLVM::MemsetOp::create(
+          modBuilder, loc, ptr, zero, byteLen,
+          fir::isa_volatile_type(converter.genType(sym)));
+    }
+
+    else if (fir::isa_integer(eleTy) || fir::isa_real(eleTy) ||
+             fir::isa_complex(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) {
+      mlir::Value zero = fir::factory::createZeroValue(*builder, loc, eleTy);
+      hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
+      lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
+      builder->create<hlfir::AssignOp>(loc, zero, lhs);
     }
   }
-};
+}
 
 /// Instantiate a local variable. Precondition: Each variable will be visited
 /// such that if its properties depend on other variables, the variables upon
@@ -1373,11 +1388,13 @@ static void 
instantiateLocal(Fortran::lower::AbstractConverter &converter,
   ///   3) allocatable arrays
   ///   4) variables that appear in an EQUIVALENCE statement
 
-  auto isEligibleForImplicitAssignment = [&var]() -> bool {
+  auto isEligibleForImplicitAssignment = [&var, &converter]() -> bool {
     if (!var.hasSymbol())
       return false;
 
     const Fortran::semantics::Symbol &sym = var.getSymbol();
+    if (!sym.GetType())
+      return false;
     if (const auto *details =
             sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
       if (details->init())
@@ -1394,19 +1411,19 @@ static void 
instantiateLocal(Fortran::lower::AbstractConverter &converter,
     if (Fortran::lower::pft::getDependentVariableList(sym).size() > 1)
       return false;
 
+    if (auto ty = converter.genType(sym)) {
+      auto charTy =
+          mlir::dyn_cast<fir::CharacterType>(hlfir::getFortranElementType(ty));
+      if (charTy && !charTy.hasConstantLen())
+        return false;
+    }
+
     return true;
   };
 
   if (isEligibleForImplicitAssignment()) {
-    // Internal state of this class holds only the -finit-* flagsets. Hence
-    // can be reused for different symbols. Also minimizes the number of
-    // calls to `getLoweringOptions()`.
-    static ImplicitAssignmentGenerator implicitAssignmentGenerator{
-        /*isInitLocalZeroFlagDefined=*/converter.getLoweringOptions()
-            .getInitLocalZeroDef() == 1};
-
-    implicitAssignmentGenerator.emitAssignment(
-        converter, converter.getCurrentLocation(), var.getSymbol(), symMap);
+    emitImplicitAssignment(converter, converter.getCurrentLocation(),
+                           var.getSymbol(), symMap);
   }
 }
 
diff --git a/flang/test/Driver/finit-local-zero.f90 
b/flang/test/Driver/finit-local-zero.f90
index 8cfadc9372edc..b69fe60ba1e70 100644
--- a/flang/test/Driver/finit-local-zero.f90
+++ b/flang/test/Driver/finit-local-zero.f90
@@ -1,7 +1,9 @@
 ! Check that the driver passes through -finit-local-zero:
 ! RUN: %flang -### -S -finit-local-zero %s -o - 2>&1 | FileCheck %s
+! RUN: %flang -### -S %s -o - 2>&1 | FileCheck %s --check-prefixes=NO-INIT
 
 ! Check that the compiler accepts -finit-local-zero:
-! RUN: %flang_fc1 -emit-hlfir -finit-local-zero %s -o /dev/null
+! RUN: %flang_fc1 -finit-local-zero %s -o /dev/null
 
 ! CHECK: "-fc1"{{.*}}"-finit-local-zero"
+! NO-INIT-NOT: -finit-local-zero
diff --git a/flang/test/Lower/init-local-zero.f90 
b/flang/test/Lower/init-local-zero.f90
index 61a4d70ad788d..2ed8ca2f615dd 100644
--- a/flang/test/Lower/init-local-zero.f90
+++ b/flang/test/Lower/init-local-zero.f90
@@ -1,66 +1,69 @@
 ! RUN: %flang_fc1 -emit-hlfir -finit-local-zero -o - %s | FileCheck %s
 
-
 !CHECK-LABEL: func.func @_QPuninitialized_integer() {
-!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca i32
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = 
"_QFuninitialized_integerEx"}
 !CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_integerEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, 
!fir.ref<i32>)
 !CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
-!CHECK: fir.store %[[ZERO]] to %[[ZERO_ALLOCA]] : !fir.ref<i32>
-!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<i32>, 
!fir.ref<i32>
+!CHECK: hlfir.assign %[[ZERO]] to %[[X]]#0 : i32, !fir.ref<i32>
 subroutine uninitialized_integer
   integer :: x
 end subroutine
 
 !CHECK-LABEL: func.func @_QPuninitialized_real() {
-!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca f32
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = 
"_QFuninitialized_realEx"}
 !CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
 !CHECK: %[[ZERO:.*]] = arith.constant 0.000000e+00 : f32
-!CHECK: fir.store %[[ZERO]] to %[[ZERO_ALLOCA]] : !fir.ref<f32>
-!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<f32>, 
!fir.ref<f32>
+!CHECK: hlfir.assign %[[ZERO]] to %[[X]]#0 : f32, !fir.ref<f32>
 subroutine uninitialized_real
    real :: x
 end subroutine
 
 !CHECK-LABEL: func.func @_QPuninitialized_logical() {
-!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca !fir.logical<4>
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", 
uniq_name = "_QFuninitialized_logicalEx"}
 !CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_logicalEx"} : (!fir.ref<!fir.logical<4>>) -> 
(!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
 !CHECK: %false = arith.constant false
 !CHECK: %[[CVT:.*]] = fir.convert %false : (i1) -> !fir.logical<4>
-!CHECK: fir.store %[[CVT]] to %[[ZERO_ALLOCA]] : !fir.ref<!fir.logical<4>>
-!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<!fir.logical<4>>, 
!fir.ref<!fir.logical<4>>
+!CHECK: hlfir.assign %[[CVT]] to %[[X]]#0 : !fir.logical<4>, 
!fir.ref<!fir.logical<4>>
 subroutine uninitialized_logical
    logical :: x
 end subroutine
 
 
 !CHECK-LABEL: func.func @_QPuninitialized_complex() {
-!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca complex<f32>
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca complex<f32> {bindc_name = "x", 
uniq_name = "_QFuninitialized_complexEx"}
 !CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {uniq_name = 
"_QFuninitialized_complexEx"} : (!fir.ref<complex<f32>>) -> 
(!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
 !CHECK: %[[CONST:.*]] = arith.constant 0.000000e+00 : f32
 !CHECK: %[[UNDEF:.*]] = fir.undefined complex<f32>
 !CHECK: %[[IDX0:.*]] = fir.insert_value %[[UNDEF]], %[[CONST]], [0 : index] : 
(complex<f32>, f32) -> complex<f32>
 !CHECK: %[[IDX1:.*]] = fir.insert_value %[[IDX0]], %[[CONST]], [1 : index] : 
(complex<f32>, f32) -> complex<f32>
-!CHECK: fir.store %[[IDX1]] to %[[ZERO_ALLOCA]] : !fir.ref<complex<f32>>
-!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<complex<f32>>, 
!fir.ref<complex<f32>>
+!CHECK: hlfir.assign %[[IDX1]] to %[[X]]#0 : complex<f32>, 
!fir.ref<complex<f32>>
 subroutine uninitialized_complex
    complex :: x
 end subroutine
 
 !CHECK-LABEL: func.func @_QPuninitialized_character() {
-!CHECK: %[[ZERO_ALLOCA:.*]] = fir.alloca !fir.char<1>
 !CHECK: %[[ONE:.*]] = arith.constant 1 : index
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.char<1> {bindc_name = "x", 
uniq_name = "_QFuninitialized_characterEx"}
-!CHECK: %3:2 = hlfir.declare %[[X_ALLOCA]] typeparams %[[ONE]] {uniq_name = 
"_QFuninitialized_characterEx"} : (!fir.ref<!fir.char<1>>, index) -> 
(!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
-!CHECK: %[[CONST:.*]] = arith.constant 0 : i32
-!CHECK: %[[CVT:.*]] = fir.convert %[[CONST]] : (i32) -> i8
-!CHECK: %[[UNDEF:.*]] = fir.undefined !fir.char<1>
-!CHECK: %[[VAL:.*]] = fir.insert_value %[[UNDEF]], %[[CVT]], [0 : index] : 
(!fir.char<1>, i8) -> !fir.char<1>
-!CHECK: fir.store %[[VAL]] to %[[ZERO_ALLOCA]] : !fir.ref<!fir.char<1>>
-!CHECK: hlfir.assign %[[ZERO_ALLOCA]] to %[[X]]#0 : !fir.ref<!fir.char<1>>, 
!fir.ref<!fir.char<1>>
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] typeparams %[[ONE]] 
{uniq_name = "_QFuninitialized_characterEx"} : (!fir.ref<!fir.char<1>>, index) 
-> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+!CHECK: %[[CVT:.*]] = fir.convert %[[ONE]] : (index) -> i64
+!CHECK: %[[CONST:.*]] = arith.constant 1 : i64
+!CHECK: %[[COUNT:.*]] = arith.muli %[[CVT]], %[[CONST]] : i64
+!CHECK: %[[CVT:.*]] = fir.convert %[[X]]#0 : (!fir.ref<!fir.char<1>>) -> 
!llvm.ptr
+!CHECK: %[[ZERO:.*]] = arith.constant 0 : i8
+!CHECK: "llvm.intr.memset"(%[[CVT]], %[[ZERO]], %[[COUNT]]) <{isVolatile = 
false}> : (!llvm.ptr, i8, i64) -> ()
 subroutine uninitialized_character
    character :: x
 end subroutine
+
+!CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = 
"x", uniq_name = "_QFallocatable_scalarEx"}
+!CHECK: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap<i32>
+!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap<i32>) -> 
!fir.box<!fir.heap<i32>>
+!CHECK: fir.store %[[EMBOX]] to %[[X_ALLOCA]] : 
!fir.ref<!fir.box<!fir.heap<i32>>>
+!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {fortran_attrs = 
#fir.var_attrs<allocatable>, uniq_name = "_QFallocatable_scalarEx"} : 
(!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, 
!fir.ref<!fir.box<!fir.heap<i32>>>)
+!CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
+!CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
+!CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<i32>>) -> 
!fir.heap<i32>
+!CHECK: hlfir.assign %[[ZERO]] to %[[ADDR]] : i32, !fir.heap<i32>
+subroutine allocatable_scalar
+   integer, allocatable :: x
+end subroutine

>From 0227f5e2f61e0688b81221354a29fcfbd0dc3822 Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Sun, 26 Jul 2026 18:35:00 +0530
Subject: [PATCH 6/7] Do not run the entire pipeline for the test

---
 flang/test/Driver/finit-local-zero.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/test/Driver/finit-local-zero.f90 
b/flang/test/Driver/finit-local-zero.f90
index b69fe60ba1e70..2de41e4df34f8 100644
--- a/flang/test/Driver/finit-local-zero.f90
+++ b/flang/test/Driver/finit-local-zero.f90
@@ -3,7 +3,7 @@
 ! RUN: %flang -### -S %s -o - 2>&1 | FileCheck %s --check-prefixes=NO-INIT
 
 ! Check that the compiler accepts -finit-local-zero:
-! RUN: %flang_fc1 -finit-local-zero %s -o /dev/null
+! RUN: %flang_fc1 -fsyntax-only -finit-local-zero %s -o /dev/null
 
 ! CHECK: "-fc1"{{.*}}"-finit-local-zero"
 ! NO-INIT-NOT: -finit-local-zero

>From 00729b38755169cbf58e11a4293a326c85033a5d Mon Sep 17 00:00:00 2001
From: NimishMishra <[email protected]>
Date: Mon, 3 Aug 2026 14:55:11 +0530
Subject: [PATCH 7/7] Address review comments

---
 .../flang/Optimizer/Builder/Character.h       | 10 ++
 flang/lib/Lower/ConvertVariable.cpp           | 99 +++++--------------
 flang/lib/Optimizer/Builder/Character.cpp     | 31 ++++++
 flang/test/Lower/init-local-zero.f90          | 15 +--
 4 files changed, 69 insertions(+), 86 deletions(-)

diff --git a/flang/include/flang/Optimizer/Builder/Character.h 
b/flang/include/flang/Optimizer/Builder/Character.h
index 658118eddcc90..f68c57852e6ec 100644
--- a/flang/include/flang/Optimizer/Builder/Character.h
+++ b/flang/include/flang/Optimizer/Builder/Character.h
@@ -13,9 +13,12 @@
 #ifndef FORTRAN_OPTIMIZER_BUILDER_CHARACTER_H
 #define FORTRAN_OPTIMIZER_BUILDER_CHARACTER_H
 
+#include "flang/Lower/AbstractConverter.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
 #include "flang/Optimizer/Builder/LowLevelIntrinsics.h"
 #include "flang/Optimizer/Builder/Runtime/Character.h"
+#include "flang/Semantics/symbol.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 
 namespace fir {
 class FirOpBuilder;
@@ -240,6 +243,13 @@ fir::CharBoxValue convertCharacterKind(fir::FirOpBuilder 
&builder,
                                        fir::CharBoxValue srcBoxChar,
                                        int toKind);
 
+/// Given a symbol `sym` and a mlir::Value `val`, emit a memset to
+/// set `sym` to the value `val`.
+mlir::LLVM::MemsetOp emitMemset(fir::FirOpBuilder &builder, mlir::Location loc,
+                                Fortran::lower::AbstractConverter &converter,
+                                const Fortran::semantics::Symbol &sym,
+                                mlir::Value val);
+
 } // namespace fir::factory
 
 #endif // FORTRAN_OPTIMIZER_BUILDER_CHARACTER_H
diff --git a/flang/lib/Lower/ConvertVariable.cpp 
b/flang/lib/Lower/ConvertVariable.cpp
index 8278340f3b7d2..69f9b69710c1f 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1232,60 +1232,24 @@ getSafeRepackAttrs(Fortran::lower::AbstractConverter 
&converter) {
 // of one or more flagsets (like -finit-* family of flags).
 // General purpose usage of this function outside the
 // scope detailed here is discouraged, and is probably wrong.
-static void emitImplicitAssignment(Fortran::lower::AbstractConverter 
&converter,
-                                   mlir::Location loc,
-                                   const Fortran::semantics::Symbol &sym,
-                                   Fortran::lower::SymMap &symMap) {
-  if (converter.getLoweringOptions().getInitLocalZeroDef()) {
-    mlir::Type eleTy = hlfir::getFortranElementType(converter.genType(sym));
-    auto *builder = &converter.getFirOpBuilder();
-
-    if (mlir::isa<fir::CharacterType>(eleTy)) {
-      fir::ExtendedValue ext = converter.getSymbolExtendedValue(sym);
-      const auto *charBox = ext.getCharBox();
-      mlir::Value buffer = charBox->getBuffer();
-      assert(buffer && "CharBox buffer is null");
-      auto eleTy = fir::unwrapRefType(buffer.getType());
-      auto charTy =
-          mlir::cast<fir::CharacterType>(fir::unwrapSequenceType(eleTy));
-      unsigned kindBytes =
-          builder->getKindMap().getCharacterBitsize(charTy.getFKind()) / 8;
-      auto lenVal = charBox->getLen();
-      mlir::Value byteLen;
-      if (lenVal) {
-
-        mlir::Value lenI64 =
-            builder->createConvert(loc, builder->getI64Type(), lenVal);
-        mlir::Value kind = builder->createIntegerConstant(
-            loc, builder->getI64Type(), kindBytes);
-        byteLen = mlir::arith::MulIOp::create(*builder, loc, lenI64, kind);
-        byteLen = builder->createConvert(loc, builder->getI64Type(), byteLen);
-      } else {
-
-        assert(charTy.hasConstantLen() && "expected constant character 
length");
-        byteLen = builder->createIntegerConstant(loc, builder->getI64Type(),
-                                                 charTy.getLen() * kindBytes);
-      }
-
-      auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder->getContext());
-      mlir::Value ptr = builder->createConvert(loc, ptrTy, buffer);
-      mlir::Value zero =
-          builder->createIntegerConstant(loc, builder->getI8Type(), 0);
-      mlir::ModuleOp mod = builder->getModule();
-      mlir::OpBuilder modBuilder(mod.getBodyRegion());
-      modBuilder.setInsertionPointToEnd(zero.getParentBlock());
-      mlir::LLVM::MemsetOp::create(
-          modBuilder, loc, ptr, zero, byteLen,
-          fir::isa_volatile_type(converter.genType(sym)));
-    }
+static void emitForcedAssignment(Fortran::lower::AbstractConverter &converter,
+                                 mlir::Location loc,
+                                 const Fortran::semantics::Symbol &sym,
+                                 Fortran::lower::SymMap &symMap) {
+  mlir::Type eleTy = hlfir::getFortranElementType(converter.genType(sym));
+  auto *builder = &converter.getFirOpBuilder();
+  if (mlir::isa<fir::CharacterType>(eleTy)) {
+    mlir::Value zero =
+        builder->createIntegerConstant(loc, builder->getI8Type(), 0);
+    fir::factory::emitMemset(*builder, loc, converter, sym, zero);
+  }
 
-    else if (fir::isa_integer(eleTy) || fir::isa_real(eleTy) ||
-             fir::isa_complex(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) {
-      mlir::Value zero = fir::factory::createZeroValue(*builder, loc, eleTy);
-      hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
-      lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
-      builder->create<hlfir::AssignOp>(loc, zero, lhs);
-    }
+  else if (fir::isa_integer(eleTy) || fir::isa_real(eleTy) ||
+           fir::isa_complex(eleTy) || mlir::isa<fir::LogicalType>(eleTy)) {
+    mlir::Value zero = fir::factory::createZeroValue(*builder, loc, eleTy);
+    hlfir::Entity lhs{symMap.lookupSymbol(sym).getAddr()};
+    lhs = hlfir::derefPointersAndAllocatables(loc, *builder, lhs);
+    hlfir::AssignOp::create(*builder, loc, zero, lhs);
   }
 }
 
@@ -1388,42 +1352,33 @@ static void 
instantiateLocal(Fortran::lower::AbstractConverter &converter,
   ///   3) allocatable arrays
   ///   4) variables that appear in an EQUIVALENCE statement
 
-  auto isEligibleForImplicitAssignment = [&var, &converter]() -> bool {
+  auto isEligibleForForcedAssignment = [&var, &converter]() -> bool {
     if (!var.hasSymbol())
       return false;
 
     const Fortran::semantics::Symbol &sym = var.getSymbol();
     if (!sym.GetType())
       return false;
-    if (const auto *details =
-            sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
-      if (details->init())
-        return false;
-    }
 
-    if (sym.attrs().test(Fortran::semantics::Attr::POINTER))
+    if (var.isGlobal() || Fortran::semantics::IsDummy(sym))
       return false;
 
-    if (sym.Rank() > 0 &&
-        sym.attrs().test(Fortran::semantics::Attr::ALLOCATABLE))
+    if (sym.attrs().test(Fortran::semantics::Attr::POINTER))
       return false;
 
-    if (Fortran::lower::pft::getDependentVariableList(sym).size() > 1)
+    if (sym.attrs().test(Fortran::semantics::Attr::ALLOCATABLE))
       return false;
 
-    if (auto ty = converter.genType(sym)) {
-      auto charTy =
-          mlir::dyn_cast<fir::CharacterType>(hlfir::getFortranElementType(ty));
-      if (charTy && !charTy.hasConstantLen())
-        return false;
-    }
+    if (Fortran::semantics::FindEquivalenceSet(sym) != nullptr)
+      return false;
 
     return true;
   };
 
-  if (isEligibleForImplicitAssignment()) {
-    emitImplicitAssignment(converter, converter.getCurrentLocation(),
-                           var.getSymbol(), symMap);
+  if (converter.getLoweringOptions().getInitLocalZeroDef() &&
+      isEligibleForForcedAssignment()) {
+    emitForcedAssignment(converter, converter.getCurrentLocation(),
+                         var.getSymbol(), symMap);
   }
 }
 
diff --git a/flang/lib/Optimizer/Builder/Character.cpp 
b/flang/lib/Optimizer/Builder/Character.cpp
index 155bc0fbd19ce..bed34fd0a3431 100644
--- a/flang/lib/Optimizer/Builder/Character.cpp
+++ b/flang/lib/Optimizer/Builder/Character.cpp
@@ -897,3 +897,34 @@ fir::factory::convertCharacterKind(fir::FirOpBuilder 
&builder,
                              dest);
   return fir::CharBoxValue{dest, srcBoxChar.getLen()};
 }
+
+mlir::LLVM::MemsetOp
+fir::factory::emitMemset(fir::FirOpBuilder &builder, mlir::Location loc,
+                         Fortran::lower::AbstractConverter &converter,
+                         const Fortran::semantics::Symbol &sym,
+                         mlir::Value val) {
+  fir::ExtendedValue ext = converter.getSymbolExtendedValue(sym);
+  const auto *charBox = ext.getCharBox();
+  mlir::Value buffer = charBox->getBuffer();
+  assert(buffer && "CharBox buffer is null");
+  auto eleTy = fir::unwrapRefType(buffer.getType());
+  auto charTy = mlir::cast<fir::CharacterType>(fir::unwrapSequenceType(eleTy));
+  unsigned kindBytes =
+      builder.getKindMap().getCharacterBitsize(charTy.getFKind()) / 8;
+  auto lenVal = charBox->getLen();
+  mlir::Value lenI64 = builder.createConvert(loc, builder.getI64Type(), 
lenVal);
+  mlir::Value kind =
+      builder.createIntegerConstant(loc, builder.getI64Type(), kindBytes);
+  auto mulOp = mlir::arith::MulIOp::create(builder, loc, lenI64, kind);
+  auto byteLen = builder.createConvert(loc, builder.getI64Type(), mulOp);
+
+  auto ptrTy = mlir::LLVM::LLVMPointerType::get(builder.getContext());
+  mlir::Value ptr = builder.createConvert(loc, ptrTy, buffer);
+
+  mlir::ModuleOp mod = builder.getModule();
+  mlir::OpBuilder modBuilder(mod.getBodyRegion());
+  modBuilder.setInsertionPointToEnd(val.getParentBlock());
+  return mlir::LLVM::MemsetOp::create(
+      modBuilder, loc, ptr, val, byteLen,
+      fir::isa_volatile_type(converter.genType(sym)));
+}
diff --git a/flang/test/Lower/init-local-zero.f90 
b/flang/test/Lower/init-local-zero.f90
index 2ed8ca2f615dd..804169c7e4f8d 100644
--- a/flang/test/Lower/init-local-zero.f90
+++ b/flang/test/Lower/init-local-zero.f90
@@ -45,25 +45,12 @@ subroutine uninitialized_complex
 !CHECK: %[[ONE:.*]] = arith.constant 1 : index
 !CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.char<1> {bindc_name = "x", 
uniq_name = "_QFuninitialized_characterEx"}
 !CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] typeparams %[[ONE]] 
{uniq_name = "_QFuninitialized_characterEx"} : (!fir.ref<!fir.char<1>>, index) 
-> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
+!CHECK: %[[ZERO:.*]] = arith.constant 0 : i8
 !CHECK: %[[CVT:.*]] = fir.convert %[[ONE]] : (index) -> i64
 !CHECK: %[[CONST:.*]] = arith.constant 1 : i64
 !CHECK: %[[COUNT:.*]] = arith.muli %[[CVT]], %[[CONST]] : i64
 !CHECK: %[[CVT:.*]] = fir.convert %[[X]]#0 : (!fir.ref<!fir.char<1>>) -> 
!llvm.ptr
-!CHECK: %[[ZERO:.*]] = arith.constant 0 : i8
 !CHECK: "llvm.intr.memset"(%[[CVT]], %[[ZERO]], %[[COUNT]]) <{isVolatile = 
false}> : (!llvm.ptr, i8, i64) -> ()
 subroutine uninitialized_character
    character :: x
 end subroutine
-
-!CHECK: %[[X_ALLOCA:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = 
"x", uniq_name = "_QFallocatable_scalarEx"}
-!CHECK: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap<i32>
-!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap<i32>) -> 
!fir.box<!fir.heap<i32>>
-!CHECK: fir.store %[[EMBOX]] to %[[X_ALLOCA]] : 
!fir.ref<!fir.box<!fir.heap<i32>>>
-!CHECK: %[[X:.*]]:2 = hlfir.declare %[[X_ALLOCA]] {fortran_attrs = 
#fir.var_attrs<allocatable>, uniq_name = "_QFallocatable_scalarEx"} : 
(!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, 
!fir.ref<!fir.box<!fir.heap<i32>>>)
-!CHECK: %[[ZERO:.*]] = arith.constant 0 : i32
-!CHECK: %[[LOAD:.*]] = fir.load %[[X]]#0 : !fir.ref<!fir.box<!fir.heap<i32>>>
-!CHECK: %[[ADDR:.*]] = fir.box_addr %[[LOAD]] : (!fir.box<!fir.heap<i32>>) -> 
!fir.heap<i32>
-!CHECK: hlfir.assign %[[ZERO]] to %[[ADDR]] : i32, !fir.heap<i32>
-subroutine allocatable_scalar
-   integer, allocatable :: x
-end subroutine

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to