Ignore:
Timestamp:
Nov 6, 2016, 8:37:11 PM (3 years ago)
Author:
nmedfort
Message:

Initial work on adding types to PabloAST and mutable Var objects.

Location:
icGREP/icgrep-devel/icgrep/pablo/optimizers
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/booleanreassociationpass.cpp

    r5160 r5202  
    145145 ** ------------------------------------------------------------------------------------------------------------- */
    146146template <class Type>
    147 inline bool intersects(const Type & A, const Type & B) {
     147inline bool intersects(Type & A, Type & B) {
    148148    auto first1 = A.begin(), last1 = A.end();
    149149    auto first2 = B.begin(), last2 = B.end();
     
    325325    const auto offset = mRefs.size();
    326326    for (Statement * stmt = block->front(); stmt; ) {
    327         if (LLVM_UNLIKELY(isa<If>(stmt))) {
    328             if (LLVM_UNLIKELY(isa<Zeroes>(cast<If>(stmt)->getCondition()))) {
     327        if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
     328            if (LLVM_UNLIKELY(isa<Zeroes>(cast<Branch>(stmt)->getCondition()))) {
    329329                stmt = stmt->eraseFromParent(true);
    330330            } else {
    331331                CharacterizationMap nested(C);
    332                 processScopes(cast<If>(stmt)->getBody(), nested);
    333                 for (Assign * def : cast<If>(stmt)->getDefined()) {
     332                processScopes(cast<Branch>(stmt)->getBody(), nested);
     333                for (Var * def : cast<Branch>(stmt)->getEscaped()) {
    334334                    C.add(def, makeVar());
    335                 }
    336                 stmt = stmt->getNextNode();
    337             }
    338         } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
    339             if (LLVM_UNLIKELY(isa<Zeroes>(cast<While>(stmt)->getCondition()))) {
    340                 stmt = stmt->eraseFromParent(true);
    341             } else {
    342                 CharacterizationMap nested(C);
    343                 processScopes(cast<While>(stmt)->getBody(), nested);
    344                 for (Next * var : cast<While>(stmt)->getVariants()) {
    345                     C.add(var, makeVar());
    346335                }
    347336                stmt = stmt->getNextNode();
     
    409398        check[1] = isa<InFile>(stmt) ? mInFile : Z3_mk_not(mContext, mInFile); assert (check[1]);
    410399        node = Z3_mk_and(mContext, 2, check);
    411     } else if (LLVM_UNLIKELY(isa<Assign>(stmt) || isa<Next>(stmt))) {
     400    } else if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
    412401        return stmt->getNextNode();
    413402    }  else {
     
    526515            }
    527516            if (LLVM_UNLIKELY(isa<If>(stmt))) {
    528                 for (Assign * def : cast<const If>(stmt)->getDefined()) {
     517                for (Var * def : cast<If>(stmt)->getEscaped()) {
    529518                    const Vertex v = makeVertex(TypeId::Var, def, C, S, M, G);
    530519                    add_edge(def, u, v, G);
     
    537526                // we make the loop dependent on the original value of each Next node and
    538527                // the Next node dependent on the loop.
    539                 for (Next * var : cast<const While>(stmt)->getVariants()) {
     528                for (Var * var : cast<While>(stmt)->getEscaped()) {
    540529                    const Vertex v = makeVertex(TypeId::Var, var, C, S, M, G);
    541530                    assert (in_degree(v, G) == 1);
     
    574563            if (LLVM_UNLIKELY(parent != mBlock)) {
    575564                for (;;) {
    576                     if (parent->getPredecessor () == mBlock) {
     565                    if (parent->getPredecessor() == mBlock) {
    577566                        Statement * const branch = parent->getBranch();
    578567                        if (LLVM_UNLIKELY(branch != ignoreIfThis)) {
     
    585574                        break;
    586575                    }
    587                     parent = parent->getPredecessor ();
     576                    parent = parent->getPredecessor();
    588577                    if (LLVM_UNLIKELY(parent == nullptr)) {
    589                         assert (isa<Assign>(expr) || isa<Next>(expr));
     578                        assert (isa<Assign>(expr));
    590579                        break;
    591580                    }
     
    811800            continue;
    812801        } else if (isDistributive(G[u])) {
    813             const TypeId outerTypeId = getType(G[u]);
    814             const TypeId innerTypeId = (outerTypeId == TypeId::And) ? TypeId::Or : TypeId::And;
     802            TypeId outerTypeId = getType(G[u]);
     803            TypeId innerTypeId = (outerTypeId == TypeId::And) ? TypeId::Or : TypeId::And;
    815804            flat_set<Vertex> distributable;
    816805            for (auto e : make_iterator_range(in_edges(u, G))) {
     
    855844 * @brief recomputeDefinition
    856845 ** ------------------------------------------------------------------------------------------------------------- */
    857 inline Z3_ast BooleanReassociationPass::computeDefinition(const TypeId typeId, const Vertex u, Graph & G, const bool use_expensive_minimization) const {
     846inline Z3_ast BooleanReassociationPass::computeDefinition(TypeId typeId, const Vertex u, Graph & G, const bool use_expensive_minimization) const {
    858847    const unsigned n = in_degree(u, G);
    859848    Z3_ast operands[n];
     
    876865 * Apply the distribution law to reduce computations whenever possible.
    877866 ** ------------------------------------------------------------------------------------------------------------- */
    878 Vertex BooleanReassociationPass::updateIntermediaryDefinition(const TypeId typeId, const Vertex u, VertexMap & M, Graph & G) {
     867Vertex BooleanReassociationPass::updateIntermediaryDefinition(TypeId typeId, const Vertex u, VertexMap & M, Graph & G) {
    879868
    880869    Z3_ast def = computeDefinition(typeId, u, G);
     
    914903 * Apply the distribution law to reduce computations whenever possible.
    915904 ** ------------------------------------------------------------------------------------------------------------- */
    916 Vertex BooleanReassociationPass::updateSinkDefinition(const TypeId typeId, const Vertex u, CharacterizationMap & C, VertexMap & M, Graph & G) {
     905Vertex BooleanReassociationPass::updateSinkDefinition(TypeId typeId, const Vertex u, CharacterizationMap & C, VertexMap & M, Graph & G) {
    917906
    918907    Z3_ast const def = computeDefinition(typeId, u, G);
     
    10611050            const VertexSet & sinks = std::get<2>(set);
    10621051
    1063             const TypeId outerTypeId = getType(G[H[sinks.front()]]);
     1052            TypeId outerTypeId = getType(G[H[sinks.front()]]);
    10641053            assert (outerTypeId == TypeId::And || outerTypeId == TypeId::Or);
    1065             const TypeId innerTypeId = (outerTypeId == TypeId::Or) ? TypeId::And : TypeId::Or;
     1054            TypeId innerTypeId = (outerTypeId == TypeId::Or) ? TypeId::And : TypeId::Or;
    10661055
    10671056            const Vertex x = makeVertex(outerTypeId, nullptr, G);
     
    11181107    switch (getType(data)) {
    11191108        case TypeId::Assign:
    1120         case TypeId::Next:
    11211109        case TypeId::If:
    11221110        case TypeId::While:
     
    12181206 * @brief factorGraph
    12191207 ** ------------------------------------------------------------------------------------------------------------- */
    1220 bool BooleanReassociationPass::factorGraph(const TypeId typeId, Graph & G, std::vector<Vertex> & factors) const {
     1208bool BooleanReassociationPass::factorGraph(TypeId typeId, Graph & G, std::vector<Vertex> & factors) const {
    12211209
    12221210    if (LLVM_UNLIKELY(factors.empty())) {
     
    15881576* @brief makeVertex
    15891577** ------------------------------------------------------------------------------------------------------------- */
    1590 Vertex BooleanReassociationPass::makeVertex(const TypeId typeId, PabloAST * const expr, CharacterizationMap & C, StatementMap & S, VertexMap & M, Graph & G) {
     1578Vertex BooleanReassociationPass::makeVertex(TypeId typeId, PabloAST * const expr, CharacterizationMap & C, StatementMap & S, VertexMap & M, Graph & G) {
    15911579    assert (expr);
    15921580    const auto f = S.find(expr);
     
    16071595 * @brief makeVertex
    16081596 ** ------------------------------------------------------------------------------------------------------------- */
    1609 Vertex BooleanReassociationPass::makeVertex(const TypeId typeId, PabloAST * const expr, StatementMap & M, Graph & G, Z3_ast node) {
     1597Vertex BooleanReassociationPass::makeVertex(TypeId typeId, PabloAST * const expr, StatementMap & M, Graph & G, Z3_ast node) {
    16101598    assert (expr);
    16111599    const auto f = M.find(expr);
     
    16221610 * @brief makeVertex
    16231611 ** ------------------------------------------------------------------------------------------------------------- */
    1624 Vertex BooleanReassociationPass::makeVertex(const TypeId typeId, PabloAST * const expr, Graph & G, Z3_ast node) {
     1612Vertex BooleanReassociationPass::makeVertex(TypeId typeId, PabloAST * const expr, Graph & G, Z3_ast node) {
    16251613//    for (Vertex u : make_iterator_range(vertices(G))) {
    16261614//        if (LLVM_UNLIKELY(in_degree(u, G) == 0 && out_degree(u, G) == 0)) {
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/booleanreassociationpass.h

    r5160 r5202  
    5656    void reduceVertex(const Vertex u, CharacterizationMap & C, VertexMap & M, Graph & G);
    5757
    58     bool factorGraph(const TypeId typeId, Graph & G, std::vector<Vertex> & factors) const;
     58    bool factorGraph(TypeId typeId, Graph & G, std::vector<Vertex> & factors) const;
    5959    bool factorGraph(Graph & G) const;
    6060
    61     static Vertex makeVertex(const TypeId typeId, PabloAST * const expr, Graph & G, Z3_ast node = nullptr);
    62     static Vertex makeVertex(const TypeId typeId, PabloAST * const expr, StatementMap & M, Graph & G, Z3_ast node = nullptr);
    63     static Vertex makeVertex(const TypeId typeId, PabloAST * const expr, CharacterizationMap & C, StatementMap & S, VertexMap & M, Graph & G);
     61    static Vertex makeVertex(TypeId typeId, PabloAST * const expr, Graph & G, Z3_ast node = nullptr);
     62    static Vertex makeVertex(TypeId typeId, PabloAST * const expr, StatementMap & M, Graph & G, Z3_ast node = nullptr);
     63    static Vertex makeVertex(TypeId typeId, PabloAST * const expr, CharacterizationMap & C, StatementMap & S, VertexMap & M, Graph & G);
    6464
    6565    void removeVertex(const Vertex u, VertexMap & M, Graph & G) const;
    6666    void removeVertex(const Vertex u, Graph & G) const;
    6767
    68     Z3_ast computeDefinition(const TypeId typeId, const Vertex u, Graph & G, const bool use_expensive_minimization = false) const;
    69     Vertex updateIntermediaryDefinition(const TypeId typeId, const Vertex u, VertexMap & M, Graph & G);
    70     Vertex updateSinkDefinition(const TypeId typeId, const Vertex u, CharacterizationMap &C, VertexMap & M, Graph & G);
     68    Z3_ast computeDefinition(TypeId typeId, const Vertex u, Graph & G, const bool use_expensive_minimization = false) const;
     69    Vertex updateIntermediaryDefinition(TypeId typeId, const Vertex u, VertexMap & M, Graph & G);
     70    Vertex updateSinkDefinition(TypeId typeId, const Vertex u, CharacterizationMap &C, VertexMap & M, Graph & G);
    7171    bool redistributeGraph(CharacterizationMap & C, VertexMap & M, Graph & G);
    7272
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/codemotionpass.cpp

    r5160 r5202  
    3939        }
    4040    }
    41     reschedule(block);
    4241}
    4342
    4443/** ------------------------------------------------------------------------------------------------------------- *
    45  * @brief isSafeToMove
    46  ** ------------------------------------------------------------------------------------------------------------- */
    47 inline static bool isSafeToMove(Statement * stmt) {
    48     return !isa<Assign>(stmt) && !isa<Next>(stmt);
    49 }
    50 
    51 /** ------------------------------------------------------------------------------------------------------------- *
    52  * @brief calculateDepthToCurrentBlock
     44 * @brief depthTo
    5345 ** ------------------------------------------------------------------------------------------------------------- */
    5446inline static unsigned depthTo(const PabloBlock * scope, const PabloBlock * const root) {
     
    5749        ++depth;
    5850        assert (scope);
    59         scope = scope->getPredecessor ();
     51        scope = scope->getPredecessor();
    6052    }
    6153    return depth;
     
    6658 ** ------------------------------------------------------------------------------------------------------------- */
    6759template <class ScopeSet>
    68 inline bool findScopeUsages(Statement * stmt, ScopeSet & scopeSet, const PabloBlock * const block, const PabloBlock * const blocker) {
    69     for (PabloAST * use : stmt->users()) {
     60inline bool findScopeUsages(PabloAST * expr, ScopeSet & scopeSet, const PabloBlock * const block, const PabloBlock * const blocker) {
     61    for (PabloAST * use : expr->users()) {
    7062        assert (isa<Statement>(use));
    7163        PabloBlock * const parent = cast<Statement>(use)->getParent();
     
    8779    // find the least common ancestor of the scope blocks. If it is not the current scope,
    8880    // then we can sink the instruction.
    89     if (isa<If>(stmt)) {
    90         for (Assign * def : cast<If>(stmt)->getDefined()) {
    91             if (!findScopeUsages(def, scopeSet, block, cast<If>(stmt)->getBody())) {
     81    assert (scopeSet.empty());
     82    if (isa<Branch>(stmt)) {
     83        for (Var * def : cast<Branch>(stmt)->getEscaped()) {
     84            if (!findScopeUsages(def, scopeSet, block, cast<Branch>(stmt)->getBody())) {
    9285                return false;
    9386            }
    9487        }
    95     } else if (isa<While>(stmt)) {
    96         for (Next * var : cast<While>(stmt)->getVariants()) {
    97             if (escapes(var) && !findScopeUsages(var, scopeSet, block, cast<While>(stmt)->getBody())) {
    98                 return false;
    99             }
    100         }
    101     } else if (isSafeToMove(stmt)) {
     88    } else if (!isa<Assign>(stmt)) {
    10289        return findScopeUsages(stmt, scopeSet, block, nullptr);
    10390    }
     
    126113                // the scope tree until both scopes are at the same depth.
    127114                while (depth1 > depth2) {
    128                     scope1 = scope1->getPredecessor ();
     115                    scope1 = scope1->getPredecessor();
    129116                    --depth1;
    130117                }
    131118                while (depth1 < depth2) {
    132                     scope2 = scope2->getPredecessor ();
     119                    scope2 = scope2->getPredecessor();
    133120                    --depth2;
    134121                }
     
    138125                while (scope1 != scope2) {
    139126                    assert (scope1 && scope2);
    140                     scope1 = scope1->getPredecessor ();
    141                     scope2 = scope2->getPredecessor ();
     127                    scope1 = scope1->getPredecessor();
     128                    scope2 = scope2->getPredecessor();
    142129                }
    143130                assert (scope1);
     
    149136            }
    150137            assert (scopes.size() == 1);
    151             assert (isa<If>(stmt) ? (cast<If>(stmt)->getBody() != scopes.front()) : true);
    152             assert (isa<While>(stmt) ? (cast<While>(stmt)->getBody() != scopes.front()) : true);
     138            assert (isa<Branch>(stmt) ? (cast<Branch>(stmt)->getBody() != scopes.front()) : true);
    153139            stmt->insertBefore(scopes.front()->front());
    154140        }
     
    163149void CodeMotionPass::hoistLoopInvariants(While * loop) {
    164150    flat_set<const PabloAST *> loopVariants;
    165     for (Next * variant : loop->getVariants()) {
     151    for (Var * variant : loop->getEscaped()) {
    166152        loopVariants.insert(variant);
    167         loopVariants.insert(variant->getInitial());
    168153    }
    169154    Statement * outerNode = loop->getPrevNode();
    170155    Statement * stmt = loop->getBody()->front();
    171156    while (stmt) {
    172         if (isa<If>(stmt)) {
    173             for (Assign * def : cast<If>(stmt)->getDefined()) {
    174                 loopVariants.insert(def);
    175             }
    176         } else if (isa<While>(stmt)) {
    177             for (Next * var : cast<While>(stmt)->getVariants()) {
     157        if (isa<Branch>(stmt)) {
     158            for (Var * var : cast<Branch>(stmt)->getEscaped()) {
    178159                loopVariants.insert(var);
    179160            }
     
    199180}
    200181
    201 /** ------------------------------------------------------------------------------------------------------------- *
    202  * @brief reschedule
    203  ** ------------------------------------------------------------------------------------------------------------- */
    204 void CodeMotionPass::reschedule(PabloBlock * const block) {
    205 
    206 //    using Graph = adjacency_list<hash_setS, vecS, bidirectionalS, Statement *>;
    207 //    using Vertex = Graph::vertex_descriptor;
    208 //    using Map = flat_map<Statement *, Vertex>;
    209 
    210 //    const unsigned size = std::distance(block->begin(), block->end());
    211 
    212 //    Graph G(size);
    213 //    Map M;
    214 
    215 //    M.reserve(size);
    216 
    217 //    unsigned i = 0;
    218 //    for (Statement * stmt : *block) {
    219 //        G[i] = stmt;
    220 //        M.emplace(stmt, i);
    221 //        ++i;
    222 //    }
    223 
    224 //    i = 0;
    225 //    for (Statement * stmt : *block) {
    226 //        for (PabloAST * user : stmt->users()) {
    227 //            if (isa<Statement>(user)) {
    228 //                Statement * use = cast<Statement>(user);
    229 //                PabloBlock * parent = use->getParent();
    230 //                while (parent) {
    231 //                    if (parent == block) {
    232 //                        break;
    233 //                    }
    234 //                    use = parent->getBranch();
    235 //                    parent = parent->getParent();
    236 //                }
    237 //                auto f = M.find(use);
    238 //                assert (f != M.end());
    239 //                add_edge(i, f->second, G);
    240 //            }
    241 //        }
    242 //        ++i;
    243 //    }
    244 
    245 //    circular_buffer<Vertex> ordering(size);
    246 //    std::vector<unsigned> cumulativeDependencies;
    247 //    topological_sort(G, std::back_inserter(ordering));
    248    
    249 
    250 
    251182}
    252 
    253 }
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/codemotionpass.h

    r4927 r5202  
    3535    static void sink(PabloBlock * const block);
    3636    static void hoistLoopInvariants(While * loop);
    37 
    38     static void reschedule(PabloBlock * const block);
    3937};
    4038
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/distributivepass.cpp

    r5160 r5202  
    3131 ** ------------------------------------------------------------------------------------------------------------- */
    3232template <class Type>
    33 inline bool intersects(const Type & A, const Type & B) {
     33inline bool intersects(Type & A, Type & B) {
    3434    auto first1 = A.begin(), last1 = A.end();
    3535    auto first2 = B.begin(), last2 = B.end();
     
    239239inline unsigned scopeDepthOf(const PabloBlock * block) {
    240240    unsigned depth = 0;
    241     for (; block; ++depth, block = block->getPredecessor ());
     241    for (; block; ++depth, block = block->getPredecessor());
    242242    return depth;
    243243}
     
    267267        // the scope tree until both scopes are at the same depth.
    268268        while (depth1 > depth2) {
    269             scope1 = scope1->getPredecessor ();
     269            scope1 = scope1->getPredecessor();
    270270            --depth1;
    271271        }
    272272        while (depth1 < depth2) {
    273             scope2 = scope2->getPredecessor ();
     273            scope2 = scope2->getPredecessor();
    274274            --depth2;
    275275        }
     
    278278        // the LCA of our original pair.
    279279        while (scope1 != scope2) {
    280             scope1 = scope1->getPredecessor ();
    281             scope2 = scope2->getPredecessor ();
     280            scope1 = scope1->getPredecessor();
     281            scope2 = scope2->getPredecessor();
    282282        }
    283283        assert (scope1 && scope2);
     
    297297            assert (scope);
    298298            user = scope->getBranch();
    299             scope = scope->getPredecessor ();
     299            scope = scope->getPredecessor();
    300300        }
    301301        usages.insert(user);
     
    318318static inline void computeDistributionGraph(Variadic * const expr, Graph & G, VertexSet & A) {
    319319
    320     const TypeId outerTypeId = expr->getClassTypeId();
    321     const TypeId innerTypeId = (outerTypeId == TypeId::And) ? TypeId::Or : TypeId::And;
     320    TypeId outerTypeId = expr->getClassTypeId();
     321    TypeId innerTypeId = (outerTypeId == TypeId::And) ? TypeId::Or : TypeId::And;
    322322
    323323    assert (isa<And>(expr) || isa<Or>(expr));
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/pablo_automultiplexing.cpp

    r5160 r5202  
    9292                optimize(cast<If>(stmt)->getBody());
    9393            } else if (isa<While>(stmt)) {
    94                 for (const Next * var : cast<While>(stmt)->getVariants()) {
    95                     Z3_inc_ref(mContext, get(var->getInitial()));
     94                for (const Var * var : cast<While>(stmt)->getEscaped()) {
     95                    Z3_inc_ref(mContext, get(var));
    9696                }
    9797                optimize(cast<While>(stmt)->getBody());
    9898                // since we cannot be certain that we'll always execute at least one iteration of a loop, we must
    9999                // assume that the variants could either be their initial or resulting value.
    100                 for (const Next * var : cast<While>(stmt)->getVariants()) {
    101                     Z3_ast v0 = get(var->getInitial());
     100                for (const Var * var : cast<While>(stmt)->getEscaped()) {
     101                    Z3_ast v0 = get(var);
    102102                    Z3_ast & v1 = get(var);
    103103                    Z3_ast merge[2] = { v0, v1 };
     
    172172    switch (stmt->getClassTypeId()) {
    173173        case TypeId::Assign:
    174         case TypeId::Next:
    175174        case TypeId::AtEOF:
    176175        case TypeId::InFile:
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/pablo_bddminimization.cpp

    r4880 r5202  
    110110        } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
    111111            eliminateLogicallyEquivalentStatements(cast<While>(stmt)->getBody(), map);
    112             for (Next * var : cast<const While>(stmt)->getVariants()) {
    113                 if (!escapes(var)) {
    114                     bdd_delref(mCharacterizationMap[var]);
    115                     mCharacterizationMap.erase(var);
    116                 }
     112            for (Var * var : cast<const While>(stmt)->getVariants()) {
     113                bdd_delref(mCharacterizationMap[var]);
     114                mCharacterizationMap.erase(var);
    117115            }
    118116        } else { // attempt to characterize this statement and replace it if we've encountered an equivalent one
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/pablo_simplifier.cpp

    r5160 r5202  
    33#include <pablo/expression_map.hpp>
    44#include <pablo/function.h>
    5 #include <pablo/printer_pablos.h>
    65#include <pablo/analysis/pabloverifier.hpp>
    76#include <boost/container/flat_set.hpp>
    8 
     7#include <boost/container/flat_map.hpp>
    98#include <pablo/printer_pablos.h>
    109#include <iostream>
    1110
     11using namespace boost;
     12using namespace boost::container;
     13
    1214namespace pablo {
    13 
    14 template <typename Type>
    15 using SmallSet = boost::container::flat_set<Type>;
    1615
    1716using TypeId = PabloAST::ClassTypeId;
     
    7675        // Apply an implicit distribution + identity law whenever possible
    7776        //    (P ∧ Q) √ (P ∧ ¬Q) = P √ (Q ∧ ¬Q) ⇔ P
    78         const TypeId typeId = isa<And>(var) ? TypeId::Or : TypeId::And;
    79         for (unsigned i = 1; i < var->getNumOperands(); ++i) {
     77        TypeId typeId = isa<And>(var) ? TypeId::Or : TypeId::And;
     78        for (unsigned i = 0; i < var->getNumOperands(); ++i) {
    8079            if (var->getOperand(i)->getClassTypeId() == typeId) {
    8180                Variadic * const Vi = cast<Variadic>(var->getOperand(i));
    82                 if (LLVM_UNLIKELY(!std::is_sorted(Vi->begin(), Vi->end()))) {
    83                     std::sort(Vi->begin(), Vi->end());
    84                 }
     81                // Ensure the i-th operand is sorted incase it was altered after being folded.
     82                std::sort(Vi->begin(), Vi->end());
    8583                for (unsigned j = 0; j < i; ++j) {
    8684                    assert (var->getOperand(i) == Vi);
    8785                    if (var->getOperand(j)->getClassTypeId() == typeId) {
    8886                        Variadic * const Vj = cast<Variadic>(var->getOperand(j));
    89                         if (LLVM_UNLIKELY(!std::is_sorted(Vj->begin(), Vj->end()))) {
    90                             std::sort(Vj->begin(), Vj->end());
    91                         }
     87                        assert (std::is_sorted(Vj->begin(), Vj->end()));
    9288                        if (Vi->getNumOperands() == Vj->getNumOperands()) {
    93                             // If vi and vj differ by precisely one operand, say di and dj, and di ⇔ ¬dj, we can apply this rule.
     89                            // If vi and vj differ by precisely one operand, say di and dj,
     90                            // and di ⇔ ¬dj, we can apply this rule.
    9491                            unsigned vi = 0, vj = 0;
    9592                            const unsigned operands = Vi->getNumOperands();
     
    269266            if (LLVM_UNLIKELY(isa<Zeroes>(stmt->getOperand(i)))) {
    270267                switch (stmt->getClassTypeId()) {
    271                     case PabloAST::ClassTypeId::Sel:
     268                    case TypeId::Sel:
    272269                        block->setInsertPoint(stmt->getPrevNode());
    273270                        switch (i) {
     
    276273                            case 2: return block->createAnd(stmt->getOperand(0), stmt->getOperand(1));
    277274                        }
    278                     case PabloAST::ClassTypeId::ScanThru:
    279                     case PabloAST::ClassTypeId::MatchStar:
     275                    case TypeId::ScanThru:
     276                    case TypeId::MatchStar:
    280277                        return stmt->getOperand(0);
    281278                    default: break;
     
    283280            } else if (LLVM_UNLIKELY(isa<Ones>(stmt->getOperand(i)))) {
    284281                switch (stmt->getClassTypeId()) {
    285                     case PabloAST::ClassTypeId::Sel:
     282                    case TypeId::Sel:
    286283                        block->setInsertPoint(stmt->getPrevNode());
    287284                        switch (i) {
     
    290287                            case 2: return block->createOr(block->createNot(stmt->getOperand(0)), stmt->getOperand(1));
    291288                        }
    292                     case PabloAST::ClassTypeId::ScanThru:
     289                    case TypeId::ScanThru:
    293290                        if (LLVM_UNLIKELY(i == 1)) {
    294291                            return block->createZeroes(stmt->getType());
    295292                        }
    296293                        break;
    297                     case PabloAST::ClassTypeId::MatchStar:
     294                    case TypeId::MatchStar:
    298295                        if (LLVM_UNLIKELY(i == 0)) {
    299296                            return block->createOnes(stmt->getType());
     
    306303    }
    307304    return nullptr;
    308 }
    309 
    310 /** ------------------------------------------------------------------------------------------------------------- *
    311  * @brief isSuperfluous
    312  ** ------------------------------------------------------------------------------------------------------------- */
    313 inline bool Simplifier::isSuperfluous(const Assign * const assign) {
    314     if (LLVM_LIKELY(isa<Statement>(assign->getExpression()))) {
    315         for (const PabloAST * user : assign->users()) {
    316             if (LLVM_UNLIKELY(isa<PabloFunction>(user) || isa<Next>(user))) {
    317                 return false;
    318             } else if (isa<If>(user)) {
    319                 if (LLVM_UNLIKELY(cast<If>(user)->getCondition() == assign)) {
    320                     continue;
    321                 } else if (isa<Assign>(assign->getExpression())) {
    322                     continue;
    323                 }
    324                 return false;
    325             }
    326         }
    327     }
    328     return true;
    329 }
    330 
    331 /** ------------------------------------------------------------------------------------------------------------- *
    332  * @brief demoteDefinedVar
    333  ** ------------------------------------------------------------------------------------------------------------- */
    334 inline bool demoteDefinedVar(const If * ifNode, const Assign * def) {
    335     // If this value isn't used outside of this scope then there is no reason to allow it to escape it.
    336     if (!escapes(def)) {
    337         return true;
    338     }
    339     // Similarly if the defined variable is equivalent to the condition, an equivalent value is already available.
    340     if (ifNode->getCondition() == def->getExpression()) {
    341         return true;
    342     }
    343     // Finally, if the assignment is a constant, it's already known.
    344     if (isa<Zeroes>(def->getExpression()) || isa<Ones>(def->getExpression()))  {
    345         return true;
    346     }
    347     return false;
    348 }
    349 
    350 /** ------------------------------------------------------------------------------------------------------------- *
    351  * @brief replaceReachableUsersOfWith
    352  ** ------------------------------------------------------------------------------------------------------------- */
    353 inline void replaceReachableUsersOfWith(Statement * stmt, PabloAST * expr) {
    354     const PabloBlock * const root = stmt->getParent();
    355     SmallSet<const PabloBlock *> forbidden;
    356     for (PabloAST * use : stmt->users()) {
    357         if (LLVM_UNLIKELY(isa<Next>(use))) {
    358             const PabloBlock * parent = cast<Next>(use)->getParent();
    359             if (parent != root) {
    360                 forbidden.insert(parent);
    361             }
    362         }
    363     }
    364     for (PabloAST * use : stmt->users()) {
    365         if (Statement * user = dyn_cast<Statement>(use)) {
    366             const PabloBlock * parent = user->getParent();
    367             while (parent && forbidden.count(parent) == 0) {
    368                 if (LLVM_UNLIKELY(parent == root)) {
    369                     user->replaceUsesOfWith(stmt, expr);
    370                     break;
    371                 }
    372                 parent = parent->getPredecessor ();
    373             }
    374         }
    375     }
    376305}
    377306
     
    380309 *
    381310 * If this inner block is composed of only Boolean logic and Assign statements and there are fewer than 3
    382  * statements, just add the statements in the inner block to the current block->
     311 * statements, just add the statements in the inner block to the current block
    383312 ** ------------------------------------------------------------------------------------------------------------- */
    384313inline bool discardNestedIfBlock(const PabloBlock * const block) {
     
    386315    for (const Statement * stmt : *block) {
    387316        switch (stmt->getClassTypeId()) {
    388             case PabloAST::ClassTypeId::And:
    389             case PabloAST::ClassTypeId::Or:
    390             case PabloAST::ClassTypeId::Xor:
     317            case TypeId::And:
     318            case TypeId::Or:
     319            case TypeId::Xor:
    391320                if (++computations > 3) {
    392321                    return false;
    393322                }
    394             case PabloAST::ClassTypeId::Not:
    395             case PabloAST::ClassTypeId::Assign:
     323            case TypeId::Not:
     324            case TypeId::Assign:
    396325                break;
    397326            default:
     
    403332
    404333/** ------------------------------------------------------------------------------------------------------------- *
    405  * @brief removeIdenticalEscapedValues
    406  ** ------------------------------------------------------------------------------------------------------------- */
    407 template <class ValueList, class ValueType = typename ValueList::value_type>
    408 inline void removeIdenticalEscapedValues(ValueList & list) {
    409     std::vector<ValueType> identicalValues;
    410     for (auto i = list.begin(); i != list.end(); ++i) {
    411         for (auto j = i + 1; j != list.end(); ++j) {
    412             if (LLVM_UNLIKELY(equals(*i, *j))) {
    413                 identicalValues.push_back(*j);
    414             }
    415         }
    416         for (ValueType identicalValue : identicalValues) {
    417             identicalValue->replaceWith(*i);
    418         }
    419         identicalValues.clear();
    420     }
    421 }
     334 * @brief VariableTable
     335 ** ------------------------------------------------------------------------------------------------------------- */
     336struct Simplifier::VariableTable {
     337
     338    VariableTable(VariableTable * predecessor = nullptr)
     339    : mPredecessor(predecessor) {
     340
     341    }
     342
     343    PabloAST * get(PabloAST * const var) const {
     344        const auto f = mMap.find(var);
     345        if (f == mMap.end()) {
     346            return (mPredecessor) ? mPredecessor->get(var) : nullptr;
     347        }
     348        return f->second;
     349    }
     350
     351    void put(PabloAST * const var, PabloAST * value) {
     352        const auto f = mMap.find(var);
     353        if (LLVM_LIKELY(f == mMap.end())) {
     354            mMap.emplace(var, value);
     355        } else {
     356            f->second = value;
     357        }
     358        assert (get(var) == value);
     359    }
     360
     361private:
     362    VariableTable * const mPredecessor;
     363    flat_map<PabloAST *, PabloAST *> mMap;
     364};
    422365
    423366/** ------------------------------------------------------------------------------------------------------------- *
     
    427370 * as replacements. Let the DCE remove the unnecessary statements with the finalized Def-Use information.
    428371 ** ------------------------------------------------------------------------------------------------------------- */
    429 void Simplifier::redundancyElimination(PabloFunction & function, PabloBlock * const block, ExpressionTable * predecessor) {
    430     ExpressionTable encountered(predecessor);
     372void Simplifier::redundancyElimination(PabloBlock * const block, ExpressionTable * const et, VariableTable * const vt) {
     373    ExpressionTable expressions(et);
     374    VariableTable variables(vt);
     375
     376    // When processing a While body, we cannot use its initial value from the outer
     377    // body since the Var will likely be assigned a different value in the current
     378    // body that should be used on the subsequent iteration of the loop.
     379    if (While * br = dyn_cast_or_null<While>(block->getBranch())) {
     380        for (Var * var : br->getEscaped()) {
     381            variables.put(var, var);
     382        }
     383    }
     384
    431385    Statement * stmt = block->front();
    432386    while (stmt) {
    433         if (Assign * assign = dyn_cast<Assign>(stmt)) {
    434             // If we have an Assign whose users do not contain an If or Next node, we can replace its users with
    435             // the Assign's expression directly.
    436             if (isSuperfluous(assign)) {
    437                 stmt = assign->replaceWith(assign->getExpression());
    438                 continue;
    439             }
    440             // Force the uses of an Assign node that can reach the original expression to use the expression instead.
    441             replaceReachableUsersOfWith(assign, assign->getExpression());
    442         } else if (Next * next = dyn_cast<Next>(stmt)) {
    443             replaceReachableUsersOfWith(next, next->getExpr());
    444         } else if (If * ifNode = dyn_cast<If>(stmt)) {
    445             // Test whether we can ever take this branch
    446             if (LLVM_UNLIKELY(isa<Zeroes>(cast<If>(stmt)->getCondition()))) {
     387
     388        if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
     389            Assign * const assign = cast<Assign>(stmt);
     390            PabloAST * const var = assign->getVariable();
     391            PabloAST * value = assign->getValue();
     392            while (LLVM_UNLIKELY(isa<Var>(value))) {
     393                PabloAST * next = variables.get(cast<Var>(value));
     394                if (LLVM_LIKELY(next == nullptr || next == value)) {
     395                    break;
     396                }
     397                value = next;
     398                assign->setValue(value);
     399            }
     400            if (LLVM_UNLIKELY(variables.get(var) == value)) {
    447401                stmt = stmt->eraseFromParent();
    448402                continue;
    449403            }
    450             // Test whether all of the defined variables are necessary
    451             If::DefinedVars & defs = ifNode->getDefined();
    452             for (auto def = defs.begin(); def != defs.end(); ) {
    453                 if (LLVM_UNLIKELY(demoteDefinedVar(ifNode, *def))) {
    454                     (*def)->replaceWith((*def)->getExpression());
    455                     def = ifNode->removeDefined(*def);
    456                     continue;
    457                 }
    458                 ++def;
    459             }
    460 
    461             // Process the If body
    462             redundancyElimination(function, cast<If>(stmt)->getBody(), &encountered);
    463 
    464             // If we ended up removing all of the defined variables, delete the If node.
    465             if (LLVM_UNLIKELY(defs.empty())) {
     404            variables.put(var, value);
     405        } else if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
     406
     407            Branch * const br = cast<Branch>(stmt);
     408
     409            // Test whether we can ever take this branch
     410            PabloAST * cond = br->getCondition();
     411            if (isa<Var>(cond)) {
     412                PabloAST * const value = variables.get(cast<Var>(cond));
     413                if (value) {
     414                    cond = value;
     415                    // TODO: verify this works for a nested If node within a While body.
     416                    if (isa<If>(br)) {
     417                        br->setCondition(cond);
     418                    }
     419                }
     420            }
     421
     422            if (LLVM_UNLIKELY(isa<Zeroes>(cond))) {
    466423                stmt = stmt->eraseFromParent();
    467424                continue;
    468425            }
    469426
    470             // Otherwise check if we any Assign reports the same value as another. If so, replace all uses of the
    471             // second with the first. This will simplify future analysis.
    472             removeIdenticalEscapedValues(ifNode->getDefined());
    473 
    474             // Finally after we've eliminated everything we can from the If body, check whether testing the If
    475             // condition will meet or exceed the cost of executing the body.
    476             if (LLVM_UNLIKELY(discardNestedIfBlock(ifNode->getBody()))) {
    477                 Statement * nested = ifNode->getBody()->front();
     427            // Process the Branch body
     428            redundancyElimination(br->getBody(), &expressions, &variables);
     429
     430            // Check whether this If branch has enough operations nested within it to
     431            // be worth the cost of the branch.
     432            if (LLVM_UNLIKELY(isa<If>(br) && discardNestedIfBlock(br->getBody()))) {
     433                Statement * nested = br->getBody()->front();
    478434                while (nested) {
    479435                    Statement * next = nested->removeFromParent();
    480                     if (isa<Assign>(nested)) {
    481                         ifNode->removeDefined(cast<Assign>(nested));
    482                     }
    483436                    nested->insertAfter(stmt);
    484437                    stmt = nested;
    485438                    nested = next;
    486439                }
    487                 stmt = ifNode->eraseFromParent();
     440                stmt = br->eraseFromParent();
    488441                continue;
    489442            }
    490443
    491         } else if (While * whileNode = dyn_cast<While>(stmt)) {
    492             // Test whether we can ever take this branch
    493             const PabloAST * initial = cast<While>(stmt)->getCondition();
    494             if (LLVM_LIKELY(isa<Next>(initial))) {
    495                 initial = cast<Next>(initial)->getInitial();
    496             }
    497             if (LLVM_UNLIKELY(isa<Zeroes>(initial))) {
    498                 stmt = stmt->eraseFromParent();
    499                 continue;
    500             }
    501             redundancyElimination(function, whileNode->getBody(), &encountered);
    502             removeIdenticalEscapedValues(whileNode->getVariants());
    503             // If the condition's Next state is Zero, we can eliminate the loop after copying the internal
    504             // statements into the body.
    505444        } else {
     445
     446            // demote any uses of a Var whose value is in scope
     447            for (unsigned i = 0; i < stmt->getNumOperands(); ++i) {
     448                PabloAST * op = stmt->getOperand(i);
     449                if (isa<Var>(op)) {
     450                    PabloAST * const value = variables.get(cast<Var>(op));
     451                    if (value) {
     452                        stmt->setOperand(i, value);
     453                    }
     454                }
     455            }
     456
    506457            Statement * const prior = stmt->getPrevNode();
    507458            PabloAST * const folded = fold(stmt, block);
     
    513464                continue;
    514465            }
    515             // When we're creating the Pablo program, it's possible to have multiple instances of an "identical"
    516             // statement. By recording which statements have already been seen, we can detect the redundant statements
     466            // By recording which statements have already been seen, we can detect the redundant statements
    517467            // as any having the same type and operands. If so, we can replace its users with the prior statement.
    518468            // and erase this statement from the AST
    519             const auto f = encountered.findOrAdd(stmt);
     469            const auto f = expressions.findOrAdd(stmt);
    520470            if (!f.second) {
    521471                stmt = stmt->replaceWith(f.first, true);
     
    524474
    525475        }
     476
    526477        stmt = stmt->getNextNode();
    527478    }
    528 }
    529 
    530 /** ------------------------------------------------------------------------------------------------------------- *
    531  * @brief unused
    532  ** ------------------------------------------------------------------------------------------------------------- */
    533 inline static bool unused(const Statement * const stmt) {
    534     if (LLVM_UNLIKELY(stmt->getNumUses() == 0)) {
    535         // TODO: prototypes ought to state whether they have side effects.
    536         if (LLVM_UNLIKELY(isa<Call>(stmt) && cast<Call>(stmt)->getPrototype()->getNumOfResults() == 0)) {
    537             return false;
    538         }
    539         return true;
    540     }
    541     return false;
     479
     480    // If this block has a branch statement leading into it, we can verify whether an escaped value
     481    // was updated within this block and update the preceeding block's variable state appropriately.
     482
     483    if (Branch * const br = block->getBranch()) { assert (vt);
     484
     485        // When removing identical escaped values, we have to consider that the identical Vars could
     486        // be assigned new differing values later in the outer body. Thus instead of replacing them
     487        // directly, we map future uses of the duplicate Var to the initial one. The DCE pass will
     488        // later mark any Assign statement as dead if the Var is never read.
     489
     490        const auto escaped = br->getEscaped();
     491        const auto n = escaped.size();
     492        PabloAST * variable[n];
     493        PabloAST * incoming[n];
     494        PabloAST * outgoing[n];
     495
     496        size_t i = 0;
     497        for (Var * var : escaped) {
     498            incoming[i] = vt->get(var);
     499            outgoing[i] = variables.get(var);
     500            PabloAST * expr = var;
     501            if (LLVM_UNLIKELY(incoming[i] == outgoing[i])) {
     502                expr = incoming[i];
     503            } else {
     504                for (size_t j = 0; j != i; ++j) {
     505                    if ((outgoing[j] == outgoing[i]) && (incoming[j] == incoming[i])) {
     506                        expr = variable[j];
     507                        break;
     508                    }
     509                }
     510            }
     511            variable[i] = expr;
     512            vt->put(var, expr);
     513            ++i;
     514        }
     515    }
    542516}
    543517
     
    545519 * @brief deadCodeElimination
    546520 ** ------------------------------------------------------------------------------------------------------------- */
    547 void Simplifier::dce(PabloBlock * const block) {
     521void Simplifier::deadCodeElimination(PabloBlock * const block) {
     522
     523   flat_map<PabloAST *, Assign *> unread;
     524
    548525    Statement * stmt = block->front();
    549526    while (stmt) {
    550         if (LLVM_UNLIKELY(isa<If>(stmt))) {
    551             dce(cast<If>(stmt)->getBody());
    552         } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
    553             dce(cast<While>(stmt)->getBody());
    554         } else if (LLVM_UNLIKELY(unused(stmt))){
     527        if (unread.size() != 0) {
     528            for (unsigned i = 0; i < stmt->getNumOperands(); ++i) {
     529                PabloAST * const op = stmt->getOperand(i);
     530                if (LLVM_UNLIKELY(isa<Var>(op))) {
     531                    unread.erase(op);
     532                }
     533            }
     534        }
     535        if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
     536            Branch * const br = cast<Branch>(stmt);
     537            deadCodeElimination(br->getBody());
     538        } else if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
     539            // An Assign statement is locally dead whenever its variable is not read
     540            // before being reassigned a value.
     541            PabloAST * var = cast<Assign>(stmt)->getVariable();
     542            auto f = unread.find(var);
     543            if (f != unread.end()) {
     544                auto prior = f->second;
     545                prior->eraseFromParent(true);
     546                f->second = cast<Assign>(stmt);
     547            } else {
     548                unread.emplace(var, cast<Assign>(stmt));
     549            }
     550        } else if (LLVM_UNLIKELY(stmt->getNumUses() == 0)) {
    555551            stmt = stmt->eraseFromParent(true);
    556552            continue;
     
    558554        stmt = stmt->getNextNode();
    559555    }
     556}
     557
     558/** ------------------------------------------------------------------------------------------------------------- *
     559 * @brief deadCodeElimination
     560 ** ------------------------------------------------------------------------------------------------------------- */
     561void Simplifier::deadCodeElimination(PabloFunction & f) {
     562
     563    deadCodeElimination(f.getEntryBlock());
     564
     565    for (unsigned i = 0; i < f.getNumOfVariables(); ++i) {
     566        Var * var = f.getVariable(i);
     567        bool unused = true;
     568        for (PabloAST * user : var->users()) {
     569            if (isa<Assign>(user)) {
     570                if (cast<Assign>(user)->getValue() == var) {
     571                    unused = false;
     572                    break;
     573                }
     574            } else {
     575                unused = false;
     576                break;
     577            }
     578        }
     579        if (LLVM_UNLIKELY(unused)) {
     580            for (PabloAST * user : var->users()) {
     581                cast<Assign>(user)->eraseFromParent(true);
     582            }
     583        }
     584    }
     585
    560586}
    561587
     
    568594    Statement * stmt = block->front();
    569595    while (stmt) {
    570         if (isa<If>(stmt)) {
    571             strengthReduction(cast<If>(stmt)->getBody());
    572         } else if (isa<While>(stmt)) {
    573             strengthReduction(cast<While>(stmt)->getBody());
     596        if (isa<Branch>(stmt)) {
     597            strengthReduction(cast<Branch>(stmt)->getBody());
    574598        } else if (isa<Advance>(stmt)) {
    575599            Advance * adv = cast<Advance>(stmt);
     
    591615                if (LLVM_UNLIKELY(op->getNumUses() == 1)) {
    592616                    block->setInsertPoint(scanThru->getPrevNode());
    593                     PabloAST * expr = block->createAdvance(op->getOperand(0), op->getAmount() - 1);
     617                    PabloAST * expr = block->createAdvance(op->getOperand(0), block->getInteger(op->getAmount() - 1));
    594618                    scanThru->setOperand(0, expr);
    595619                    scanThru->setOperand(1, block->createOr(scanThru->getOperand(1), expr));
     
    619643 ** ------------------------------------------------------------------------------------------------------------- */
    620644bool Simplifier::optimize(PabloFunction & function) {
    621     redundancyElimination(function, function.getEntryBlock());
     645    redundancyElimination(function.getEntryBlock());
    622646    strengthReduction(function.getEntryBlock());
    623     dce(function.getEntryBlock());
     647    deadCodeElimination(function);
    624648    #ifndef NDEBUG
    625649    PabloVerifier::verify(function, "post-simplification");
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/pablo_simplifier.hpp

    r5160 r5202  
    66namespace pablo {
    77
     8class PabloFunction;
    89struct ExpressionTable;
    9 class PabloFunction;
    1010
    1111class Simplifier {
    12     friend class DistributivePass;
    13     friend class FactorizeDFG;
    1412    friend class BooleanReassociationPass;
     13    struct VariableTable;
    1514public:
    1615    static bool optimize(PabloFunction & function);
    17     static void dce(PabloBlock * const block);
    1816protected:
    1917    Simplifier() = default;
    2018private:
    21     static void redundancyElimination(PabloFunction & function, PabloBlock * const block, ExpressionTable * predecessor = nullptr);
    2219    static PabloAST * fold(Variadic * var, PabloBlock * const block);
    2320    static PabloAST * fold(Statement * const stmt, PabloBlock * const block);
     21    static void redundancyElimination(PabloBlock * const block, ExpressionTable * et = nullptr, VariableTable * const vt = nullptr);
     22    static void deadCodeElimination(PabloFunction & f);
     23    static void deadCodeElimination(PabloBlock * const block);
    2424    static void strengthReduction(PabloBlock * const block);
    25     static bool isSuperfluous(const Assign * const assign);
    2625};
    2726
  • icGREP/icgrep-devel/icgrep/pablo/optimizers/schedulingprepass.cpp

    r5160 r5202  
    6666 * @brief resolveNestedUsages
    6767 ** ------------------------------------------------------------------------------------------------------------- */
    68 static void resolveNestedUsages(Statement * const root, Statement * const stmt, DependencyGraph & G, Map & M, PabloBlock * const block) {
    69     for (PabloAST * use : stmt->users()) {
     68static void resolveNestedUsages(Statement * const root, PabloAST * const expr, DependencyGraph & G, Map & M, PabloBlock * const block) {
     69    for (PabloAST * use : expr->users()) {
    7070        if (LLVM_LIKELY(isa<Statement>(use))) {
    7171            const PabloBlock * scope = cast<Statement>(use)->getParent();
    7272            if (scope != block) {
    73                 for (PabloBlock * prior = scope->getPredecessor (); prior; scope = prior, prior = prior->getPredecessor ()) {
     73                for (PabloBlock * prior = scope->getPredecessor(); prior; scope = prior, prior = prior->getPredecessor()) {
    7474                    if (prior == block) {
    7575                        assert (scope->getBranch());
     
    111111                    assert (v->second != u);
    112112                    add_edge(v->second, u, G);
    113                 } else if (isa<Assign>(op) || isa<Next>(op)) {
     113                } else if (isa<Assign>(op)) {
    114114                    // if this statement isn't an Assign or Next node, it cannot come from a nested scope
    115115                    // unless the function is invalid.
    116                     for (PabloBlock * prior = scope->getPredecessor (); prior; scope = prior, prior = prior->getPredecessor ()) {
     116                    for (PabloBlock * prior = scope->getPredecessor(); prior; scope = prior, prior = prior->getPredecessor()) {
    117117                        // Was this instruction computed by a nested block?
    118118                        if (prior == block) {
     
    132132    // Do a second pass to ensure that we've accounted for any nested usage of an If or While statement
    133133    for (Statement * stmt : *block) {
    134         if (LLVM_UNLIKELY(isa<If>(stmt))) {
    135             for (Assign * def : cast<If>(stmt)->getDefined()) {
    136                 resolveNestedUsages(stmt, def, G, M, block);
    137             }
    138         } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
    139             for (Next * var : cast<While>(stmt)->getVariants()) {
     134        if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
     135            for (Var * var : cast<Branch>(stmt)->getEscaped()) {
    140136                resolveNestedUsages(stmt, var, G, M, block);
    141137            }
Note: See TracChangeset for help on using the changeset viewer.