Пример #1
0
// Do partial redundancy elimination, looking for copies of one expression expr
// within the basic block root.  A control flow graph for root must be provided
// in cfg, with a map from nodes to their statements in node_statements, a map
// from edges to their CFG edge types in edge_type, and a map from edges to
// their insertion points in edge_insertion_point.  The algorithm used is that
// of Paleri, Srikant, and Shankar ("Partial redundancy elimination: a simple,
// pragmatic, and provably correct algorithm", Science of Computer Programming
// 48 (2003) 1--20).
void PRE::partialRedundancyEliminationOne( SgExpression* expr, SgBasicBlock* root, const myControlFlowGraph& cfg)
{
    // SgBasicBlock* myFunctionBody = getFunctionDefinition(expr)->get_body();

    // DQ (3/16/2006): Added assertions
    ROSE_ASSERT(expr != NULL);
    ROSE_ASSERT(root != NULL);

    vector<SgVariableSymbol*> symbols_in_expression = SageInterface::getSymbolsUsedInExpression(expr);

    if (anyOfListPotentiallyModifiedIn(symbols_in_expression, expr))
    {
        // This expression updates its own arguments, and so is not idempotent
        // Return immediately
        return;
    }

    // Simple or not user-definable expressions
    if (isSgVarRefExp(expr)) return;
    if (isSgValueExp(expr)) return;
    if (isSgFunctionRefExp(expr)) return;
    if (isSgExprListExp(expr)) return;
    if (isSgInitializer(expr)) return;
#if 0
    if ( (isSgAddOp(expr) || isSgSubtractOp(expr)) &&
            (isSgVarRefExp(isSgBinaryOp(expr)->get_lhs_operand()) ||
             isSgValueExp(isSgBinaryOp(expr)->get_lhs_operand())) &&
            (isSgVarRefExp(isSgBinaryOp(expr)->get_rhs_operand()) ||
             isSgValueExp(isSgBinaryOp(expr)->get_rhs_operand())))
        return;
#endif

    // Expressions which do not keep a consistent value each time they are used
    if (!expressionTreeEqual(expr, expr))
        return;

    // cerr << "Trying to do PRE using expression " << expr->unparseToString() << " whose type is " << expr->sage_class_name() << endl;

    VertexIter i   = cfg.graph.vertices().begin(),
               end = cfg.graph.vertices().end();

    // cerr << "CFG has " << distance(i, end) << " nodes" << endl;

    bool needToMakeCachevar = false;
    set<SgNode*> replacements;
    vector<pair<SgNode*, bool /* before */> > insertions;

    vector<bool> transp(cfg.graph.vertices().size()),
           comp(cfg.graph.vertices().size()),
           antloc(cfg.graph.vertices().size());

    vector<SgNode*> first_computation(cfg.graph.vertices().size()),
           last_computation(cfg.graph.vertices().size());

    // Set values of local node properties
    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        const vector<SgNode*>& stmts = cfg.node_statements[*i];

        // Precompute test values for each statement
        vector<bool> argumentsModifiedInStatement(stmts.size());
        vector<int> expressionComputedInStatement(stmts.size());
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            if (anyOfListPotentiallyModifiedIn(symbols_in_expression, stmts[j]))
                argumentsModifiedInStatement[j] = true;
            expressionComputedInStatement[j] = countComputationsOfExpressionIn(expr, stmts[j]);
        }

        // Compute transp
        transp[*i] = true;
        for (unsigned int j = 0; j < stmts.size(); ++j)
            if (argumentsModifiedInStatement[j])
                transp[*i] = false;

        // Compute comp and do local redundancy elimination
        comp[*i] = false;
        SgNode* firstComputationInChain = 0;
        bool needToInsertComputation = false;
        bool computationInsertedOrUsed = false;
        // cout << "In node " << *i << endl;
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            // cout << "In stmt " << j << ", expressionComputedInStatement = " << expressionComputedInStatement[j]
            //      << ", argumentsModifiedInStatement = " << argumentsModifiedInStatement[j] << endl;
            if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j] && comp[*i] /* from last iter */)
            {
                // Do local redundancy elimination
                if (firstComputationInChain && needToInsertComputation)
                {
                    insertions.push_back(make_pair(firstComputationInChain, true));
                    replacements.insert(firstComputationInChain);
                    needToInsertComputation = false;
                }
                replacements.insert(stmts[j]);
                computationInsertedOrUsed = true;
                needToMakeCachevar = true;
            }
            if (expressionComputedInStatement[j])
            {
                comp[*i] = true;
                if (!firstComputationInChain)
                {
                    firstComputationInChain = stmts[j];
                    needToInsertComputation = true;
                    if (expressionComputedInStatement[j] >= 2)
                    {
                        insertions.push_back(make_pair(stmts[j], true));
                        needToMakeCachevar = true;
                        needToInsertComputation = false;
                        computationInsertedOrUsed = true;
                        replacements.insert(stmts[j]);
                    }
                }
                last_computation[*i] = stmts[j];
            }
            if (argumentsModifiedInStatement[j])
            {
                comp[*i] = false; // Must come after expressionComputedInStatement check
                firstComputationInChain = 0;
                needToInsertComputation = false;
            }
        }

        assert (!computationInsertedOrUsed || needToMakeCachevar);

        // Compute antloc
        antloc[*i] = false;
        for (unsigned int j = 0; j < stmts.size(); ++j)
        {
            if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j])
            {
                antloc[*i] = true;
                first_computation[*i] = stmts[j];
                break;
            }
            if (argumentsModifiedInStatement[j])
            {
                antloc[*i] = false;
                break;
            }
        }
    }

// #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl;
#define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl;
    PRINT_PROPERTY(transp);
    PRINT_PROPERTY(comp);
    PRINT_PROPERTY(antloc);

    int (simpleGraph::*source_ptr)(int) const = &simpleGraph::source;
    int (simpleGraph::*target_ptr)(int) const = &simpleGraph::target;

    vector<bool> avin(cfg.graph.vertices().size(), true);
    vector<bool> avout(cfg.graph.vertices().size(), true);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(avin, cfg);
    FIXPOINT_OUTPUT_BEGIN(avout, cfg);
    avin[v] = accumulate_neighbors(cfg, v, avout,cfg.graph.in_edges(v),&simpleGraph::source, logical_and<bool>(), true, false);
    avout[v] = comp[v] || (avin[v] && transp[v]);
    FIXPOINT_OUTPUT_END(avout, <=, cfg);
    FIXPOINT_OUTPUT_END(avin, <=, cfg);
    FIXPOINT_END(cfg, out_edges, OutEdgeIter)

    PRINT_PROPERTY(avin);
    PRINT_PROPERTY(avout);

    vector<bool> antin(cfg.graph.vertices().size(), true);
    vector<bool> antout(cfg.graph.vertices().size(), true);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(antin, cfg);
    FIXPOINT_OUTPUT_BEGIN(antout, cfg);
    antout[v] = accumulate_neighbors(cfg, v, antin, cfg.graph.out_edges(v), target_ptr, logical_and<bool>(), true, false);
    antin[v] = antloc[v] || (antout[v] && transp[v]);
    FIXPOINT_OUTPUT_END(antout, <=, cfg);
    FIXPOINT_OUTPUT_END(antin, <=, cfg);
    FIXPOINT_END(cfg, in_edges, InEdgeIter)

    PRINT_PROPERTY(antin);
    PRINT_PROPERTY(antout);

    vector<bool> safein(cfg.graph.vertices().size()), safeout(cfg.graph.vertices().size());

    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        safein[*i] = avin[*i] || antin[*i];
        safeout[*i] = avout[*i] || antout[*i];
    }

    PRINT_PROPERTY(safein);
    PRINT_PROPERTY(safeout);

    vector<bool> spavin(cfg.graph.vertices().size(), false);
    vector<bool> spavout(cfg.graph.vertices().size(), false);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(spavin, cfg);
    FIXPOINT_OUTPUT_BEGIN(spavout, cfg);
    spavin[v] = safein[v] && accumulate_neighbors(cfg, v, spavout, cfg.graph.in_edges(v), source_ptr, logical_or<bool>(), false, false);
    spavout[v] = safeout[v] && (comp[v] || (spavin[v] && transp[v]));
    FIXPOINT_OUTPUT_END(spavout, >=, cfg);
    FIXPOINT_OUTPUT_END(spavin, >=, cfg);
    FIXPOINT_END(cfg, out_edges, OutEdgeIter)

    PRINT_PROPERTY(spavin);
    PRINT_PROPERTY(spavout);

    vector<bool> spantin(cfg.graph.vertices().size(), false);
    vector<bool> spantout(cfg.graph.vertices().size(), false);
    FIXPOINT_BEGIN(cfg)
    FIXPOINT_OUTPUT_BEGIN(spantin, cfg);
    FIXPOINT_OUTPUT_BEGIN(spantout, cfg);
    spantout[v] = safeout[v] && accumulate_neighbors(cfg, v, spantin, cfg.graph.out_edges(v), target_ptr, logical_or<bool>(), false, false);
    spantin[v] = safein[v] && (antloc[v] || (spantout[v] && transp[v]));
    FIXPOINT_OUTPUT_END(spantout, >=, cfg);
    FIXPOINT_OUTPUT_END(spantin, >=, cfg);
    FIXPOINT_END(cfg, in_edges, InEdgeIter)

    PRINT_PROPERTY(spantin);
    PRINT_PROPERTY(spantout);
#undef PRINT_PROPERTY

    vector<bool> node_insert(cfg.graph.vertices().size());
    vector<bool> replacef(cfg.graph.vertices().size());
    vector<bool> replacel(cfg.graph.vertices().size());

    // printf ("Intermediate test 1: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    for (i = cfg.graph.vertices().begin(); i != end; ++i)
    {
        node_insert[*i] = comp[*i] && spantout[*i] && (!transp[*i] || !spavin[*i]);
        replacef[*i] = antloc[*i] && (spavin[*i] || (transp[*i] && spantout[*i]));
        replacel[*i] = comp[*i] && (spantout[*i] || (transp[*i] && spavin[*i]));

        if (node_insert[*i])
        {
            needToMakeCachevar = true;
            insertions.push_back(make_pair(last_computation[*i], true));
            // cerr << "Insert computation of " << expr->unparseToString() << " just before last computation in " << *i << endl;
        }

        if (replacef[*i])
        {
            needToMakeCachevar = true;
            replacements.insert(first_computation[*i]);
            // cerr << "Replace first computation of " << *i << endl;
        }

        if (replacel[*i])
        {
            needToMakeCachevar = true;
            replacements.insert(last_computation[*i]);
            // cerr << "Replace last computation of " << *i << endl;
        }
    }

    vector<bool> edge_insert(cfg.graph.edges().size());

    // printf ("Intermediate test 2: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    EdgeIter j = cfg.graph.edges().begin(), jend = cfg.graph.edges().end();
    for (; j != jend; ++j)
    {
        edge_insert[*j] = !spavout[cfg.graph.source(*j)] && spavin[cfg.graph.target(*j)] && spantin[cfg.graph.target(*j)];

        // printf ("edge_insert[*j] = %s \n",edge_insert[*j] ? "true" : "false");
        if (edge_insert[*j])
        {
            needToMakeCachevar = true;
            // cerr << "Insert computation of " << expr->unparseToString() << " on edge from "
            //      << cfg.graph.source(*j) << " to " << cfg.graph.target(*j) << endl;
        }
    }

    // printf ("Before final test: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false");

    // Add cache variable if necessary
    SgVarRefExp* cachevar = 0;
    if (needToMakeCachevar)
    {
        SgName cachevarname = "cachevar__";
        cachevarname << ++SageInterface::gensym_counter;

        // printf ("Building variable name = %s \n",cachevarname.str());

        SgType* type = expr->get_type();
        if (isSgArrayType(type))
            type = new SgPointerType(isSgArrayType(type)->get_base_type());
        assert (SageInterface::isDefaultConstructible(type));
        // FIXME: assert (isAssignable(type));
        SgVariableDeclaration* decl = new SgVariableDeclaration(SgNULL_FILE, cachevarname, type, NULL);
        decl->set_definingDeclaration(decl);
        SgInitializedName* initname = decl->get_variables().back();

        // DQ (10/5/2007): Added an assertion.
        ROSE_ASSERT(initname != NULL);

        decl->addToAttachedPreprocessingInfo(
            new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,
                                  (string("// Partial redundancy elimination: ") + cachevarname.str() +
                                   " is a cache of " + expr->unparseToString()).c_str(),
                                  "Compiler-Generated in PRE", 0, 0, 0, PreprocessingInfo::before));
        SgVariableSymbol* cachevarsym = new SgVariableSymbol(initname);
        decl->set_parent(root);

        // DQ (10/5/2007): Added scope (suggested by Jeremiah).
        initname->set_scope(root);

        root->get_statements().insert(root->get_statements().begin(),decl);

        root->insert_symbol(cachevarname, cachevarsym);
        cachevar = new SgVarRefExp(SgNULL_FILE, cachevarsym);
        cachevar->set_endOfConstruct(SgNULL_FILE);
    }

    // Do expression computation replacements
    for (set<SgNode*>::iterator i = replacements.begin(); i != replacements.end(); ++i)
    {
        ReplaceExpressionWithVarrefVisitor(expr, cachevar).traverse(*i, postorder);
    }

    // Do edge insertions
    // int count = 0;
    bool failAtEndOfFunction = false;
    for (j = cfg.graph.edges().begin(); j != jend; ++j)
    {
        // printf ("Build the insertion list! count = %d \n",count++);
        if (edge_insert[*j])
        {
#if 0
            // DQ (3/13/2006): Compiler warns that "src" is unused, so I have commented it out!
            Vertex src = cfg.graph.source(*j), tgt = cfg.graph.target(*j);
            cerr << "Doing insertion between " << src << " and " << tgt << endl;
#endif
            pair<SgNode*, bool> insert_point = cfg.edge_insertion_point[*j];
            if (insert_point.first)
            {
                insertions.push_back(insert_point);
            }
            else
            {
                // DQ (3/16/2006): This is a visited when we fixup the NULL pointer to the initializer in a SgForStatment.
                cerr << "Warning: no insertion point found" << endl; //FIXME was assert
                printf ("Need to figure out what to do here! cfg.edge_insertion_point[*j] = %p \n",&(cfg.edge_insertion_point[*j]));

                failAtEndOfFunction = true;
                ROSE_ASSERT(false);
            }
        }
    }

    // Do within-node insertions
    // printf ("At start of loop: insertions.size() = %zu \n",insertions.size());
    for (vector<pair<SgNode*, bool> >::iterator i = insertions.begin(); i != insertions.end(); ++i)
    {
        SgTreeCopy tc1, tc2;
        SgVarRefExp* cachevarCopy = isSgVarRefExp(cachevar->copy(tc1));
        ROSE_ASSERT (cachevarCopy);
        cachevarCopy->set_lvalue(true);
        SgExpression* operation = new SgAssignOp(SgNULL_FILE, cachevarCopy, isSgExpression(expr->copy(tc2)));
#if 0
        printf ("Inside of loop: insertions.size() = %zu \n",insertions.size());
        printf ("\n\ni->first = %p = %s = %s \n",i->first,i->first->class_name().c_str(),i->first->unparseToString().c_str());
        printf ("operation = %p = %s = %s \n",operation,operation->class_name().c_str(),operation->unparseToString().c_str());
#endif
        if (isSgExpression(i->first) && !i->second)
        {
            SgNode* ifp = i->first->get_parent();
            SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, isSgExpression(i->first), operation);
            operation->set_parent(comma);
            comma->set_parent(ifp);
            i->first->set_parent(comma);
            if (isSgForStatement(ifp))
            {
                isSgForStatement(ifp)->set_increment(comma);
            }
            else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_lhs_operand() == i->first)
            {
                isSgBinaryOp(ifp)->set_lhs_operand(comma);
            }
            else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_rhs_operand() == i->first)
            {
                isSgBinaryOp(ifp)->set_rhs_operand(comma);
            }
            else if (isSgUnaryOp(ifp) && isSgUnaryOp(ifp)->get_operand() == i->first)
            {
                isSgUnaryOp(ifp)->set_operand(comma);
            }
            else
            {
                cerr << ifp->sage_class_name() << endl;
                assert (!"Bad parent type for inserting comma expression");
            }
        }
        else
        {
            SgStatement* the_computation = new SgExprStatement(SgNULL_FILE, operation);
            operation->set_parent(the_computation);
            // printf ("In pre.C: the_computation = %p = %s \n",the_computation,the_computation->class_name().c_str());

            if (isSgBasicBlock(i->first) && i->second)
            {
                isSgBasicBlock(i->first)->get_statements().insert(isSgBasicBlock(i->first)->get_statements().begin(),the_computation);
                the_computation->set_parent(i->first);
            }
            else
            {
#if 0
                // DQ (3/14/2006): Bug here when SgExprStatement from SgForStatement test is used here!
                printf ("Bug here when SgExprStatement from SgForStatement test is used: i->first = %s \n",i->first->class_name().c_str());
                i->first->get_file_info()->display("Location i->first");
                printf ("Bug here when SgExprStatement from SgForStatement test is used: TransformationSupport::getStatement(i->first) = %s \n",
                        TransformationSupport::getStatement(i->first)->class_name().c_str());
                printf ("Bug here when SgExprStatement from SgForStatement test is used: the_computation = %s \n",the_computation->class_name().c_str());
                the_computation->get_file_info()->display("Location the_computation: debug");
                ROSE_ASSERT(i->first != NULL);
                ROSE_ASSERT(i->first->get_parent() != NULL);
                printf ("i->first->get_parent() = %s \n",i->first->get_parent()->class_name().c_str());
                i->first->get_file_info()->display("Location i->first: debug");
#endif

                SgForStatement*  forStatement = isSgForStatement(i->first->get_parent());
                if (forStatement != NULL)
                {
                    // Make sure that both pointers are not equal because they are both NULL!
                    ROSE_ASSERT(forStatement->get_test() != NULL);
                    SgExprStatement* possibleTest = isSgExprStatement(i->first);
                    if ( forStatement->get_test() == possibleTest )
                    {
                        // This is a special case of a SgExpressionStatement as a target in a SgForStatement
                        // printf ("Found special case of target being the test of a SgForStatement \n");
                        forStatement->set_test(the_computation);
                        the_computation->set_parent(forStatement);
                    }
                }
                else
                {
                    SgForInitStatement*  forInitStatement = isSgForInitStatement(i->first->get_parent());
                    if (forInitStatement != NULL)
                    {
                        // printf ("Found the SgForInitStatement \n");
                        SgVariableDeclaration* possibleVariable = isSgVariableDeclaration(i->first);
                        SgExprStatement* possibleExpression = isSgExprStatement(i->first);
                        SgStatementPtrList & statementList = forInitStatement->get_init_stmt();
                        SgStatementPtrList::iterator i = statementList.begin();
                        bool addToForInitList = false;
                        while ( (addToForInitList == false) && (i != statementList.end()) )
                        {
                            // if ( *i == possibleVariable )
                            if ( *i == possibleVariable || *i == possibleExpression )
                            {
                                // This is a special case of a SgExpressionStatement as a target in a SgForStatement
                                // printf ("Found special case of SgForInitStatement transformation \n");
                                addToForInitList = true;
                            }
                            i++;
                        }

                        // Only modify the STL list outside of the loop over the list to avoid interator invalidation
                        if (addToForInitList == true)
                        {
                            // Add the the_computation statment to the list in the SgForInitStatement.
                            // Later if we abandon the SgForInitStatement then we would have to add it to
                            // the list of SgInitializedName objects in the SgVariableDeclaration OR modify
                            // the expression list to handle the extra expression (but I think this case in
                            // handled above).
                            // printf ("Adding the_computation to the list in the SgForInitStatement \n");
                            statementList.push_back(the_computation);
                            the_computation->set_parent(forInitStatement);
                        }
                    }
                    else
                    {
                        myStatementInsert(TransformationSupport::getStatement(i->first),the_computation,i->second,true);
                        the_computation->set_parent(TransformationSupport::getStatement(i->first));
                    }
                }
            }
        }
    }

    // DQ (3/16/2006): debugging code to force failure at inspection point
    if (failAtEndOfFunction == true)
    {
        printf ("Error: internal error detected \n");
        ROSE_ASSERT(false);
    }
}
Пример #2
0
// Do finite differencing on one expression within one context.  The expression
// must be defined and valid within the entire body of root.  The rewrite rules
// are used to simplify expressions.  When a variable var is updated from
// old_value to new_value, an expression of the form (var, (old_value,
// new_value)) is created and rewritten.  The rewrite rules may either produce
// an arbitrary expression (which will be used as-is) or one of the form (var,
// (something, value)) (which will be changed to (var = value)).
void doFiniteDifferencingOne(SgExpression* e, 
                             SgBasicBlock* root,
                             RewriteRule* rules)
   {
     SgStatementPtrList& root_stmts = root->get_statements();
     SgStatementPtrList::iterator i;
     for (i = root_stmts.begin(); i != root_stmts.end(); ++i)
        {
          if (expressionComputedIn(e, *i))
               break;
        }
     if (i == root_stmts.end())
          return; // Expression is not used within root, so quit
     vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e);
     SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter;
     SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */);
     SgInitializedName* cachevar = cachedecl->get_variables().back();
     ROSE_ASSERT (cachevar);
     root->get_statements().insert(i, cachedecl);
     cachedecl->set_parent(root);
     cachedecl->set_definingDeclaration(cachedecl);
     cachevar->set_scope(root);
     SgVariableSymbol* sym = new SgVariableSymbol(cachevar);
     root->insert_symbol(cachename, sym);
     SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym);
     vr->set_endOfConstruct(SgNULL_FILE);
     replaceCopiesOfExpression(e, vr, root);

     vector<SgExpression*> modifications_to_used_symbols;
     FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root);

     cachedecl->addToAttachedPreprocessingInfo( 
          new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + 
               cachename.str() + " is a cache of " + 
               e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before));

     if (modifications_to_used_symbols.size() == 0)
        {
          SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e);
          e->set_parent(cacheinit);
          cachevar->set_initializer(cacheinit);
          cacheinit->set_parent(cachevar);
        }
       else
        {
          for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i)
             {
               SgExpression* modstmt = modifications_to_used_symbols[i];
#ifdef FD_DEBUG
               cout << "Updating cache after " << modstmt->unparseToString() << endl;
#endif
               SgExpression* updateCache = 0;
               SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym);
               varref->set_endOfConstruct(SgNULL_FILE);
               SgTreeCopy tc;
               SgExpression* eCopy = isSgExpression(e->copy(tc));
               switch (modstmt->variantT())
                  {
                    case V_SgAssignOp:
                       {
                         SgAssignOp* assignment = isSgAssignOp(modstmt);
                         assert (assignment);
                         SgExpression* lhs = assignment->get_lhs_operand();
                         SgExpression* rhs = assignment->get_rhs_operand();
                         replaceCopiesOfExpression(lhs, rhs, eCopy);
                       }
                    break;

                    case V_SgPlusAssignOp:
                    case V_SgMinusAssignOp:
                    case V_SgAndAssignOp:
                    case V_SgIorAssignOp:
                    case V_SgMultAssignOp:
                    case V_SgDivAssignOp:
                    case V_SgModAssignOp:
                    case V_SgXorAssignOp:
                    case V_SgLshiftAssignOp:
                    case V_SgRshiftAssignOp:
                       {
                         SgBinaryOp* assignment = isSgBinaryOp(modstmt);
                         assert (assignment);
                         SgExpression* lhs = assignment->get_lhs_operand();
                         SgExpression* rhs = assignment->get_rhs_operand();
                         SgTreeCopy tc;
                         SgExpression* rhsCopy = isSgExpression(rhs->copy(tc));
                         SgExpression* newval = 0;
                         switch (modstmt->variantT())
                            {
#define DO_OP(op, nonassignment) \
                              case V_##op: { \
                                   newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \
                                   newval->set_endOfConstruct(SgNULL_FILE); \
                              } \
                              break

                              DO_OP(SgPlusAssignOp, SgAddOp);
                              DO_OP(SgMinusAssignOp, SgSubtractOp);
                              DO_OP(SgAndAssignOp, SgBitAndOp);
                              DO_OP(SgIorAssignOp, SgBitOrOp);
                              DO_OP(SgMultAssignOp, SgMultiplyOp);
                              DO_OP(SgDivAssignOp, SgDivideOp);
                              DO_OP(SgModAssignOp, SgModOp);
                              DO_OP(SgXorAssignOp, SgBitXorOp);
                              DO_OP(SgLshiftAssignOp, SgLshiftOp);
                              DO_OP(SgRshiftAssignOp, SgRshiftOp);
#undef DO_OP

                              default: break;
                            }
                         assert (newval);
                         replaceCopiesOfExpression(lhs, newval, eCopy);
                       }
                    break;

                    case V_SgPlusPlusOp:
                       {
                         SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand();
                         SgIntVal* one = new SgIntVal(SgNULL_FILE, 1);
                         one->set_endOfConstruct(SgNULL_FILE);
                         SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one);
                         add->set_endOfConstruct(SgNULL_FILE);
                         lhs->set_parent(add);
                         one->set_parent(add);
                         replaceCopiesOfExpression(lhs,add,eCopy);
                            }
                    break;

                    case V_SgMinusMinusOp:
                       {
                         SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand();
                         SgIntVal* one = new SgIntVal(SgNULL_FILE, 1);
                         one->set_endOfConstruct(SgNULL_FILE);
                         SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one);
                         sub->set_endOfConstruct(SgNULL_FILE);
                         lhs->set_parent(sub);
                         one->set_parent(sub);
                         replaceCopiesOfExpression(lhs,sub,eCopy);
                       }
                    break;

                    default:
                         cerr << modstmt->sage_class_name() << endl;
                         assert (false);
                         break;
                  }

#ifdef FD_DEBUG
            cout << "e is " << e->unparseToString() << endl;
            cout << "eCopy is " << eCopy->unparseToString() << endl;
#endif
               updateCache = doFdVariableUpdate(rules, varref, e, eCopy);
#ifdef FD_DEBUG
            cout << "updateCache is " << updateCache->unparseToString() << endl;
#endif
               if (updateCache)
                  {
                    ROSE_ASSERT(modstmt != NULL);
                    SgNode* ifp = modstmt->get_parent();
                    SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt);
                    modstmt->set_parent(comma);
                    updateCache->set_parent(comma);

                    if (ifp == NULL)
                       {
                         printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str());
                         modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug");
                       }
                    ROSE_ASSERT(ifp != NULL);
#ifdef FD_DEBUG
                 cout << "New expression is " << comma->unparseToString() << endl;
                 cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl;
#endif
                    if (isSgExpression(ifp))
                       {
                         isSgExpression(ifp)->replace_expression(modstmt, comma);
                         comma->set_parent(ifp);
                       }
                      else
                       {
                      // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!)
                      // cerr << ifp->sage_class_name() << endl;
                      // assert (!"Bad parent type for inserting comma expression");
                         SgStatement* statement = isSgStatement(ifp);
                         if (statement != NULL)
                            {
#ifdef FD_DEBUG
                              printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str());
                              SgExprStatement* expresionStatement = isSgExprStatement(statement);
                              if (expresionStatement != NULL)
                                 {
                                   SgExpression* expression = expresionStatement->get_expression();
                                   printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str());
                                 }
#endif
                              statement->replace_expression(modstmt, comma);
                              comma->set_parent(statement);
                            }
                           else
                            {
                              ROSE_ASSERT(ifp != NULL);
                              printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str());
                              ROSE_ASSERT(false);
                            }
                       }

#ifdef FD_DEBUG
                    cout << "IFP is now " << ifp->unparseToString() << endl;
#endif
                  }
             }
        }
   }