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>
(cherry picked from commit 957e3d482f)
This commit is contained in:
parent
48e26a44d7
commit
7d3c25f39a
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