Пример #1
0
// Substitute s into all members of the set
void LocationSet::substitute(Assign& a)
{
    Exp* lhs = a.getLeft();
    if (lhs == NULL) return;
    Exp* rhs = a.getRight();
    if (rhs == NULL) return;		// ? Will this ever happen?
    std::set<Exp*, lessExpStar>::iterator it;
    // Note: it's important not to change the pointer in the set of pointers to expressions, without removing and
    // inserting again. Otherwise, the set becomes out of order, and operations such as set comparison fail!
    // To avoid any funny behaviour when iterating the loop, we use the following two sets
    LocationSet removeSet;			// These will be removed after the loop
    LocationSet removeAndDelete;	// These will be removed then deleted
    LocationSet insertSet;			// These will be inserted after the loop
    bool change;
    for (it = lset.begin(); it != lset.end(); it++)
        {
            Exp* loc = *it;
            Exp* replace;
            if (loc->search(lhs, replace))
                {
                    if (rhs->isTerminal())
                        {
                            // This is no longer a location of interest (e.g. %pc)
                            removeSet.insert(loc);
                            continue;
                        }
                    loc = loc->clone()->searchReplaceAll(lhs, rhs, change);
                    if (change)
                        {
                            loc = loc->simplifyArith();
                            loc = loc->simplify();
                            // If the result is no longer a register or memory (e.g.
                            // r[28]-4), then delete this expression and insert any
                            // components it uses (in the example, just r[28])
                            if (!loc->isRegOf() && !loc->isMemOf())
                                {
                                    // Note: can't delete the expression yet, because the
                                    // act of insertion into the remove set requires silent
                                    // calls to the compare function
                                    removeAndDelete.insert(*it);
                                    loc->addUsedLocs(insertSet);
                                    continue;
                                }
                            // Else we just want to replace it
                            // Regardless of whether the top level expression pointer has
                            // changed, remove and insert it from the set of pointers
                            removeSet.insert(*it);		// Note: remove the unmodified ptr
                            insertSet.insert(loc);
                        }
                }
        }
    makeDiff(removeSet);	   // Remove the items to be removed
    makeDiff(removeAndDelete); // These are to be removed as well
    makeUnion(insertSet);	   // Insert the items to be added
    // Now delete the expressions that are no longer needed
    std::set<Exp*, lessExpStar>::iterator dd;
    for (dd = removeAndDelete.lset.begin(); dd != removeAndDelete.lset.end();
            dd++)
        delete *dd;				// Plug that memory leak
}
bool StrengthReductionReversalPass::execute(UserProc *proc)
{
    StatementList stmts;
    proc->getStatements(stmts);

    for (Statement *s : stmts) {
        if (!s->isAssign()) {
            continue;
        }

        Assign *as = static_cast<Assign *>(s);

        // of the form x = x{p} + c
        if ((as->getRight()->getOper() == opPlus) && as->getRight()->getSubExp1()->isSubscript() &&
            (*as->getLeft() == *as->getRight()->getSubExp1()->getSubExp1()) &&
            as->getRight()->getSubExp2()->isIntConst()) {
            int c  = as->getRight()->access<Const, 2>()->getInt();
            auto r = as->getRight()->access<RefExp, 1>();

            if (r->getDef() && r->getDef()->isPhi()) {
                PhiAssign *p = static_cast<PhiAssign *>(r->getDef());

                if (p->getNumDefs() == 2) {
                    Statement *first  = p->begin()->getDef();
                    Statement *second = p->rbegin()->getDef();

                    if (first == as) {
                        // want the increment in second
                        std::swap(first, second);
                    }

                    // first must be of form x := 0
                    if (first && first->isAssign() &&
                        static_cast<Assign *>(first)->getRight()->isIntConst() &&
                        static_cast<Assign *>(first)->getRight()->access<Const>()->getInt() == 0) {
                        // ok, fun, now we need to find every reference to p and
                        // replace with x{p} * c
                        StatementList stmts2;
                        proc->getStatements(stmts2);

                        for (Statement *stmt2 : stmts2) {
                            if (stmt2 != as) {
                                stmt2->searchAndReplace(
                                    *r, Binary::get(opMult, r->clone(), Const::get(c)));
                            }
                        }

                        // that done we can replace c with 1 in as
                        as->getRight()->access<Const, 2>()->setInt(1);
                    }
                }
            }
        }
    }

    return true;
}