From: José Fonseca Date: Wed, 6 Oct 2010 16:44:05 +0000 (+0100) Subject: gallivm: Fast implementation of iround(log2(x)) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=012d57737b1b4e4263aa3414abe433195ff8a713;p=mesa.git gallivm: Fast implementation of iround(log2(x)) Not tested yet, but should be correct. --- diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index ff94f498acf..15b74410188 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -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; +} diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h index 3ed4fec2333..f36197479f0 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h @@ -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,