Merge pull request #573 from larsclausen/short-circuit-logical-operator
Short circuit logical operator
This commit is contained in:
commit
18cc3b91a1
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*lc = dynamic_cast<const NetEConst*>(l);
|
||||||
const NetEConst*rc = dynamic_cast<const NetEConst*>(r);
|
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;
|
if (lc == 0 || rc == 0) return 0;
|
||||||
|
|
||||||
verinum::V lv = verinum::V0;
|
verinum::V lv = verinum::V0;
|
||||||
|
|
|
||||||
|
|
@ -278,22 +278,39 @@ static int draw_condition_binary_le(ivl_expr_t expr)
|
||||||
|
|
||||||
static int draw_condition_binary_lor(ivl_expr_t expr)
|
static int draw_condition_binary_lor(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
|
unsigned label_out = local_count++;
|
||||||
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
ivl_expr_t re = ivl_expr_oper2(expr);
|
||||||
|
|
||||||
int lx = draw_eval_condition(le);
|
int lx = draw_eval_condition(le);
|
||||||
|
int tmp_flag = lx;
|
||||||
|
|
||||||
|
/* Short circuit right hand side if necessary */
|
||||||
|
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %d;\n", thread_count, label_out, lx);
|
||||||
|
|
||||||
if (lx < 8) {
|
if (lx < 8) {
|
||||||
int tmp = allocate_flag();
|
tmp_flag = allocate_flag();
|
||||||
fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp, lx);
|
fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp_flag, lx);
|
||||||
lx = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rx = draw_eval_condition(re);
|
int rx = draw_eval_condition(re);
|
||||||
|
|
||||||
fprintf(vvp_out, " %%flag_or %d, %d;\n", rx, lx);
|
/*
|
||||||
clr_flag(lx);
|
* The flag needs to be in the same position regardless of whether the
|
||||||
return rx;
|
* right side is short-cicuited or not.
|
||||||
|
*/
|
||||||
|
if (lx == tmp_flag) {
|
||||||
|
fprintf(vvp_out, " %%flag_or %d, %d;\n", lx, rx);
|
||||||
|
} else {
|
||||||
|
fprintf(vvp_out, " %%flag_or %d, %d;\n", rx, tmp_flag);
|
||||||
|
if (lx != rx)
|
||||||
|
fprintf(vvp_out, " %%flag_mov %d, %d;\n", lx, rx);
|
||||||
|
clr_flag(tmp_flag);
|
||||||
|
}
|
||||||
|
fprintf(vvp_out, "T_%u.%u;\n", thread_count, label_out);
|
||||||
|
clr_flag(rx);
|
||||||
|
return lx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int draw_condition_binary(ivl_expr_t expr)
|
static int draw_condition_binary(ivl_expr_t expr)
|
||||||
|
|
|
||||||
|
|
@ -432,25 +432,45 @@ static void draw_binary_vec4_lequiv(ivl_expr_t expr)
|
||||||
assert(ivl_expr_width(expr) == 1);
|
assert(ivl_expr_width(expr) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_binary_vec4_land(ivl_expr_t expr)
|
static void draw_binary_vec4_logical(ivl_expr_t expr, char op)
|
||||||
{
|
{
|
||||||
|
const char *opcode;
|
||||||
|
const char *jmp_type;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case 'a':
|
||||||
|
opcode = "and";
|
||||||
|
jmp_type = "0";
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
opcode = "or";
|
||||||
|
jmp_type = "1";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned label_out = local_count++;
|
||||||
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
ivl_expr_t re = ivl_expr_oper2(expr);
|
||||||
|
|
||||||
/* Push the left expression. Reduce it to a single bit if
|
/* Evaluate the left expression as a conditon and skip the right expression
|
||||||
necessary. */
|
* if the left is false. */
|
||||||
draw_eval_vec4(le);
|
int flag = draw_eval_condition(le);
|
||||||
if (ivl_expr_width(le) > 1)
|
fprintf(vvp_out, " %%flag_get/vec4 %d;\n", flag);
|
||||||
fprintf(vvp_out, " %%or/r;\n");
|
fprintf(vvp_out, " %%jmp/%s T_%u.%u, %d;\n", jmp_type, thread_count,
|
||||||
|
label_out, flag);
|
||||||
/* Now push the right expression. Again, reduce to a single
|
clr_flag(flag);
|
||||||
bit if necessary. */
|
/* Now push the right expression. Reduce to a single bit if necessary. */
|
||||||
draw_eval_vec4(re);
|
draw_eval_vec4(re);
|
||||||
if (ivl_expr_width(re) > 1)
|
if (ivl_expr_width(re) > 1)
|
||||||
fprintf(vvp_out, " %%or/r;\n");
|
fprintf(vvp_out, " %%or/r;\n");
|
||||||
|
|
||||||
fprintf(vvp_out, " %%and;\n");
|
fprintf(vvp_out, " %%%s;\n", opcode);
|
||||||
|
|
||||||
|
fprintf(vvp_out, "T_%u.%u;\n", thread_count, label_out);
|
||||||
if (ivl_expr_width(expr) > 1)
|
if (ivl_expr_width(expr) > 1)
|
||||||
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
|
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
|
||||||
}
|
}
|
||||||
|
|
@ -632,29 +652,6 @@ static void draw_binary_vec4_le(ivl_expr_t expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_binary_vec4_lor(ivl_expr_t expr)
|
|
||||||
{
|
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
|
||||||
ivl_expr_t re = ivl_expr_oper2(expr);
|
|
||||||
|
|
||||||
/* Push the left expression. Reduce it to a single bit if
|
|
||||||
necessary. */
|
|
||||||
draw_eval_vec4(le);
|
|
||||||
if (ivl_expr_width(le) > 1)
|
|
||||||
fprintf(vvp_out, " %%or/r;\n");
|
|
||||||
|
|
||||||
/* Now push the right expression. Again, reduce to a single
|
|
||||||
bit if necessary. */
|
|
||||||
draw_eval_vec4(re);
|
|
||||||
if (ivl_expr_width(re) > 1)
|
|
||||||
fprintf(vvp_out, " %%or/r;\n");
|
|
||||||
|
|
||||||
fprintf(vvp_out, " %%or;\n");
|
|
||||||
|
|
||||||
if (ivl_expr_width(expr) > 1)
|
|
||||||
fprintf(vvp_out, " %%pad/u %u;\n", ivl_expr_width(expr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_binary_vec4_lrs(ivl_expr_t expr)
|
static void draw_binary_vec4_lrs(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
ivl_expr_t le = ivl_expr_oper1(expr);
|
ivl_expr_t le = ivl_expr_oper1(expr);
|
||||||
|
|
@ -695,7 +692,8 @@ static void draw_binary_vec4(ivl_expr_t expr)
|
||||||
{
|
{
|
||||||
switch (ivl_expr_opcode(expr)) {
|
switch (ivl_expr_opcode(expr)) {
|
||||||
case 'a': /* Logical && */
|
case 'a': /* Logical && */
|
||||||
draw_binary_vec4_land(expr);
|
case 'o': /* || (logical or) */
|
||||||
|
draw_binary_vec4_logical(expr, ivl_expr_opcode(expr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
|
|
@ -738,10 +736,6 @@ static void draw_binary_vec4(ivl_expr_t expr)
|
||||||
draw_binary_vec4_lrs(expr);
|
draw_binary_vec4_lrs(expr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'o': /* || (logical or) */
|
|
||||||
draw_binary_vec4_lor(expr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'q': /* -> (logical implication) */
|
case 'q': /* -> (logical implication) */
|
||||||
draw_binary_vec4_limpl(expr);
|
draw_binary_vec4_limpl(expr);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue