Program Listing for File affineInequality.h#
↰ Return to documentation for file (src/midend/programAnalysis/genericDataflow/lattice/affineInequality.h)
#include <featureTests.h>
#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
#ifndef AFFINE_INEQUALITY_H
#define AFFINE_INEQUALITY_H
#include "genericDataflowCommon.h"
#include "VirtualCFGIterator.h"
#include "cfgUtils.h"
#include "CallGraphTraverse.h"
#include "analysis.h"
#include "divAnalysis.h"
#include "printAnalysisStates.h"
#include "LogicalCond.h"
#include <sstream>
#include <iostream>
#include <string>
#include <functional>
#include <queue>
#include <list>
#include <set>
// represents the constraint on variables x and y: x*a <= y*b + c
class affineInequality: public printable // : public LogicalCond
{
friend class varAffineInequality;
public:
// The different signs that a variable may have
typedef enum{
// This variable's state is unknown
unknownSgn,
// This variable is =zero
eqZero,
// This variable is positive or =zero
posZero,
// This variable is negative or =zero
negZero} signs;
protected:
//varID y;
int a;
int b;
int c;
// flags that indicate whether the x or y variables are = zeroVar
bool xZero;
bool yZero;
// indicate the sign of x and y
signs xSign;
signs ySign;
public:
// Possible levels of this constraint. Above bottom the levels are ordered according to their
// information content. False has the most content (admits fewest points), then a specific
// affine inequality and finally, top, which represents a state where the true inequality is
// too complex to be represented as an affine inequality, meaning that the only affine inequality
// that can do the job is x <= y + infinity.
// no constraint known since current constraints are not representable using a single affine
// inequality (i.e. x <= y + infinity)
static const short top=3;
// some affine inequality constraint is known
static const short constrKnown=2;
// it is known that the affine constraints are inconsistent: x<=y-infinity
//static const short falseConstr=1;
// the values of the variables are not constrained relative to each other (effectively, bottom == uninitialized)
// (this object would not even be created in this case)
static const short bottom=0;
protected:
// the current level in this constraint's lattice
short level;
public:
affineInequality();
affineInequality(const affineInequality& that);
affineInequality(int a, int b, int c, bool xZero, bool yZero, signs xSign, signs ySign);
// given a constraint on x, z and a constraint on z, y, infers the corresponding constraint on x, y
// and sets this constraint to it
affineInequality(const affineInequality& xz, const affineInequality& zy/*, bool xZero, bool yZero, DivLattice* divX, DivLattice* divY, varID z*/);
void operator=(const affineInequality& that);
bool operator==(const affineInequality& that) const;
bool operator!=(const affineInequality& that) const;
// lexicographic ordering (total order)
bool operator<(const affineInequality& that) const;
// Semantic affineInequality ordering (partial order)
// Returns true if this affineInequality represents less or more information (less information is
// top, more information is bottom) than that for all values of x and y and false otherwise
//bool operator<<(const affineInequality& that) const;
// !!! NOTE: WE MAY WANT A SEMANTIC LESS-THAN-OR-EQ SINCE THAT CAN BE COMPUTED MORE PRECISELY BASED IN <= INFORMATION
bool semLessThan(const affineInequality& that, bool xEqZero, bool yEqZero) const;
bool semLessThan(const affineInequality& that,
const affineInequality* xZero, const affineInequality* zeroX,
const affineInequality* yZero, const affineInequality* zeroY, std::string indent="") const;
bool semLessThanEq(const affineInequality& that,
bool xIsZeroVar,
const affineInequality* xZero, const affineInequality* zeroX,
bool yIsZeroVar,
const affineInequality* yZero, const affineInequality* zeroY, std::string indent="") const;
// Semantic affineInequality ordering (partial order), focused on negated inequalities
// Returns true if the negation of this affineInequality represents more information (less information is
// top, more information is bottom) than the nagation of that for all values of x and y and false otherwise
//bool affineInequality::semLessThanNeg(const affineInequality& that) const
bool semLessThanNeg(const affineInequality& that, bool xEqZero, bool yEqZero) const;
bool set(const affineInequality& that);
bool set(int a, int b, int c);
bool set(int a, int b, int c, bool xZero, bool yZero, signs xSign, signs ySign);
bool setA(int a);
bool setB(int b);
bool setC(int c);
// sets this constraint object to bottom
bool setToBottom();
// sets this constraint object to false
//bool setToFalse();
// sets this constraint object to top
bool setToTop();
// returns y, a, b or c
int getA() const;
int getB() const;
int getC() const;
short getLevel() const;
bool isXZero() const;
bool isYZero() const;
signs getXSign() const;
signs getYSign() const;
protected:
// divide out from a, b and c any common factors, reducing the triple to its normal form
// return true if this modifies this constraint and false otherwise
bool normalize();
public:
// INTERSECT this with that, saving the result in this
// Intersection = the affine inequality that contains the constraint information of both
// this AND that (i.e. the line that is lower than both lines)
// (moves this/that upward in the lattice)
void operator*=(const affineInequality& that);
// Just like *=, except intersectUpd() returns true if the operation causes this
// affineInequality to change and false otherwise.
bool intersectUpd(const affineInequality& that);
// UNION this with that, saving the result in this
// Union = the affine inequality that contains no more information than either
// this OR that (i.e. the line that is higher than both lines)
// (moves this/that downward in the lattice)
void operator+=(const affineInequality& that);
// Just like +=, except unionUpd() returns true if the operation causes this
// affineInequality to change and false otherwise.
bool unionUpd(const affineInequality& that);
// WIDEN this with that, saving the result in this
//void operator^=(const affineInequality& that);
// returns true if the x-y constraint constrXY is consistent with the y-x constraint constrYX for
// some values of x and y and false otherwise. Since affineInequalities are conservative in the
// sense that they don't contain any more information than is definitely true, it may be
// that the true constraints are in fact inconsistent but we do not have enough information to
// prove this.
static bool mayConsistent(const affineInequality& constrXY, const affineInequality& constrYX);
static std::string signToString(signs sign);
std::string str(std::string indent="");
std::string str(std::string indent="") const;
std::string str(varID x, varID y, std::string indent="") const;
// Prints out the negation of the constraint ax <= by+c
std::string strNeg(varID x, varID y, std::string indent) const;
public:
// the basic logical operations that must be supported by any implementation of
// a logical condition: NOT, AND and OR
/*void notUpd();
void andUpd(LogicalCond& that);
void orUpd(LogicalCond& that);*/
};
// represents a full affine inequality, including the variables involved in the inequality
class varAffineInequality : public printable //: public LogicalCond
{
protected:
varID x;
varID y;
affineInequality ineq;
public:
varAffineInequality(const varAffineInequality& that);
varAffineInequality(const varID& x, const varID& y, const affineInequality& ineq);
varAffineInequality(const varID& x, const varID& y, int a, int b, int c, bool xZero, bool yZero);
// get methods
/*varID& getX() const;
varID& getY() const;
affineInequality& getIneq() const;*/
const varID& getX() const;
const varID& getY() const;
int getA() const;
int getB() const;
int getC() const;
const affineInequality& getIneq() const;
// set methods, return true if this object changes
const bool setX(const varID& x);
const bool setY(const varID& y);
const bool setA(int a);
const bool setB(int b);
const bool setC(int c);
const bool setIneq(affineInequality& ineq);
// comparison methods
bool operator==(const varAffineInequality& that) const;
bool operator<(const varAffineInequality& that) const;
std::string str(std::string indent="");
std::string str(std::string indent="") const;
// Parses expr and returns the corresponding varAffineInequality if expr can be represented
// as such and NULL otherwise.
//static varAffineInequality* parseIneq(SgExpression* expr);
public:
// the basic logical operations that must be supported by any implementation of
// a logical condition: NOT, AND and OR
/*void notUpd();
void andUpd(LogicalCond& that);
void orUpd(LogicalCond& that);
// returns a copy of this LogicalCond object
LogicalCond* copy();*/
};
/****************************
*** affineInequalityFact ***
****************************/
class affineInequalityFact : public NodeFact
{
public:
std::set<varAffineInequality> ineqs;
affineInequalityFact()
{}
affineInequalityFact(const affineInequalityFact& that)
{
this->ineqs = that.ineqs;
}
NodeFact* copy() const;
std::string str(std::string indent="");
std::string str(std::string indent="") const;
};
/********************************
*** affineInequalitiesPlacer ***
********************************/
// points trueIneqFact and falseIneqFact to freshly allocated objects that represent the true and false
// branches of the control flow guarded by the given expression. They are set to NULL if our representation
// cannot represent one of the expressions.
// doFalseBranch - if =true, falseIneqFact is set to the correct false-branch condition and to NULL otherwise
void setTrueFalseIneq(SgExpression* expr,
affineInequalityFact **trueIneqFact, affineInequalityFact **falseIneqFact,
bool doFalseBranch);
class affineInequalitiesPlacer : public UnstructuredPassIntraAnalysis
{
public:
void visit(const Function& func, const DataflowNode& n, NodeState& state);
};
/*// Looks over all the conditional statements in the application and associates appropriate
// affine inequalities with the SgNodes that depend on these statements. Each inequality
// is a must: it must be true of the node that it is associated with.
void initAffineIneqs(SgProject* project);
// return the set of varAffineInequalities associated with this node or NULL if none are available
std::set<varAffineInequality>* getAffineIneq(SgNode* n);*/
/*class printAffineInequalities : public UnstructuredPassIntraAnalysis
{
affineInequalitiesPlacer* placer;
public:
printAffineInequalities(affineInequalitiesPlacer *placer);
void visit(const Function& func, const DataflowNode& n, NodeState& state);
};*/
// prints the inequality facts set by the given affineInequalityPlacer
void printAffineInequalities(affineInequalitiesPlacer* aip, std::string indent="");
// Runs the Affine Inequality Placer analysis
void runAffineIneqPlacer(bool printStates=false);
// returns the set of inequalities known to be true at the given DataflowNode
const std::set<varAffineInequality>& getAffineIneq(const DataflowNode& n);
// Returns the set of inequalities known to be true at the given DataflowNode's descendants
std::list<std::set<varAffineInequality> > getAffineIneqDesc(const DataflowNode& n);
#endif
#endif