+2011-07-27 Yukhin Kirill <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/i386.exp (check_effective_target_bmi): New.
+ * gcc.target/i386/bmi-andn-1.c: New test.
+ * gcc.target/i386/bmi-andn-1a.c: Likewise.
+ * gcc.target/i386/bmi-andn-2.c: Likewise.
+ * gcc.target/i386/bmi-andn-2a.c: Likewise.
+ * gcc.target/i386/bmi-bextr-1.c: Likewise.
+ * gcc.target/i386/bmi-bextr-1a.c: Likewise.
+ * gcc.target/i386/bmi-bextr-2.c: Likewise.
+ * gcc.target/i386/bmi-bextr-2a.c: Likewise.
+ * gcc.target/i386/bmi-blsi-1.c: Likewise.
+ * gcc.target/i386/bmi-blsi-1a.c: Likewise.
+ * gcc.target/i386/bmi-blsi-2.c: Likewise.
+ * gcc.target/i386/bmi-blsi-2a.c: Likewise.
+ * gcc.target/i386/bmi-blsmsk-1.c: Likewise.
+ * gcc.target/i386/bmi-blsmsk-1a.c: Likewise.
+ * gcc.target/i386/bmi-blsmsk-2.c: Likewise.
+ * gcc.target/i386/bmi-blsmsk-2a.c: Likewise.
+ * gcc.target/i386/bmi-blsr-1.c: Likewise.
+ * gcc.target/i386/bmi-blsr-1a.c: Likewise.
+ * gcc.target/i386/bmi-blsr-2.c: Likewise.
+ * gcc.target/i386/bmi-blsr-2a.c: Likewise.
+ * gcc.target/i386/bmi-tzcnt-1.c: Likewise.
+ * gcc.target/i386/bmi-tzcnt-1a.c: Likewise.
+ * gcc.target/i386/bmi-tzcnt-2.c: Likewise.
+ * gcc.target/i386/bmi-tzcnt-2a.c: Likewise.
+
2011-07-27 Sebastian Pop <sebastian.pop@amd.com>
PR middle-end/47691
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+long long calc_andn_u64 (long long src1,
+ long long src2,
+ long long dummy)
+{
+ return (~src1 + dummy) & (src2);
+}
+
+static void
+bmi_test()
+{
+ unsigned i;
+
+ long long src = 0xfacec0ffeefacec0;
+ long long res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_andn_u64 (src, src+i, 0);
+ res = __andn_u64 (src, src+i);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-andn-1.c"
+
+/* { dg-final { scan-assembler-times "bmi_andn_di" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+long long calc_andn_u32 (int src1, int src2, int dummy)
+{
+ return (~src1+dummy) & (src2);
+}
+
+static void
+bmi_test()
+{
+ unsigned i;
+
+ int src = 0xfacec0ff;
+ int res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_andn_u32 (src, src+i, 0);
+ res = __andn_u32 (src, src+i);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-andn-2.c"
+
+/* { dg-final { scan-assembler-times "bmi_andn_si" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+long long calc_bextr_u64 (unsigned long long src1,
+ unsigned long long src2)
+{
+ long long res = 0;
+ unsigned char start = (src2 & 0xff);
+ unsigned char len = (int) ((src2 >> 8) & 0xff);
+ if (start < 64) {
+ unsigned i;
+ unsigned last = (start+len) < 64 ? start+len : 64;
+
+ src1 >>= start;
+ for (i=start; i<last; ++i) {
+ res |= (src1 & 1) << (i-start);
+ src1 >>= 1;
+ }
+ }
+
+ return res;
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ unsigned char start, len;
+ unsigned long long src1 = 0xfacec0ffeefacec0;
+ unsigned long long res, res_ref, src2;
+
+ for (i=0; i<5; ++i) {
+ start = (i * 1983) % 64;
+ len = i + (i * 1983) % 64;
+
+ src1 = src1 * 3;
+ src2 = start | (((long long)len) << 8);
+
+ res_ref = calc_bextr_u64 (src1, src2);
+ res = __bextr_u64 (src1, src2);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-bextr-1.c"
+
+/* { dg-final { scan-assembler-times "bmi_bextr_di" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-require-effective-target bmi } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+unsigned calc_bextr_u32 (unsigned src1, unsigned src2)
+{
+ unsigned res = 0;
+ unsigned char start = (src2 & 0xff);
+ unsigned char len = (int) ((src2 >> 8) & 0xff);
+ if (start < 32) {
+ unsigned i;
+ unsigned last = (start+len) < 32 ? start+len : 32;
+
+ src1 >>= start;
+ for (i=start; i<last; ++i) {
+ res |= (src1 & 1) << (i-start);
+ src1 >>= 1;
+ }
+ }
+
+ return res;
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ unsigned char start, len;
+ unsigned src1 = 0xfacec0ff;
+ unsigned res, res_ref, src2;
+
+ for (i=0; i<5; ++i) {
+ start = (i * 1983) % 32;
+ len = i + (i * 1983) % 32;
+
+ src1 = src1 * 3;
+ src2 = start | (((unsigned)len) << 8);
+
+ res_ref = calc_bextr_u32 (src1, src2);
+ res = __bextr_u32 (src1, src2);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-bextr-2.c"
+
+/* { dg-final { scan-assembler-times "bmi_bextr_si" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+/* To fool compiler, so it not generate blsi here. */
+long long calc_blsi_u64 (long long src1, long long src2)
+{
+ return (-src1) & (src2);
+}
+
+static void
+bmi_test()
+{
+ unsigned i;
+
+ long long src = 0xfacec0ffeefacec0;
+ long long res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsi_u64 (src, src);
+ res = __blsi_u64 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsi-1.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsi_di" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+/* To fool compiler, so it not generate blsi here. */
+int calc_blsi_u32 (int src1, int src2)
+{
+ return (-src1) & (src2);
+}
+
+static void
+bmi_test()
+{
+ unsigned i;
+ int src = 0xfacec0ff;
+ int res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsi_u32 (src, src);
+ res = __blsi_u32 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsi-2.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsi_si" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+/* Trick compiler in order not to generate target insn here. */
+long long calc_blsmsk_u64 (long long src1, long long src2)
+{
+ return (src1-1) ^ (src2);
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ long long src = 0xfacec0ffeefacec0;
+ long long res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsmsk_u64 (src, src);
+ res = __blsmsk_u64 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsmsk-1.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsmsk_di" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+/* Trick compiler in order not to generate target insn here. */
+int calc_blsmsk_u32 (int src1, int src2)
+{
+ return (src1-1) ^ (src2);
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ int src = 0xfacec0ff;
+ int res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsmsk_u32 (src, src);
+ res = __blsmsk_u32 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsmsk-2.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsmsk_si" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+long long calc_blsr_u64 (long long src1, long long src2)
+{
+ return (src1-1) & (src2);
+}
+
+static void
+bmi_test()
+{
+ unsigned i;
+ long long src = 0xfacec0ffeefacec0;
+ long long res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsr_u64 (src, src);
+ res = __blsr_u64 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsr-1.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsr_di" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+int calc_blsr_u32 (int src1, int src2)
+{
+ return (src1-1) & (src2);
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ int src = 0xfacec0ff;
+ int res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_blsr_u32 (src, src);
+ res = __blsr_u32 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline -dp" } */
+
+#include "bmi-blsr-2.c"
+
+/* { dg-final { scan-assembler-times "bmi_blsr_si" 1 } } */
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "cpuid.h"
+
+static void bmi_test (void);
+
+static void
+__attribute__ ((noinline))
+do_test (void)
+{
+ bmi_test ();
+}
+
+int
+main ()
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+ /* Run BMI test only if host has BMI support. */
+ if (ebx & bit_BMI)
+ {
+ do_test ();
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+ }
+#ifdef DEBUG
+ else
+ printf ("SKIPPED\n");
+#endif
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { target { bmi && { ! ia32 } } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+long long calc_tzcnt_u64 (long long src)
+{
+ int i;
+ int res = 0;
+
+ while ( (res<64) && ((src&1) == 0)) {
+ ++res;
+ src >>= 1;
+ }
+
+ return res;
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ long long src = 0xfacec0ffeefacec0;
+ long long res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_tzcnt_u64 (src);
+ res = __tzcnt_u64 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include "bmi-tzcnt-1.c"
+
+/* { dg-final { scan-assembler-times "tzcntq" 1 } } */
--- /dev/null
+/* { dg-do run { target { bmi } } } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include <x86intrin.h>
+
+#include "bmi-check.h"
+
+int calc_tzcnt_u32 (int src)
+{
+ int i;
+ int res = 0;
+
+ while ( (res<32) && ((src&1) == 0)) {
+ ++res;
+ src >>= 1;
+ }
+ return res;
+}
+
+static void
+bmi_test ()
+{
+ unsigned i;
+ int src = 0xfacec0ff;
+ int res, res_ref;
+
+ for (i=0; i<5; ++i) {
+ src = i + src << i;
+
+ res_ref = calc_tzcnt_u32 (src);
+ res = __tzcnt_u32 (src);
+
+ if (res != res_ref)
+ abort();
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbmi -fno-inline" } */
+
+#include "bmi-tzcnt-2.c"
+
+/* { dg-final { scan-assembler-times "tzcntl" 1 } } */
} "-O2 -mxop" ]
}
+# Return 1 if bmi instructions can be compiled.
+proc check_effective_target_bmi { } {
+ return [check_no_compiler_messages bmi object {
+ void __bextr_u32 (void)
+ {
+ __builtin_ia32_bextr_u32 (0, 0);
+ }
+ } "-mbmi" ]
+}
+
# If the linker used understands -M <mapfile>, pass it to clear hardware
# capabilities set by the Sun assembler.
set clearcap_ldflags "-Wl,-M,$srcdir/$subdir/clearcap.map"