* stage constant folding, where, witht he help of the AST, operator
* usages can be constant folded. Then there is the constant folding
* in the IR for things like eliding if statements, can occur.
- *
+ *
* This file is thus, split into two parts.
*/
/*
* Implementation of basic vector math for vec3_t, for trivial constant
* folding.
- *
+ *
* TODO: gcc/clang hinting for autovectorization
*/
static GMQCC_INLINE vec3_t vec3_add(vec3_t a, vec3_t b) {
return out;
}
+static GMQCC_INLINE vec3_t vec3_or(vec3_t a, vec3_t b) {
+ vec3_t out;
+ out.x = (qcfloat_t)(((qcint_t)a.x) | ((qcint_t)b.x));
+ out.y = (qcfloat_t)(((qcint_t)a.y) | ((qcint_t)b.y));
+ out.z = (qcfloat_t)(((qcint_t)a.z) | ((qcint_t)b.z));
+ return out;
+}
+
+static GMQCC_INLINE vec3_t vec3_orvf(vec3_t a, qcfloat_t b) {
+ vec3_t out;
+ out.x = (qcfloat_t)(((qcint_t)a.x) | ((qcint_t)b));
+ out.y = (qcfloat_t)(((qcint_t)a.y) | ((qcint_t)b));
+ out.z = (qcfloat_t)(((qcint_t)a.z) | ((qcint_t)b));
+ return out;
+}
+
+static GMQCC_INLINE vec3_t vec3_and(vec3_t a, vec3_t b) {
+ vec3_t out;
+ out.x = (qcfloat_t)(((qcint_t)a.x) & ((qcint_t)b.x));
+ out.y = (qcfloat_t)(((qcint_t)a.y) & ((qcint_t)b.y));
+ out.z = (qcfloat_t)(((qcint_t)a.z) & ((qcint_t)b.z));
+ return out;
+}
+
+static GMQCC_INLINE vec3_t vec3_andvf(vec3_t a, qcfloat_t b) {
+ vec3_t out;
+ out.x = (qcfloat_t)(((qcint_t)a.x) & ((qcint_t)b));
+ out.y = (qcfloat_t)(((qcint_t)a.y) & ((qcint_t)b));
+ out.z = (qcfloat_t)(((qcint_t)a.z) & ((qcint_t)b));
+ return out;
+}
+
static GMQCC_INLINE vec3_t vec3_xor(vec3_t a, vec3_t b) {
vec3_t out;
out.x = (qcfloat_t)(((qcint_t)a.x) ^ ((qcint_t)b.x));
return out;
}
+static GMQCC_INLINE vec3_t vec3_not(vec3_t a) {
+ vec3_t out;
+ out.x = (qcfloat_t)(~((qcint_t)a.x));
+ out.y = (qcfloat_t)(~((qcint_t)a.y));
+ out.z = (qcfloat_t)(~((qcint_t)a.z));
+ return out;
+}
+
static GMQCC_INLINE qcfloat_t vec3_mulvv(vec3_t a, vec3_t b) {
return (a.x * b.x + a.y * b.y + a.z * b.z);
}
return !!v->constval.vfloat;
case TYPE_INTEGER:
return !!v->constval.vint;
- case TYPE_VECTOR:
+ case TYPE_VECTOR:
if (OPTS_FLAG(CORRECT_LOGIC))
return vec3_pbool(v->constval.vvec);
return !!(v->constval.vvec.x);
(void)fold_constgen_float (fold, -1.0f);
(void)fold_constgen_vector(fold, vec3_create(0.0f, 0.0f, 0.0f));
+ (void)fold_constgen_vector(fold, vec3_create(-1.0f, -1.0f, -1.0f));
return fold;
}
/*
* vector-component constant folding works by matching the component sets
* to eliminate expensive operations on whole-vectors (3 components at runtime).
- * to achive this effect in a clean manner this function generalizes the
+ * to achive this effect in a clean manner this function generalizes the
* values through the use of a set paramater, which is used as an indexing method
* for creating the elided ast binary expression.
*
* vec.z is the same as set[2]-'x' for when set[2] is 'z', 'z'-'x' results in a
* literal value of 2, using this 2, we know that taking the address of vec->x (float)
* and indxing it with this literal will yeild the immediate address of that component
- *
+ *
* Of course more work needs to be done to generate the correct index for the ast_member_new
* call, which is no problem: set[0]-'x' suffices that job.
*/
}
static GMQCC_INLINE ast_expression *fold_op_bor(fold_t *fold, ast_value *a, ast_value *b) {
- if (fold_can_2(a, b))
- return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) | ((qcint_t)fold_immvalue_float(b))));
+ if (isfloat(a)) {
+ if (fold_can_2(a, b))
+ return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) | ((qcint_t)fold_immvalue_float(b))));
+ } else {
+ if (isvector(b)) {
+ if (fold_can_2(a, b))
+ return fold_constgen_vector(fold, vec3_or(fold_immvalue_vector(a), fold_immvalue_vector(b)));
+ } else {
+ if (fold_can_2(a, b))
+ return fold_constgen_vector(fold, vec3_orvf(fold_immvalue_vector(a), fold_immvalue_float(b)));
+ }
+ }
return NULL;
}
static GMQCC_INLINE ast_expression *fold_op_band(fold_t *fold, ast_value *a, ast_value *b) {
- if (fold_can_2(a, b))
- return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) & ((qcint_t)fold_immvalue_float(b))));
+ if (isfloat(a)) {
+ if (fold_can_2(a, b))
+ return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) & ((qcint_t)fold_immvalue_float(b))));
+ } else {
+ if (isvector(b)) {
+ if (fold_can_2(a, b))
+ return fold_constgen_vector(fold, vec3_and(fold_immvalue_vector(a), fold_immvalue_vector(b)));
+ } else {
+ if (fold_can_2(a, b))
+ return fold_constgen_vector(fold, vec3_andvf(fold_immvalue_vector(a), fold_immvalue_float(b)));
+ }
+ }
return NULL;
}
return (ast_expression*)b;
} else {
return fold_constgen_float (
- fold,
+ fold,
((expr) ? (fold_immediate_true(fold, a) || fold_immediate_true(fold, b))
: (fold_immediate_true(fold, a) && fold_immediate_true(fold, b)))
? 1
}
static GMQCC_INLINE ast_expression *fold_op_bnot(fold_t *fold, ast_value *a) {
- if (fold_can_1(a))
- return fold_constgen_float(fold, ~((qcint_t)fold_immvalue_float(a)));
+ if (isfloat(a)) {
+ if (fold_can_1(a))
+ return fold_constgen_float(fold, ~((qcint_t)fold_immvalue_float(a)));
+ } else {
+ if (isvector(a)) {
+ if (fold_can_1(a))
+ return fold_constgen_vector(fold, vec3_not(fold_immvalue_vector(a)));
+ }
+ }
return NULL;
}