diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -4907,6 +4907,13 @@ // Get the DIM argument. mlir::Value dim = fir::getBase(args[1]); + if (std::optional cstDim = fir::getIntIfConstant(dim)) { + // If it is a compile time constant, skip the runtime call. + return builder.createConvert(loc, resultType, + fir::factory::readExtent(builder, loc, + fir::BoxValue{array}, + cstDim.value() - 1)); + } if (!fir::isa_ref_type(dim.getType())) return builder.createConvert( loc, resultType, fir::runtime::genSizeDim(builder, loc, array, dim)); diff --git a/flang/test/Lower/Intrinsics/ubound.f90 b/flang/test/Lower/Intrinsics/ubound.f90 --- a/flang/test/Lower/Intrinsics/ubound.f90 +++ b/flang/test/Lower/Intrinsics/ubound.f90 @@ -69,3 +69,15 @@ ! CHECK: fir.store %[[VAL_16]] to %{{.*}} : !fir.ref res = ubound(a, dim, 8) end subroutine + + +! CHECK-LABEL: func @_QPubound_test_const_dim( +subroutine ubound_test_const_dim(array) + real :: array(11:) + integer :: res +! Should not call _FortranASizeDim when dim is compile time constant. But instead load from descriptor directly. +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[DIMS:.*]]:3 = fir.box_dims %arg0, %[[C0]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %{{.*}} = fir.convert %[[DIMS]]#1 : (index) -> i32 + res = ubound(array, 1) +end subroutine