diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index ac7d4fbe23e67..d781650069442 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -217,7 +217,7 @@ static constexpr IntrinsicHandler handlers[]{ {"execute_command_line", &I::genExecuteCommandLine, {{{"command", asBox}, - {"wait", asValue, handleDynamicOptional}, + {"wait", asAddr, handleDynamicOptional}, {"exitstat", asBox, handleDynamicOptional}, {"cmdstat", asBox, handleDynamicOptional}, {"cmdmsg", asBox, handleDynamicOptional}}}, @@ -2914,7 +2914,9 @@ IntrinsicLibrary::genEoshift(mlir::Type resultType, void IntrinsicLibrary::genExecuteCommandLine( llvm::ArrayRef args) { assert(args.size() == 5); + mlir::Value command = fir::getBase(args[0]); + // Optional arguments: wait, exitstat, cmdstat, cmdmsg. const fir::ExtendedValue &wait = args[1]; const fir::ExtendedValue &exitstat = args[2]; const fir::ExtendedValue &cmdstat = args[3]; @@ -2925,9 +2927,30 @@ void IntrinsicLibrary::genExecuteCommandLine( mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType()); - mlir::Value waitBool = isStaticallyPresent(wait) - ? fir::getBase(wait) - : builder.createBool(loc, true); + mlir::Value waitBool; + if (isStaticallyAbsent(wait)) { + waitBool = builder.createBool(loc, true); + } else { + mlir::Type i1Ty = builder.getI1Type(); + mlir::Value waitAddr = fir::getBase(wait); + mlir::Value waitIsPresentAtRuntime = + builder.genIsNotNullAddr(loc, waitAddr); + waitBool = builder + .genIfOp(loc, {i1Ty}, waitIsPresentAtRuntime, + /*withElseRegion=*/true) + .genThen([&]() { + auto waitLoad = builder.create(loc, waitAddr); + mlir::Value cast = + builder.createConvert(loc, i1Ty, waitLoad); + builder.create(loc, cast); + }) + .genElse([&]() { + mlir::Value trueVal = builder.createBool(loc, true); + builder.create(loc, trueVal); + }) + .getResults()[0]; + } + mlir::Value exitstatBox = isStaticallyPresent(exitstat) ? fir::getBase(exitstat) diff --git a/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 b/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 index e51c0e5fca300..0b75a20216af7 100644 --- a/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 +++ b/flang/test/Lower/Intrinsics/execute_command_line-optional.f90 @@ -12,7 +12,10 @@ subroutine all_args_optional(command, isWait, exitVal, cmdVal, msg) LOGICAL, OPTIONAL :: isWait ! Note: command is not optional in execute_command_line and must be present call execute_command_line(command, isWait, exitVal, cmdVal, msg) -! CHECK: %[[cmdstatDeclare:.*]] = fir.declare %[[cmdstatArg]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFall_args_optionalEcmdval"} : (!fir.ref) -> !fir.ref +! CHECK-NEXT: %[[c14:.*]] = arith.constant 14 : i32 +! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[cmdstatDeclare:.*]] = fir.declare %[[cmdstatArg]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFall_args_optionalEcmdval"} : (!fir.ref) -> !fir.ref ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandUnbox]]#0 typeparams %[[commandUnbox]]#1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFall_args_optionalEcommand"} : (!fir.ref>, index) -> !fir.ref> ! CHECK-NEXT: %[[commandBoxTemp:.*]] = fir.emboxchar %[[commandDeclare]], %[[commandUnbox]]#1 : (!fir.ref>, index) -> !fir.boxchar<1> @@ -21,18 +24,10 @@ subroutine all_args_optional(command, isWait, exitVal, cmdVal, msg) ! CHECK-NEXT: %[[cmdmsgUnbox:.*]]:2 = fir.unboxchar %[[cmdmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgUnbox]]#0 typeparams %[[cmdmsgUnbox]]#1 {fortran_attrs = #fir.var_attrs, uniq_name = "_QFall_args_optionalEmsg"} : (!fir.ref>, index) -> !fir.ref> ! CHECK-NEXT: %[[cmdmsgBoxTemp:.*]] = fir.emboxchar %[[cmdmsgDeclare]], %[[cmdmsgUnbox]]#1 : (!fir.ref>, index) -> !fir.boxchar<1> -! CHECK-NEXT: %[[waitIsPresent:.*]] = fir.is_present %[[waitDeclare]] : (!fir.ref>) -> i1 ! CHECK-NEXT: %[[exitstatIsPresent:.*]] = fir.is_present %[[exitstatDeclare]] : (!fir.ref) -> i1 ! CHECK-NEXT: %[[cmdstatIsPresent:.*]] = fir.is_present %[[cmdstatDeclare]] : (!fir.ref) -> i1 ! CHECK-NEXT: %[[cmdmsgIsPresent:.*]] = fir.is_present %[[cmdmsgBoxTemp]] : (!fir.boxchar<1>) -> i1 ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]] typeparams %[[commandUnbox]]#1 : (!fir.ref>, index) -> !fir.box> -! CHECK-NEXT: %[[waitLoaded:.*]] = fir.if %[[waitIsPresent]] -> (!fir.logical<4>) { -! CHECK-NEXT: %[[VAL_31:.*]] = fir.load %[[waitDeclare]] : !fir.ref> -! CHECK-NEXT: fir.result %[[VAL_31]] : !fir.logical<4> -! CHECK-NEXT: } else { -! CHECK-NEXT: %[[VAL_31:.*]] = fir.convert %false : (i1) -> !fir.logical<4> -! CHECK-NEXT: fir.result %[[VAL_31]] : !fir.logical<4> -! CHECK-NEXT: } ! CHECK-NEXT: %[[exitstatArgBox:.*]] = fir.embox %[[exitstatDeclare]] : (!fir.ref) -> !fir.box ! CHECK-NEXT: %[[absentBoxi32:.*]] = fir.absent !fir.box ! CHECK-NEXT: %[[exitstatBox:.*]] = arith.select %[[exitstatIsPresent]], %[[exitstatArgBox]], %[[absentBoxi32]] : !fir.box @@ -41,11 +36,19 @@ subroutine all_args_optional(command, isWait, exitVal, cmdVal, msg) ! CHECK-NEXT: %[[cmdmsgArgBox:.*]] = fir.embox %[[cmdmsgDeclare]] typeparams %[[cmdmsgUnbox]]#1 : (!fir.ref>, index) -> !fir.box> ! CHECK-NEXT: %[[absentBox:.*]] = fir.absent !fir.box> ! CHECK-NEXT: %[[cmdmsgBox:.*]] = arith.select %[[cmdmsgIsPresent]], %[[cmdmsgArgBox]], %[[absentBox]] : !fir.box> +! CHECK-NEXT: %[[waitCast:.*]] = fir.convert %[[waitDeclare]] : (!fir.ref>) -> i64 +! CHECK-NEXT: %[[waitPresent:.*]] = arith.cmpi ne, %[[waitCast]], %[[c0]] : i64 +! CHECK-NEXT: %[[wait:.*]] = fir.if %[[waitPresent]] -> (i1) { +! CHECK-NEXT: %[[waitLoaded:.*]] = fir.load %[[waitDeclare]] : !fir.ref> +! CHECK-NEXT: %[[waitTrueVal:.*]] = fir.convert %[[waitLoaded]] : (!fir.logical<4>) -> i1 +! CHECK-NEXT: fir.result %[[waitTrueVal]] : i1 +! CHECK-NEXT: } else { +! CHECK-NEXT: fir.result %true : i1 +! CHECK-NEXT: } ! CHECK: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box>) -> !fir.box -! CHECK-NEXT: %[[wait:.*]] = fir.convert %[[waitLoaded]] : (!fir.logical<4>) -> i1 ! CHECK-NEXT: %[[exitstat:.*]] = fir.convert %[[exitstatBox]] : (!fir.box) -> !fir.box ! CHECK-NEXT: %[[cmdstat:.*]] = fir.convert %[[cmdstatBox]] : (!fir.box) -> !fir.box ! CHECK-NEXT: %[[cmdmsg:.*]] = fir.convert %[[cmdmsgBox]] : (!fir.box>) -> !fir.box -! CHECK: %[[VAL_30:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %[[wait]], %[[exitstat]], %[[cmdstat]], %[[cmdmsg]], %[[VAL_29:.*]], %c14_i32) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none +! CHECK: %[[VAL_30:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %[[wait]], %[[exitstat]], %[[cmdstat]], %[[cmdmsg]], %[[VAL_29:.*]], %[[c14]]) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none ! CHECK-NEXT: return end subroutine all_args_optional diff --git a/flang/test/Lower/Intrinsics/execute_command_line.f90 b/flang/test/Lower/Intrinsics/execute_command_line.f90 index 1b65bbd5e1550..8aacd34346b4d 100644 --- a/flang/test/Lower/Intrinsics/execute_command_line.f90 +++ b/flang/test/Lower/Intrinsics/execute_command_line.f90 @@ -11,26 +11,37 @@ subroutine all_args(command, isWait, exitVal, cmdVal, msg) INTEGER :: exitVal, cmdVal LOGICAL :: isWait call execute_command_line(command, isWait, exitVal, cmdVal, msg) -! CHECK: %[[cmdstatsDeclear:.*]] = fir.declare %[[cmdstatArg]] {uniq_name = "_QFall_argsEcmdval"} : (!fir.ref) -> !fir.ref +! CHECK-NEXT: %[[c13:.*]] = arith.constant 13 : i32 +! CHECK-NEXT: %true = arith.constant true +! CHECK-NEXT: %[[c0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[c30:.*]] = arith.constant 30 : index +! CHECK-NEXT: %[[cmdstatsDeclare:.*]] = fir.declare %[[cmdstatArg]] {uniq_name = "_QFall_argsEcmdval"} : (!fir.ref) -> !fir.ref ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[commandArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[commandCast:.*]] = fir.convert %[[commandUnbox]]#0 : (!fir.ref>) -> !fir.ref> -! CHECK-NEXT: %[[commandDeclear:.*]] = fir.declare %[[commandCast]] typeparams %c30 {uniq_name = "_QFall_argsEcommand"} : (!fir.ref>, index) -> !fir.ref> -! CHECK-NEXT: %[[exitstatDeclear:.*]] = fir.declare %[[exitstatArg]] {uniq_name = "_QFall_argsEexitval"} : (!fir.ref) -> !fir.ref -! CHECK-NEXT: %[[waitDeclear:.*]] = fir.declare %[[waitArg]] {uniq_name = "_QFall_argsEiswait"} : (!fir.ref>) -> !fir.ref> +! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] {uniq_name = "_QFall_argsEcommand"} : (!fir.ref>, index) -> !fir.ref> +! CHECK-NEXT: %[[exitstatDeclare:.*]] = fir.declare %[[exitstatArg]] {uniq_name = "_QFall_argsEexitval"} : (!fir.ref) -> !fir.ref +! CHECK-NEXT: %[[waitDeclare:.*]] = fir.declare %[[waitArg]] {uniq_name = "_QFall_argsEiswait"} : (!fir.ref>) -> !fir.ref> ! CHECK-NEXT: %[[cmdmsgUnbox:.*]]:2 = fir.unboxchar %[[cmdmsgArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[cmdmsgCast:.*]] = fir.convert %[[cmdmsgUnbox]]#0 : (!fir.ref>) -> !fir.ref> -! CHECK-NEXT: %[[cmdmsgDeclear:.*]] = fir.declare %[[cmdmsgCast]] typeparams %c30 {uniq_name = "_QFall_argsEmsg"} : (!fir.ref>, index) -> !fir.ref> -! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclear]] : (!fir.ref>) -> !fir.box> -! CHECK-NEXT: %[[waitLoaded:.*]] = fir.load %[[waitDeclear]] : !fir.ref> -! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[exitstatDeclear]] : (!fir.ref) -> !fir.box -! CHECK-NEXT: %[[cmdstatBox:.*]] = fir.embox %[[cmdstatsDeclear]] : (!fir.ref) -> !fir.box -! CHECK-NEXT: %[[cmdmsgBox:.*]] = fir.embox %[[cmdmsgDeclear]] : (!fir.ref>) -> !fir.box> +! CHECK-NEXT: %[[cmdmsgDeclare:.*]] = fir.declare %[[cmdmsgCast]] typeparams %[[c30]] {uniq_name = "_QFall_argsEmsg"} : (!fir.ref>, index) -> !fir.ref> +! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]] : (!fir.ref>) -> !fir.box> +! CHECK-NEXT: %[[exitstatBox:.*]] = fir.embox %[[exitstatDeclare]] : (!fir.ref) -> !fir.box +! CHECK-NEXT: %[[cmdstatBox:.*]] = fir.embox %[[cmdstatsDeclare]] : (!fir.ref) -> !fir.box +! CHECK-NEXT: %[[cmdmsgBox:.*]] = fir.embox %[[cmdmsgDeclare]] : (!fir.ref>) -> !fir.box> +! CHECK-NEXT: %[[waitCast:.*]] = fir.convert %[[waitDeclare]] : (!fir.ref>) -> i64 +! CHECK-NEXT: %[[waitPresent:.*]] = arith.cmpi ne, %[[waitCast]], %[[c0]] : i64 +! CHECK-NEXT: %[[wait:.*]] = fir.if %[[waitPresent]] -> (i1) { +! CHECK-NEXT: %[[waitLoaded:.*]] = fir.load %[[waitDeclare]] : !fir.ref> +! CHECK-NEXT: %[[waitTrueVal:.*]] = fir.convert %[[waitLoaded]] : (!fir.logical<4>) -> i1 +! CHECK-NEXT: fir.result %[[waitTrueVal]] : i1 +! CHECK-NEXT: } else { +! CHECK-NEXT: fir.result %true : i1 +! CHECK-NEXT: } ! CHECK: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box>) -> !fir.box -! CHECK-NEXT: %[[wait:.*]] = fir.convert %[[waitLoaded]] : (!fir.logical<4>) -> i1 ! CHECK-NEXT: %[[exitstat:.*]] = fir.convert %[[exitstatBox]] : (!fir.box) -> !fir.box ! CHECK-NEXT: %[[cmdstat:.*]] = fir.convert %[[cmdstatBox]] : (!fir.box) -> !fir.box ! CHECK-NEXT: %[[cmdmsg:.*]] = fir.convert %[[cmdmsgBox]] : (!fir.box>) -> !fir.box -! CHECK: %[[VAL_21:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %[[wait]], %[[exitstat]], %[[cmdstat]], %[[cmdmsg]], %[[VAL_20:.*]], %c13_i32) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none +! CHECK: %[[VAL_22:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %[[wait]], %[[exitstat]], %[[cmdstat]], %[[cmdmsg]], %[[VAL_20:.*]], %[[c13]]) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none ! CHECK-NEXT: return end subroutine all_args @@ -39,15 +50,15 @@ end subroutine all_args subroutine only_command_default_wait_true(command) CHARACTER(30) :: command call execute_command_line(command) -! CHECK-NEXT: %c41_i32 = arith.constant 41 : i32 +! CHECK-NEXT: %[[c52:.*]] = arith.constant 52 : i32 ! CHECK-NEXT: %true = arith.constant true -! CHECK-NEXT: %c30 = arith.constant 30 : index +! CHECK-NEXT: %[[c30:.*]] = arith.constant 30 : index ! CHECK-NEXT: %[[commandUnbox:.*]]:2 = fir.unboxchar %[[cmdArg]] : (!fir.boxchar<1>) -> (!fir.ref>, index) ! CHECK-NEXT: %[[commandCast:.*]] = fir.convert %[[commandUnbox]]#0 : (!fir.ref>) -> !fir.ref> -! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %c30 {uniq_name = "_QFonly_command_default_wait_trueEcommand"} : (!fir.ref>, index) -> !fir.ref> +! CHECK-NEXT: %[[commandDeclare:.*]] = fir.declare %[[commandCast]] typeparams %[[c30]] {uniq_name = "_QFonly_command_default_wait_trueEcommand"} : (!fir.ref>, index) -> !fir.ref> ! CHECK-NEXT: %[[commandBox:.*]] = fir.embox %[[commandDeclare]] : (!fir.ref>) -> !fir.box> ! CHECK-NEXT: %[[absent:.*]] = fir.absent !fir.box ! CHECK: %[[command:.*]] = fir.convert %[[commandBox]] : (!fir.box>) -> !fir.box -! CHECK: %[[VAL_21:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %true, %[[absent]], %[[absent]], %[[absent]], %[[VAL_7:.*]], %c41_i32) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none +! CHECK: %[[VAL_8:.*]] = fir.call @_FortranAExecuteCommandLine(%[[command]], %true, %[[absent]], %[[absent]], %[[absent]], %[[VAL_7:.*]], %[[c52]]) fastmath : (!fir.box, i1, !fir.box, !fir.box, !fir.box, !fir.ref, i32) -> none ! CHECK-NEXT: return end subroutine only_command_default_wait_true