}
}
else if (type.floating && util_cpu_caps.has_altivec) {
- debug_printf("%s: altivec doesn't support nan behavior modes\n",
- __FUNCTION__);
+ if (nan_behavior == GALLIVM_NAN_RETURN_NAN) {
+ debug_printf("%s: altivec doesn't support nan return nan behavior\n",
+ __FUNCTION__);
+ }
if (type.width == 32 && type.length == 4) {
intrinsic = "llvm.ppc.altivec.vminfp";
intr_size = 128;
}
} else if (util_cpu_caps.has_altivec) {
intr_size = 128;
- debug_printf("%s: altivec doesn't support nan behavior modes\n",
- __FUNCTION__);
if (type.width == 8) {
if (!type.sign) {
intrinsic = "llvm.ppc.altivec.vminub";
*/
if (util_cpu_caps.has_sse && type.floating &&
nan_behavior != GALLIVM_NAN_BEHAVIOR_UNDEFINED &&
- nan_behavior != GALLIVM_NAN_RETURN_SECOND) {
+ nan_behavior != GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN) {
LLVMValueRef isnan, max;
max = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
type,
return lp_build_select(bld, cond, a, b);
}
break;
- case GALLIVM_NAN_RETURN_SECOND:
+ case GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN:
cond = lp_build_cmp_ordered(bld, PIPE_FUNC_LESS, a, b);
return lp_build_select(bld, cond, a, b);
case GALLIVM_NAN_BEHAVIOR_UNDEFINED:
}
}
else if (type.floating && util_cpu_caps.has_altivec) {
- debug_printf("%s: altivec doesn't support nan behavior modes\n",
- __FUNCTION__);
+ if (nan_behavior == GALLIVM_NAN_RETURN_NAN) {
+ debug_printf("%s: altivec doesn't support nan return nan behavior\n",
+ __FUNCTION__);
+ }
if (type.width == 32 || type.length == 4) {
intrinsic = "llvm.ppc.altivec.vmaxfp";
intr_size = 128;
}
} else if (util_cpu_caps.has_altivec) {
intr_size = 128;
- debug_printf("%s: altivec doesn't support nan behavior modes\n",
- __FUNCTION__);
if (type.width == 8) {
if (!type.sign) {
intrinsic = "llvm.ppc.altivec.vmaxub";
if(intrinsic) {
if (util_cpu_caps.has_sse && type.floating &&
nan_behavior != GALLIVM_NAN_BEHAVIOR_UNDEFINED &&
- nan_behavior != GALLIVM_NAN_RETURN_SECOND) {
+ nan_behavior != GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN) {
LLVMValueRef isnan, min;
min = lp_build_intrinsic_binary_anylength(bld->gallivm, intrinsic,
type,
return lp_build_select(bld, cond, a, b);
}
break;
- case GALLIVM_NAN_RETURN_SECOND:
+ case GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN:
cond = lp_build_cmp_ordered(bld, PIPE_FUNC_GREATER, a, b);
return lp_build_select(bld, cond, a, b);
case GALLIVM_NAN_BEHAVIOR_UNDEFINED:
/**
* Generate clamp(a, min, max)
+ * NaN behavior (for any of a, min, max) is undefined.
* Do checks for special cases.
*/
LLVMValueRef
}
+/**
+ * Generate clamp(a, 0, 1)
+ * A NaN will get converted to zero.
+ */
+LLVMValueRef
+lp_build_clamp_zero_one_nanzero(struct lp_build_context *bld,
+ LLVMValueRef a)
+{
+ a = lp_build_max_ext(bld, a, bld->zero, GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN);
+ a = lp_build_min(bld, a, bld->one);
+ return a;
+}
+
+
/**
* Generate abs(a)
*/
/* We want to preserve NaN and make sure than for exp2 if x > 128,
* the result is INF and if it's smaller than -126.9 the result is 0 */
x = lp_build_min_ext(bld, lp_build_const_vec(bld->gallivm, type, 128.0), x,
- GALLIVM_NAN_RETURN_SECOND);
- x = lp_build_max_ext(bld, lp_build_const_vec(bld->gallivm, type, -126.99999), x,
- GALLIVM_NAN_RETURN_SECOND);
+ GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN);
+ x = lp_build_max(bld, lp_build_const_vec(bld->gallivm, type, -126.99999), x);
/* ipart = floor(x) */
/* fpart = x - ipart */
GALLIVM_NAN_RETURN_NAN,
/* If one of the inputs is NaN, the other operand is returned */
GALLIVM_NAN_RETURN_OTHER,
- /* If one of the inputs is NaN, the second operand is returned.
- * In min/max it will be as fast as undefined with sse opcodes */
- GALLIVM_NAN_RETURN_SECOND
+ /* If one of the inputs is NaN, the other operand is returned,
+ * but we guarantee the second operand is not a NaN.
+ * In min/max it will be as fast as undefined with sse opcodes,
+ * and archs having native return_other can benefit too. */
+ GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN
};
LLVMValueRef
LLVMValueRef min,
LLVMValueRef max);
+LLVMValueRef
+lp_build_clamp_zero_one_nanzero(struct lp_build_context *bld,
+ LLVMValueRef a);
+
LLVMValueRef
lp_build_abs(struct lp_build_context *bld,
LLVMValueRef a);
assert(dtype == TGSI_TYPE_FLOAT ||
dtype == TGSI_TYPE_UNTYPED);
value = LLVMBuildBitCast(builder, value, float_bld->vec_type, "");
- value = lp_build_max_ext(float_bld, value, float_bld->zero,
- GALLIVM_NAN_RETURN_SECOND);
- value = lp_build_min_ext(float_bld, value, float_bld->one,
- GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ value = lp_build_clamp_zero_one_nanzero(float_bld, value);
break;
case TGSI_SAT_MINUS_PLUS_ONE:
assert(dtype == TGSI_TYPE_FLOAT ||
dtype == TGSI_TYPE_UNTYPED);
value = LLVMBuildBitCast(builder, value, float_bld->vec_type, "");
+ /* This will give -1.0 for NaN which is probably not what we want. */
value = lp_build_max_ext(float_bld, value,
lp_build_const_vec(gallivm, float_bld->type, -1.0),
- GALLIVM_NAN_RETURN_SECOND);
- value = lp_build_min_ext(float_bld, value, float_bld->one,
- GALLIVM_NAN_BEHAVIOR_UNDEFINED);
+ GALLIVM_NAN_RETURN_OTHER_SECOND_NONNAN);
+ value = lp_build_min(float_bld, value, float_bld->one);
break;
default: