@@ -4353,30 +4353,12 @@ class FirConverter : public Fortran::lower::AbstractConverter {
4353
4353
stmtCtx);
4354
4354
}
4355
4355
4356
- void genForallPointerAssignment (
4357
- mlir::Location loc, const Fortran::evaluate::Assignment &assign,
4358
- const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) {
4359
- std::optional<Fortran::evaluate::DynamicType> lhsType =
4360
- assign.lhs .GetType ();
4361
- // Polymorphic pointer assignment is delegated to the runtime, and
4362
- // PointerAssociateLowerBounds needs the lower bounds as arguments, so they
4363
- // must be preserved.
4364
- if (lhsType && lhsType->IsPolymorphic ())
4365
- TODO (loc, " polymorphic pointer assignment in FORALL" );
4366
- // Nullification is special, there is no RHS that can be prepared,
4367
- // need to encode it in HLFIR.
4368
- if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
4369
- assign.rhs ))
4370
- TODO (loc, " NULL pointer assignment in FORALL" );
4371
- // Lower bounds could be "applied" when preparing RHS, but in order
4372
- // to deal with the polymorphic case and to reuse existing pointer
4373
- // assignment helpers in HLFIR codegen, it is better to keep them
4374
- // separate.
4375
- if (!lbExprs.empty ())
4376
- TODO (loc, " Pointer assignment with new lower bounds inside FORALL" );
4377
- // Otherwise, this is a "dumb" pointer assignment that can be represented
4378
- // with hlfir.region_assign with descriptor address/value and later
4379
- // implemented with a store.
4356
+ void genForallPointerAssignment (mlir::Location loc,
4357
+ const Fortran::evaluate::Assignment &assign) {
4358
+ // Lower pointer assignment inside forall with hlfir.region_assign with
4359
+ // descriptor address/value and later implemented with a store.
4360
+ // The RHS is fully prepared in lowering, so that all that is left
4361
+ // in hlfir.region_assign code generation is the store.
4380
4362
auto regionAssignOp = builder->create <hlfir::RegionAssignOp>(loc);
4381
4363
4382
4364
// Lower LHS in its own region.
@@ -4400,22 +4382,73 @@ class FirConverter : public Fortran::lower::AbstractConverter {
4400
4382
builder->setInsertionPointAfter (regionAssignOp);
4401
4383
}
4402
4384
4385
+ mlir::Value lowerToIndexValue (mlir::Location loc,
4386
+ const Fortran::evaluate::ExtentExpr &expr,
4387
+ Fortran::lower::StatementContext &stmtCtx) {
4388
+ mlir::Value val = fir::getBase (genExprValue (toEvExpr (expr), stmtCtx));
4389
+ return builder->createConvert (loc, builder->getIndexType (), val);
4390
+ }
4391
+
4403
4392
mlir::Value
4404
4393
genForallPointerAssignmentRhs (mlir::Location loc, mlir::Value lhs,
4405
4394
const Fortran::evaluate::Assignment &assign,
4406
4395
Fortran::lower::StatementContext &rhsContext) {
4407
- if (Fortran::evaluate::IsProcedureDesignator (assign.rhs ))
4396
+ if (Fortran::evaluate::IsProcedureDesignator (assign.lhs )) {
4397
+ if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
4398
+ assign.rhs ))
4399
+ return fir::factory::createNullBoxProc (
4400
+ *builder, loc, fir::unwrapRefType (lhs.getType ()));
4408
4401
return fir::getBase (Fortran::lower::convertExprToAddress (
4409
4402
loc, *this , assign.rhs , localSymbols, rhsContext));
4403
+ }
4410
4404
// Data target.
4405
+ auto lhsBoxType =
4406
+ llvm::cast<fir::BaseBoxType>(fir::unwrapRefType (lhs.getType ()));
4407
+ // For NULL, create disassociated descriptor whose dynamic type is
4408
+ // the static type of the LHS.
4409
+ if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(
4410
+ assign.rhs ))
4411
+ return fir::factory::createUnallocatedBox (*builder, loc, lhsBoxType,
4412
+ std::nullopt);
4411
4413
hlfir::Entity rhs = Fortran::lower::convertExprToHLFIR (
4412
4414
loc, *this , assign.rhs , localSymbols, rhsContext);
4413
4415
// Create pointer descriptor value from the RHS.
4414
4416
if (rhs.isMutableBox ())
4415
4417
rhs = hlfir::Entity{builder->create <fir::LoadOp>(loc, rhs)};
4416
- auto lhsBoxType =
4417
- llvm::cast<fir::BaseBoxType>(fir::unwrapRefType (lhs.getType ()));
4418
- return hlfir::genVariableBox (loc, *builder, rhs, lhsBoxType);
4418
+ mlir::Value rhsBox = hlfir::genVariableBox (
4419
+ loc, *builder, rhs, lhsBoxType.getBoxTypeWithNewShape (rhs.getRank ()));
4420
+ // Apply lower bounds or reshaping if any.
4421
+ if (const auto *lbExprs =
4422
+ std::get_if<Fortran::evaluate::Assignment::BoundsSpec>(&assign.u );
4423
+ lbExprs && !lbExprs->empty ()) {
4424
+ // Override target lower bounds with the LHS bounds spec.
4425
+ llvm::SmallVector<mlir::Value> lbounds;
4426
+ for (const Fortran::evaluate::ExtentExpr &lbExpr : *lbExprs)
4427
+ lbounds.push_back (lowerToIndexValue (loc, lbExpr, rhsContext));
4428
+ mlir::Value shift = builder->genShift (loc, lbounds);
4429
+ rhsBox = builder->create <fir::ReboxOp>(loc, lhsBoxType, rhsBox, shift,
4430
+ /* slice=*/ mlir::Value{});
4431
+ } else if (const auto *boundExprs =
4432
+ std::get_if<Fortran::evaluate::Assignment::BoundsRemapping>(
4433
+ &assign.u );
4434
+ boundExprs && !boundExprs->empty ()) {
4435
+ // Reshape the target according to the LHS bounds remapping.
4436
+ llvm::SmallVector<mlir::Value> lbounds;
4437
+ llvm::SmallVector<mlir::Value> extents;
4438
+ mlir::Type indexTy = builder->getIndexType ();
4439
+ mlir::Value zero = builder->createIntegerConstant (loc, indexTy, 0 );
4440
+ mlir::Value one = builder->createIntegerConstant (loc, indexTy, 1 );
4441
+ for (const auto &[lbExpr, ubExpr] : *boundExprs) {
4442
+ lbounds.push_back (lowerToIndexValue (loc, lbExpr, rhsContext));
4443
+ mlir::Value ub = lowerToIndexValue (loc, ubExpr, rhsContext);
4444
+ extents.push_back (fir::factory::computeExtent (
4445
+ *builder, loc, lbounds.back (), ub, zero, one));
4446
+ }
4447
+ mlir::Value shape = builder->genShape (loc, lbounds, extents);
4448
+ rhsBox = builder->create <fir::ReboxOp>(loc, lhsBoxType, rhsBox, shape,
4449
+ /* slice=*/ mlir::Value{});
4450
+ }
4451
+ return rhsBox;
4419
4452
}
4420
4453
4421
4454
// Create the 2 x newRank array with the bounds to be passed to the runtime as
@@ -4856,17 +4889,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
4856
4889
},
4857
4890
[&](const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) {
4858
4891
if (isInsideHlfirForallOrWhere ())
4859
- genForallPointerAssignment (loc, assign, lbExprs );
4892
+ genForallPointerAssignment (loc, assign);
4860
4893
else
4861
4894
genPointerAssignment (loc, assign, lbExprs);
4862
4895
},
4863
4896
[&](const Fortran::evaluate::Assignment::BoundsRemapping
4864
4897
&boundExprs) {
4865
4898
if (isInsideHlfirForallOrWhere ())
4866
- TODO (
4867
- loc,
4868
- " pointer assignment with bounds remapping inside FORALL" );
4869
- genPointerAssignment (loc, assign, boundExprs);
4899
+ genForallPointerAssignment (loc, assign);
4900
+ else
4901
+ genPointerAssignment (loc, assign, boundExprs);
4870
4902
},
4871
4903
},
4872
4904
assign.u );
0 commit comments