Short circuit logical operator to constant if possible
If the left-hand side of a logical operator is a constant that causes the right-hand side to be short-circuited the right-hand side can be discarded even if it is not constant. In this case replace the expression by a constant. E.g. * `0 && expr` will be replaced by a constant 0. * `1 || expr` will be replaced by a constant 1. * `0 -> expr` will be replaced by a constant 1. Note that it is not possible to replace the expression by a constant if only the right-hand side is a constant, even when the value of the expression is constant. The left side still has to be evaluated for side effects. E.g. it is known at elaboration that `a++ && 0` will yield 0, but the increment on `a` has to be executed regardless. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
d4334139d3
commit
957e3d482f
30
eval_tree.cc
30
eval_tree.cc
|
|
@ -811,6 +811,36 @@ NetEConst* NetEBLogic::eval_arguments_(const NetExpr*l, const NetExpr*r) const
|
|||
|
||||
const NetEConst*lc = dynamic_cast<const NetEConst*>(l);
|
||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
||||
|
||||
// If the left side is constant and the right side is short circuited
|
||||
// replace the expression with a constant
|
||||
if (rc == 0 && lc != 0) {
|
||||
verinum v = lc->value();
|
||||
verinum::V res = verinum::Vx;
|
||||
switch (op_) {
|
||||
case 'a': // Logical AND (&&)
|
||||
if (v.is_zero())
|
||||
res = verinum::V0;
|
||||
break;
|
||||
case 'o': // Logical OR (||)
|
||||
if (! v.is_zero() && v.is_defined())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
case 'q': // Logical implication (->)
|
||||
if (v.is_zero())
|
||||
res = verinum::V1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (res != verinum::Vx) {
|
||||
NetEConst*tmp = new NetEConst(verinum(res, 1));
|
||||
ivl_assert(*this, tmp);
|
||||
eval_debug(this, tmp, false);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (lc == 0 || rc == 0) return 0;
|
||||
|
||||
verinum::V lv = verinum::V0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue