unsigned PopInsn::getNumOfBytes() const { if (analysis::isIntConstant(getRhs())) { return arithmetic::getValue<unsigned>(getRhs()); } else { return 4; } }
bool QuantifiedConnective::eq(const PathExpressionImpl &o) const { auto optr = static_cast<const QuantifiedConnective*>(&o); for (auto qvars : util::zip(getQuantifiedVars(), optr->getQuantifiedVars())) { if (qvars.first != qvars.second) { return false; } } return getLhs() == optr->getLhs() && getRhs() == optr->getRhs(); }
/** * @brief Replaces @a var with @a expr in @a stmt. */ void replaceVarWithExprInStmt(ShPtr<Variable> var, ShPtr<Expression> expr, ShPtr<Statement> stmt) { // If stmt is not a variable-defining/assign statement, we can directly // replace the variable. if (!isVarDefOrAssignStmt(stmt)) { stmt->replace(var, expr); return; } // The statement is of the form // // someVar = rhs(stmt) // // If the left-hand side of the statement differs from var, we may also // directly replace the variable in the statement. if (getLhs(stmt) != var) { stmt->replace(var, expr); return; } // The statement is of the form // // var = rhs(stmt) // // We have to replace var only on the right-hand side of the statement. // If rhs(stmt) differs from vars, we may directly replace the variable in // the right-hand side of the statement. if (getRhs(stmt) != var) { getRhs(stmt)->replace(var, expr); return; } // The statement is of the form // // var = var // // so set the right-hand side using the appropriate methods instead of // using getRhs(stmt)->replace(), which wouldn't work in this case. if (auto assignStmt = cast<AssignStmt>(stmt)) { assignStmt->setRhs(expr); } else if (auto varDefStmt = cast<VarDefStmt>(stmt)) { varDefStmt->setInitializer(expr); } else { FAIL("this should never happen since stmt has to be either a VarDefStmt" " or AssignStmt; stmt is `" << stmt << "`"); } }
element_type rhs_project(const space_ptrtype & Xh, const double & val) { ex solution = getRhs(val); auto mesh = Xh->mesh(); auto gproj = vf::project( _space=Xh, _range=elements( mesh ), _expr=expr(solution,vars) ); return gproj; }
bool Link::lt(const PathExpressionImpl &o) const { auto optr = static_cast<const Link*>(&o); if (!hasStencil() && optr->hasStencil()) { return true; } else if (hasStencil() && !optr->hasStencil()) { return false; } else if (hasStencil() && optr->hasStencil()) { if (getStencil() != optr->getStencil()) return getStencil() < optr->getStencil(); } return (getLhs().getSet() != optr->getLhs().getSet()) ? getLhs().getSet() < optr->getLhs().getSet() : getRhs().getSet() < optr->getRhs().getSet(); }
bool Link::eq(const PathExpressionImpl &o) const { auto optr = static_cast<const Link*>(&o); return this->getLhs().getSet() == optr->getLhs().getSet() && this->getRhs().getSet() == optr->getRhs().getSet() && this->hasStencil() == optr->hasStencil() && (!this->hasStencil() || this->getStencil() == optr->getStencil()); }
bool QuantifiedConnective::lt(const PathExpressionImpl &o) const { auto optr = static_cast<const QuantifiedConnective*>(&o); if (getLhs() != optr->getLhs()) { return getLhs() < optr->getLhs(); } else if (getRhs() != optr->getRhs()) { return getRhs() < optr->getRhs(); } else { if (getQuantifiedVars().size() != optr->getQuantifiedVars().size()) { return getQuantifiedVars().size() < optr->getQuantifiedVars().size(); } for (auto qv : util::zip(getQuantifiedVars(), optr->getQuantifiedVars())) { if (qv.first != qv.second) { return qv.first < qv.second; } } return false; } }
ArrayRCP<ArrayRCP<Scalar> > dft_PolyLinProbMgr<Scalar,MatrixType>:: applyMatrix (const ArrayView<const ArrayView<const Scalar> >& x) const { this->setLhs(x); schurOperator_->ApplyGlobal(*lhs1_, *lhs2_, *rhs1_, *rhs2_); return (getRhs()); } //end applyMatrix
/** * @brief Removes the given variable definition/assignment statement. * * @param[in] stmt Statement to be removed. * @param[in] func If non-null and the removed statement is a variable definition * statement, updates the set of local variables of the function. * * @return A vector of statements (possibly empty) with which @a stmt has been * replaced. * * If there are function calls in the right-hand side of @a stmt, they are * preserved, and returned in the resulting list. Debug comments are also * preserved. * * Precondition: * - @a stmt is either a variable definition statement or an assign statement */ StmtVector removeVarDefOrAssignStatement(ShPtr<Statement> stmt, ShPtr<Function> func) { PRECONDITION(isVarDefOrAssignStmt(stmt), "the statement `" << stmt << "` is not a variable-defining or assign statement"); // A vector of statements with which stmt has been replaced. StmtVector newStmts; // Update also the set of local variables in func? if (auto varDefStmt = cast<VarDefStmt>(stmt)) { if (func) { func->removeLocalVar(varDefStmt->getVar()); } } // Is there a right-hand side? auto rhs = getRhs(stmt); if (!rhs) { // There is an empty initializer, so there are no function calls. Statement::removeStatementButKeepDebugComment(stmt); return newStmts; } // Are there any function calls in the right-hand side? auto calls = CallsObtainer::getCalls(rhs); if (calls.empty()) { // There are no function calls in the right-hand side. Statement::removeStatementButKeepDebugComment(stmt); return newStmts; } // // There are some function calls, so preserve them. // // Insert the first found call. auto callStmt = CallStmt::create(*calls.begin()); callStmt->setMetadata(stmt->getMetadata()); Statement::replaceStatement(stmt, callStmt); newStmts.push_back(callStmt); calls.erase(calls.begin()); // Insert the remaining calls. auto lastCallStmt = callStmt; for (auto call : calls) { callStmt = CallStmt::create(call); lastCallStmt->appendStatement(callStmt); newStmts.push_back(callStmt); lastCallStmt = callStmt; } return newStmts; }
peano::applications::faxen::records::RegularGridCell peano::applications::faxen::records::RegularGridCellPacked::convert() const{ return RegularGridCell( getP(), getU(), getV(), getF(), getG(), getRhs(), getRes(), getIsInside() ); }
std::ostream& PhiInsn::printTo(std::ostream& stream) const { getLhs()->printTo(stream); stream << " = phi("; bool first = true; for (const auto& cur : getRhs()) { if (first) { first = false; } else stream << ","; cur->printTo(stream); } stream << ")"; return stream; }
/** * @brief Tries to perform the case (2) optimization from the class description * on the given statement. * * For the preconditions, see tryOptimization(), which is the place from where * this function should be called. */ void SimpleCopyPropagationOptimizer::tryOptimizationCase2( ShPtr<Statement> stmt, ShPtr<Variable> lhsVar, ShPtr<Expression> rhs) { // TODO Currently, we optimize (2) only if `expr` is a variable. Otherwise, // in some cases, the result of the optimization is less readable than // the original code. // TODO When optimizing also non-variable expressions, we have to use // clone() when replacing the expression. Otherwise, there may be // several expressions with the same address. if (!isa<Variable>(rhs)) { return; } // First, check whether the optimization can be done. StmtSet lhsUses(LhsRhsUsesCFGTraversal::getUses(stmt, currCFG, va, cio)); if (lhsUses.empty()) { return; } // Check the correspondence between allLhsUses and lhsUses. In a greater // detail, allLhsUses has to contain all the statements in lhsUses + stmt // and possibly a variable-defining statement defining lhsVar without an // initializer. // TODO Can this restriction (empty initializer) be relaxed a bit? ShPtr<VarDefStmt> lhsDefStmt; ShPtr<VarUses> allLhsUses(vuv->getUses(lhsVar, currFunc)); for (const auto &dirUse : allLhsUses->dirUses) { if (hasItem(lhsUses, dirUse) || stmt == dirUse) { continue; } lhsDefStmt = cast<VarDefStmt>(dirUse); if (!lhsDefStmt || lhsDefStmt->getVar() != lhsVar || lhsDefStmt->getInitializer()) { return; } } // Do the optimization. for (const auto &lhsUse : lhsUses) { replaceVarWithExprInStmt(lhsVar, getRhs(stmt), lhsUse); va->removeFromCache(lhsUse); } removeVarDefOrAssignStatement(stmt); currCFG->removeStmt(stmt); if (lhsDefStmt) { removeVarDefOrAssignStatement(lhsDefStmt, currFunc); currCFG->removeStmt(lhsDefStmt); } }
void print() const { LOG(INFO) << "============================================================\n"; LOG(INFO) << "Error Information\n"; LOG(INFO) << " exact : " << getSolution() << "\n"; LOG(INFO) << " params : "; boost::for_each( parameters, [](symbol const& s ) {LOG(INFO) << s.get_name() << " ";}); LOG(INFO) << "\n"; if ( !M_rhs.empty() ) { LOG(INFO) << " rhs : " << getRhs() << "\n"; } LOG(INFO) << " convergence : " << convergence() << "\n"; LOG(INFO) << " convergence steps : " << numberOfConvergenceSteps() << "\n"; }
void peano::applications::faxen::records::RegularGridCellPacked::toString (std::ostream& out) const { out << "("; out << "P:" << getP(); out << ","; out << "U:" << getU(); out << ","; out << "V:" << getV(); out << ","; out << "F:" << getF(); out << ","; out << "G:" << getG(); out << ","; out << "rhs:" << getRhs(); out << ","; out << "res:" << getRes(); out << ","; out << "isInside:" << getIsInside(); out << ")"; }
/** * @brief Tries to perform the optimization on the given statement. * * @par Preconditions * - @a stmt is either a VarDefStmt or AssignStmt */ void SimpleCopyPropagationOptimizer::tryOptimization(ShPtr<Statement> stmt) { ShPtr<Variable> lhsVar(cast<Variable>(getLhs(stmt))); ShPtr<Expression> rhs(getRhs(stmt)); if (!lhsVar || !rhs) { // There is nothing we can do in this case. return; } if (hasItem(triedVars, lhsVar)) { // We have already tried this variable. return; } triedVars.insert(lhsVar); if (!currFunc->hasLocalVar(lhsVar)) { // The left-hand side is not a local variable. return; } if (module->hasAssignedDebugName(lhsVar)) { // The left-hand side has assigned a name from debug information. return; } if (lhsVar->isExternal()) { // We do not want to optimize external variables (used in a volatile // load/store, see #1146). return; } if (va->mayBePointed(lhsVar)) { // The left-hand side may be used indirectly. return; } if (isa<ConstString>(rhs) || isa<ConstArray>(rhs) || isa<ConstStruct>(rhs)) { // The expression cannot be any of the above types. // TODO What about dropping this restriction? return; } if (lhsVar == rhs) { // Do not optimize self assigns, i.e. statements of the form `a = a;`. // This is done in other optimizations. return; } ShPtr<ValueData> stmtData(va->getValueData(stmt)); if (stmtData->hasAddressOps() || stmtData->hasDerefs() || stmtData->hasArrayAccesses() || stmtData->hasStructAccesses()) { // A forbidden construction is used. return; } // Try to perform the proper case of the optimization (see the class // description). if (stmtData->hasCalls()) { tryOptimizationCase1(stmt, lhsVar, rhs); } else { tryOptimizationCase2(stmt, lhsVar, rhs); } }
/** * @brief Computes the FuncInfo and returns it. */ ShPtr<OptimFuncInfo> OptimFuncInfoCFGTraversal::performComputation() { // First, we pre-compute varsAlwaysModifiedBeforeRead. The reason is that // their computation differs from the computation of the rest of the sets. precomputeAlwaysModifiedVarsBeforeRead(); // Every function's body is of the following form: // // (1) definitions of local variables, including assignments of global // variables into local variables // (2) other statements // // We store which variables are read/modified in (1). Then, we start the // traversal from (2). During the traversal, we check which variables are // read/modified and update funcInfo accordingly. The stored information // from (1) is used to compute the set of global variables which are read // in the function, but not modified. // // To give a specific example, consider the following code: // // def func(mango): // global orange // global plum // lychee = orange // achira = plum // orange = mango // plum = rand() // result = plum * apple + orange // orange = lychee // plum = achira // return result // // Here, even though the global variable orange is modified, its value // before calling func() is the same as after calling func(). Indeed, its // value is restored before the return statement. Hence, we may put it into // funcInfo->varsWithNeverChangedValue. // TODO Implement a more robust analysis. ShPtr<Statement> currStmt = traversedFunc->getBody(); while (isVarDefOrAssignStmt(currStmt)) { updateFuncInfo(currStmt); ShPtr<Expression> lhs(getLhs(currStmt)); ShPtr<Expression> rhs(getRhs(currStmt)); // If there is no right-hand side, it is a VarDefStmt with no // initializer, which we may skip. if (!rhs) { currStmt = currStmt->getSuccessor(); continue; } // If there are any function calls or dereferences, we have reached // (2). ShPtr<ValueData> currStmtData(va->getValueData(currStmt)); if (currStmtData->hasCalls() || currStmtData->hasDerefs()) { break; } // Check whether the statement is of the form localVar = globalVar. ShPtr<Variable> localVar(cast<Variable>(lhs)); ShPtr<Variable> globalVar(cast<Variable>(rhs)); if (!localVar || !globalVar || hasItem(globalVars, localVar) || !hasItem(globalVars, globalVar)) { // It is not of the abovementioned form, so skip it. currStmt = currStmt->getSuccessor(); continue; } storedGlobalVars[globalVar] = localVar; currStmt = currStmt->getSuccessor(); } // Perform the traversal only if we haven't reached the end of the function // yet. Since empty statements are not present in a CFG, skip them before // the traversal. if ((currStmt = skipEmptyStmts(currStmt))) { performTraversal(currStmt); } // We use the exit node of the CFG to check that every variable from // storedGlobalVars is retrieved its original value before every return. ShPtr<CFG::Node> exitNode(cfg->getExitNode()); // For every predecessor of the exit node... for (auto i = exitNode->pred_begin(), e = exitNode->pred_end(); i != e; ++i) { bool checkingShouldContinue = checkExitNodesPredecessor((*i)->getSrc()); if (!checkingShouldContinue) { break; } } // Update funcInfo using the remaining variables in storedGlobalVars. for (const auto &p : storedGlobalVars) { funcInfo->varsWithNeverChangedValue.insert(p.first); } // Update funcInfo->never{Read,Modified}Vars by global variables which are // untouched in this function. for (auto i = module->global_var_begin(), e = module->global_var_end(); i != e; ++i) { ShPtr<Variable> var((*i)->getVar()); if (!hasItem(funcInfo->mayBeReadVars, var) && !hasItem(funcInfo->mayBeModifiedVars, var)) { funcInfo->neverReadVars.insert(var); funcInfo->neverModifiedVars.insert(var); } } // If the cfg contains only a single non-{entry,exit} node, every // mayBe{Read,Modifed} variable can be turned into a always{Read,Modified} // variable. if (cfg->getNumberOfNodes() == 3) { addToSet(funcInfo->mayBeReadVars, funcInfo->alwaysReadVars); addToSet(funcInfo->mayBeModifiedVars, funcInfo->alwaysModifiedVars); } // Add all variables which are never read and never modified to // varsWithNeverChangedValue. VarSet neverReadAndModifedVars(setIntersection(funcInfo->neverReadVars, funcInfo->neverModifiedVars)); addToSet(neverReadAndModifedVars, funcInfo->varsWithNeverChangedValue); // Add all global variables are not read in this function into // varsAlwaysModifiedBeforeRead. addToSet(setDifference(globalVars, funcInfo->mayBeReadVars), funcInfo->varsAlwaysModifiedBeforeRead); return funcInfo; }