diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp index 9eec8534006d0..e43f3a3a5fb15 100644 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -267,6 +267,7 @@ struct IntrinsicLibrary { fir::ExtendedValue genAssociated(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genChar(mlir::Type, llvm::ArrayRef); + mlir::Value genDim(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genDotProduct(mlir::Type, llvm::ArrayRef); template @@ -380,6 +381,7 @@ static constexpr IntrinsicHandler handlers[]{ {{{"pointer", asInquired}, {"target", asInquired}}}, /*isElemental=*/false}, {"char", &I::genChar}, + {"dim", &I::genDim}, {"dot_product", &I::genDotProduct, {{{"vector_a", asBox}, {"vector_b", asBox}}}, @@ -1259,6 +1261,25 @@ IntrinsicLibrary::genChar(mlir::Type type, return fir::CharBoxValue{cast, len}; } +// DIM +mlir::Value IntrinsicLibrary::genDim(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 2); + if (resultType.isa()) { + mlir::Value zero = builder.createIntegerConstant(loc, resultType, 0); + auto diff = builder.create(loc, args[0], args[1]); + auto cmp = builder.create( + loc, mlir::arith::CmpIPredicate::sgt, diff, zero); + return builder.create(loc, cmp, diff, zero); + } + assert(fir::isa_real(resultType) && "Only expects real and integer in DIM"); + mlir::Value zero = builder.createRealZeroConstant(loc, resultType); + auto diff = builder.create(loc, args[0], args[1]); + auto cmp = builder.create( + loc, mlir::arith::CmpFPredicate::OGT, diff, zero); + return builder.create(loc, cmp, diff, zero); +} + // DOT_PRODUCT fir::ExtendedValue IntrinsicLibrary::genDotProduct(mlir::Type resultType, diff --git a/flang/test/Lower/Intrinsics/dim.f90 b/flang/test/Lower/Intrinsics/dim.f90 new file mode 100644 index 0000000000000..9ceecdfd74ad0 --- /dev/null +++ b/flang/test/Lower/Intrinsics/dim.f90 @@ -0,0 +1,33 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func @_QPdim_testr( +! CHECK-SAME: %[[VAL_0:[a-z]+[0-9]]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}, %[[VAL_2:.*]]: !fir.ref{{.*}}) { +subroutine dim_testr(x, y, z) +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[VAL_6:.*]] = arith.subf %[[VAL_3]], %[[VAL_4]] : f32 +! CHECK: %[[VAL_7:.*]] = arith.cmpf ogt, %[[VAL_6]], %[[VAL_5]] : f32 +! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_6]], %[[VAL_5]] : f32 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_2]] : !fir.ref +! CHECK: return + real :: x, y, z + z = dim(x, y) +end subroutine + +! CHECK-LABEL: func @_QPdim_testi( +! CHECK-SAME: %[[VAL_0:[a-z]+[0-9]]]: !fir.ref{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}, %[[VAL_2:.*]]: !fir.ref{{.*}}) { +subroutine dim_testi(i, j, k) +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_1]] : !fir.ref +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_6:.*]] = arith.subi %[[VAL_3]], %[[VAL_4]] : i32 +! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_6]], %[[VAL_5]] : i32 +! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_6]], %[[VAL_5]] : i32 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_2]] : !fir.ref +! CHECK: return + integer :: i, j, k + k = dim(i, j) +end subroutine +