int Specialization::substituteConstArrayIndexExprsWithConst(VariableIdMapping* variableIdMapping, ExprAnalyzer* exprAnalyzer, const EState* estate, SgNode* root) { typedef pair<SgExpression*,int> SubstitutionPair; typedef list<SubstitutionPair > SubstitutionList; SubstitutionList substitutionList; AstMatching m; MatchResult res; int numConstExprElim=0; #pragma omp critical(EXPRSUBSTITUTION) { res=m.performMatching("SgPntrArrRefExp(_,$ArrayIndexExpr)",root); } if(res.size()>0) { for(MatchResult::iterator i=res.begin();i!=res.end();++i) { // match found SgExpression* arrayIndexExpr=isSgExpression((*i)["$ArrayIndexExpr"]); if(arrayIndexExpr) { // avoid substituting a constant by a constant if(!isSgIntVal(arrayIndexExpr)) { list<SingleEvalResultConstInt> evalResultList=exprAnalyzer->evalConstInt(arrayIndexExpr,*estate,true, true); // only when we get exactly one result it is considered for substitution // there can be multiple const-results which do not allow to replace it with a single const if(evalResultList.size()==1) { list<SingleEvalResultConstInt>::iterator i=evalResultList.begin(); ROSE_ASSERT(evalResultList.size()==1); AValue varVal=(*i).value(); if(varVal.isConstInt()) { int varIntValue=varVal.getIntValue(); //cout<<"INFO: const: "<<varIntValue<<" substituting: "<<arrayIndexExpr->unparseToString()<<endl; SgNodeHelper::replaceExpression(arrayIndexExpr,SageBuilder::buildIntVal(varIntValue),false); numConstExprElim++; } } } } } } return numConstExprElim; }
void Specialization::transformArrayProgram(SgProject* root, Analyzer* analyzer) { // 1) transform initializers of global variables : a[]={1,2,3} ==> int a_0=1;int a_1=2;int a_2=3; // 2) eliminate initializers of pointer variables: int p* = a; ==> \eps // 3) replace uses of p[k]: with a_k (where k is a constant) //ad 1 and 2) VariableIdMapping* variableIdMapping=analyzer->getVariableIdMapping(); Analyzer::VariableDeclarationList usedGlobalVariableDeclarationList=analyzer->computeUsedGlobalVariableDeclarationList(root); cout<<"STATUS: number of used global variables: "<<usedGlobalVariableDeclarationList.size()<<endl; list<pair<SgNode*,string> > toReplaceArrayInitializations; list<SgVariableDeclaration*> toDeleteDeclarations; typedef map<VariableId,VariableId> ArrayPointerMapType; ArrayPointerMapType arrayPointer; // var,arrayName for(Analyzer::VariableDeclarationList::iterator i=usedGlobalVariableDeclarationList.begin(); i!=usedGlobalVariableDeclarationList.end(); ++i) { SgVariableDeclaration* decl=*i; //cout<<"DEBUG: variableDeclaration:"<<decl->unparseToString()<<endl; SgNode* initName0=decl->get_traversalSuccessorByIndex(1); // get-InitializedName ROSE_ASSERT(initName0); if(SgInitializedName* initName=isSgInitializedName(initName0)) { // array initializer SgInitializer* arrayInitializer=initName->get_initializer(); //string arrayName=variableIdMapping->variableName(variableIdMapping->variableId(*i)); if(isSgAggregateInitializer(arrayInitializer)) { string transformedArrayInitializer=flattenArrayInitializer(decl,variableIdMapping); toReplaceArrayInitializations.push_back(make_pair(decl,transformedArrayInitializer)); //SgNodeHelper::replaceAstWithString(decl,transformedArrayInitializer); } else { //cout<<"initName:"<<astTermWithNullValuesToString(initName)<<endl; VariableId lhsVarId=variableIdMapping->variableId(*i); string lhsVariableName=variableIdMapping->variableName(lhsVarId); SgType* type=variableIdMapping->getType(variableIdMapping->variableId(*i)); // match: SgInitializedName(SgAssignInitializer(SgVarRefExp)) // variable on lhs // check if variable is a pointer variable if(isSgPointerType(type)) { AstMatching m; MatchResult res; res=m.performMatching("SgInitializedName(SgAssignInitializer($varRef=SgVarRefExp))|SgInitializedName(SgAssignInitializer(SgAddressOfOp($varRef=SgVarRefExp)))",initName); if(res.size()==1) { toDeleteDeclarations.push_back(decl); MatchResult::iterator j=res.begin(); SgVarRefExp* rhsVarRef=isSgVarRefExp((*j)["$varRef"]); VariableId rhsVarId=variableIdMapping->variableId(rhsVarRef); arrayPointer[lhsVarId]=rhsVarId; //cout<<"Inserted pair "<<variableName<<":"<<rhsVarName<<endl; } } } } } typedef list<pair<SgPntrArrRefExp*,ArrayElementAccessData> > ArrayAccessInfoType; ArrayAccessInfoType arrayAccesses; RoseAst ast(root); for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { SgExpression* exp=isSgExpression(*i); if(exp) { if(SgPntrArrRefExp* arrAccess=isSgPntrArrRefExp(exp)) { ArrayElementAccessData aead(arrAccess,analyzer->getVariableIdMapping()); ROSE_ASSERT(aead.isValid()); //VariableId arrayVar=aead.varId; //cout<<"array-element: "<<variableIdMapping->variableName(arrayVar); if(aead.subscripts.size()==1) { //cout<<" ArrayIndex:"<<*aead.subscripts.begin(); arrayAccesses.push_back(make_pair(arrAccess,aead)); } else { cout<<"Error: ArrayIndex: unknown (dimension>1)"; exit(1); } } } } #if 0 cout<<"Array-Pointer Map:"<<endl; for(ArrayPointerMapType::iterator i=arrayPointer.begin();i!=arrayPointer.end();++i) { cout<<(*i).first.toString()<<":"<<(*i).second.toString()<<endl; } #endif cout<<"STATUS: Replacing array-initializations."<<endl; for(list<pair<SgNode*,string> >::iterator i=toReplaceArrayInitializations.begin();i!=toReplaceArrayInitializations.end();++i) { //cout<<(*i).first->unparseToString()<<":\n"<<(*i).second<<endl; SgNodeHelper::replaceAstWithString((*i).first,"\n"+(*i).second); } cout<<"STATUS: Transforming pointer declarations."<<endl; for(list<SgVariableDeclaration*>::iterator i=toDeleteDeclarations.begin();i!=toDeleteDeclarations.end();++i) { //cout<<(*i)->unparseToString()<<endl; VariableId declaredPointerVar=variableIdMapping->variableId(*i); SgNode* initName0=(*i)->get_traversalSuccessorByIndex(1); // get-InitializedName ROSE_ASSERT(initName0); if(SgInitializedName* initName=isSgInitializedName(initName0)) { // initializer SgInitializer* initializer=initName->get_initializer(); if(SgAssignInitializer* assignInitializer=isSgAssignInitializer(initializer)) { //cout<<"var-initializer:"<<initializer->unparseToString()<<astTermWithNullValuesToString(initializer)<<endl; SgExpression* assignInitOperand=assignInitializer->get_operand_i(); if(isSgAddressOfOp(assignInitOperand)) { assignInitOperand=isSgExpression(SgNodeHelper::getFirstChild(assignInitOperand)); ROSE_ASSERT(assignInitOperand); } if(SgVarRefExp* rhsInitVar=isSgVarRefExp(assignInitOperand)) { VariableId arrayVar=variableIdMapping->variableId(rhsInitVar); SgExpressionPtrList& arrayInitializerList=variableIdMapping->getInitializerListOfArrayVariable(arrayVar); //cout<<"DEBUG: rhs array:"<<arrayInitializerList.size()<<" elements"<<endl; int num=0; stringstream ss; for(SgExpressionPtrList::iterator j=arrayInitializerList.begin();j!=arrayInitializerList.end();++j) { ss<<"int "<<variableIdMapping->variableName(declaredPointerVar)<<"_"<<num<<" = " <<(*j)->unparseToString() <<";\n" ; num++; } SgNodeHelper::replaceAstWithString(*i,"\n"+ss.str()); } } } #if 0 ArrayElementAccessData arrayAccess= ROSE_ASSERT(arrayAccess.getDimensions()==1); VariableId accessVar=arrayAccess.getVariable(); int accessSubscript=arrayAccess.getSubscript(0); #endif //SageInterface::removeStatement(*i); //SgNodeHelper::replaceAstWithString((*i),"POINTER-INIT-ARRAY:"+(*i)->unparseToString()+"...;"); } //list<pair<SgPntrArrRefExp*,ArrayElementAccessData> > cout<<"STATUS: Replacing Expressions ... "; for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) { if(isSgAssignOp(*i)) { if(SgVarRefExp* lhsVar=isSgVarRefExp(SgNodeHelper::getLhs(*i))) { if(SgNodeHelper::isPointerVariable(lhsVar)) { //cout<<"DEBUG: pointer var on lhs :"<<(*i)->unparseToString()<<endl; SgExpression* rhsExp=isSgExpression(SgNodeHelper::getRhs(*i)); ROSE_ASSERT(rhsExp); if(isSgAddressOfOp(rhsExp)) { rhsExp=isSgExpression(SgNodeHelper::getFirstChild(rhsExp)); ROSE_ASSERT(rhsExp); } if(SgVarRefExp* rhsVar=isSgVarRefExp(rhsExp)) { VariableId lhsVarId=variableIdMapping->variableId(lhsVar); VariableId rhsVarId=variableIdMapping->variableId(rhsVar); SgExpressionPtrList& arrayInitializerList=variableIdMapping->getInitializerListOfArrayVariable(rhsVarId); //cout<<"DEBUG: rhs array:"<<arrayInitializerList.size()<<" elements"<<endl; int num=0; stringstream ss; for(SgExpressionPtrList::iterator j=arrayInitializerList.begin();j!=arrayInitializerList.end();++j) { ss<<variableIdMapping->variableName(lhsVarId)<<"_"<<num<<" = " <<(*j)->unparseToString(); // workaround for the fact that the ROSE unparser generates a "\n;" for a replaced assignment { SgExpressionPtrList::iterator j2=j; j2++; if(j2!=arrayInitializerList.end()) ss<<";\n"; } num++; } SgNodeHelper::replaceAstWithString(*i,ss.str()); //SgNodeHelper::replaceAstWithString(*i,"COPY-ARRAY("+lhsVar->unparseToString()+"<="+rhsVar->unparseToString()+")"); } } else { RoseAst subAst(*i); for(RoseAst::iterator j=subAst.begin();j!=subAst.end();++j) { if(SgNodeHelper::isArrayAccess(*j)) { //cout<<"DEBUG: arrays access on rhs of assignment :"<<(*i)->unparseToString()<<endl; transformArrayAccess(*j,analyzer->getVariableIdMapping()); } } } } } if(SgNodeHelper::isCond(*i)) { RoseAst subAst(*i); for(RoseAst::iterator j=subAst.begin();j!=subAst.end();++j) { if(SgNodeHelper::isArrayAccess(*j)) { transformArrayAccess(*j,analyzer->getVariableIdMapping()); } } } } cout<<" done."<<endl; #if 0 for(ArrayAccessInfoType::iterator i=arrayAccesses.begin();i!=arrayAccesses.end();++i) { //cout<<(*i).first->unparseToString()<<":"/*<<(*i).second.xxxx*/<<endl; ArrayElementAccessData arrayAccess=(*i).second; ROSE_ASSERT(arrayAccess.getDimensions()==1); VariableId accessVar=arrayAccess.getVariable(); int accessSubscript=arrayAccess.getSubscript(0); // expression is now: VariableId[subscript] // information available is: arrayPointer map: VariableId:pointer -> VariableId:array // pointerArray // if the variable is not a pointer var it will now be added to the stl-map but with // a default VariableId. Default variableIds are not valid() IDs. // therefor this becomes a cheap check, whether we need to replace the expression or not. VariableId mappedVar=arrayPointer[accessVar]; if(mappedVar.isValid()) { // need to replace stringstream newAccess; #if 0 newAccess<<variableIdMapping->variableName(mappedVar)<<"["<<accessSubscript<<"]"; #else newAccess<<variableIdMapping->variableName(accessVar)<<"_"<<accessSubscript<<" "; #endif cout<<"to replace: @"<<(*i).first<<":"<<(*i).first->unparseToString()<<" ==> "<<newAccess.str()<<endl; SgNodeHelper::replaceAstWithString((*i).first,newAccess.str()); } } #endif Analyzer::VariableDeclarationList unusedGlobalVariableDeclarationList=analyzer->computeUnusedGlobalVariableDeclarationList(root); cout<<"STATUS: deleting unused global variables."<<endl; for(Analyzer::VariableDeclarationList::iterator i=unusedGlobalVariableDeclarationList.begin(); i!=unusedGlobalVariableDeclarationList.end(); ++i) { SgVariableDeclaration* decl=*i; SageInterface::removeStatement(decl); } }