gallivm: Fast implementation of iround(log2(x))

Not tested yet, but should be correct.
This commit is contained in:
José Fonseca 2010-10-06 17:44:05 +01:00
parent 4648846bd6
commit 012d57737b
2 changed files with 39 additions and 0 deletions

View File

@ -2330,3 +2330,38 @@ lp_build_fast_log2(struct lp_build_context *bld,
/* floor(log2(x)) + frac(x) */
return LLVMBuildFAdd(bld->builder, ipart, fpart, "");
}
/**
* Fast implementation of iround(log2(x)).
*
* Not an approximation -- it should give accurate results all the time.
*/
LLVMValueRef
lp_build_ilog2(struct lp_build_context *bld,
LLVMValueRef x)
{
const struct lp_type type = bld->type;
LLVMTypeRef int_vec_type = bld->int_vec_type;
unsigned mantissa = lp_mantissa(type);
LLVMValueRef sqrt2 = lp_build_const_vec(type, 1.4142135623730951);
LLVMValueRef ipart;
assert(lp_check_value(bld->type, x));
assert(type.floating);
/* x * 2^(0.5) i.e., add 0.5 to the log2(x) */
x = LLVMBuildFMul(bld->builder, x, sqrt2, "");
x = LLVMBuildBitCast(bld->builder, x, int_vec_type, "");
/* ipart = floor(log2(x) + 0.5) */
ipart = LLVMBuildLShr(bld->builder, x, lp_build_const_int_vec(type, mantissa), "");
ipart = LLVMBuildAnd(bld->builder, ipart, lp_build_const_int_vec(type, 255), "");
ipart = LLVMBuildSub(bld->builder, ipart, lp_build_const_int_vec(type, 127), "");
return ipart;
}

View File

@ -216,6 +216,10 @@ LLVMValueRef
lp_build_fast_log2(struct lp_build_context *bld,
LLVMValueRef a);
LLVMValueRef
lp_build_ilog2(struct lp_build_context *bld,
LLVMValueRef x);
void
lp_build_exp2_approx(struct lp_build_context *bld,