Lines Matching +full:actions +full:- +full:builder

1 //===- LowerHLFIROrderedAssignments.cpp - Lower HLFIR ordered assignments -===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
18 //===----------------------------------------------------------------------===//
21 #include "flang/Optimizer/Builder/FIRBuilder.h"
22 #include "flang/Optimizer/Builder/HLFIRTools.h"
23 #include "flang/Optimizer/Builder/TemporaryStorage.h"
24 #include "flang/Optimizer/Builder/Todo.h"
39 #define DEBUG_TYPE "flang-ordered-assignment"
45 "flang-dbg-order-assignment-schedule-only",
64 void generateNoneElementalPart(fir::FirOpBuilder &builder,
71 mlir::Value generateShape(fir::FirOpBuilder &builder,
75 mlir::Value generateElementalParts(fir::FirOpBuilder &builder,
80 void generateNoneElementalCleanupIfAny(fir::FirOpBuilder &builder,
83 /// Helper to clone the clean-ups of the masked expr region terminator.
86 mlir::Operation *generateMaskedExprCleanUps(fir::FirOpBuilder &builder,
110 OrderedAssignmentRewriter(fir::FirOpBuilder &builder,
112 : builder{builder}, root{root} {}
124 /// After all run have been lowered, clean-up all the temporary
128 temp.second.destroy(root.getLoc(), builder);
132 /// clean-up needs to be cloned after usage.
181 /// optionally return the (uncloned) yield if there is any clean-up that
197 /// Generate the left-hand side. If the left-hand side is vector
205 /// If \p maybeYield is present and has a clean-up, generate the clean-up
240 auto insertionPoint = builder.saveInsertionPoint();
241 builder.setInsertionPoint(constructStack[0]);
243 builder.restoreInsertionPoint(insertionPoint);
259 return &inserted.first->second;
262 fir::FirOpBuilder &builder;
280 /// that saves them has been lowered. It is kept in-between runs.
316 insertionPoint = builder.saveInsertionPoint();
322 builder.restoreInsertionPoint(insertionPoint);
331 for (mlir::Operation &op : body->getOps())
345 mlir::Type idxTy = builder.getIndexType();
351 auto insertionPoint = builder.saveInsertionPoint();
353 builder.setInsertionPoint(constructStack[0]);
354 step = builder.createIntegerConstant(loc, idxTy, 1);
356 builder.restoreInsertionPoint(insertionPoint);
360 auto doLoop = builder.create<fir::DoLoopOp>(loc, lb, ub, step);
361 builder.setInsertionPointToStart(doLoop.getBody());
364 builder.createConvert(loc, oldIndex.getType(), doLoop.getInductionVar());
371 builder.setInsertionPointAfter(constructStack.pop_back_val());
378 builder.createTemporary(loc, intTy, forallIndexOp.getName());
380 builder.createStoreWithConvert(loc, newVal, indexVar);
387 builder.getI1Type());
388 auto ifOp = builder.create<fir::IfOp>(loc, std::nullopt, mask, false);
389 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
395 builder.setInsertionPointAfter(constructStack.pop_back_val());
400 /// it must be used as a variable or vice-versa. These mismatches may occur
402 /// argument that was lowered for them. The actual may be an in-memory copy
405 convertToMoldType(mlir::Location loc, fir::FirOpBuilder &builder,
410 fir::FirOpBuilder *b = &builder;
414 mlir::Value load = builder.create<fir::LoadOp>(loc, input);
415 return hlfir::Entity{builder.createConvert(loc, mold.getType(), load)};
418 mlir::Value asExpr = builder.create<hlfir::AsExprOp>(loc, input);
421 cleanups.emplace_back([=]() { b->create<hlfir::DestroyOp>(loc, asExpr); });
427 loc, builder, input, mold.getFortranElementType(), ".tmp.val2ref");
429 [=]() { b->create<hlfir::EndAssociateOp>(loc, associate); });
438 auto emboxed = hlfir::convertToBox(loc, builder, input, mold.getType());
442 return hlfir::Entity{builder.createConvert(loc, mold.getType(), input)};
456 loc, builder, rhsEntity,
457 loweredLhs.vectorSubscriptLoopNest->oneBasedIndices);
465 mlir::Value shape = hlfir::genShape(loc, builder, lhsEntity);
466 elementalLoopNest = hlfir::genLoopNest(loc, builder, shape);
467 builder.setInsertionPointToStart(elementalLoopNest->body);
468 lhsEntity = hlfir::getElementAt(loc, builder, lhsEntity,
469 elementalLoopNest->oneBasedIndices);
470 rhsEntity = hlfir::getElementAt(loc, builder, rhsEntity,
471 elementalLoopNest->oneBasedIndices);
475 lhsEntity = convertToMoldType(loc, builder, lhsEntity, userAssignLhs,
477 rhsEntity = convertToMoldType(loc, builder, rhsEntity, userAssignRhs,
483 (void)builder.clone(op, mapper);
487 builder.setInsertionPointAfter(elementalLoopNest->outerOp);
491 builder.create<hlfir::AssignOp>(loc, rhsEntity, lhsEntity);
495 builder.setInsertionPointAfter(loweredLhs.vectorSubscriptLoopNest->outerOp);
502 cdt = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{cdt});
503 cdt = builder.createConvert(loc, builder.getI1Type(), cdt);
504 auto ifOp = builder.create<fir::IfOp>(cdt.getLoc(), std::nullopt, cdt,
507 builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
513 // This is the top-level WHERE. Start a loop nest iterating on the shape of
517 hlfir::Entity savedMask{maybeSaved->first};
518 mlir::Value shape = hlfir::genShape(loc, builder, savedMask);
519 whereLoopNest = hlfir::genLoopNest(loc, builder, shape);
520 constructStack.push_back(whereLoopNest->outerOp);
521 builder.setInsertionPointToStart(whereLoopNest->body);
522 mlir::Value cdt = hlfir::getElementAt(loc, builder, savedMask,
523 whereLoopNest->oneBasedIndices);
525 if (maybeSaved->second) {
526 // If this is the same run as the one that saved the value, the clean-up
527 // was left-over to be done now.
528 auto insertionPoint = builder.saveInsertionPoint();
529 builder.setInsertionPointAfter(whereLoopNest->outerOp);
530 generateCleanupIfAny(maybeSaved->second);
531 builder.restoreInsertionPoint(insertionPoint);
535 // The mask was not evaluated yet or can be safely re-evaluated.
538 mask.generateNoneElementalPart(builder, mapper);
539 mlir::Value shape = mask.generateShape(builder, mapper);
540 whereLoopNest = hlfir::genLoopNest(loc, builder, shape);
541 constructStack.push_back(whereLoopNest->outerOp);
542 builder.setInsertionPointToStart(whereLoopNest->body);
557 builder.setInsertionPointAfter(constructStack.pop_back_val());
562 builder.setInsertionPointAfter(constructStack.pop_back_val());
573 builder.createBlock(&ifOp.getElseRegion());
574 auto end = builder.create<fir::ResultOp>(loc);
575 builder.setInsertionPoint(end);
577 builder.setInsertionPoint(&ifOp.getElseRegion().back().back());
595 builder.setInsertionPointAfter(constructStack.pop_back_val());
604 return block->isEntryBlock() &&
605 mlir::isa_and_nonnull<hlfir::ForallOp>(block->getParentOp());
612 castIfNeeded(mlir::Location loc, fir::FirOpBuilder &builder,
618 builder.createConvert(loc, *castToType, valueAndCleanUp.first);
624 mlir::Location loc = region.getParentOp()->getLoc();
626 // instead of fetching the temp, and do clean-up, if any, that were delayed.
632 return savedInSameRun->second;
635 doBeforeLoopNest([&]() { temp->second.resetFetchPosition(loc, builder); });
636 return ValueAndCleanUp{temp->second.fetch(loc, builder), std::nullopt};
651 mlir::Location loc = region.getParentOp()->getLoc();
653 return castIfNeeded(loc, builder, *maybeValueAndCleanUp, castToType);
660 return castIfNeeded(loc, builder, {maskedValue, std::nullopt}, castToType);
675 region.walk([&](mlir::Operation *op) -> mlir::WalkResult {
676 if (llvm::any_of(op->getOperands(), [](mlir::Value value) {
684 auto insertionPoint = builder.saveInsertionPoint();
686 builder.setInsertionPoint(constructStack[0]);
691 (void)builder.clone(op, mapper);
698 builder.createConvert(newEntity.getLoc(), *castToType, newEntity);
701 // Hoisted trivial scalars clean-up can be done right away, the value is
704 builder.restoreInsertionPoint(insertionPoint);
714 mlir::Location loc = region.getParentOp()->getLoc();
716 value = hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{value});
731 doBeforeLoopNest([&]() { temp->second.resetFetchPosition(loc, builder); });
738 if (loweredRhs && loweredRhs->isArray()) {
742 hlfir::genShape(loc, builder, *loweredRhs);
747 temp->second.cast<fir::factory::AnyVectorSubscriptStack>();
748 loweredLhs.vectorSubscriptShape = vectorTmp.fetchShape(loc, builder);
751 loc, builder, loweredLhs.vectorSubscriptShape.value());
752 builder.setInsertionPointToStart(
753 loweredLhs.vectorSubscriptLoopNest->body);
755 loweredLhs.lhs = temp->second.fetch(loc, builder);
764 (void)builder.clone(op, mapper);
768 hlfir::genLoopNest(loc, builder, *loweredLhs.vectorSubscriptShape,
770 builder.setInsertionPointToStart(loweredLhs.vectorSubscriptLoopNest->body);
772 loweredLhs.vectorSubscriptLoopNest->oneBasedIndices);
774 (void)builder.clone(op, mapper);
777 mapper.lookupOrDefault(loweredLhs.elementalCleanup->getEntity());
783 if (yield && !yield->getCleanup().empty())
784 loweredLhs.nonElementalCleanup = &yield->getCleanup();
792 auto insertionPoint = builder.saveInsertionPoint();
796 builder.setInsertionPoint(whereLoopNest->outerOp);
797 maskedExpr.generateNoneElementalPart(builder, mapper);
800 builder.setInsertionPointAfter(whereLoopNest->outerOp);
801 maskedExpr.generateNoneElementalCleanupIfAny(builder, mapper);
805 builder.restoreInsertionPoint(insertionPoint);
807 builder, whereLoopNest->oneBasedIndices, mapper);
812 maskedExpr.generateMaskedExprCleanUps(builder, mapper))
813 builder.setInsertionPoint(firstCleanup);
820 generateCleanupIfAny(&maybeYield->getCleanup());
824 if (cleanupRegion && !cleanupRegion->empty()) {
825 assert(cleanupRegion->hasOneBlock() && "region must contain one block");
826 for (auto &op : cleanupRegion->back().without_terminator())
827 builder.clone(op, mapper);
834 for (auto &action : currentRun->actions)
837 if (node.getOperation() == savedEntity->yieldRegion->getParentOp())
849 for (auto &action : currentRun->actions)
857 if (node->isProperAncestor(savedEntity->yieldRegion->getParentOp()))
861 if (node->isAncestor(assign.getOperation()))
880 /// Gather the tree of hlfir::ElementalOpInterface use-def, if any, starting
890 // section 10.2.3.2, point 10 imply that impure elemental sub-expression
925 void MaskedArrayExpr::generateNoneElementalPart(fir::FirOpBuilder &builder,
937 (void)builder.clone(op, mapper);
946 // the evaluation of sub-expression tree whose root was a non elemental
953 (void)builder.clone(subOp, mapper);
962 mlir::Value MaskedArrayExpr::generateShape(fir::FirOpBuilder &builder,
978 return hlfir::genShape(loc, builder, hlfir::Entity{clonedEntity});
982 MaskedArrayExpr::generateElementalParts(fir::FirOpBuilder &builder,
992 (void)builder.clone(op, mapper);
1008 return hlfir::getElementAt(loc, builder, clonedEntity, oneBasedIndices);
1013 [&](hlfir::ElementalOp appliedElemental) -> bool {
1016 return inlineElementalOp(loc, builder, elemental, oneBasedIndices, mapper,
1021 MaskedArrayExpr::generateMaskedExprCleanUps(fir::FirOpBuilder &builder,
1023 // Clone the clean-ups from the region itself, except for the destroy
1033 if (cleanupRegion->empty())
1036 for (mlir::Operation &op : cleanupRegion->front().without_terminator()) {
1040 mlir::Operation *cleanup = builder.clone(op, mapper);
1048 fir::FirOpBuilder &builder, mlir::IRMapping &mapper) {
1050 // Clone clean-ups of hlfir.exactly_once operations (in reverse order
1060 (void)builder.clone(cleanupOp, mapper);
1063 // For the outer mask, the region clean-ups must be generated
1066 generateMaskedExprCleanUps(builder, mapper);
1088 if (llvm::any_of(doLoop->getOperands(), [&](mlir::Value value) {
1098 currentConstruct = currentConstruct->getParentOp();
1104 computeLoopNestIterationNumber(mlir::Location loc, fir::FirOpBuilder &builder,
1108 mlir::Value extent = builder.genExtentFromTriplet(
1110 builder.getIndexType());
1114 loopExtent = builder.create<mlir::arith::MulIOp>(loc, loopExtent, extent);
1143 mlir::Location loc = region.getParentOp()->getLoc();
1147 entity = hlfir::loadTrivialScalar(loc, builder, entity);
1157 region, fir::factory::SimpleCopy(loc, builder, entity, tempName));
1167 /// pre-computed, create a rank-1 array outside of the loops. It will be
1172 computeLoopNestIterationNumber(loc, builder, loopNest);
1174 mlir::cast<fir::SequenceType>(builder.getVarLenSeqTy(entityType));
1177 loc, builder, sequenceType, loopExtent,
1184 // or dynamic type, use the runtime to create and manage a stack-like
1187 region, fir::factory::AnyValueStack{loc, builder, entityType});
1191 // the value to the temp and do clean-ups for the value if any.
1192 temp->pushValue(loc, builder, entity);
1195 // Delay the clean-up if the entity will be used in the same run (i.e., the
1201 (!temp->canBeFetchedAfterPush() ||
1210 // Here the clean-up code is inserted after the original
1213 // operations, because the clean-up is handled specially
1217 auto insertionPoint = builder.saveInsertionPoint();
1218 builder.setInsertionPointAfter(region.getParentOp());
1220 builder.restoreInsertionPoint(insertionPoint);
1236 mlir::Location loc = region.getParentOp()->getLoc();
1240 constructStack.push_back(loweredLhs.vectorSubscriptLoopNest->outerOp);
1256 loc, builder, loweredLhs.lhs.getType(),
1261 auto &vectorTmp = temp->cast<fir::factory::AnyVectorSubscriptStack>();
1262 auto insertionPoint = builder.saveInsertionPoint();
1263 builder.setInsertionPoint(loweredLhs.vectorSubscriptLoopNest->outerOp);
1264 vectorTmp.pushShape(loc, builder, shape);
1265 builder.restoreInsertionPoint(insertionPoint);
1280 region, fir::factory::AnyVariableStack{loc, builder,
1284 temp->pushValue(loc, builder, loweredLhs.lhs);
1288 builder.setInsertionPointAfter(loweredLhs.vectorSubscriptLoopNest->outerOp);
1296 auto module = root->getParentOfType<mlir::ModuleOp>();
1297 fir::FirOpBuilder builder(rewriter, module);
1298 OrderedAssignmentRewriter assignmentRewriter(builder, root);
1386 auto module = this->getOperation();
1394 context, this->tryFusingAssignments.getValue());