[flang] lower RANK intrinsic (#93694)
First commit is reviewed in https://github.com/llvm/llvm-project/pull/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.
This commit is contained in:
@@ -334,6 +334,9 @@ void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
Entity entity);
|
||||
|
||||
mlir::Value genRank(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
Entity entity, mlir::Type resultType);
|
||||
|
||||
/// Return the fir base, shape, and type parameters for a variable. Note that
|
||||
/// type parameters are only added if the entity is not a box and the type
|
||||
/// parameters is not a constant in the base type. This matches the arguments
|
||||
|
||||
@@ -62,6 +62,12 @@ class fir_SimpleOneResultOp<string mnemonic, list<Trait> traits = []> :
|
||||
let builders = [fir_OneResultOpBuilder];
|
||||
}
|
||||
|
||||
// Whether a type is a BaseBoxType or a reference to a BaseBoxType.
|
||||
def IsBoxAddressOrValueTypePred
|
||||
: CPred<"::fir::isBoxAddressOrValue($_self)">;
|
||||
def fir_BoxAddressOrValueType : Type<IsBoxAddressOrValueTypePred,
|
||||
"fir.box or fir.class type or reference">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Memory SSA operations
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -1205,7 +1211,8 @@ def fir_BoxProcHostOp : fir_SimpleOp<"boxproc_host", [NoMemoryEffect]> {
|
||||
let results = (outs fir_ReferenceType);
|
||||
}
|
||||
|
||||
def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank", [NoMemoryEffect]> {
|
||||
def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank",
|
||||
[DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
|
||||
let summary = "return the number of dimensions for the boxed value";
|
||||
|
||||
let description = [{
|
||||
@@ -1222,7 +1229,7 @@ def fir_BoxRankOp : fir_SimpleOneResultOp<"box_rank", [NoMemoryEffect]> {
|
||||
descriptor may be either an array or a scalar, so the value is nonnegative.
|
||||
}];
|
||||
|
||||
let arguments = (ins fir_BoxType:$val);
|
||||
let arguments = (ins fir_BoxAddressOrValueType:$box);
|
||||
|
||||
let results = (outs AnyIntegerType);
|
||||
}
|
||||
|
||||
@@ -1626,7 +1626,7 @@ private:
|
||||
return castResult(
|
||||
hlfir::genExtent(loc, builder, entity, desc.dimension()));
|
||||
case Fortran::evaluate::DescriptorInquiry::Field::Rank:
|
||||
TODO(loc, "rank inquiry on assumed rank");
|
||||
return castResult(hlfir::genRank(loc, builder, entity, resultType));
|
||||
case Fortran::evaluate::DescriptorInquiry::Field::Stride:
|
||||
// So far the front end does not generate this inquiry.
|
||||
TODO(loc, "stride inquiry");
|
||||
|
||||
@@ -642,6 +642,15 @@ mlir::Value hlfir::genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
return lenParams[0];
|
||||
}
|
||||
|
||||
mlir::Value hlfir::genRank(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
hlfir::Entity entity, mlir::Type resultType) {
|
||||
if (!entity.isAssumedRank())
|
||||
return builder.createIntegerConstant(loc, resultType, entity.getRank());
|
||||
assert(entity.isBoxAddressOrValue() &&
|
||||
"assumed-ranks are box addresses or values");
|
||||
return builder.create<fir::BoxRankOp>(loc, resultType, entity);
|
||||
}
|
||||
|
||||
// Return a "shape" that can be used in fir.embox/fir.rebox with \p exv base.
|
||||
static mlir::Value asEmboxShape(mlir::Location loc, fir::FirOpBuilder &builder,
|
||||
const fir::ExtendedValue &exv,
|
||||
|
||||
@@ -428,7 +428,8 @@ struct BoxRankOpConversion : public fir::FIROpConversion<fir::BoxRankOp> {
|
||||
mlir::Value a = adaptor.getOperands()[0];
|
||||
auto loc = boxrank.getLoc();
|
||||
mlir::Type ty = convertType(boxrank.getType());
|
||||
TypePair boxTyPair = getBoxTypePair(boxrank.getVal().getType());
|
||||
TypePair boxTyPair =
|
||||
getBoxTypePair(fir::unwrapRefType(boxrank.getBox().getType()));
|
||||
mlir::Value rank = getRankFromBox(loc, boxTyPair, a, rewriter);
|
||||
mlir::Value result = integerCast(loc, rewriter, ty, rank);
|
||||
rewriter.replaceOp(boxrank, result);
|
||||
|
||||
@@ -675,6 +675,20 @@ mlir::Type fir::BoxDimsOp::getTupleType() {
|
||||
return mlir::TupleType::get(getContext(), triple);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BoxRankOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void fir::BoxRankOp::getEffects(
|
||||
llvm::SmallVectorImpl<
|
||||
mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
|
||||
&effects) {
|
||||
mlir::Value inputBox = getBox();
|
||||
if (fir::isBoxAddress(inputBox.getType()))
|
||||
effects.emplace_back(mlir::MemoryEffects::Read::get(), inputBox,
|
||||
mlir::SideEffects::DefaultResource::get());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallOp
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -970,6 +970,18 @@ func.func @extract_rank(%arg0: !fir.box<!fir.array<*:f64>>) -> i32 {
|
||||
// CHECK: %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
|
||||
// CHECK: llvm.return %[[RANK]] : i32
|
||||
|
||||
func.func @extract_rank2(%arg0: !fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32 {
|
||||
%0 = fir.box_rank %arg0 : (!fir.ref<!fir.box<!fir.array<*:f64>>>) -> i32
|
||||
return %0 : i32
|
||||
}
|
||||
|
||||
// CHECK-LABEL: llvm.func @extract_rank2(
|
||||
// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr) -> i32
|
||||
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ARG0]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>
|
||||
// CHECK: %[[RAW_RANK:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i8
|
||||
// CHECK: %[[RANK:.*]] = llvm.sext %[[RAW_RANK]] : i8 to i32
|
||||
// CHECK: llvm.return %[[RANK]] : i32
|
||||
|
||||
// -----
|
||||
|
||||
// Test `fir.box_addr` conversion.
|
||||
|
||||
Reference in New Issue
Block a user