From: Brian Paul Date: Thu, 4 Mar 2010 16:45:34 +0000 (-0700) Subject: gallivm: added lp_build_set_sign() X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6464d81e779e8c05ef96c9e5dab4422ff1f25464;p=mesa.git gallivm: added lp_build_set_sign() --- diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c index f60a7a213ac..42ae9f6a22c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c @@ -717,6 +717,41 @@ lp_build_sgn(struct lp_build_context *bld, } +/** + * Set the sign of float vector 'a' according to 'sign'. + * If sign==0, return abs(a). + * If sign==1, return -abs(a); + * Other values for sign produce undefined results. + */ +LLVMValueRef +lp_build_set_sign(struct lp_build_context *bld, + LLVMValueRef a, LLVMValueRef sign) +{ + const struct lp_type type = bld->type; + LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); + LLVMTypeRef vec_type = lp_build_vec_type(type); + LLVMValueRef shift = lp_build_int_const_scalar(type, type.width - 1); + LLVMValueRef mask = lp_build_int_const_scalar(type, + ~((unsigned long long) 1 << (type.width - 1))); + LLVMValueRef val, res; + + assert(type.floating); + + /* val = reinterpret_cast(a) */ + val = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); + /* val = val & mask */ + val = LLVMBuildAnd(bld->builder, val, mask, ""); + /* sign = sign << shift */ + sign = LLVMBuildShl(bld->builder, sign, shift, ""); + /* res = val | sign */ + res = LLVMBuildOr(bld->builder, val, sign, ""); + /* res = reinterpret_cast(res) */ + res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); + + return res; +} + + /** * Convert vector of int to vector of float. */ diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.h b/src/gallium/auxiliary/gallivm/lp_bld_arit.h index 2d19ec06b43..866349d8cba 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_arit.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.h @@ -124,6 +124,10 @@ LLVMValueRef lp_build_sgn(struct lp_build_context *bld, LLVMValueRef a); +LLVMValueRef +lp_build_set_sign(struct lp_build_context *bld, + LLVMValueRef a, LLVMValueRef sign); + LLVMValueRef lp_build_int_to_float(struct lp_build_context *bld, LLVMValueRef a);