aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorKirill Yukhin <kirill.yukhin@intel.com>2013-12-05 11:23:39 +0000
committerKirill Yukhin <kyukhin@gcc.gnu.org>2013-12-05 11:23:39 +0000
commit9bbd48d120d203e8eade09e0bb830370b6d69801 (patch)
tree3ba8009e419b90953be79c501271dcc9db592b66 /gcc
parent46db94aa6a7619350c9d8b75fe0cc4fa3c4d2182 (diff)
downloadgcc-9bbd48d120d203e8eade09e0bb830370b6d69801.zip
gcc-9bbd48d120d203e8eade09e0bb830370b6d69801.tar.gz
gcc-9bbd48d120d203e8eade09e0bb830370b6d69801.tar.bz2
i386.c (IX86_BUILTIN_READ_FLAGS): New.
ChangeLog/ * config/i386/i386.c(IX86_BUILTIN_READ_FLAGS): New. (IX86_BUILTIN_WRITE_FLAGS): Ditto. (ix86_init_mmx_sse_builtins): Define __builtin_ia32_writeeflags_u32, __builtin_ia32_writeeflags_u64, __builtin_ia32_readeflags_u32, __builtin_ia32_readeflags_u64. (ix86_expand_builtin): Expand them. * config/i386/ia32intrin.h (__readeflags): New. (__writeeflags): Ditto. * gcc/config/i386/i386.md (*pushfl<mode>): Ditto. (*popfl<mode>1): Ditto. testsuite/ChangeLog/ * gcc.target/i386/readeflags-1.c: New. * gcc.target/i386/writeeflags-1.c: Ditto. From-SVN: r205703
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/i386/i386.c37
-rw-r--r--gcc/config/i386/i386.md17
-rw-r--r--gcc/config/i386/ia32intrin.h33
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/readeflags-1.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/writeeflags-1.c30
7 files changed, 175 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ae50704..6440950 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2013-12-05 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * config/i386/i386.c(IX86_BUILTIN_READ_FLAGS): New.
+ (IX86_BUILTIN_WRITE_FLAGS): Ditto.
+ (ix86_init_mmx_sse_builtins): Define
+ __builtin_ia32_writeeflags_u32, __builtin_ia32_writeeflags_u64,
+ __builtin_ia32_readeflags_u32, __builtin_ia32_readeflags_u64.
+ (ix86_expand_builtin): Expand them.
+ * config/i386/ia32intrin.h (__readeflags): New.
+ (__writeeflags): Ditto.
+ * gcc/config/i386/i386.md (*pushfl<mode>): Ditto.
+ (*popfl<mode>1): Ditto.
+
2013-12-05 Richard Biener <rguenther@suse.de>
PR tree-optimization/59374
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7bf8c1e..848b8508 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -27920,6 +27920,10 @@ enum ix86_builtins
IX86_BUILTIN_CPU_IS,
IX86_BUILTIN_CPU_SUPPORTS,
+ /* Read/write FLAGS register built-ins. */
+ IX86_BUILTIN_READ_FLAGS,
+ IX86_BUILTIN_WRITE_FLAGS,
+
IX86_BUILTIN_MAX
};
@@ -29761,6 +29765,17 @@ ix86_init_mmx_sse_builtins (void)
UCHAR_FTYPE_UCHAR_ULONGLONG_ULONGLONG_PULONGLONG,
IX86_BUILTIN_ADDCARRYX64);
+ /* Read/write FLAGS. */
+ def_builtin (~OPTION_MASK_ISA_64BIT, "__builtin_ia32_readeflags_u32",
+ UNSIGNED_FTYPE_VOID, IX86_BUILTIN_READ_FLAGS);
+ def_builtin (OPTION_MASK_ISA_64BIT, "__builtin_ia32_readeflags_u64",
+ UINT64_FTYPE_VOID, IX86_BUILTIN_READ_FLAGS);
+ def_builtin (~OPTION_MASK_ISA_64BIT, "__builtin_ia32_writeeflags_u32",
+ VOID_FTYPE_UNSIGNED, IX86_BUILTIN_WRITE_FLAGS);
+ def_builtin (OPTION_MASK_ISA_64BIT, "__builtin_ia32_writeeflags_u64",
+ VOID_FTYPE_UINT64, IX86_BUILTIN_WRITE_FLAGS);
+
+
/* Add FMA4 multi-arg argument instructions */
for (i = 0, d = bdesc_multi_arg; i < ARRAY_SIZE (bdesc_multi_arg); i++, d++)
{
@@ -33439,6 +33454,28 @@ addcarryx:
emit_insn (gen_rtx_SET (VOIDmode, target, pat));
return target;
+ case IX86_BUILTIN_READ_FLAGS:
+ emit_insn (gen_push (gen_rtx_REG (word_mode, FLAGS_REG)));
+
+ if (target == NULL_RTX
+ || !register_operand (target, word_mode)
+ || GET_MODE (target) != word_mode)
+ target = gen_reg_rtx (word_mode);
+
+ emit_insn (gen_pop (target));
+ return target;
+
+ case IX86_BUILTIN_WRITE_FLAGS:
+
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ op0 = expand_normal (arg0);
+ if (!general_no_elim_operand (op0, word_mode))
+ op0 = copy_to_mode_reg (word_mode, op0);
+
+ emit_insn (gen_push (op0));
+ emit_insn (gen_pop (gen_rtx_REG (word_mode, FLAGS_REG)));
+ return 0;
+
case IX86_BUILTIN_GATHERSIV2DF:
icode = CODE_FOR_avx2_gathersiv2df;
goto gather_gen;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 5ff66cc..7075332 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1721,6 +1721,23 @@
"pop{<imodesuffix>}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "<MODE>")])
+
+(define_insn "*pushfl<mode>"
+ [(set (match_operand:DWIH 0 "push_operand" "=<")
+ (match_operand:DWIH 1 "flags_reg_operand"))]
+ ""
+ "pushf{<imodesuffix>}"
+ [(set_attr "type" "push")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*popfl<mode>"
+ [(set (match_operand:DWIH 0 "flags_reg_operand")
+ (match_operand:DWIH 1 "pop_operand" ">"))]
+ ""
+ "popf{<imodesuffix>}"
+ [(set_attr "type" "pop")
+ (set_attr "mode" "<MODE>")])
+
;; Move instructions.
diff --git a/gcc/config/i386/ia32intrin.h b/gcc/config/i386/ia32intrin.h
index b26dc46..65642e4 100644
--- a/gcc/config/i386/ia32intrin.h
+++ b/gcc/config/i386/ia32intrin.h
@@ -238,6 +238,22 @@ __rorq (unsigned long long __X, int __C)
return (__X >> __C) | (__X << (64 - __C));
}
+/* Read flags register */
+extern __inline unsigned long long
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__readeflags (void)
+{
+ return __builtin_ia32_readeflags_u64 ();
+}
+
+/* Write flags register */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__writeeflags (unsigned long long X)
+{
+ __builtin_ia32_writeeflags_u64 (X);
+}
+
#define _bswap64(a) __bswapq(a)
#define _popcnt64(a) __popcntq(a)
#define _lrotl(a,b) __rolq((a), (b))
@@ -245,6 +261,23 @@ __rorq (unsigned long long __X, int __C)
#else
#define _lrotl(a,b) __rold((a), (b))
#define _lrotr(a,b) __rord((a), (b))
+
+/* Read flags register */
+extern __inline unsigned int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__readeflags (void)
+{
+ return __builtin_ia32_readeflags_u32 ();
+}
+
+/* Write flags register */
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+__writeeflags (unsigned int X)
+{
+ __builtin_ia32_writeeflags_u32 (X);
+}
+
#endif
#define _bit_scan_forward(a) __bsfd(a)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 592f64c..699ff7e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-05 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/readeflags-1.c: New.
+ * gcc.target/i386/writeeflags-1.c: Ditto.
+
2013-12-05 Yury Gribov <y.gribov@samsung.com>
PR sanitizer/59369
diff --git a/gcc/testsuite/gcc.target/i386/readeflags-1.c b/gcc/testsuite/gcc.target/i386/readeflags-1.c
new file mode 100644
index 0000000..6b2fa7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/readeflags-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+
+#include <x86intrin.h>
+
+#ifdef __x86_64__
+#define EFLAGS_TYPE unsigned long long int
+#else
+#define EFLAGS_TYPE unsigned int
+#endif
+
+static EFLAGS_TYPE
+readeflags_test (unsigned int a, unsigned int b)
+{
+ unsigned x = (a == b);
+ return __readeflags ();
+}
+
+int
+main ()
+{
+ EFLAGS_TYPE flags;
+
+ flags = readeflags_test (100, 100);
+
+ if ((flags & 1) != 0) /* Read CF */
+ abort ();
+
+ flags = readeflags_test (100, 101);
+
+ if ((flags & 1) == 0) /* Read CF */
+ abort ();
+
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/writeeflags-1.c b/gcc/testsuite/gcc.target/i386/writeeflags-1.c
new file mode 100644
index 0000000..446840c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/writeeflags-1.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+
+#include <x86intrin.h>
+
+#ifdef __x86_64__
+#define EFLAGS_TYPE unsigned long long int
+#else
+#define EFLAGS_TYPE unsigned int
+#endif
+
+int
+main ()
+{
+ EFLAGS_TYPE flags = 0xD7; /* 111010111b */
+
+ __writeeflags (flags);
+
+ flags = __readeflags ();
+
+ if ((flags & 0xFF) != 0xD7)
+ abort ();
+
+#ifdef DEBUG
+ printf ("PASSED\n");
+#endif
+
+ return 0;
+}
+