ManagerAffineExpr.cpp

Go to the documentation of this file.
00001 #include "ManagerAffineExpr.hpp"
00002 
00003 namespace OA {
00004 namespace AffineExpr {
00005 
00006 ManagerAffineExpr::ManagerAffineExpr(OA_ptr<AffineExprIRInterface> _ir)
00007     :
00008     mIR(_ir)
00009 {
00010 }
00011 
00012 
00013 OA_ptr<AffineExprAbstraction> ManagerAffineExpr::analyzeMemRefExp(
00014         ExprHandle hExp,
00015         ProcHandle hProc,
00016         const set<OA_ptr<NamedLoc> > & indexVars,
00017         const set<OA_ptr<NamedLoc> > & nonConstVars,
00018         OA_ptr<Alias::Interface> aliasResults,
00019         AffineAnlState *state)
00020 {
00021     OA_ptr<AffineExprAbstraction> afnExp;
00022     afnExp = new AffineExprAbstraction();
00023 
00024     // convert the expression into an expression tree
00025     OA_ptr<ExprTree> expTree = mIR->getExprTree(hExp);
00026 
00027     // an affine expression abstraction is constructed by visiting each
00028     // of the nodes in an expression tree and determining the expressions
00029     // terms and factors.  The AffineExprExprTreeVisitor does this.
00030     AffineExprExprTreeVisitor visitor(
00031         afnExp, mIR, hProc, indexVars, nonConstVars, aliasResults);
00032     expTree->acceptVisitor(visitor);
00033 
00034     // the success or failure of converting the expression tree into an
00035     // affine expression abstraction is stored in a state variable passed
00036     // as an argument.
00037     *state = visitor.getState();
00038 
00039     return afnExp;
00040 }
00041 
00042 
00043 // Visitor class:
00044 // ----------------------------------
00045 
00046 void AffineExprExprTreeVisitor::visitOpNode(ExprTree::OpNode& n) {
00047     // don't continue when in an error state
00048     if(mState != VALID_AFFINE_EXP) { return; }
00049 
00050     // iterate over children in order to do a post-order traversal
00051     for(int i = 0; i < n.num_children(); i++) {
00052         ExprTree::ChildNodesIterator iterChildren(n);
00053 
00054         for(; iterChildren.isValid(); ++iterChildren) {
00055             OA_ptr<ExprTree::Node> child;
00056             child = iterChildren.current();
00057             child->acceptVisitor(*this);
00058         }
00059     }
00060 
00061     // determine what to do based on the type of operator
00062     OpHandle hOp = n.getHandle();
00063     switch(mIR->getOpType(hOp)) {
00064         // if it's a plus sign analyze for a term
00065         case OP_ADD:
00066         case OP_SUBTRACT:
00067             term();
00068             break;
00069 
00070         // if it's a multiply sign analyze for a term
00071         case OP_MULTIPLY:
00072             term();
00073             break;
00074 
00075         // in all other cases change the error state
00076         case OP_DIVIDE:
00077         case OP_MODULO:
00078         case OP_SHIFT_LEFT:
00079         case OP_SHIFT_RIGHT:
00080         case OP_BIT_AND:
00081         case OP_BIT_OR:
00082         case OP_BIT_XOR:
00083         case OP_OTHER:
00084             mState = INVALID_OPERATOR;
00085             break;
00086     }
00087 }
00088 
00089 void AffineExprExprTreeVisitor::visitCallNode(ExprTree::CallNode& n) {
00090     // don't continue when in an error state
00091     if(mState != VALID_AFFINE_EXP) { return; }
00092 
00093     // any time a function is called in an affine expression it is
00094     // assumed to be non-linear
00095     mState = NON_LINEAR_TERM;
00096 }
00097 
00098 void AffineExprExprTreeVisitor::visitMemRefNode(ExprTree::MemRefNode& n) {
00099     // don't continue when in an error state
00100     if(mState != VALID_AFFINE_EXP) { return; }
00101 
00102     OA_ptr<NamedLoc> var;
00103     // get a named location for the memory reference:
00104 
00105     // If we have alias information:
00106     // ....
00107     /*
00108         // convert the MRE into a MemRefHandle
00109         
00110         // use aliasing information to get a named location
00111         OA_ptr<LocIterator> locs;
00112         locs = mAliasResults->getMayLocs(hMemRef);
00113         OA_ptr<Location> loc = locs->current();*
00114         OA_ptr<NamedLoc> var = loc.convert<NamedLoc>();
00115         var->output(*mIR);
00116     */
00117 
00118     // IF we don't have alias information:
00119     // there should be one MRE asscociated with the MemRefNode, if this
00120     // is not the case than the variable is considered indirect.
00121     MemRefHandle hMemRef = n.getHandle();
00122     OA_ptr<MemRefExprIterator> iterMRE = mIR->getMemRefExprIterator(hMemRef);
00123     OA_ptr<MemRefExpr> mre = iterMRE->current();
00124     (*iterMRE)++;
00125     if(iterMRE->isValid()) { mState = INDIRECT_REF; return; }
00126 
00127     // convert the MRE to a NamedRef, use information from the
00128     // NamedRef class to get the location asscociated with it
00129     if(mre->isaNamed()) {
00130         OA_ptr<Location> loc;
00131         OA_ptr<NamedRef> namedRef;
00132         namedRef = mre.convert<NamedRef>();
00133         SymHandle hSym = namedRef->getSymHandle();
00134         loc = mIR->getLocation(mhProc, hSym);
00135         var = loc.convert<NamedLoc>();
00136     } else { assert(false); }
00137 
00138     // Now that we've got a location check to see if it's for a valid variable.
00139     // It's not valid if the variable has been reassigned or its not
00140     if(mNonConstVars.find(var) == mNonConstVars.end()) {
00141         mState = INVALID_VAR;
00142         return;
00143     }
00144 
00145     // if the variable was legal, recognize it
00146     pushVar(var);
00147 }
00148 
00149 void AffineExprExprTreeVisitor::visitConstSymNode(ExprTree::ConstSymNode& n) {
00150     assert(false);
00151 }
00152 
00153 void AffineExprExprTreeVisitor::visitConstValNode(ExprTree::ConstValNode& n) {
00154     int val = mIR->constValIntVal(n.getHandle());
00155     pushScaler(val);
00156 }
00157 
00158 void AffineExprExprTreeVisitor::pushVar(OA_ptr<NamedLoc> var) {
00159     // convert the passed var into an object encoded for the stack, then
00160     // push it onto the stack
00161     StackObj oVar;
00162     oVar.var = var;
00163     oVar.isVar = true;
00164     mStack.push(oVar);
00165 }
00166 
00167 void AffineExprExprTreeVisitor::pushScaler(int val) {
00168     // convert the passed int into an object encoded for the stack, then
00169     // push it onto the stack
00170     StackObj oVal;
00171     oVal.val = val;
00172     oVal.isVar = false;
00173     mStack.push(oVal);
00174 }
00175 
00176 void AffineExprExprTreeVisitor::term() {
00177     // don't continue when in an error state
00178     if(mState != VALID_AFFINE_EXP) { return; }
00179 
00180     // pop off the last two items added to the stack
00181     StackObj item1 = mStack.top();  mStack.pop();
00182     StackObj item2 = mStack.top();  mStack.pop();
00183 
00184     // if one item is a variable and the other is a scalar set it so
00185     // that item 1 is the scalar and item 2 is the variable
00186     if(item1.isVar && !item2.isVar) {
00187         StackObj tmp = item1;
00188         item1 = item2;
00189         item2 = tmp;
00190     }
00191 
00192     // if any variable term 
00193 
00194     if(item1.isVar && item2.isVar) {
00195         mState = NON_LINEAR_TERM;
00196     } else {
00197         if(item1.isVar) {
00198             mAfExp->addTerm(item1.var, item2.val);
00199         } else {
00200             mAfExp->addTerm(item2.var, item1.val);
00201         }
00202     }
00203 }
00204 
00205 /*
00206 void AffineExprExprTreeVisitor::term() {
00207     // don't continue when in an error state
00208     if(mState != VALID_AFFINE_EXP) { return; }
00209 
00210     // check to make sure the last thing added to the stack was a val, add
00211     // it as the offset in the affine expression abstraction
00212     StackObj item = mStack.top(); mStack.pop();
00213     assert(item.isVar == false);
00214     mAfExp->setOffset(item.val);
00215 }
00216 */
00217 
00218 } } // end namespaces
00219