Generate better code for condition expressions.

This commit is contained in:
Stephen Williams 2014-11-20 14:47:44 -08:00
parent c71ab5869a
commit a9db765f98
4 changed files with 64 additions and 6 deletions

View File

@ -71,19 +71,39 @@ static int draw_condition_binary_compare(ivl_expr_t expr)
if (ivl_expr_width(re) > use_wid)
use_wid = ivl_expr_width(re);
/* If the le is constant, then swap the operands so that we
can possibly take advantage of the immediate version of the
%cmp instruction. */
if (ivl_expr_width(le)==use_wid && test_immediate_vec4_ok(le)) {
ivl_expr_t tmp = le;
re = le;
le = tmp;
}
draw_eval_vec4(le);
resize_vec4_wid(le, use_wid);
draw_eval_vec4(re);
resize_vec4_wid(re, use_wid);
if (ivl_expr_width(re)==use_wid && test_immediate_vec4_ok(re)) {
/* Special case: If the right operand can be handled as
an immediate operand, then use that instead. */
draw_immediate_vec4(re, "%cmpi/u");
} else {
draw_eval_vec4(re);
resize_vec4_wid(re, use_wid);
fprintf(vvp_out, " %%cmp/u;\n");
}
switch (ivl_expr_opcode(expr)) {
case 'n': /* != */
fprintf(vvp_out, " %%flag_inv 4;\n");
; /* fall through.. */
case 'e': /* == */
fprintf(vvp_out, " %%cmp/u;\n");
return 4;
break;
case 'N': /* !== */
fprintf(vvp_out, " %%flag_inv 6;\n");
; /* fall through.. */
case 'E': /* === */
fprintf(vvp_out, " %%cmp/u;\n");
return 6;
default:
assert(0);
@ -174,17 +194,41 @@ static int draw_condition_binary_le(ivl_expr_t expr)
}
}
static int draw_condition_binary_lor(ivl_expr_t expr)
{
ivl_expr_t le = ivl_expr_oper1(expr);
ivl_expr_t re = ivl_expr_oper2(expr);
int lx = draw_eval_condition(le);
if (lx < 8) {
int tmp = allocate_flag();
fprintf(vvp_out, " %%flag_mov %d, %d;\n", tmp, lx);
lx = tmp;
}
int rx = draw_eval_condition(re);
fprintf(vvp_out, " %%flag_or %d, %d;\n", rx, lx);
clr_flag(lx);
return rx;
}
static int draw_condition_binary(ivl_expr_t expr)
{
switch (ivl_expr_opcode(expr)) {
case 'e': /* == */
case 'E': /* === */
case 'n': /* != */
case 'N': /* !== */
return draw_condition_binary_compare(expr);
case '<':
case '>':
case 'L': /* <= */
case 'G': /* >= */
return draw_condition_binary_le(expr);
case 'o': /* Logical or (||) */
return draw_condition_binary_lor(expr);
default:
return draw_condition_fallback(expr);
}

View File

@ -103,6 +103,7 @@ extern bool of_EVCTLI(vthread_t thr, vvp_code_t code);
extern bool of_EVCTLS(vthread_t thr, vvp_code_t code);
extern bool of_FILE_LINE(vthread_t thr, vvp_code_t code);
extern bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t code);
extern bool of_FLAG_INV(vthread_t thr, vvp_code_t code);
extern bool of_FLAG_MOV(vthread_t thr, vvp_code_t code);
extern bool of_FLAG_OR(vthread_t thr, vvp_code_t code);
extern bool of_FLAG_SET_IMM(vthread_t thr, vvp_code_t code);

View File

@ -152,6 +152,7 @@ static const struct opcode_table_s opcode_table[] = {
{ "%evctl/s",of_EVCTLS, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%event", of_EVENT, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%flag_get/vec4", of_FLAG_GET_VEC4, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%flag_inv", of_FLAG_INV, 1, {OA_BIT1, OA_NONE, OA_NONE} },
{ "%flag_mov", of_FLAG_MOV, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%flag_or", of_FLAG_OR, 2, {OA_BIT1, OA_BIT2, OA_NONE} },
{ "%flag_set/imm", of_FLAG_SET_IMM, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },

View File

@ -2648,7 +2648,18 @@ bool of_FLAG_GET_VEC4(vthread_t thr, vvp_code_t cp)
}
/*
* %flag_mov <flag1>, <flag2)
* %flag_inv <flag1>
*/
bool of_FLAG_INV(vthread_t thr, vvp_code_t cp)
{
int flag1 = cp->bit_idx[0];
thr->flags[flag1] = ~ thr->flags[flag1];
return true;
}
/*
* %flag_mov <flag1>, <flag2>
*/
bool of_FLAG_MOV(vthread_t thr, vvp_code_t cp)
{
@ -2971,7 +2982,7 @@ bool of_IX_GETV_S(vthread_t thr, vvp_code_t cp)
static uint64_t vec4_to_index(vthread_t thr, bool signed_flag)
{
vvp_vector4_t val = thr->pop_vec4();
const vvp_vector4_t&val = thr->peek_vec4();
uint64_t v = 0;
bool unknown_flag = false;
@ -2995,6 +3006,7 @@ static uint64_t vec4_to_index(vthread_t thr, bool signed_flag)
}
thr->flags[4] = unknown_flag? BIT4_1 : BIT4_0;
thr->pop_vec4(1);
return v;
}