diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 977a69af52813..2731392e6707b 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -334,6 +334,7 @@ struct IntrinsicLibrary { mlir::Value genScale(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef); mlir::Value genSelectedIntKind(mlir::Type, llvm::ArrayRef); + mlir::Value genSelectedLogicalKind(mlir::Type, llvm::ArrayRef); mlir::Value genSelectedRealKind(mlir::Type, llvm::ArrayRef); mlir::Value genSetExponent(mlir::Type resultType, llvm::ArrayRef args); diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h index fec8c9906effe..84a8e10e69c58 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h @@ -50,6 +50,10 @@ mlir::Value genScale(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value genSelectedIntKind(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x); +/// Generate call to Selected_logical_kind intrinsic runtime routine. +mlir::Value genSelectedLogicalKind(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value x); + /// Generate call to Selected_real_kind intrinsic runtime routine. mlir::Value genSelectedRealKind(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value precision, mlir::Value range, diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index ae7e650987448..e45f7d59c1489 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -553,6 +553,10 @@ static constexpr IntrinsicHandler handlers[]{ &I::genSelectedIntKind, {{{"scalar", asAddr}}}, /*isElemental=*/false}, + {"selected_logical_kind", + &I::genSelectedLogicalKind, + {{{"bits", asAddr}}}, + /*isElemental=*/false}, {"selected_real_kind", &I::genSelectedRealKind, {{{"precision", asAddr, handleDynamicOptional}, @@ -5884,6 +5888,17 @@ IntrinsicLibrary::genSelectedIntKind(mlir::Type resultType, fir::runtime::genSelectedIntKind(builder, loc, fir::getBase(args[0]))); } +// SELECTED_LOGICAL_KIND +mlir::Value +IntrinsicLibrary::genSelectedLogicalKind(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + + return builder.createConvert(loc, resultType, + fir::runtime::genSelectedLogicalKind( + builder, loc, fir::getBase(args[0]))); +} + // SELECTED_REAL_KIND mlir::Value IntrinsicLibrary::genSelectedRealKind(mlir::Type resultType, diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index 81d5d21ece7ae..93e4a297af43b 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -489,6 +489,27 @@ mlir::Value fir::runtime::genSelectedIntKind(fir::FirOpBuilder &builder, return builder.create(loc, func, args).getResult(0); } +/// Generate call to Selected_logical_kind intrinsic runtime routine. +mlir::Value fir::runtime::genSelectedLogicalKind(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value x) { + mlir::func::FuncOp func = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getFunctionType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(1)); + if (!fir::isa_ref_type(x.getType())) + fir::emitFatalError(loc, "argument address for runtime not found"); + mlir::Type eleTy = fir::unwrapRefType(x.getType()); + mlir::Value xKind = builder.createIntegerConstant( + loc, fTy.getInput(3), eleTy.getIntOrFloatBitWidth() / 8); + auto args = fir::runtime::createArguments(builder, loc, fTy, sourceFile, + sourceLine, x, xKind); + + return builder.create(loc, func, args).getResult(0); +} + /// Generate call to Selected_real_kind intrinsic runtime routine. mlir::Value fir::runtime::genSelectedRealKind(fir::FirOpBuilder &builder, mlir::Location loc, diff --git a/flang/test/Lower/Intrinsics/selected_logical_kind.f90 b/flang/test/Lower/Intrinsics/selected_logical_kind.f90 new file mode 100644 index 0000000000000..93952762cce5e --- /dev/null +++ b/flang/test/Lower/Intrinsics/selected_logical_kind.f90 @@ -0,0 +1,71 @@ +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s + +subroutine selected_logical_kind_test1(input) + integer(1) :: input, res + res = selected_logical_kind(input) +end + +! CHECK-LABEL: func.func @_QPselected_logical_kind_test1( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "input"}) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test1Einput"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i8 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test1Eres"} +! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test1Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[KIND:.*]] = arith.constant 1 : i32 +! CHECK: %[[INPUT_ADDR:.*]] = fir.convert %1#1 : (!fir.ref) -> !fir.llvm_ptr +! CHECK: %{{.*}} = fir.call @_FortranASelectedLogicalKind(%{{.*}}, %{{.*}}, %[[INPUT_ADDR]], %[[KIND]]) fastmath : (!fir.ref, i32, !fir.llvm_ptr, i32) -> i32 + +subroutine selected_logical_kind_test2(input) + integer(2) :: input, res + res = selected_logical_kind(input) +end + +! CHECK-LABEL: func.func @_QPselected_logical_kind_test2( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "input"}) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test2Einput"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i16 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test2Eres"} +! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test2Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[KIND:.*]] = arith.constant 2 : i32 +! CHECK: %[[INPUT_ADDR:.*]] = fir.convert %[[INPUT]]#1 : (!fir.ref) -> !fir.llvm_ptr +! CHECK: %{{.*}} = fir.call @_FortranASelectedLogicalKind(%{{.*}}, %{{.*}}, %[[INPUT_ADDR]], %[[KIND]]) fastmath : (!fir.ref, i32, !fir.llvm_ptr, i32) -> i32 + +subroutine selected_logical_kind_test4(input) + integer(4) :: input, res + res = selected_logical_kind(input) +end + +! CHECK-LABEL: func.func @_QPselected_logical_kind_test4( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "input"}) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %arg0 dummy_scope %0 {uniq_name = "_QFselected_logical_kind_test4Einput"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test4Eres"} +! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test4Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[KIND:.*]] = arith.constant 4 : i32 +! CHECK: %[[INPUT_ADDR:.*]] = fir.convert %[[INPUT]]#1 : (!fir.ref) -> !fir.llvm_ptr +! CHECK: %{{.*}} = fir.call @_FortranASelectedLogicalKind(%{{.*}}, %{{.*}}, %[[INPUT_ADDR]], %[[KIND]]) fastmath : (!fir.ref, i32, !fir.llvm_ptr, i32) -> i32 + +subroutine selected_logical_kind_test8(input) + integer(8) :: input, res + res = selected_logical_kind(input) +end + +! CHECK-LABEL: func.func @_QPselected_logical_kind_test8( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "input"}) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test8Einput"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[RES_ALLOCA]] = fir.alloca i64 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test8Eres"} +! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test8Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[KIND:.*]] = arith.constant 8 : i32 +! CHECK: %[[INPUT_ADDR:.*]] = fir.convert %[[INPUT]]#1 : (!fir.ref) -> !fir.llvm_ptr +! CHECK: %{{.*}} = fir.call @_FortranASelectedLogicalKind(%{{.*}}, %{{.*}}, %[[INPUT_ADDR]], %[[KIND]]) fastmath : (!fir.ref, i32, !fir.llvm_ptr, i32) -> i32 + +subroutine selected_logical_kind_test16(input) + integer(16) :: input, res + res = selected_logical_kind(input) +end + +! CHECK-LABEL: func.func @_QPselected_logical_kind_test16( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref {fir.bindc_name = "input"}) +! CHECK: %[[INPUT:.*]]:2 = hlfir.declare %[[ARG0]] dummy_scope %{{.*}} {uniq_name = "_QFselected_logical_kind_test16Einput"} : (!fir.ref, !fir.dscope) -> (!fir.ref, !fir.ref) +! CHECK: %[[RES_ALLOCA:.*]] = fir.alloca i128 {bindc_name = "res", uniq_name = "_QFselected_logical_kind_test16Eres"} +! CHECK: %[[RES:.*]]:2 = hlfir.declare %[[RES_ALLOCA]] {uniq_name = "_QFselected_logical_kind_test16Eres"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[KIND:.*]] = arith.constant 16 : i32 +! CHECK: %[[INPUT_ADDR:.*]] = fir.convert %[[INPUT]]#1 : (!fir.ref) -> !fir.llvm_ptr +! CHECK: %{{.*}} = fir.call @_FortranASelectedLogicalKind(%{{.*}}, %{{.*}}, %[[INPUT_ADDR]], %[[KIND]]) fastmath : (!fir.ref, i32, !fir.llvm_ptr, i32) -> i32