Skip to content

Commit fd8b2d2

Browse files
authored
[flang] lower RANK intrinsic (#93694)
First commit is reviewed in #93682. Lower RANK using fir.box_rank. This patches updates fir.box_rank to accept box reference, this avoids the need of generating an assumed-rank fir.load just for the sake of reading ALLOCATABLE/POINTER rank. The fir.load would generate a "dynamic" memcpy that is hard to optimize without further knowledge. A read effect is conditionally given to the operation.
1 parent 32b91ec commit fd8b2d2

File tree

7 files changed

+50
-4
lines changed

7 files changed

+50
-4
lines changed

flang/include/flang/Optimizer/Builder/HLFIRTools.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
334334
mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
335335
Entity entity);
336336

337+
mlir::Value genRank(mlir::Location loc, fir::FirOpBuilder &builder,
338+
Entity entity, mlir::Type resultType);
339+
337340
/// Return the fir base, shape, and type parameters for a variable. Note that
338341
/// type parameters are only added if the entity is not a box and the type
339342
/// parameters is not a constant in the base type. This matches the arguments

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ class fir_SimpleOneResultOp<string mnemonic, list<Trait> traits = []> :
6262
let builders = [fir_OneResultOpBuilder];
6363
}
6464

65+
// Whether a type is a BaseBoxType or a reference to a BaseBoxType.
66+
def IsBoxAddressOrValueTypePred
67+
: CPred<"::fir::isBoxAddressOrValue($_self)">;
68+
def fir_BoxAddressOrValueType : Type<IsBoxAddressOrValueTypePred,
69+
"fir.box or fir.class type or reference">;
70+
6571
//===----------------------------------------------------------------------===//
6672
// Memory SSA operations
6773
//===----------------------------------------------------------------------===//
@@ -1205,7 +1211,8 @@ def fir_BoxProcHostOp : fir_SimpleOp<"boxproc_host", [NoMemoryEffect]> {
12051211
let results = (outs fir_ReferenceType);
12061212
}
12071213

1208-
def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank", [NoMemoryEffect]> {
1214+
def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank",
1215+
[DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
12091216
let summary = "return the number of dimensions for the boxed value";
12101217

12111218
let description = [{
@@ -1222,7 +1229,7 @@ def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank", [NoMemoryEffect]> {
12221229
descriptor may be either an array or a scalar, so the value is nonnegative.
12231230
}];
12241231

1225-
let arguments = (ins fir_BoxType:$val);
1232+
let arguments = (ins fir_BoxAddressOrValueType:$box);
12261233

12271234
let results = (outs AnyIntegerType);
12281235
}

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ class HlfirBuilder {
16261626
return castResult(
16271627
hlfir::genExtent(loc, builder, entity, desc.dimension()));
16281628
case Fortran::evaluate::DescriptorInquiry::Field::Rank:
1629-
TODO(loc, "rank inquiry on assumed rank");
1629+
return castResult(hlfir::genRank(loc, builder, entity, resultType));
16301630
case Fortran::evaluate::DescriptorInquiry::Field::Stride:
16311631
// So far the front end does not generate this inquiry.
16321632
TODO(loc, "stride inquiry");

flang/lib/Optimizer/Builder/HLFIRTools.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,15 @@ mlir::Value hlfir::genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
642642
return lenParams[0];
643643
}
644644

645+
mlir::Value hlfir::genRank(mlir::Location loc, fir::FirOpBuilder &builder,
646+
hlfir::Entity entity, mlir::Type resultType) {
647+
if (!entity.isAssumedRank())
648+
return builder.createIntegerConstant(loc, resultType, entity.getRank());
649+
assert(entity.isBoxAddressOrValue() &&
650+
"assumed-ranks are box addresses or values");
651+
return builder.create<fir::BoxRankOp>(loc, resultType, entity);
652+
}
653+
645654
// Return a "shape" that can be used in fir.embox/fir.rebox with \p exv base.
646655
static mlir::Value asEmboxShape(mlir::Location loc, fir::FirOpBuilder &builder,
647656
const fir::ExtendedValue &exv,

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,8 @@ struct BoxRankOpConversion : public fir::FIROpConversion<fir::BoxRankOp> {
428428
mlir::Value a = adaptor.getOperands()[0];
429429
auto loc = boxrank.getLoc();
430430
mlir::Type ty = convertType(boxrank.getType());
431-
TypePair boxTyPair = getBoxTypePair(boxrank.getVal().getType());
431+
TypePair boxTyPair =
432+
getBoxTypePair(fir::unwrapRefType(boxrank.getBox().getType()));
432433
mlir::Value rank = getRankFromBox(loc, boxTyPair, a, rewriter);
433434
mlir::Value result = integerCast(loc, rewriter, ty, rank);
434435
rewriter.replaceOp(boxrank, result);

flang/lib/Optimizer/Dialect/FIROps.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,20 @@ mlir::Type fir::BoxDimsOp::getTupleType() {
675675
return mlir::TupleType::get(getContext(), triple);
676676
}
677677

678+
//===----------------------------------------------------------------------===//
679+
// BoxRankOp
680+
//===----------------------------------------------------------------------===//
681+
682+
void fir::BoxRankOp::getEffects(
683+
llvm::SmallVectorImpl<
684+
mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
685+
&effects) {
686+
mlir::Value inputBox = getBox();
687+
if (fir::isBoxAddress(inputBox.getType()))
688+
effects.emplace_back(mlir::MemoryEffects::Read::get(), inputBox,
689+
mlir::SideEffects::DefaultResource::get());
690+
}
691+
678692
//===----------------------------------------------------------------------===//
679693
// CallOp
680694
//===----------------------------------------------------------------------===//

flang/test/Fir/convert-to-llvm.fir

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,18 @@ func.func @extract_rank(%arg0: !fir.box<!fir.array<*:f64>>) -> i32 {
970970
// CHECK: %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
971971
// CHECK: llvm.return %[[RANK]] : i32
972972

973+
func.func @extract_rank2(%arg0: !fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32 {
974+
%0 = fir.box_rank %arg0 : (!fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32
975+
return %0 : i32
976+
}
977+
978+
// CHECK-LABEL: llvm.func @extract_rank2(
979+
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr) -> i32
980+
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
981+
// CHECK: %[[RAW_RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
982+
// CHECK: %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
983+
// CHECK: llvm.return %[[RANK]] : i32
984+
973985
// -----
974986

975987
// Test `fir.box_addr` conversion.

0 commit comments

Comments
 (0)