[qfcc] Use new extend instruction instead of swizzle

While swizzle does work, it requires the source to be properly aligned
and thus is not really the best choice. The extend instruction has no
alignment requirements (at all) and thus is much better suited to
converting a scalar to a vector type.

Fixes #30
This commit is contained in:
Bill Currie 2022-08-18 17:46:14 +09:00
parent d9d0a80752
commit 95b8424ddf
6 changed files with 71 additions and 8 deletions

View file

@ -269,6 +269,12 @@ typedef struct {
struct type_s *type; ///< result type
} ex_swizzle_t;
typedef struct {
struct expr_s *src; ///< source expression
int extend; ///< extend mode 0: 0, 1: 1, 2: copy/0 3:-1
struct type_s *type; ///< result type;
} ex_extend_t;
#define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val)
typedef struct expr_s {
@ -305,6 +311,7 @@ typedef struct expr_s {
struct type_s *nil; ///< type for nil if known
ex_horizontal_t hop; ///< horizontal vector operation
ex_swizzle_t swizzle; ///< vector swizzle operation
ex_extend_t extend; ///< vector extend operation
} e;
} expr_t;
@ -494,6 +501,8 @@ expr_t *new_horizontal_expr (int op, expr_t *vec, struct type_s *type);
expr_t *new_swizzle_expr (expr_t *src, const char *swizzle);
expr_t *new_extend_expr (expr_t *src, struct type_s *type, int ext);
/** Create a new def reference (non-temporary variable) expression node.
\return The new def reference expression node (::def_t).

View file

@ -64,5 +64,6 @@ EX_EXPR(with) ///< with expression (::ex_with_t)
EX_EXPR(args) ///< @args marker in parameter list. no data
EX_EXPR(horizontal) ///< horizontal vector operation (::ex_horzontal_t)
EX_EXPR(swizzle) ///< vector swizzle operation (::ex_swizzle_t)
EX_EXPR(extend) ///< vector extend operation (::ex_extend_t)
///@}

View file

@ -197,6 +197,8 @@ get_type (expr_t *e)
return e->e.hop.type;
case ex_swizzle:
return e->e.swizzle.type;
case ex_extend:
return e->e.extend.type;
case ex_count:
internal_error (e, "invalid expression");
}
@ -432,6 +434,11 @@ copy_expr (expr_t *e)
*n = *e;
e->e.swizzle.src = copy_expr (e->e.swizzle.src);
return n;
case ex_extend:
n = new_expr ();
*n = *e;
e->e.extend.src = copy_expr (e->e.extend.src);
return n;
case ex_count:
break;
}
@ -686,6 +693,17 @@ new_swizzle_expr (expr_t *src, const char *swizzle)
return expr;
}
expr_t *
new_extend_expr (expr_t *src, type_t *type, int ext)
{
expr_t *expr = new_expr ();
expr->type = ex_extend;
expr->e.extend.src = src;
expr->e.extend.extend = ext;
expr->e.extend.type = type;
return expr;
}
expr_t *
new_def_expr (def_t *def)
{
@ -1624,6 +1642,8 @@ has_function_call (expr_t *e)
return has_function_call (e->e.hop.vec);
case ex_swizzle:
return has_function_call (e->e.swizzle.src);
case ex_extend:
return has_function_call (e->e.extend.src);
case ex_error:
case ex_state:
case ex_label:
@ -1770,6 +1790,7 @@ unary_expr (int op, expr_t *e)
case ex_assign:
case ex_horizontal:
case ex_swizzle:
case ex_extend:
{
expr_t *n = new_unary_expr (op, e);
@ -1864,6 +1885,7 @@ unary_expr (int op, expr_t *e)
case ex_assign:
case ex_horizontal:
case ex_swizzle:
case ex_extend:
if (options.code.progsversion == PROG_VERSION) {
return binary_expr (EQ, e, new_nil_expr ());
} else {
@ -1954,6 +1976,7 @@ unary_expr (int op, expr_t *e)
case ex_assign:
case ex_horizontal:
case ex_swizzle:
case ex_extend:
bitnot_expr:
if (options.code.progsversion == PROG_ID_VERSION) {
expr_t *n1 = new_int_expr (-1);

View file

@ -143,6 +143,7 @@ is_lvalue (const expr_t *expr)
case ex_args:
case ex_horizontal:
case ex_swizzle:
case ex_extend:
break;
case ex_count:
internal_error (expr, "invalid expression");

View file

@ -667,14 +667,7 @@ convert_scalar (expr_t *scalar, int op, expr_t *vec)
return new_vector_list (scalar);
}
char swizzle[] = "xxxx";
type_t *vec_base = base_type (vec_type);
expr_t *tmp = new_temp_def_expr (vector_type (vec_base, 4));
expr_t *block = new_block_expr ();
swizzle[type_width (vec_type)] = 0;
append_expr (block, assign_expr (tmp, new_swizzle_expr (scalar, swizzle)));
block->e.block.result = new_alias_expr (vec_type, tmp);
return block;
return new_extend_expr (scalar, vec_type, 2);//2 = copy
}
static expr_t *

View file

@ -1810,6 +1810,41 @@ expr_swizzle (sblock_t *sblock, expr_t *e, operand_t **op)
return sblock;
}
static sblock_t *
expr_extend (sblock_t *sblock, expr_t *e, operand_t **op)
{
type_t *src_type = get_type (e->e.extend.src);
type_t *res_type = e->e.extend.type;
int src_width = type_width (src_type);
int res_width = type_width (res_type);
type_t *src_base = base_type (src_type);
type_t *res_base = base_type (res_type);
static int mode[4][4] = {
{-1, 0, 1, 2},
{-1,-1, 3, 4},
{-1,-1,-1, 5},
{-1,-1,-1,-1},
};
int ext = mode[src_width - 1][res_width - 1];
ext |= (e->e.extend.extend & 3) << 3;
ext |= (pr_type_size[res_base->type] - 1) << 5;
if (ext < 0 || res_base != src_base) {
internal_error (e, "invalid type combination for extend %d %d %d",
ext, src_width, res_width);
}
statement_t *s = new_statement (st_expr, "extend", e);
sblock = statement_subexpr (sblock, e->e.extend.src, &s->opa);
s->opb = short_operand (ext, e);
if (!*op) {
*op = temp_operand (res_type, e);
}
s->opc = *op;
sblock_add_statement (sblock, s);
return sblock;
}
static sblock_t *
expr_def (sblock_t *sblock, expr_t *e, operand_t **op)
{
@ -1954,6 +1989,7 @@ statement_subexpr (sblock_t *sblock, expr_t *e, operand_t **op)
[ex_address] = expr_address,
[ex_assign] = expr_assign,
[ex_branch] = expr_branch,
[ex_extend] = expr_extend,
};
if (!e) {
*op = 0;