summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_arit.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 6b17fbd2d31..d07cf689de3 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -2163,7 +2163,8 @@ lp_build_polynomial(struct lp_build_context *bld,
unsigned num_coeffs)
{
const struct lp_type type = bld->type;
- LLVMValueRef res = NULL;
+ LLVMValueRef even = NULL, odd = NULL;
+ LLVMValueRef x2;
unsigned i;
assert(lp_check_value(bld->type, x));
@@ -2175,19 +2176,36 @@ lp_build_polynomial(struct lp_build_context *bld,
__FUNCTION__);
}
+ /*
+ * Calculate odd and even terms seperately to decrease data dependency
+ * Ex:
+ * c[0] + x^2 * c[2] + x^4 * c[4] ...
+ * + x * (c[1] + x^2 * c[3] + x^4 * c[5]) ...
+ */
+ x2 = lp_build_mul(bld, x, x);
+
for (i = num_coeffs; i--; ) {
LLVMValueRef coeff;
coeff = lp_build_const_vec(bld->gallivm, type, coeffs[i]);
- if(res)
- res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res));
- else
- res = coeff;
+ if (i % 2 == 0) {
+ if (even)
+ even = lp_build_add(bld, coeff, lp_build_mul(bld, x2, even));
+ else
+ even = coeff;
+ } else {
+ if (odd)
+ odd = lp_build_add(bld, coeff, lp_build_mul(bld, x2, odd));
+ else
+ odd = coeff;
+ }
}
- if(res)
- return res;
+ if (odd)
+ return lp_build_add(bld, lp_build_mul(bld, odd, x), even);
+ else if (even)
+ return even;
else
return bld->undef;
}