}
}
- if(intrinsic) {
+ if (intrinsic) {
/* We need to handle nan's for floating point numbers. If one of the
* inputs is nan the other should be returned (required by both D3D10+
* and OpenCL).
nan_behavior != GALLIVM_NAN_BEHAVIOR_UNDEFINED &&
nan_behavior != GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN &&
nan_behavior != GALLIVM_NAN_RETURN_NAN_FIRST_NONNAN) {
- LLVMValueRef isnan, max;
- max = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
+ LLVMValueRef isnan, min;
+ min = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
type,
intr_size, a, b);
if (nan_behavior == GALLIVM_NAN_RETURN_OTHER) {
isnan = lp_build_isnan(bld, b);
- return lp_build_select(bld, isnan, a, max);
+ return lp_build_select(bld, isnan, a, min);
} else {
assert(nan_behavior == GALLIVM_NAN_RETURN_NAN);
isnan = lp_build_isnan(bld, a);
- return lp_build_select(bld, isnan, a, max);
+ return lp_build_select(bld, isnan, a, min);
}
} else {
return lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
}
}
- if(intrinsic) {
+ if (intrinsic) {
if (util_cpu_caps.has_sse && type.floating &&
nan_behavior != GALLIVM_NAN_BEHAVIOR_UNDEFINED &&
nan_behavior != GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN &&
nan_behavior != GALLIVM_NAN_RETURN_NAN_FIRST_NONNAN) {
- LLVMValueRef isnan, min;
- min = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
+ LLVMValueRef isnan, max;
+ max = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
type,
intr_size, a, b);
if (nan_behavior == GALLIVM_NAN_RETURN_OTHER) {
isnan = lp_build_isnan(bld, b);
- return lp_build_select(bld, isnan, a, min);
+ return lp_build_select(bld, isnan, a, max);
} else {
assert(nan_behavior == GALLIVM_NAN_RETURN_NAN);
isnan = lp_build_isnan(bld, a);
- return lp_build_select(bld, isnan, a, min);
+ return lp_build_select(bld, isnan, a, max);
}
} else {
return lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
}
}
- if(intrinsic)
+ if (intrinsic)
return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b);
}
- /* TODO: handle signed case */
- if(type.norm && !type.floating && !type.fixed && !type.sign)
- a = lp_build_min_simple(bld, a, lp_build_comp(bld, b), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ if(type.norm && !type.floating && !type.fixed) {
+ if (type.sign) {
+ uint64_t sign = (uint64_t)1 << (type.width - 1);
+ LLVMValueRef max_val = lp_build_const_int_vec(bld->gallivm, type, sign - 1);
+ LLVMValueRef min_val = lp_build_const_int_vec(bld->gallivm, type, sign);
+ /* a_clamp_max is the maximum a for positive b,
+ a_clamp_min is the minimum a for negative b. */
+ LLVMValueRef a_clamp_max = lp_build_min_simple(bld, a, LLVMBuildSub(builder, max_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ LLVMValueRef a_clamp_min = lp_build_max_simple(bld, a, LLVMBuildSub(builder, min_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ a = lp_build_select(bld, lp_build_cmp(bld, PIPE_FUNC_GREATER, b, bld->zero), a_clamp_max, a_clamp_min);
+ } else {
+ a = lp_build_min_simple(bld, a, lp_build_comp(bld, b), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ }
+ }
if(LLVMIsConstant(a) && LLVMIsConstant(b))
if (type.floating)
}
}
- if(intrinsic)
+ if (intrinsic)
return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b);
}
- /* TODO: handle signed case */
- if(type.norm && !type.floating && !type.fixed && !type.sign)
- a = lp_build_max_simple(bld, a, b, GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ if(type.norm && !type.floating && !type.fixed) {
+ if (type.sign) {
+ uint64_t sign = (uint64_t)1 << (type.width - 1);
+ LLVMValueRef max_val = lp_build_const_int_vec(bld->gallivm, type, sign - 1);
+ LLVMValueRef min_val = lp_build_const_int_vec(bld->gallivm, type, sign);
+ /* a_clamp_max is the maximum a for negative b,
+ a_clamp_min is the minimum a for positive b. */
+ LLVMValueRef a_clamp_max = lp_build_min_simple(bld, a, LLVMBuildAdd(builder, max_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ LLVMValueRef a_clamp_min = lp_build_max_simple(bld, a, LLVMBuildAdd(builder, min_val, b, ""), GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ a = lp_build_select(bld, lp_build_cmp(bld, PIPE_FUNC_GREATER, b, bld->zero), a_clamp_min, a_clamp_max);
+ } else {
+ a = lp_build_max_simple(bld, a, b, GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ }
+ }
if(LLVMIsConstant(a) && LLVMIsConstant(b))
if (type.floating)
* half = sgn(ab) * 0.5 * (2 ** n) = sgn(ab) * (1 << (n - 1))
*/
- half = lp_build_const_int_vec(gallivm, wide_type, 1 << (n - 1));
+ half = lp_build_const_int_vec(gallivm, wide_type, 1LL << (n - 1));
if (wide_type.sign) {
LLVMValueRef minus_half = LLVMBuildNeg(builder, half, "");
LLVMValueRef sign = lp_build_shr_imm(&bld, ab, wide_type.width - 1);
if(a == bld->zero)
return bld->zero;
- if(a == bld->one)
+ if(a == bld->one && type.floating)
return lp_build_rcp(bld, b);
if(b == bld->zero)
return bld->undef;
*
* @sa http://www.stereopsis.com/doubleblend.html
*/
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_lerp_simple(struct lp_build_context *bld,
LLVMValueRef x,
LLVMValueRef v0,
* NOTE: In the SSE4.1's nearest mode, if two values are equally close, the
* result is the even value. That is, rounding 2.5 will be 2.0, and not 3.0.
*/
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_round_sse41(struct lp_build_context *bld,
LLVMValueRef a,
enum lp_build_round_mode mode)
args[2] = LLVMConstInt(i32t, mode, 0);
res = lp_build_intrinsic(builder, intrinsic,
- vec_type, args, Elements(args));
+ vec_type, args, Elements(args), 0);
res = LLVMBuildExtractElement(builder, res, index0, "");
}
}
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_iround_nearest_sse2(struct lp_build_context *bld,
LLVMValueRef a)
{
/*
*/
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_round_altivec(struct lp_build_context *bld,
LLVMValueRef a,
enum lp_build_round_mode mode)
assert(lp_check_value(type, a));
assert(util_cpu_caps.has_altivec);
+ (void)type;
+
switch (mode) {
case LP_BUILD_ROUND_NEAREST:
intrinsic = "llvm.ppc.altivec.vrfin";
return lp_build_intrinsic_unary(builder, intrinsic, bld->vec_type, a);
}
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_round_arch(struct lp_build_context *bld,
LLVMValueRef a,
enum lp_build_round_mode mode)
const struct lp_type type = bld->type;
struct lp_type inttype;
struct lp_build_context intbld;
- LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 2^24);
+ LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 1<<24);
LLVMValueRef trunc, res, anosign, mask;
LLVMTypeRef int_vec_type = bld->int_vec_type;
LLVMTypeRef vec_type = bld->vec_type;
const struct lp_type type = bld->type;
struct lp_type inttype;
struct lp_build_context intbld;
- LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 2^24);
+ LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 1<<24);
LLVMValueRef res, anosign, mask;
LLVMTypeRef int_vec_type = bld->int_vec_type;
LLVMTypeRef vec_type = bld->vec_type;
const struct lp_type type = bld->type;
struct lp_type inttype;
struct lp_build_context intbld;
- LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 2^24);
+ LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 1<<24);
LLVMValueRef trunc, res, anosign, mask;
LLVMTypeRef int_vec_type = bld->int_vec_type;
LLVMTypeRef vec_type = bld->vec_type;
+ if (type.width != 32) {
+ char intrinsic[32];
+ util_snprintf(intrinsic, sizeof intrinsic, "llvm.floor.v%uf%u", type.length, type.width);
+ return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a);
+ }
+
assert(type.width == 32); /* might want to handle doubles at some point */
inttype = type;
const struct lp_type type = bld->type;
struct lp_type inttype;
struct lp_build_context intbld;
- LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 2^24);
+ LLVMValueRef cmpval = lp_build_const_vec(bld->gallivm, type, 1<<24);
LLVMValueRef trunc, res, anosign, mask, tmp;
LLVMTypeRef int_vec_type = bld->int_vec_type;
LLVMTypeRef vec_type = bld->vec_type;
+ if (type.width != 32) {
+ char intrinsic[32];
+ util_snprintf(intrinsic, sizeof intrinsic, "llvm.ceil.v%uf%u", type.length, type.width);
+ return lp_build_intrinsic_unary(builder, intrinsic, vec_type, a);
+ }
+
assert(type.width == 32); /* might want to handle doubles at some point */
inttype = type;
* - http://en.wikipedia.org/wiki/Division_(digital)#Newton.E2.80.93Raphson_division
* - http://softwarecommunity.intel.com/articles/eng/1818.htm
*/
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_rcp_refine(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef rcp_a)
*
* See also Intel 64 and IA-32 Architectures Optimization Manual.
*/
-static INLINE LLVMValueRef
+static inline LLVMValueRef
lp_build_rsqrt_refine(struct lp_build_context *bld,
LLVMValueRef a,
LLVMValueRef rsqrt_a)
lp_build_rsqrt(struct lp_build_context *bld,
LLVMValueRef a)
{
- LLVMBuilderRef builder = bld->gallivm->builder;
const struct lp_type type = bld->type;
assert(lp_check_value(type, a));
* All numbers smaller than FLT_MIN will result in +infinity
* (rsqrtps treats all denormals as zero).
*/
- /*
- * Certain non-c99 compilers don't know INFINITY and might not support
- * hacks to evaluate it at compile time neither.
- */
- const unsigned posinf_int = 0x7F800000;
LLVMValueRef cmp;
LLVMValueRef flt_min = lp_build_const_vec(bld->gallivm, type, FLT_MIN);
- LLVMValueRef inf = lp_build_const_int_vec(bld->gallivm, type, posinf_int);
-
- inf = LLVMBuildBitCast(builder, inf, lp_build_vec_type(bld->gallivm, type), "");
+ LLVMValueRef inf = lp_build_const_vec(bld->gallivm, type, INFINITY);
for (i = 0; i < num_iterations; ++i) {
res = lp_build_rsqrt_refine(bld, a, res);
logexp = LLVMBuildSIToFP(builder, logexp, vec_type, "");
}
- if(p_log2) {
+ if (p_log2) {
/* mant = 1 + (float) mantissa(x) */
mant = LLVMBuildAnd(builder, i, mantmask, "");
mant = LLVMBuildOr(builder, mant, one, "");
}
}
- if(p_exp) {
+ if (p_exp) {
exp = LLVMBuildBitCast(builder, exp, vec_type, "");
*p_exp = exp;
}
- if(p_floor_log2)
+ if (p_floor_log2)
*p_floor_log2 = logexp;
- if(p_log2)
+ if (p_log2)
*p_log2 = res;
}
lp_build_intrinsic(builder,
"llvm.x86.sse.stmxcsr",
LLVMVoidTypeInContext(gallivm->context),
- &mxcsr_ptr8, 1);
+ &mxcsr_ptr8, 1, 0);
return mxcsr_ptr;
}
return 0;
lp_build_intrinsic(builder,
"llvm.x86.sse.ldmxcsr",
LLVMVoidTypeInContext(gallivm->context),
- &mxcsr_ptr, 1);
+ &mxcsr_ptr, 1, 0);
}
}