[flang-commits] [flang] 189cb7d - [flang] Lower optionals in GET_COMMAND_ARGUMENT and GET_ENVIRONMENT_VARIABLE

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Apr 11 00:35:10 PDT 2022


Author: jeanPerier
Date: 2022-04-11T09:33:49+02:00
New Revision: 189cb7df911b0d1aafbe60bec1a9e921827e9875

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

LOG: [flang] Lower optionals in GET_COMMAND_ARGUMENT and  GET_ENVIRONMENT_VARIABLE

Handle dynamic optional argument in GET_COMMAND_ARGUMENT and GET_ENVIRONMENT_VARIABLE
(previously compiled but caused segfaults). The previous code
handled static presence/absence aspects, but not when an absent dummy optional was
passed to one of the optional intrinsic arguments.

Simplify the runtime call lowering to simply lower the runtime call without
dealing with optionality there. This keeps the optional handling logic in
IntrinsicCall.cpp.

Note that the new code will generate some extra "if (not null addr )/then/else"
when the actual arguments are always there at runtime. That makes the implementation
a lot simpler/safer, and I think it is OK for now (I do not expect these runtime
function to be called in hot loop nests).

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

Added: 
    flang/test/Lower/Intrinsics/get_command_argument-optional.f90
    flang/test/Lower/Intrinsics/get_environment_variable-optional.f90

Modified: 
    flang/include/flang/Optimizer/Builder/FIRBuilder.h
    flang/include/flang/Optimizer/Builder/Runtime/Command.h
    flang/lib/Lower/IntrinsicCall.cpp
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/lib/Optimizer/Builder/Runtime/Command.cpp
    flang/test/Lower/Intrinsics/get_command_argument.f90
    flang/test/Lower/Intrinsics/get_environment_variable.f90
    flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index fae5cfa7c52ec..c350d44df33e1 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -247,6 +247,11 @@ class FirOpBuilder : public mlir::OpBuilder {
   mlir::Value createConvert(mlir::Location loc, mlir::Type toTy,
                             mlir::Value val);
 
+  /// Create a fir.store of \p val into \p addr. A lazy conversion
+  /// of \p val to the element type of \p addr is created if needed.
+  void createStoreWithConvert(mlir::Location loc, mlir::Value val,
+                              mlir::Value addr);
+
   /// Create a new FuncOp. If the function may have already been created, use
   /// `addNamedFunction` instead.
   mlir::FuncOp createFunction(mlir::Location loc, llvm::StringRef name,

diff  --git a/flang/include/flang/Optimizer/Builder/Runtime/Command.h b/flang/include/flang/Optimizer/Builder/Runtime/Command.h
index 7cd168bcaddb3..fb829f81b7970 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/Command.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/Command.h
@@ -23,23 +23,35 @@ namespace fir::runtime {
 /// Generate call to COMMAND_ARGUMENT_COUNT intrinsic runtime routine.
 mlir::Value genCommandArgumentCount(fir::FirOpBuilder &, mlir::Location);
 
-/// Generate call to GET_COMMAND_ARGUMENT intrinsic runtime routine.
-/// Note that GET_COMMAND_ARGUMENT intrinsic is split between 2 functions in
-/// implementation; ArgumentValue and ArgumentLength. So we handle each
-/// seperately.
-void genGetCommandArgument(fir::FirOpBuilder &, mlir::Location,
-                           mlir::Value number, mlir::Value value,
-                           mlir::Value length, mlir::Value status,
-                           mlir::Value errmsg);
-
-/// Generate call to GET_ENVIRONMENT_VARIABLE intrinsic runtime routine.
-/// Note that GET_ENVIRONMENT_ARGUMENT intrinsic is split between 2 functions in
-/// implementation; EnvVariableValue and EnvVariableLength. So we handle each
-/// seperately.
-void genGetEnvironmentVariable(fir::FirOpBuilder &, mlir::Location,
-                               mlir::Value number, mlir::Value value,
-                               mlir::Value length, mlir::Value status,
-                               mlir::Value trimName, mlir::Value errmsg);
+/// Generate a call to ArgumentValue runtime function which implements
+/// the part of GET_COMMAND_ARGUMENT related to VALUE, ERRMSG, and STATUS.
+/// \p value and \p errmsg must be fir.box that can be absent (but not null
+/// mlir values). The status value is returned.
+mlir::Value genArgumentValue(fir::FirOpBuilder &, mlir::Location,
+                             mlir::Value number, mlir::Value value,
+                             mlir::Value errmsg);
+
+/// Generate a call to ArgumentLength runtime function which implements
+/// the part of GET_COMMAND_ARGUMENT related to LENGTH.
+/// It returns the length of the \p number command arguments.
+mlir::Value genArgumentLength(fir::FirOpBuilder &, mlir::Location,
+                              mlir::Value number);
+
+/// Generate a call to EnvVariableValue runtime function which implements
+/// the part of GET_ENVIRONMENT_ARGUMENT related to VALUE, ERRMSG, and STATUS.
+/// \p value and \p errmsg must be fir.box that can be absent (but not null
+/// mlir values). The status value is returned. \p name must be a fir.box.
+/// and \p trimName a boolean value.
+mlir::Value genEnvVariableValue(fir::FirOpBuilder &, mlir::Location,
+                                mlir::Value name, mlir::Value value,
+                                mlir::Value trimName, mlir::Value errmsg);
+
+/// Generate a call to EnvVariableLength runtime function which implements
+/// the part of GET_ENVIRONMENT_ARGUMENT related to LENGTH.
+/// It returns the length of the \p number command arguments.
+/// \p name must be a fir.box and \p trimName a boolean value.
+mlir::Value genEnvVariableLength(fir::FirOpBuilder &, mlir::Location,
+                                 mlir::Value name, mlir::Value trimName);
 
 } // namespace fir::runtime
 #endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H

diff  --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp
index 9baedab34c462..1b02bdcf9e4d4 100644
--- a/flang/lib/Lower/IntrinsicCall.cpp
+++ b/flang/lib/Lower/IntrinsicCall.cpp
@@ -737,19 +737,19 @@ static constexpr IntrinsicHandler handlers[]{
     {"get_command_argument",
      &I::genGetCommandArgument,
      {{{"number", asValue},
-       {"value", asAddr},
+       {"value", asBox, handleDynamicOptional},
        {"length", asAddr},
        {"status", asAddr},
-       {"errmsg", asAddr}}},
+       {"errmsg", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
     {"get_environment_variable",
      &I::genGetEnvironmentVariable,
-     {{{"name", asValue},
-       {"value", asAddr},
+     {{{"name", asBox},
+       {"value", asBox, handleDynamicOptional},
        {"length", asAddr},
        {"status", asAddr},
-       {"trim_name", asValue},
-       {"errmsg", asAddr}}},
+       {"trim_name", asAddr},
+       {"errmsg", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
     {"iachar", &I::genIchar},
     {"iand", &I::genIand},
@@ -2399,100 +2399,119 @@ mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType,
 void IntrinsicLibrary::genGetCommandArgument(
     llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 5);
-
-  auto processCharBox = [&](llvm::Optional<fir::CharBoxValue> arg,
-                            mlir::Value &value) -> void {
-    if (arg.hasValue()) {
-      value = builder.createBox(loc, *arg);
-    } else {
-      value = builder
-                  .create<fir::AbsentOp>(
-                      loc, fir::BoxType::get(builder.getNoneType()))
-                  .getResult();
-    }
-  };
-
-  // Handle NUMBER argument
   mlir::Value number = fir::getBase(args[0]);
+  const fir::ExtendedValue &value = args[1];
+  const fir::ExtendedValue &length = args[2];
+  const fir::ExtendedValue &status = args[3];
+  const fir::ExtendedValue &errmsg = args[4];
+
   if (!number)
     fir::emitFatalError(loc, "expected NUMBER parameter");
 
-  // Handle optional VALUE argument
-  mlir::Value value;
-  llvm::Optional<fir::CharBoxValue> valBox;
-  if (const fir::CharBoxValue *charBox = args[1].getCharBox())
-    valBox = *charBox;
-  processCharBox(valBox, value);
-
-  // Handle optional LENGTH argument
-  mlir::Value length = fir::getBase(args[2]);
-
-  // Handle optional STATUS argument
-  mlir::Value status = fir::getBase(args[3]);
-
-  // Handle optional ERRMSG argument
-  mlir::Value errmsg;
-  llvm::Optional<fir::CharBoxValue> errmsgBox;
-  if (const fir::CharBoxValue *charBox = args[4].getCharBox())
-    errmsgBox = *charBox;
-  processCharBox(errmsgBox, errmsg);
-
-  fir::runtime::genGetCommandArgument(builder, loc, number, value, length,
-                                      status, errmsg);
+  if (isStaticallyPresent(value) || isStaticallyPresent(status) ||
+      isStaticallyPresent(errmsg)) {
+    mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
+    mlir::Value valBox =
+        isStaticallyPresent(value)
+            ? fir::getBase(value)
+            : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+    mlir::Value errBox =
+        isStaticallyPresent(errmsg)
+            ? fir::getBase(errmsg)
+            : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+    mlir::Value stat =
+        fir::runtime::genArgumentValue(builder, loc, number, valBox, errBox);
+    if (isStaticallyPresent(status)) {
+      mlir::Value statAddr = fir::getBase(status);
+      mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr);
+      builder.genIfThen(loc, statIsPresentAtRuntime)
+          .genThen(
+              [&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
+          .end();
+    }
+  }
+  if (isStaticallyPresent(length)) {
+    mlir::Value lenAddr = fir::getBase(length);
+    mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr);
+    builder.genIfThen(loc, lenIsPresentAtRuntime)
+        .genThen([&]() {
+          mlir::Value len =
+              fir::runtime::genArgumentLength(builder, loc, number);
+          builder.createStoreWithConvert(loc, len, lenAddr);
+        })
+        .end();
+  }
 }
 
 // GET_ENVIRONMENT_VARIABLE
 void IntrinsicLibrary::genGetEnvironmentVariable(
     llvm::ArrayRef<fir::ExtendedValue> args) {
   assert(args.size() == 6);
+  mlir::Value name = fir::getBase(args[0]);
+  const fir::ExtendedValue &value = args[1];
+  const fir::ExtendedValue &length = args[2];
+  const fir::ExtendedValue &status = args[3];
+  const fir::ExtendedValue &trimName = args[4];
+  const fir::ExtendedValue &errmsg = args[5];
 
-  auto processCharBox = [&](llvm::Optional<fir::CharBoxValue> arg,
-                            mlir::Value &value) -> void {
-    if (arg.hasValue()) {
-      value = builder.createBox(loc, *arg);
-    } else {
-      value = builder
-                  .create<fir::AbsentOp>(
-                      loc, fir::BoxType::get(builder.getNoneType()))
-                  .getResult();
-    }
-  };
-
-  // Handle NAME argument
-  mlir::Value name;
-  if (const fir::CharBoxValue *charBox = args[0].getCharBox()) {
-    llvm::Optional<fir::CharBoxValue> nameBox = *charBox;
-    assert(nameBox.hasValue());
-    name = builder.createBox(loc, *nameBox);
+  // Handle optional TRIM_NAME argument
+  mlir::Value trim;
+  if (isStaticallyAbsent(trimName)) {
+    trim = builder.createBool(loc, true);
+  } else {
+    mlir::Type i1Ty = builder.getI1Type();
+    mlir::Value trimNameAddr = fir::getBase(trimName);
+    mlir::Value trimNameIsPresentAtRuntime =
+        builder.genIsNotNull(loc, trimNameAddr);
+    trim = builder
+               .genIfOp(loc, {i1Ty}, trimNameIsPresentAtRuntime,
+                        /*withElseRegion=*/true)
+               .genThen([&]() {
+                 auto trimLoad = builder.create<fir::LoadOp>(loc, trimNameAddr);
+                 mlir::Value cast = builder.createConvert(loc, i1Ty, trimLoad);
+                 builder.create<fir::ResultOp>(loc, cast);
+               })
+               .genElse([&]() {
+                 mlir::Value trueVal = builder.createBool(loc, true);
+                 builder.create<fir::ResultOp>(loc, trueVal);
+               })
+               .getResults()[0];
   }
 
-  // Handle optional VALUE argument
-  mlir::Value value;
-  llvm::Optional<fir::CharBoxValue> valBox;
-  if (const fir::CharBoxValue *charBox = args[1].getCharBox())
-    valBox = *charBox;
-  processCharBox(valBox, value);
-
-  // Handle optional LENGTH argument
-  mlir::Value length = fir::getBase(args[2]);
-
-  // Handle optional STATUS argument
-  mlir::Value status = fir::getBase(args[3]);
+  if (isStaticallyPresent(value) || isStaticallyPresent(status) ||
+      isStaticallyPresent(errmsg)) {
+    mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
+    mlir::Value valBox =
+        isStaticallyPresent(value)
+            ? fir::getBase(value)
+            : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+    mlir::Value errBox =
+        isStaticallyPresent(errmsg)
+            ? fir::getBase(errmsg)
+            : builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
+    mlir::Value stat = fir::runtime::genEnvVariableValue(builder, loc, name,
+                                                         valBox, trim, errBox);
+    if (isStaticallyPresent(status)) {
+      mlir::Value statAddr = fir::getBase(status);
+      mlir::Value statIsPresentAtRuntime = builder.genIsNotNull(loc, statAddr);
+      builder.genIfThen(loc, statIsPresentAtRuntime)
+          .genThen(
+              [&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
+          .end();
+    }
+  }
 
-  // Handle optional TRIM_NAME argument
-  mlir::Value trim_name = isStaticallyAbsent(args[4])
-                              ? builder.createBool(loc, true)
-                              : fir::getBase(args[4]);
-
-  // Handle optional ERRMSG argument
-  mlir::Value errmsg;
-  llvm::Optional<fir::CharBoxValue> errmsgBox;
-  if (const fir::CharBoxValue *charBox = args[5].getCharBox())
-    errmsgBox = *charBox;
-  processCharBox(errmsgBox, errmsg);
-
-  fir::runtime::genGetEnvironmentVariable(builder, loc, name, value, length,
-                                          status, trim_name, errmsg);
+  if (isStaticallyPresent(length)) {
+    mlir::Value lenAddr = fir::getBase(length);
+    mlir::Value lenIsPresentAtRuntime = builder.genIsNotNull(loc, lenAddr);
+    builder.genIfThen(loc, lenIsPresentAtRuntime)
+        .genThen([&]() {
+          mlir::Value len =
+              fir::runtime::genEnvVariableLength(builder, loc, name, trim);
+          builder.createStoreWithConvert(loc, len, lenAddr);
+        })
+        .end();
+  }
 }
 
 // IAND

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index b53d79e61f897..83fe892d68e25 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -334,6 +334,14 @@ mlir::Value fir::FirOpBuilder::createConvert(mlir::Location loc,
   return val;
 }
 
+void fir::FirOpBuilder::createStoreWithConvert(mlir::Location loc,
+                                               mlir::Value val,
+                                               mlir::Value addr) {
+  mlir::Value cast =
+      createConvert(loc, fir::unwrapRefType(addr.getType()), val);
+  create<fir::StoreOp>(loc, cast, addr);
+}
+
 fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc,
                                                       llvm::StringRef data) {
   auto type = fir::CharacterType::get(getContext(), 1, data.size());

diff  --git a/flang/lib/Optimizer/Builder/Runtime/Command.cpp b/flang/lib/Optimizer/Builder/Runtime/Command.cpp
index 817fceb62be5d..9e12f649f95e7 100644
--- a/flang/lib/Optimizer/Builder/Runtime/Command.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/Command.cpp
@@ -32,96 +32,55 @@ mlir::Value fir::runtime::genCommandArgumentCount(fir::FirOpBuilder &builder,
   return builder.create<fir::CallOp>(loc, argumentCountFunc).getResult(0);
 }
 
-void fir::runtime::genGetCommandArgument(fir::FirOpBuilder &builder,
-                                         mlir::Location loc, mlir::Value number,
-                                         mlir::Value value, mlir::Value length,
-                                         mlir::Value status,
-                                         mlir::Value errmsg) {
+mlir::Value fir::runtime::genArgumentValue(fir::FirOpBuilder &builder,
+                                           mlir::Location loc,
+                                           mlir::Value number,
+                                           mlir::Value value,
+                                           mlir::Value errmsg) {
   auto argumentValueFunc =
       fir::runtime::getRuntimeFunc<mkRTKey(ArgumentValue)>(loc, builder);
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, argumentValueFunc.getFunctionType(), number, value, errmsg);
+  return builder.create<fir::CallOp>(loc, argumentValueFunc, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genArgumentLength(fir::FirOpBuilder &builder,
+                                            mlir::Location loc,
+                                            mlir::Value number) {
   auto argumentLengthFunc =
       fir::runtime::getRuntimeFunc<mkRTKey(ArgumentLength)>(loc, builder);
-
-  mlir::Value valueResult;
-  // Run `ArgumentValue` intrinsic only if we have a "value" in either "VALUE",
-  // "STATUS" or "ERRMSG" parameters.
-  if (!isAbsent(value) || status || !isAbsent(errmsg)) {
-    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-        builder, loc, argumentValueFunc.getFunctionType(), number, value,
-        errmsg);
-    valueResult =
-        builder.create<fir::CallOp>(loc, argumentValueFunc, args).getResult(0);
-  }
-
-  // Only save result of `ArgumentValue` if "STATUS" parameter has been given
-  if (status) {
-    const mlir::Value statusLoaded = builder.create<fir::LoadOp>(loc, status);
-    mlir::Value resultCast =
-        builder.createConvert(loc, statusLoaded.getType(), valueResult);
-    builder.create<fir::StoreOp>(loc, resultCast, status);
-  }
-
-  // Only run `ArgumentLength` intrinsic if "LENGTH" parameter provided
-  if (length) {
-    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-        builder, loc, argumentLengthFunc.getFunctionType(), number);
-    mlir::Value result =
-        builder.create<fir::CallOp>(loc, argumentLengthFunc, args).getResult(0);
-    const mlir::Value valueLoaded = builder.create<fir::LoadOp>(loc, length);
-    mlir::Value resultCast =
-        builder.createConvert(loc, valueLoaded.getType(), result);
-    builder.create<fir::StoreOp>(loc, resultCast, length);
-  }
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, argumentLengthFunc.getFunctionType(), number);
+  return builder.create<fir::CallOp>(loc, argumentLengthFunc, args)
+      .getResult(0);
 }
 
-void fir::runtime::genGetEnvironmentVariable(
+mlir::Value fir::runtime::genEnvVariableValue(
     fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value name,
-    mlir::Value value, mlir::Value length, mlir::Value status,
-    mlir::Value trimName, mlir::Value errmsg) {
+    mlir::Value value, mlir::Value trimName, mlir::Value errmsg) {
   auto valueFunc =
       fir::runtime::getRuntimeFunc<mkRTKey(EnvVariableValue)>(loc, builder);
+  mlir::FunctionType valueFuncTy = valueFunc.getFunctionType();
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, valueFuncTy.getInput(5));
+  llvm::SmallVector<mlir::Value> args =
+      fir::runtime::createArguments(builder, loc, valueFuncTy, name, value,
+                                    trimName, errmsg, sourceFile, sourceLine);
+  return builder.create<fir::CallOp>(loc, valueFunc, args).getResult(0);
+}
+
+mlir::Value fir::runtime::genEnvVariableLength(fir::FirOpBuilder &builder,
+                                               mlir::Location loc,
+                                               mlir::Value name,
+                                               mlir::Value trimName) {
   auto lengthFunc =
       fir::runtime::getRuntimeFunc<mkRTKey(EnvVariableLength)>(loc, builder);
-
-  mlir::Value sourceFile;
-  mlir::Value sourceLine;
-  // We only need `sourceFile` and `sourceLine` variables when calling either
-  // `EnvVariableValue` or `EnvVariableLength` below.
-  if (!isAbsent(value) || status || !isAbsent(errmsg) || length) {
-    sourceFile = fir::factory::locationToFilename(builder, loc);
-    sourceLine = fir::factory::locationToLineNo(
-        builder, loc, valueFunc.getFunctionType().getInput(5));
-  }
-
-  mlir::Value valueResult;
-  // Run `EnvVariableValue` intrinsic only if we have a "value" in either
-  // "VALUE", "STATUS" or "ERRMSG" parameters.
-  if (!isAbsent(value) || status || !isAbsent(errmsg)) {
-    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-        builder, loc, valueFunc.getFunctionType(), name, value, trimName,
-        errmsg, sourceFile, sourceLine);
-    valueResult =
-        builder.create<fir::CallOp>(loc, valueFunc, args).getResult(0);
-  }
-
-  // Only save result of `EnvVariableValue` if "STATUS" parameter provided
-  if (status) {
-    const mlir::Value statusLoaded = builder.create<fir::LoadOp>(loc, status);
-    mlir::Value resultCast =
-        builder.createConvert(loc, statusLoaded.getType(), valueResult);
-    builder.create<fir::StoreOp>(loc, resultCast, status);
-  }
-
-  // Only run `EnvVariableLength` intrinsic if "LENGTH" parameter provided
-  if (length) {
-    llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
-        builder, loc, lengthFunc.getFunctionType(), name, trimName, sourceFile,
-        sourceLine);
-    mlir::Value result =
-        builder.create<fir::CallOp>(loc, lengthFunc, args).getResult(0);
-    const mlir::Value lengthLoaded = builder.create<fir::LoadOp>(loc, length);
-    mlir::Value resultCast =
-        builder.createConvert(loc, lengthLoaded.getType(), result);
-    builder.create<fir::StoreOp>(loc, resultCast, length);
-  }
+  mlir::FunctionType lengthFuncTy = lengthFunc.getFunctionType();
+  mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
+  mlir::Value sourceLine =
+      fir::factory::locationToLineNo(builder, loc, lengthFuncTy.getInput(3));
+  llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
+      builder, loc, lengthFuncTy, name, trimName, sourceFile, sourceLine);
+  return builder.create<fir::CallOp>(loc, lengthFunc, args).getResult(0);
 }

diff  --git a/flang/test/Lower/Intrinsics/get_command_argument-optional.f90 b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90
new file mode 100644
index 0000000000000..bab0e6c98ddff
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/get_command_argument-optional.f90
@@ -0,0 +1,43 @@
+! Test GET_COMMAND_ARGUMENT with dynamically optional arguments.
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func @_QPtest(
+! CHECK-SAME:  %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "number", fir.optional},
+! CHECK-SAME:  %[[VAL_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "value", fir.optional},
+! CHECK-SAME:  %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional},
+! CHECK-SAME:  %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional},
+! CHECK-SAME:  %[[VAL_4:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg", fir.optional}) {
+subroutine test(number, value, length, status, errmsg) 
+  integer, optional :: number, status, length
+  character(*), optional :: value, errmsg
+  ! Note: number cannot be absent
+  call get_command_argument(number, value, length, status, errmsg) 
+! CHECK:  %[[VAL_5:.*]]:2 = fir.unboxchar %[[VAL_4]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK:  %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK:  %[[VAL_9:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_10:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_11:.*]] = arith.select %[[VAL_8]], %[[VAL_9]], %[[VAL_10]] : !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_12:.*]] = fir.is_present %[[VAL_5]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK:  %[[VAL_13:.*]] = fir.embox %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_14:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_15:.*]] = arith.select %[[VAL_12]], %[[VAL_13]], %[[VAL_14]] : !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_16:.*]] = fir.convert %[[VAL_11]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:  %[[VAL_17:.*]] = fir.convert %[[VAL_15]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:  %[[VAL_18:.*]] = fir.call @_FortranAArgumentValue(%[[VAL_7]], %[[VAL_16]], %[[VAL_17]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
+! CHECK:  %[[VAL_19:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i32>) -> i64
+! CHECK:  %[[VAL_20:.*]] = arith.constant 0 : i64
+! CHECK:  %[[VAL_21:.*]] = arith.cmpi ne, %[[VAL_19]], %[[VAL_20]] : i64
+! CHECK:  fir.if %[[VAL_21]] {
+! CHECK:    fir.store %[[VAL_18]] to %[[VAL_3]] : !fir.ref<i32>
+! CHECK:  }
+! CHECK:  %[[VAL_22:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<i32>) -> i64
+! CHECK:  %[[VAL_23:.*]] = arith.constant 0 : i64
+! CHECK:  %[[VAL_24:.*]] = arith.cmpi ne, %[[VAL_22]], %[[VAL_23]] : i64
+! CHECK:  fir.if %[[VAL_24]] {
+! CHECK:    %[[VAL_25:.*]] = fir.call @_FortranAArgumentLength(%[[VAL_7]]) : (i32) -> i64
+! CHECK:    %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i64) -> i32
+! CHECK:    fir.store %[[VAL_26]] to %[[VAL_2]] : !fir.ref<i32>
+! CHECK:  }
+end subroutine

diff  --git a/flang/test/Lower/Intrinsics/get_command_argument.f90 b/flang/test/Lower/Intrinsics/get_command_argument.f90
index bcd62babf362f..3dc3f9ac20cd9 100644
--- a/flang/test/Lower/Intrinsics/get_command_argument.f90
+++ b/flang/test/Lower/Intrinsics/get_command_argument.f90
@@ -47,11 +47,11 @@ subroutine all_arguments(num, value, length, status, errmsg)
 ! CHECK-NEXT: %[[errmsgBuffer:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
 ! CHECK-32-NEXT: %[[statusResult:.*]] = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
 ! CHECK-64-NEXT: %[[statusResult32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[valueBuffer]], %[[errmsgBuffer]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
-! CHECK-64-NEXT: %[[statusResult:.*]] = fir.convert %[[statusResult32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[statusResult]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
-! CHECK-32-NEXT: %[[lengthResult64:.*]] = fir.call @_FortranAArgumentLength(%[[numUnboxed]]) : (i32) -> i64
-! CHECK-64-NEXT: %[[lengthResult:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
+! CHECK-64: %[[statusResult:.*]] = fir.convert %[[statusResult32]] : (i32) -> i64
+! CHECK: fir.store %[[statusResult]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
+! CHECK-32: %[[lengthResult64:.*]] = fir.call @_FortranAArgumentLength(%[[numUnboxed]]) : (i32) -> i64
+! CHECK-64: %[[lengthResult:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
 ! CHECK-32-NEXT: %[[lengthResult:.*]] = fir.convert %[[lengthResult64]] : (i64) -> i32
 ! CHECK-NEXT: fir.store %[[lengthResult]] to %[[length]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
 end subroutine all_arguments
@@ -63,12 +63,11 @@ subroutine number_and_length_only(num, length)
     call get_command_argument(num, LENGTH=length)
 ! CHECK-NOT: fir.call @_FortranAArgumentValue
 ! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
-! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAArgumentLength(%[[numLoaded]]) : (i32) -> i64
-! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
+! CHECK-32: %[[result64:.*]] = fir.call @_FortranAArgumentLength(%[[numLoaded]]) : (i32) -> i64
+! CHECK-64: %[[result:.*]] = fir.call @_FortranAArgumentLength(%[[numCast]]) : (i32) -> i64
 ! CHECK-32-NEXT: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
 ! CHECK-NEXT: fir.store %[[result]] to %[[length]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
 end subroutine number_and_length_only
 
 ! CHECK-LABEL: func @_QPnumber_and_status_only(
@@ -79,11 +78,11 @@ subroutine number_and_status_only(num, status)
 ! CHECK: %[[numLoaded:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
 ! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numLoaded]] : (i64) -> i32
 ! CHECK-32-NEXT: %[[result:.*]] = fir.call @_FortranAArgumentValue(%[[numLoaded]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
 ! CHECK-64-NEXT: %[[result32:.*]] = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
-! CHECK-64-NEXT: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64
-! CHECK-32-NEXT: fir.store %[[result]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[result:.*]] = fir.convert %[[result32]] : (i32) -> i64
+! CHECK-32: fir.store %[[result]] to %[[status]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
 ! CHECK-NOT: fir.call @_FortranAArgumentLength
 end subroutine number_and_status_only
 
@@ -96,9 +95,9 @@ subroutine number_and_errmsg_only(num, errmsg)
 ! CHECK: %[[errmsgUnboxed:.*]]:2 = fir.unboxchar %[[errmsg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK-NEXT: %[[errmsgLength:.*]] = arith.constant 32 : index
 ! CHECK-NEXT: %[[numUnboxed:.*]] = fir.load %[[num]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnboxed]]#0 typeparams %[[errmsgLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-64-NEXT: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
+! CHECK-64: %[[numCast:.*]] = fir.convert %[[numUnboxed]] : (i64) -> i32
 ! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
 ! CHECK-32-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numUnboxed]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32
 ! CHECK-64-NEXT: %{{[0-9]+}} = fir.call @_FortranAArgumentValue(%[[numCast]], %[[value]], %[[errmsg]]) : (i32, !fir.box<none>, !fir.box<none>) -> i32

diff  --git a/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90 b/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90
new file mode 100644
index 0000000000000..90e8eff6bfef1
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/get_environment_variable-optional.f90
@@ -0,0 +1,60 @@
+! Test GET_ENVIRONMENT_VARIABLE with dynamically optional arguments.
+! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+
+! CHECK-LABEL: func @_QPtest(
+! CHECK-SAME:  %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "name", fir.optional},
+! CHECK-SAME:  %[[VAL_1:.*]]: !fir.boxchar<1> {fir.bindc_name = "value", fir.optional},
+! CHECK-SAME:  %[[VAL_2:.*]]: !fir.ref<i32> {fir.bindc_name = "length", fir.optional},
+! CHECK-SAME:  %[[VAL_3:.*]]: !fir.ref<i32> {fir.bindc_name = "status", fir.optional},
+! CHECK-SAME:  %[[VAL_4:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "trim_name", fir.optional},
+! CHECK-SAME:  %[[VAL_5:.*]]: !fir.boxchar<1> {fir.bindc_name = "errmsg", fir.optional}) {
+subroutine test(name, value, length, status, trim_name, errmsg) 
+  integer, optional :: status, length
+  character(*), optional :: name, value, errmsg
+  logical, optional :: trim_name
+  ! Note: name is not optional in et_environment_variable and must be present
+  call get_environment_variable(name, value, length, status, trim_name, errmsg) 
+! CHECK:  %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_5]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK:  %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK:  %[[VAL_8:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK:  %[[VAL_9:.*]] = fir.embox %[[VAL_7]]#0 typeparams %[[VAL_7]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_10:.*]] = fir.is_present %[[VAL_8]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK:  %[[VAL_11:.*]] = fir.embox %[[VAL_8]]#0 typeparams %[[VAL_8]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_12:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_13:.*]] = arith.select %[[VAL_10]], %[[VAL_11]], %[[VAL_12]] : !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_14:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.ref<!fir.char<1,?>>) -> i1
+! CHECK:  %[[VAL_15:.*]] = fir.embox %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_16:.*]] = fir.absent !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_17:.*]] = arith.select %[[VAL_14]], %[[VAL_15]], %[[VAL_16]] : !fir.box<!fir.char<1,?>>
+! CHECK:  %[[VAL_18:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.logical<4>>) -> i64
+! CHECK:  %[[VAL_19:.*]] = arith.constant 0 : i64
+! CHECK:  %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i64
+! CHECK:  %[[VAL_21:.*]] = fir.if %[[VAL_20]] -> (i1) {
+! CHECK:    %[[VAL_22:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.logical<4>>
+! CHECK:    %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1
+! CHECK:    fir.result %[[VAL_23]] : i1
+! CHECK:  } else {
+! CHECK:    %[[VAL_24:.*]] = arith.constant true
+! CHECK:    fir.result %[[VAL_24]] : i1
+! CHECK:  }
+! CHECK:  %[[VAL_27:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:  %[[VAL_28:.*]] = fir.convert %[[VAL_13]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:  %[[VAL_29:.*]] = fir.convert %[[VAL_17]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:  %[[VAL_31:.*]] = fir.call @_FortranAEnvVariableValue(%[[VAL_27]], %[[VAL_28]], %[[VAL_32:.*]], %[[VAL_29]], %{{.*}}, %{{.*}}) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+! CHECK:  %[[VAL_33:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<i32>) -> i64
+! CHECK:  %[[VAL_34:.*]] = arith.constant 0 : i64
+! CHECK:  %[[VAL_35:.*]] = arith.cmpi ne, %[[VAL_33]], %[[VAL_34]] : i64
+! CHECK:  fir.if %[[VAL_35]] {
+! CHECK:    fir.store %[[VAL_31]] to %[[VAL_3]] : !fir.ref<i32>
+! CHECK:  }
+! CHECK:  %[[VAL_36:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<i32>) -> i64
+! CHECK:  %[[VAL_37:.*]] = arith.constant 0 : i64
+! CHECK:  %[[VAL_38:.*]] = arith.cmpi ne, %[[VAL_36]], %[[VAL_37]] : i64
+! CHECK:  fir.if %[[VAL_38]] {
+! CHECK:    %[[VAL_41:.*]] = fir.convert %[[VAL_9]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+! CHECK:    %[[VAL_43:.*]] = fir.call @_FortranAEnvVariableLength(%[[VAL_41]], %[[VAL_32]], %{{.*}}, %{{.*}}) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK:    %[[VAL_44:.*]] = fir.convert %[[VAL_43]] : (i64) -> i32
+! CHECK:    fir.store %[[VAL_44]] to %[[VAL_2]] : !fir.ref<i32>
+! CHECK:  }
+end subroutine

diff  --git a/flang/test/Lower/Intrinsics/get_environment_variable.f90 b/flang/test/Lower/Intrinsics/get_environment_variable.f90
index 98795c0b0212f..b0a889c375f33 100644
--- a/flang/test/Lower/Intrinsics/get_environment_variable.f90
+++ b/flang/test/Lower/Intrinsics/get_environment_variable.f90
@@ -46,7 +46,7 @@ subroutine name_and_length_only(name, length)
 ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
 ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %0#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
 ! CHECK-NEXT: %true = arith.constant true
-! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
+! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
 ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 7]] : i32
 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
 ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
@@ -54,7 +54,6 @@ subroutine name_and_length_only(name, length)
 ! CHECK-64-NEXT: %[[length:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %true, %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
 ! CHECK-32-NEXT: %[[length:.*]] = fir.convert %[[length64]] : (i64) -> i32
 ! CHECK-NEXT: fir.store %[[length]] to %[[lengthArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
 end subroutine name_and_length_only
 
 ! CHECK-LABEL: func @_QPname_and_status_only(
@@ -67,8 +66,8 @@ subroutine name_and_status_only(name, status)
 ! CHECK: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
 ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %true = arith.constant true
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %[[errmsg:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
 ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 8]] : i32
@@ -76,9 +75,8 @@ subroutine name_and_status_only(name, status)
 ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[sourceFileLength]]>>) -> !fir.ref<i8>
 ! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
 ! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %true, %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
-! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
+! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
+! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
 end subroutine name_and_status_only
 
 ! CHECK-LABEL: func @_QPname_and_trim_name_only(
@@ -104,9 +102,9 @@ subroutine name_and_errmsg_only(name, errmsg)
 ! CHECK-NEXT: %[[nameUnbox:.*]]:2 = fir.unboxchar %[[nameArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
 ! CHECK-NEXT: %[[nameBox:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
-! CHECK-NEXT: %true = arith.constant true
 ! CHECK-NEXT: %[[errmsgBox:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %c32 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+! CHECK-NEXT: %true = arith.constant true
+! CHECK-NEXT: %[[value:.*]] = fir.absent !fir.box<none>
 ! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.{{.*}}) : !fir.ref<!fir.char<1,[[sourceFileLength:.*]]>>
 ! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 10]] : i32
 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBox]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
@@ -134,27 +132,33 @@ subroutine all_arguments(name, value, length, status, trim_name, errmsg)
 ! CHECK-NEXT: %[[nameLength:.*]] = arith.constant 32 : index
 ! CHECK-NEXT: %[[valueUnbox:.*]]:2 = fir.unboxchar %[[valueArg]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
 ! CHECK-NEXT: %[[valueLength:.*]] = arith.constant 32 : index
-! CHECK-NEXT: %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref<!fir.logical<4>>
 ! CHECK-NEXT: %[[nameBoxed:.*]] = fir.embox %[[nameUnbox]]#0 typeparams %[[nameLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
 ! CHECK-NEXT: %[[valueBoxed:.*]] = fir.embox %[[valueUnbox]]#0 typeparams %[[valueLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
 ! CHECK-NEXT: %[[errmsgBoxed:.*]] = fir.embox %[[errmsgUnbox]]#0 typeparams %[[errmsgLength]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
-! CHECK-NEXT: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.[[fileString:.*]]) : !fir.ref<!fir.char<1,[[fileStringLength:.*]]>>
-! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 12]] : i32
+! CHECK:      %[[trimName:.*]] = fir.if %{{.*}} -> (i1) {
+! CHECK-NEXT:   %[[trimNameLoaded:.*]] = fir.load %[[trimNameArg]] : !fir.ref<!fir.logical<4>>
+! CHECK-NEXT:   %[[trimCast:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
+! CHECK-NEXT:   fir.result %[[trimCast]] : i1
+! CHECK-NEXT: } else {
+! CHECK-NEXT:   %[[trueVal:.*]] = arith.constant true
+! CHECK-NEXT:   fir.result %[[trueVal]] : i1
+! CHECK-NEXT: }
+! CHECK: %[[sourceFileString:.*]] = fir.address_of(@_QQcl.[[fileString:.*]]) : !fir.ref<!fir.char<1,[[fileStringLength:.*]]>>
+! CHECK-NEXT: %[[sourceLine:.*]] = arith.constant [[# @LINE - 19]] : i32
 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
 ! CHECK-NEXT: %[[value:.*]] = fir.convert %[[valueBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
-! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
 ! CHECK-NEXT: %[[errmsg:.*]] = fir.convert %[[errmsgBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
 ! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
 ! CHECK-32-NEXT: %[[status:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
 ! CHECK-64-NEXT: %[[status32:.*]] = fir.call @_FortranAEnvVariableValue(%[[name]], %[[value]], %[[trimName]], %[[errmsg]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, !fir.box<none>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
-! CHECK-64-NEXT: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
-! CHECK-NEXT: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK-64: %[[status:.*]] = fir.convert %[[status32]] : (i32) -> i64
+! CHECK: fir.store %[[status]] to %[[statusArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
+! CHECK: %[[sourceFileString2:.*]] = fir.address_of(@_QQcl.[[fileString]]) : !fir.ref<!fir.char<1,[[fileStringLength]]>>
+! CHECK-NEXT: %[[sourceLine2:.*]] = arith.constant [[# @LINE - 29]] : i32
 ! CHECK-NEXT: %[[name:.*]] = fir.convert %[[nameBoxed]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
-! CHECK-NEXT: %[[trimName:.*]] = fir.convert %[[trimNameLoaded]] : (!fir.logical<4>) -> i1
-! CHECK-NEXT: %[[sourceFile:.*]] = fir.convert %[[sourceFileString]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
-! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
-! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile]], %[[sourceLine]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
-! CHECK-32-NEXT: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
+! CHECK-NEXT: %[[sourceFile2:.*]] = fir.convert %[[sourceFileString2]] : (!fir.ref<!fir.char<1,[[fileStringLength]]>>) -> !fir.ref<i8>
+! CHECK-32-NEXT: %[[result64:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK-64-NEXT: %[[result:.*]] = fir.call @_FortranAEnvVariableLength(%[[name]], %[[trimName]], %[[sourceFile2]], %[[sourceLine2]]) : (!fir.box<none>, i1, !fir.ref<i8>, i32) -> i64
+! CHECK-32: %[[result:.*]] = fir.convert %[[result64]] : (i64) -> i32
 ! CHECK-NEXT: fir.store %[[result]] to %[[lengthArg]] : !fir.ref<i[[DEFAULT_INTEGER_SIZE]]>
-! CHECK-NEXT: return
 end subroutine all_arguments

diff  --git a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
index 1e48cfaf65124..577e525896645 100644
--- a/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
+++ b/flang/unittests/Optimizer/Builder/Runtime/CommandTest.cpp
@@ -17,43 +17,51 @@ TEST_F(RuntimeCallTest, genCommandArgumentCountTest) {
       /*addLocArgs=*/false);
 }
 
-TEST_F(RuntimeCallTest, genGetCommandArgument) {
+TEST_F(RuntimeCallTest, genArgumentValue) {
   mlir::Location loc = firBuilder->getUnknownLoc();
   mlir::Type intTy = firBuilder->getDefaultIntegerType();
   mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
   mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
   mlir::Value value = firBuilder->create<fir::UndefOp>(loc, charTy);
   mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, charTy);
-  // genGetCommandArgument expects `length` and `status` to be memory references
-  mlir::Value length = firBuilder->create<fir::AllocaOp>(loc, intTy);
-  mlir::Value status = firBuilder->create<fir::AllocaOp>(loc, intTy);
+  mlir::Value result =
+      fir::runtime::genArgumentValue(*firBuilder, loc, number, value, errmsg);
+  checkCallOp(result.getDefiningOp(), "_FortranAArgumentValue", /*nbArgs=*/3,
+      /*addLocArgs=*/false);
+}
 
-  fir::runtime::genGetCommandArgument(
-      *firBuilder, loc, number, value, length, status, errmsg);
-  checkCallOpFromResultBox(
-      value, "_FortranAArgumentValue", /*nbArgs=*/3, /*addLocArgs=*/false);
-  mlir::Block *block = firBuilder->getBlock();
-  EXPECT_TRUE(block) << "Failed to retrieve the block!";
-  checkBlockForCallOp(block, "_FortranAArgumentLength", /*nbArgs=*/1);
+TEST_F(RuntimeCallTest, genArgumentLen) {
+  mlir::Location loc = firBuilder->getUnknownLoc();
+  mlir::Type intTy = firBuilder->getDefaultIntegerType();
+  mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
+  mlir::Value result =
+      fir::runtime::genArgumentLength(*firBuilder, loc, number);
+  checkCallOp(result.getDefiningOp(), "_FortranAArgumentLength", /*nbArgs=*/1,
+      /*addLocArgs=*/false);
 }
 
-TEST_F(RuntimeCallTest, genGetEnvironmentVariable) {
+TEST_F(RuntimeCallTest, genEnvVariableValue) {
   mlir::Location loc = firBuilder->getUnknownLoc();
   mlir::Type intTy = firBuilder->getDefaultIntegerType();
   mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
-  mlir::Value number = firBuilder->create<fir::UndefOp>(loc, intTy);
+  mlir::Value name = firBuilder->create<fir::UndefOp>(loc, charTy);
   mlir::Value value = firBuilder->create<fir::UndefOp>(loc, charTy);
   mlir::Value trimName = firBuilder->create<fir::UndefOp>(loc, i1Ty);
   mlir::Value errmsg = firBuilder->create<fir::UndefOp>(loc, charTy);
-  // genGetCommandArgument expects `length` and `status` to be memory references
-  mlir::Value length = firBuilder->create<fir::AllocaOp>(loc, intTy);
-  mlir::Value status = firBuilder->create<fir::AllocaOp>(loc, intTy);
+  mlir::Value result = fir::runtime::genEnvVariableValue(
+      *firBuilder, loc, name, value, trimName, errmsg);
+  checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableValue", /*nbArgs=*/4,
+      /*addLocArgs=*/true);
+}
 
-  fir::runtime::genGetEnvironmentVariable(
-      *firBuilder, loc, number, value, length, status, trimName, errmsg);
-  checkCallOpFromResultBox(
-      value, "_FortranAEnvVariableValue", /*nbArgs=*/6, /*addLocArgs=*/false);
-  mlir::Block *block = firBuilder->getBlock();
-  EXPECT_TRUE(block) << "Failed to retrieve the block!";
-  checkBlockForCallOp(block, "_FortranAEnvVariableLength", /*nbArgs=*/4);
+TEST_F(RuntimeCallTest, genEnvVariableLength) {
+  mlir::Location loc = firBuilder->getUnknownLoc();
+  mlir::Type intTy = firBuilder->getDefaultIntegerType();
+  mlir::Type charTy = fir::BoxType::get(firBuilder->getNoneType());
+  mlir::Value name = firBuilder->create<fir::UndefOp>(loc, charTy);
+  mlir::Value trimName = firBuilder->create<fir::UndefOp>(loc, i1Ty);
+  mlir::Value result =
+      fir::runtime::genEnvVariableLength(*firBuilder, loc, name, trimName);
+  checkCallOp(result.getDefiningOp(), "_FortranAEnvVariableLength",
+      /*nbArgs=*/2, /*addLocArgs=*/true);
 }


        


More information about the flang-commits mailing list