[PowerPC] Provide XL-compatible vec_round implementation
The XL implementation of vec_round for vector double uses
"round-to-nearest, ties to even" just as the vector float
`version does. However clang and gcc use "round-to-nearest-away"
for vector double and "round-to-nearest, ties to even"
for vector float.
The XL behaviour is implemented under the __XL_COMPAT_ALTIVEC__
macro similarly to other instances of incompatibility.
Differential revision: https://reviews.llvm.org/D113642
GitOrigin-RevId: b7bf937bbee38c2db0c0640176ef618d9c746538
diff --git a/lib/Headers/altivec.h b/lib/Headers/altivec.h
index fb808d7..3366e1f 100644
--- a/lib/Headers/altivec.h
+++ b/lib/Headers/altivec.h
@@ -8413,9 +8413,20 @@
}
#ifdef __VSX__
+#ifdef __XL_COMPAT_ALTIVEC__
+static __inline__ vector double __ATTRS_o_ai vec_rint(vector double __a);
+static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) {
+ double __fpscr = __builtin_readflm();
+ __builtin_setrnd(0);
+ vector double __rounded = vec_rint(__a);
+ __builtin_setflm(__fpscr);
+ return __rounded;
+}
+#else
static __inline__ vector double __ATTRS_o_ai vec_round(vector double __a) {
return __builtin_vsx_xvrdpi(__a);
}
+#endif
/* vec_rint */
diff --git a/test/CodeGen/builtins-ppc-vsx.c b/test/CodeGen/builtins-ppc-vsx.c
index da16124..b0028e9 100644
--- a/test/CodeGen/builtins-ppc-vsx.c
+++ b/test/CodeGen/builtins-ppc-vsx.c
@@ -409,10 +409,6 @@
// CHECK: call <4 x float> @llvm.ppc.altivec.vrfin(<4 x float>
// CHECK-LE: call <4 x float> @llvm.ppc.altivec.vrfin(<4 x float>
- res_vd = vec_round(vd);
-// CHECK: call <2 x double> @llvm.round.v2f64(<2 x double>
-// CHECK-LE: call <2 x double> @llvm.round.v2f64(<2 x double>
-
res_vd = vec_perm(vd, vd, vuc);
// CHECK: @llvm.ppc.altivec.vperm
// CHECK-LE: @llvm.ppc.altivec.vperm
diff --git a/test/CodeGen/builtins-ppc-xlcompat.c b/test/CodeGen/builtins-ppc-xlcompat.c
index 7d350fb..5c27b9d 100644
--- a/test/CodeGen/builtins-ppc-xlcompat.c
+++ b/test/CodeGen/builtins-ppc-xlcompat.c
@@ -5,11 +5,16 @@
// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \
// RUN: -triple powerpc64le-unknown-linux-gnu -emit-llvm %s -o - \
// RUN: -D__XL_COMPAT_ALTIVEC__ -target-cpu pwr8 | FileCheck %s
+// RUN: %clang_cc1 -target-feature +altivec -target-feature +vsx \
+// RUN: -triple powerpc64le-unknown-linux-gnu -emit-llvm %s -o - \
+// RUN: -U__XL_COMPAT_ALTIVEC__ -target-cpu pwr8 | FileCheck \
+// RUN: --check-prefix=NOCOMPAT %s
#include <altivec.h>
vector double vd = { 3.4e22, 1.8e-3 };
vector signed long long vsll = { -12345678999ll, 12345678999 };
vector unsigned long long vull = { 11547229456923630743llu, 18014402265226391llu };
vector float res_vf;
+vector double res_vd;
vector signed int res_vsi;
vector unsigned int res_vui;
@@ -38,4 +43,11 @@
// CHECK: [[TMP8:%.*]] = load <2 x double>, <2 x double>* @vd, align 16
// CHECK-NEXT: fmul <2 x double> [[TMP8]], <double 1.600000e+01, double 1.600000e+01>
// CHECK: call <4 x i32> @llvm.ppc.vsx.xvcvdpuxws(<2 x double>
+
+ res_vd = vec_round(vd);
+// CHECK: call double @llvm.ppc.readflm()
+// CHECK: call double @llvm.ppc.setrnd(i32 0)
+// CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double>
+// CHECK: call double @llvm.ppc.setflm(double
+// NOCOMPAT: call <2 x double> @llvm.round.v2f64(<2 x double>
}