Skip to content
Permalink
Browse files

Expr: fixed hash computation

Since expressions are immutable, this can be done on expression creation

Signed-off-by: Vitaly Chipounov <vitaly@cyberhaven.io>
  • Loading branch information
vitalych committed Nov 27, 2019
1 parent 391f09e commit 823ca86f6ca5d03bdbe75d6c1e319b7a7f9d52c8
Showing with 66 additions and 53 deletions.
  1. +49 −25 include/klee/Expr.h
  2. +7 −21 lib/Expr/Expr.cpp
  3. +10 −7 lib/Expr/Updates.cpp
@@ -193,7 +193,7 @@ class Expr {
protected:
unsigned hashValue;

Expr() : refCount(0) {
Expr() : refCount(0), hashValue(0) {
}

public:
@@ -216,10 +216,6 @@ class Expr {
return hashValue;
}

/// (Re)computes the hash of the current expression.
/// Returns the hash value.
virtual unsigned computeHash();

/// Compares `b` to `this` Expr for structural equivalence.
///
/// This method effectively defines a total order over all Expr.
@@ -374,7 +370,6 @@ class ConstantExpr : public Expr {

for (uint64_t j = 0; j < max; ++j) {
ref<ConstantExpr> r(new ConstantExpr(llvm::APInt(i, j)));
r->computeHash();
_const_table[i][j] = r;
}
}
@@ -391,7 +386,6 @@ class ConstantExpr : public Expr {
}

ref<ConstantExpr> r(new ConstantExpr(v));
r->computeHash();
return r;
}

@@ -400,6 +394,11 @@ class ConstantExpr : public Expr {
};

ConstantExpr(const llvm::APInt &v) : Expr(), value(v) {
if (v.getBitWidth() <= 64) {
hashValue = v.getZExtValue();
} else {
hashValue = *v.getRawData();
}
}

public:
@@ -610,6 +609,7 @@ class BinaryExpr : public NonConstantExpr {

protected:
BinaryExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {
hashValue = (left->hash() ^ right->hash()) * MAGIC_HASH_CONSTANT;
}

protected:
@@ -749,11 +749,12 @@ class UpdateNode {
private:
UpdateNode(const UpdateNodePtr &_next, const ref<Expr> &_index, const ref<Expr> &_value);

UpdateNode() : m_refCount(0) {
UpdateNode() : m_refCount(0), hashValue(0) {
}

~UpdateNode();

unsigned computeHash();
void computeHash();

friend void intrusive_ptr_add_ref(UpdateNode *ptr);
friend void intrusive_ptr_release(UpdateNode *ptr);
@@ -891,8 +892,12 @@ class UpdateList {

std::atomic<unsigned> m_refCount;

unsigned m_hashValue;

UpdateList(ArrayPtr _root, UpdateNodePtr _head);

void computeHash();

public:
static UpdateListPtr create(ArrayPtr _root, UpdateNodePtr _head) {
return UpdateListPtr(new UpdateList(_root, _head));
@@ -906,7 +911,9 @@ class UpdateList {
void extend(const ref<Expr> &index, const ref<Expr> &value);

int compare(const UpdateListPtr &b) const;
unsigned hash() const;
unsigned hash() const {
return m_hashValue;
}

const ArrayPtr &getRoot() const {
return root;
@@ -941,8 +948,11 @@ class ReadExpr : public NonConstantExpr {
ref<Expr> index;

ReadExpr(const UpdateListPtr &_updates, const ref<Expr> &_index) : updates(_updates), index(_index) {
computeHash();
}

void computeHash();

public:
virtual ~ReadExpr() {
}
@@ -985,8 +995,6 @@ class ReadExpr : public NonConstantExpr {
return create(updates, kids[0]);
}

virtual unsigned computeHash();

static bool classof(const Expr *E) {
return E->getKind() == Expr::Read;
}
@@ -1087,6 +1095,7 @@ class SelectExpr : public NonConstantExpr {

private:
SelectExpr(const ref<Expr> &c, const ref<Expr> &t, const ref<Expr> &f) : cond(c), trueExpr(t), falseExpr(f) {
hashValue = c->hash() ^ t->hash() ^ f->hash() ^ getKind();
}

public:
@@ -1160,6 +1169,7 @@ class ConcatExpr : public NonConstantExpr {
private:
ConcatExpr(const ref<Expr> &l, const ref<Expr> &r) : left(l), right(r) {
width = l->getWidth() + r->getWidth();
hashValue = l->hash() ^ r->hash() ^ getKind();
}

public:
@@ -1231,12 +1241,13 @@ class ExtractExpr : public NonConstantExpr {
return create(kids[0], offset, width);
}

virtual unsigned computeHash();

private:
ExtractExpr(const ref<Expr> &e, unsigned b, Width w) : expr(e), offset(b), width(w) {
computeHash();
}

void computeHash();

public:
static bool classof(const Expr *E) {
return E->getKind() == Expr::Extract;
@@ -1296,8 +1307,6 @@ class NotExpr : public NonConstantExpr {
return create(kids[0]);
}

virtual unsigned computeHash();

public:
static bool classof(const Expr *E) {
return E->getKind() == Expr::Not;
@@ -1308,7 +1317,10 @@ class NotExpr : public NonConstantExpr {

private:
NotExpr(const ref<Expr> &e) : expr(e) {
computeHash();
}

void computeHash();
};

// Casting
@@ -1318,10 +1330,14 @@ class CastExpr : public NonConstantExpr {
ref<Expr> src;
Width width;

public:
void computeHash();

protected:
CastExpr(const ref<Expr> &e, Width w) : src(e), width(w) {
computeHash();
}

public:
Width getWidth() const {
return width;
}
@@ -1348,8 +1364,6 @@ class CastExpr : public NonConstantExpr {
return 0;
}

virtual unsigned computeHash();

static bool classof(const Expr *E) {
Expr::Kind k = E->getKind();
return Expr::CastKindFirst <= k && k <= Expr::CastKindLast;
@@ -1365,11 +1379,14 @@ class CastExpr : public NonConstantExpr {
static const Kind kind = _class_kind; \
static const unsigned numKids = 1; \
\
protected: \
_class_kind##Expr(const ref<Expr> &e, Width w) : CastExpr(e, w) { \
hashValue ^= getKind(); \
} \
\
public: \
virtual ~_class_kind##Expr() { \
} \
_class_kind##Expr(const ref<Expr> &e, Width w) : CastExpr(e, w) { \
} \
static ref<Expr> alloc(const ref<Expr> &e, Width w) { \
return ref<Expr>(new _class_kind##Expr(e, w)); \
} \
@@ -1400,11 +1417,15 @@ CAST_EXPR_CLASS(ZExt)
static const Kind kind = _class_kind; \
static const unsigned numKids = 2; \
\
protected: \
_class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) : BinaryExpr(l, r) { \
hashValue ^= getKind(); \
} \
\
public: \
virtual ~_class_kind##Expr() { \
} \
_class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) : BinaryExpr(l, r) { \
} \
\
static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
return ref<Expr>(new _class_kind##Expr(l, r)); \
} \
@@ -1450,11 +1471,14 @@ ARITHMETIC_EXPR_CLASS(AShr)
static const Kind kind = _class_kind; \
static const unsigned numKids = 2; \
\
protected: \
_class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) : CmpExpr(l, r) { \
hashValue ^= getKind(); \
} \
\
public: \
virtual ~_class_kind##Expr() { \
} \
_class_kind##Expr(const ref<Expr> &l, const ref<Expr> &r) : CmpExpr(l, r) { \
} \
static ref<Expr> alloc(const ref<Expr> &l, const ref<Expr> &r) { \
return ref<Expr>(new _class_kind##Expr(l, r)); \
} \
@@ -278,47 +278,33 @@ void Expr::printKind(llvm::raw_ostream &os, Kind k) {
//
///////

unsigned Expr::computeHash() {
unsigned res = getKind() * Expr::MAGIC_HASH_CONSTANT;

int n = getNumKids();
for (int i = 0; i < n; i++) {
res <<= 1;
res ^= getKid(i)->hash() * Expr::MAGIC_HASH_CONSTANT;
}

hashValue = res;
return hashValue;
}

unsigned ConstantExpr::computeHash() {
hashValue = hash_value(value) ^ (getWidth() * MAGIC_HASH_CONSTANT);
return hashValue;
}

unsigned CastExpr::computeHash() {
void CastExpr::computeHash() {
unsigned res = getWidth() * Expr::MAGIC_HASH_CONSTANT;
hashValue = res ^ src->hash() * Expr::MAGIC_HASH_CONSTANT;
return hashValue;
}

unsigned ExtractExpr::computeHash() {
void ExtractExpr::computeHash() {
unsigned res = offset * Expr::MAGIC_HASH_CONSTANT;
res ^= getWidth() * Expr::MAGIC_HASH_CONSTANT;
res ^= getKind();
hashValue = res ^ expr->hash() * Expr::MAGIC_HASH_CONSTANT;
return hashValue;
}

unsigned ReadExpr::computeHash() {
void ReadExpr::computeHash() {
unsigned res = index->hash() * Expr::MAGIC_HASH_CONSTANT;
res ^= updates->hash();
res ^= getKind();
hashValue = res;
return hashValue;
}

unsigned NotExpr::computeHash() {
void NotExpr::computeHash() {
hashValue = expr->hash() * Expr::MAGIC_HASH_CONSTANT * Expr::Not;
return hashValue;
hashValue ^= getKind();
}

void Expr::printWidth(llvm::raw_ostream &os, Width width) {
@@ -36,17 +36,18 @@ int UpdateNode::compare(const UpdateNodePtr &b) const {
return value.compare(b->value);
}

unsigned UpdateNode::computeHash() {
void UpdateNode::computeHash() {
hashValue = index->hash() ^ value->hash();
if (next) {
hashValue ^= next->hash();
}
return hashValue;
}

///

UpdateList::UpdateList(ArrayPtr _root, const UpdateNodePtr _head) : root(_root), head(_head), m_refCount(0) {
UpdateList::UpdateList(ArrayPtr _root, const UpdateNodePtr _head)
: root(_root), head(_head), m_refCount(0), m_hashValue(0) {
computeHash();
}

void UpdateList::extend(const ref<Expr> &index, const ref<Expr> &value) {
@@ -85,15 +86,17 @@ int UpdateList::compare(const UpdateListPtr &b) const {
return 0;
}

unsigned UpdateList::hash() const {
void UpdateList::computeHash() {
unsigned res = 0;
for (unsigned i = 0, e = root->getName().size(); i != e; ++i) {
res = (res * Expr::MAGIC_HASH_CONSTANT) + root->getName()[i];
if (root) {
for (unsigned i = 0, e = root->getName().size(); i != e; ++i) {
res = (res * Expr::MAGIC_HASH_CONSTANT) + root->getName()[i];
}
}

if (head) {
res ^= head->hash();
}

return res;
m_hashValue = res;
}

0 comments on commit 823ca86

Please sign in to comment.
You can’t perform that action at this time.