brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · 409195d Raw
155 lines · cpp
1//===-- lib/Semantics/canonicalize-do.cpp ---------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "canonicalize-do.h"10#include "flang/Parser/openmp-utils.h"11#include "flang/Parser/parse-tree-visitor.h"12#include "flang/Parser/tools.h"13 14namespace Fortran::parser {15 16class CanonicalizationOfDoLoops {17  struct LabelInfo {18    Block::iterator iter;19    Label label;20  };21 22public:23  template <typename T> bool Pre(T &) { return true; }24  template <typename T> void Post(T &) {}25  void Post(Block &block) {26    std::vector<LabelInfo> stack;27    for (auto i{block.begin()}, end{block.end()}; i != end; ++i) {28      if (auto *executableConstruct{std::get_if<ExecutableConstruct>(&i->u)}) {29        common::visit(30            common::visitors{31                [](auto &) {},32                // Labels on end-stmt of constructs are accepted by f18 as an33                // extension.34                [&](common::Indirection<AssociateConstruct> &associate) {35                  CanonicalizeIfMatch(block, stack, i,36                      std::get<Statement<EndAssociateStmt>>(37                          associate.value().t));38                },39                [&](common::Indirection<BlockConstruct> &blockConstruct) {40                  CanonicalizeIfMatch(block, stack, i,41                      std::get<Statement<EndBlockStmt>>(42                          blockConstruct.value().t));43                },44                [&](common::Indirection<ChangeTeamConstruct> &changeTeam) {45                  CanonicalizeIfMatch(block, stack, i,46                      std::get<Statement<EndChangeTeamStmt>>(47                          changeTeam.value().t));48                },49                [&](common::Indirection<CriticalConstruct> &critical) {50                  CanonicalizeIfMatch(block, stack, i,51                      std::get<Statement<EndCriticalStmt>>(critical.value().t));52                },53                [&](common::Indirection<DoConstruct> &doConstruct) {54                  CanonicalizeIfMatch(block, stack, i,55                      std::get<Statement<EndDoStmt>>(doConstruct.value().t));56                },57                [&](common::Indirection<IfConstruct> &ifConstruct) {58                  CanonicalizeIfMatch(block, stack, i,59                      std::get<Statement<EndIfStmt>>(ifConstruct.value().t));60                },61                [&](common::Indirection<CaseConstruct> &caseConstruct) {62                  CanonicalizeIfMatch(block, stack, i,63                      std::get<Statement<EndSelectStmt>>(64                          caseConstruct.value().t));65                },66                [&](common::Indirection<SelectRankConstruct> &selectRank) {67                  CanonicalizeIfMatch(block, stack, i,68                      std::get<Statement<EndSelectStmt>>(selectRank.value().t));69                },70                [&](common::Indirection<SelectTypeConstruct> &selectType) {71                  CanonicalizeIfMatch(block, stack, i,72                      std::get<Statement<EndSelectStmt>>(selectType.value().t));73                },74                [&](common::Indirection<ForallConstruct> &forall) {75                  CanonicalizeIfMatch(block, stack, i,76                      std::get<Statement<EndForallStmt>>(forall.value().t));77                },78                [&](common::Indirection<WhereConstruct> &where) {79                  CanonicalizeIfMatch(block, stack, i,80                      std::get<Statement<EndWhereStmt>>(where.value().t));81                },82                [&](Statement<common::Indirection<LabelDoStmt>> &labelDoStmt) {83                  auto &label{std::get<Label>(labelDoStmt.statement.value().t)};84                  stack.push_back(LabelInfo{i, label});85                },86                [&](Statement<common::Indirection<EndDoStmt>> &endDoStmt) {87                  CanonicalizeIfMatch(block, stack, i, endDoStmt);88                },89                [&](Statement<ActionStmt> &actionStmt) {90                  CanonicalizeIfMatch(block, stack, i, actionStmt);91                },92                [&](common::Indirection<OpenMPConstruct> &construct) {93                  // If the body of the OpenMP construct ends with a label,94                  // treat the label as ending the construct itself.95                  CanonicalizeIfMatch(96                      block, stack, i, omp::GetFinalLabel(construct.value()));97                },98            },99            executableConstruct->u);100      }101    }102  }103 104private:105  template <typename T>106  void CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack,107      Block::iterator &i, Statement<T> &statement) {108    CanonicalizeIfMatch(originalBlock, stack, i, statement.label);109  }110 111  void CanonicalizeIfMatch(Block &originalBlock, std::vector<LabelInfo> &stack,112      Block::iterator &i, std::optional<Label> label) {113    if (!stack.empty() && label && stack.back().label == *label) {114      auto currentLabel{stack.back().label};115      if (Unwrap<EndDoStmt>(*i)) {116        std::get<ExecutableConstruct>(i->u).u = Statement<ActionStmt>{117            std::optional<Label>{currentLabel}, ContinueStmt{}};118      }119      auto next{++i};120      do {121        Block block;122        auto doLoop{stack.back().iter};123        auto originalSource{124            std::get<Statement<common::Indirection<LabelDoStmt>>>(125                std::get<ExecutableConstruct>(doLoop->u).u)126                .source};127        block.splice(block.begin(), originalBlock, ++stack.back().iter, next);128        auto &labelDo{std::get<Statement<common::Indirection<LabelDoStmt>>>(129            std::get<ExecutableConstruct>(doLoop->u).u)};130        auto &loopControl{131            std::get<std::optional<LoopControl>>(labelDo.statement.value().t)};132        Statement<NonLabelDoStmt> nonLabelDoStmt{std::move(labelDo.label),133            NonLabelDoStmt{std::make_tuple(std::optional<Name>{},134                std::optional<Label>{}, std::move(loopControl))}};135        nonLabelDoStmt.source = originalSource;136        std::get<ExecutableConstruct>(doLoop->u).u =137            common::Indirection<DoConstruct>{138                std::make_tuple(std::move(nonLabelDoStmt), std::move(block),139                    Statement<EndDoStmt>{std::optional<Label>{},140                        EndDoStmt{std::optional<Name>{}}})};141        stack.pop_back();142      } while (!stack.empty() && stack.back().label == currentLabel);143      i = --next;144    }145  }146};147 148bool CanonicalizeDo(Program &program) {149  CanonicalizationOfDoLoops canonicalizationOfDoLoops;150  Walk(program, canonicalizationOfDoLoops);151  return true;152}153 154} // namespace Fortran::parser155