gallivm: added lp_build_set_sign()

This commit is contained in:
Brian Paul 2010-03-04 09:45:34 -07:00
parent 7d230dae70
commit 6464d81e77
2 changed files with 39 additions and 0 deletions

View file

@ -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<int>(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<float>(res) */
res = LLVMBuildBitCast(bld->builder, res, vec_type, "");
return res;
}
/**
* Convert vector of int to vector of float.
*/

View file

@ -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);