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*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;
|
||||
|
|
|
|||
|
|
@ -278,22 +278,39 @@ static int draw_condition_binary_le(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 re = ivl_expr_oper2(expr);
|
||||
|
||||
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) {
|
||||
int tmp = allocate_flag();
|
||||
fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp, lx);
|
||||
lx = tmp;
|
||||
tmp_flag = allocate_flag();
|
||||
fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp_flag, lx);
|
||||
}
|
||||
|
||||
int rx = draw_eval_condition(re);
|
||||
|
||||
fprintf(vvp_out, " %%flag_or %d, %d;\n", rx, lx);
|
||||
clr_flag(lx);
|
||||
return rx;
|
||||
/*
|
||||
* The flag needs to be in the same position regardless of whether the
|
||||
* 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)
|
||||
|
|
|
|||
|
|
@ -432,25 +432,45 @@ static void draw_binary_vec4_lequiv(ivl_expr_t expr)
|
|||
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 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. */
|
||||
/* Evaluate the left expression as a conditon and skip the right expression
|
||||
* if the left is false. */
|
||||
int flag = draw_eval_condition(le);
|
||||
fprintf(vvp_out, " %%flag_get/vec4 %d;\n", flag);
|
||||
fprintf(vvp_out, " %%jmp/%s T_%u.%u, %d;\n", jmp_type, thread_count,
|
||||
label_out, flag);
|
||||
clr_flag(flag);
|
||||
/* Now push the right expression. 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, " %%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)
|
||||
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)
|
||||
{
|
||||
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)) {
|
||||
case 'a': /* Logical && */
|
||||
draw_binary_vec4_land(expr);
|
||||
case 'o': /* || (logical or) */
|
||||
draw_binary_vec4_logical(expr, ivl_expr_opcode(expr));
|
||||
break;
|
||||
|
||||
case '+':
|
||||
|
|
@ -738,10 +736,6 @@ static void draw_binary_vec4(ivl_expr_t expr)
|
|||
draw_binary_vec4_lrs(expr);
|
||||
break;
|
||||
|
||||
case 'o': /* || (logical or) */
|
||||
draw_binary_vec4_lor(expr);
|
||||
break;
|
||||
|
||||
case 'q': /* -> (logical implication) */
|
||||
draw_binary_vec4_limpl(expr);
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue