Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flang/include/flang/Optimizer/Builder/HLFIRTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Entity : public mlir::Value {
bool isVariable() const { return !isValue(); }
bool isMutableBox() const { return hlfir::isBoxAddressType(getType()); }
bool isProcedurePointer() const {
return fir::isBoxProcAddressType(getType());
return hlfir::isFortranProcedurePointerType(getType());
}
bool isBoxAddressOrValue() const {
return hlfir::isBoxAddressOrValueType(getType());
Expand Down
19 changes: 10 additions & 9 deletions flang/include/flang/Optimizer/Builder/TemporaryStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class AnyValueStack {
/// dynamic type, bounds, and type parameters as the Nth variable that was
/// pushed. It is implemented using runtime.
/// Note that this is not meant to save POINTER or ALLOCATABLE descriptor
/// addresses, use AnyDescriptorAddressStack instead.
/// addresses, use AnyAddressStack instead.
class AnyVariableStack {
public:
AnyVariableStack(mlir::Location loc, fir::FirOpBuilder &builder,
Expand All @@ -205,19 +205,21 @@ class AnyVariableStack {
mlir::Value retValueBox;
};

/// Data structure to stack descriptor addresses. It stores the descriptor
/// addresses as int_ptr values under the hood.
class AnyDescriptorAddressStack : public AnyValueStack {
/// Data structure to stack simple addresses (C pointers). It can be used to
/// store data base addresses, descriptor addresses, procedure addresses, and
/// pointer procedure address. It stores the addresses as int_ptr values under
/// the hood.
class AnyAddressStack : public AnyValueStack {
public:
AnyDescriptorAddressStack(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Type descriptorAddressType);
AnyAddressStack(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Type addressType);

void pushValue(mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Value value);
mlir::Value fetch(mlir::Location loc, fir::FirOpBuilder &builder);

private:
mlir::Type descriptorAddressType;
mlir::Type addressType;
};

class TemporaryStorage;
Expand Down Expand Up @@ -281,8 +283,7 @@ class TemporaryStorage {

private:
std::variant<HomogeneousScalarStack, SimpleCopy, SSARegister, AnyValueStack,
AnyVariableStack, AnyVectorSubscriptStack,
AnyDescriptorAddressStack>
AnyVariableStack, AnyVectorSubscriptStack, AnyAddressStack>
impl;
};
} // namespace fir::factory
Expand Down
11 changes: 11 additions & 0 deletions flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ inline bool isPolymorphicType(mlir::Type type) {
return fir::isPolymorphicType(type);
}

/// Is this the FIR type of a Fortran procedure pointer?
inline bool isFortranProcedurePointerType(mlir::Type type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decide to give this a hlfir wrapper? Are you expecting this to diverge from fir::isBoxProcAddressType some time in the future?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, but HLFIR predicate names tends to use Fortran concepts, I find it easier to read/understand isFortranProcedurePointerType in lowering from the parse tree rather than to get that fir::isBoxProcAddressType implies that we are talking about procedure pointers because that is how they are implemented.

return fir::isBoxProcAddressType(type);
}

inline bool isFortranPointerObjectType(mlir::Type type) {
auto boxTy =
llvm::dyn_cast_or_null<fir::BaseBoxType>(fir::dyn_cast_ptrEleTy(type));
return boxTy && boxTy.isPointer();
}

/// Is this an SSA value type for the value of a Fortran procedure
/// designator ?
inline bool isFortranProcedureValue(mlir::Type type) {
Expand Down
7 changes: 3 additions & 4 deletions flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,9 @@ def IsFortranVariablePred
def AnyFortranVariable : Type<IsFortranVariablePred, "any HLFIR variable type">;


def AnyFortranValue : TypeConstraint<Or<[AnyLogicalLike.predicate,
AnyIntegerLike.predicate, AnyRealLike.predicate,
AnyFirComplexLike.predicate,
hlfir_ExprType.predicate]>, "any Fortran value type">;
def IsFortranValuePred : CPred<"::hlfir::isFortranValueType($_self)">;
def AnyFortranValue
: TypeConstraint<IsFortranValuePred, "any Fortran value type">;


def AnyFortranEntity : TypeConstraint<Or<[AnyFortranVariable.predicate,
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Optimizer/HLFIR/HLFIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,8 @@ def hlfir_RegionAssignOp : hlfir_Op<"region_assign", [hlfir_OrderedAssignmentTre
}
mlir::Region* getSubTreeRegion() { return nullptr; }
bool isPointerAssignment();
bool isPointerObjectAssignment();
bool isProcedurePointerAssignment();
}];

let hasCustomAssemblyFormat = 1;
Expand Down
27 changes: 18 additions & 9 deletions flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4353,8 +4353,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
void genForallPointerAssignment(
mlir::Location loc, const Fortran::evaluate::Assignment &assign,
const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) {
if (Fortran::evaluate::IsProcedureDesignator(assign.rhs))
TODO(loc, "procedure pointer assignment inside FORALL");
std::optional<Fortran::evaluate::DynamicType> lhsType =
assign.lhs.GetType();
// Polymorphic pointer assignment is delegated to the runtime, and
Expand Down Expand Up @@ -4383,27 +4381,38 @@ class FirConverter : public Fortran::lower::AbstractConverter {
Fortran::lower::StatementContext lhsContext;
hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR(
loc, *this, assign.lhs, localSymbols, lhsContext);

auto lhsYieldOp = builder->create<hlfir::YieldOp>(loc, lhs);
Fortran::lower::genCleanUpInRegionIfAny(
loc, *builder, lhsYieldOp.getCleanup(), lhsContext);

// Lower RHS in its own region.
builder->createBlock(&regionAssignOp.getRhsRegion());
Fortran::lower::StatementContext rhsContext;
mlir::Value rhs =
genForallPointerAssignmentRhs(loc, lhs, assign, rhsContext);
auto rhsYieldOp = builder->create<hlfir::YieldOp>(loc, rhs);
Fortran::lower::genCleanUpInRegionIfAny(
loc, *builder, rhsYieldOp.getCleanup(), rhsContext);

builder->setInsertionPointAfter(regionAssignOp);
}

mlir::Value
genForallPointerAssignmentRhs(mlir::Location loc, mlir::Value lhs,
const Fortran::evaluate::Assignment &assign,
Fortran::lower::StatementContext &rhsContext) {
if (Fortran::evaluate::IsProcedureDesignator(assign.rhs))
return fir::getBase(Fortran::lower::convertExprToAddress(
loc, *this, assign.rhs, localSymbols, rhsContext));
// Data target.
hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR(
loc, *this, assign.rhs, localSymbols, rhsContext);
// Create pointer descriptor value from the RHS.
if (rhs.isMutableBox())
rhs = hlfir::Entity{builder->create<fir::LoadOp>(loc, rhs)};
auto lhsBoxType =
llvm::cast<fir::BaseBoxType>(fir::unwrapRefType(lhs.getType()));
mlir::Value newBox = hlfir::genVariableBox(loc, *builder, rhs, lhsBoxType);
auto rhsYieldOp = builder->create<hlfir::YieldOp>(loc, newBox);
Fortran::lower::genCleanUpInRegionIfAny(
loc, *builder, rhsYieldOp.getCleanup(), rhsContext);

builder->setInsertionPointAfter(regionAssignOp);
return hlfir::genVariableBox(loc, *builder, rhs, lhsBoxType);
}

// Create the 2 x newRank array with the bounds to be passed to the runtime as
Expand Down
36 changes: 22 additions & 14 deletions flang/lib/Optimizer/Builder/TemporaryStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,25 +357,33 @@ void fir::factory::AnyVectorSubscriptStack::destroy(
}

//===----------------------------------------------------------------------===//
// fir::factory::AnyDescriptorAddressStack implementation.
// fir::factory::AnyAddressStack implementation.
//===----------------------------------------------------------------------===//

fir::factory::AnyDescriptorAddressStack::AnyDescriptorAddressStack(
mlir::Location loc, fir::FirOpBuilder &builder,
mlir::Type descriptorAddressType)
fir::factory::AnyAddressStack::AnyAddressStack(mlir::Location loc,
fir::FirOpBuilder &builder,
mlir::Type addressType)
: AnyValueStack(loc, builder, builder.getIntPtrType()),
descriptorAddressType{descriptorAddressType} {}

void fir::factory::AnyDescriptorAddressStack::pushValue(
mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value variable) {
mlir::Value cast =
builder.createConvert(loc, builder.getIntPtrType(), variable);
addressType{addressType} {}

void fir::factory::AnyAddressStack::pushValue(mlir::Location loc,
fir::FirOpBuilder &builder,
mlir::Value variable) {
mlir::Value cast = variable;
if (auto boxProcType = llvm::dyn_cast<fir::BoxProcType>(variable.getType())) {
cast =
builder.create<fir::BoxAddrOp>(loc, boxProcType.getEleTy(), variable);
}
cast = builder.createConvert(loc, builder.getIntPtrType(), cast);
static_cast<AnyValueStack *>(this)->pushValue(loc, builder, cast);
}

mlir::Value
fir::factory::AnyDescriptorAddressStack::fetch(mlir::Location loc,
fir::FirOpBuilder &builder) {
mlir::Value fir::factory::AnyAddressStack::fetch(mlir::Location loc,
fir::FirOpBuilder &builder) {
mlir::Value addr = static_cast<AnyValueStack *>(this)->fetch(loc, builder);
return builder.createConvert(loc, descriptorAddressType, addr);
if (auto boxProcType = llvm::dyn_cast<fir::BoxProcType>(addressType)) {
mlir::Value cast = builder.createConvert(loc, boxProcType.getEleTy(), addr);
return builder.create<fir::EmboxProcOp>(loc, boxProcType, cast);
}
return builder.createConvert(loc, addressType, addr);
}
31 changes: 23 additions & 8 deletions flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1891,18 +1891,33 @@ llvm::LogicalResult hlfir::RegionAssignOp::verify() {
return mlir::success();
}

bool hlfir::RegionAssignOp::isPointerAssignment() {
static mlir::Type
getNonVectorSubscriptedLhsType(hlfir::RegionAssignOp regionAssign) {
hlfir::YieldOp yieldOp = mlir::dyn_cast_or_null<hlfir::YieldOp>(
getTerminator(regionAssign.getLhsRegion()));
return yieldOp ? yieldOp.getEntity().getType() : mlir::Type{};
}

bool hlfir::RegionAssignOp::isPointerObjectAssignment() {
if (!getUserDefinedAssignment().empty())
return false;
hlfir::YieldOp yieldOp =
mlir::dyn_cast_or_null<hlfir::YieldOp>(getTerminator(getLhsRegion()));
if (!yieldOp)
mlir::Type lhsType = getNonVectorSubscriptedLhsType(*this);
return lhsType && hlfir::isFortranPointerObjectType(lhsType);
}

bool hlfir::RegionAssignOp::isProcedurePointerAssignment() {
if (!getUserDefinedAssignment().empty())
return false;
mlir::Type lhsType = yieldOp.getEntity().getType();
if (!hlfir::isBoxAddressType(lhsType))
mlir::Type lhsType = getNonVectorSubscriptedLhsType(*this);
return lhsType && hlfir::isFortranProcedurePointerType(lhsType);
}

bool hlfir::RegionAssignOp::isPointerAssignment() {
if (!getUserDefinedAssignment().empty())
return false;
auto baseBoxType = llvm::cast<fir::BaseBoxType>(fir::unwrapRefType(lhsType));
return baseBoxType.isPointer();
mlir::Type lhsType = getNonVectorSubscriptedLhsType(*this);
return lhsType && (hlfir::isFortranPointerObjectType(lhsType) ||
hlfir::isFortranProcedurePointerType(lhsType));
}

//===----------------------------------------------------------------------===//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1277,11 +1277,13 @@ void OrderedAssignmentRewriter::saveNonVectorSubscriptedAddress(
[&] { temp = insertSavedEntity(region, fir::factory::SSARegister{}); });
else
doBeforeLoopNest([&] {
if (var.isMutableBox())
temp =
insertSavedEntity(region, fir::factory::AnyDescriptorAddressStack{
loc, builder, var.getType()});
if (var.isMutableBox() || var.isProcedure() || var.isProcedurePointer())
// Store single C pointer to entity.
temp = insertSavedEntity(
region, fir::factory::AnyAddressStack{loc, builder, var.getType()});
else
// Store the base address and dynamic shape/length/type information
// as descriptor.
temp = insertSavedEntity(region, fir::factory::AnyVariableStack{
loc, builder, var.getType()});
});
Expand Down
Loading