diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ae5070481368013e3d7bdcc40925f9f3bb8c74e6..6440950f47056ed610930ea89358058272887e95 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 7bf8c1ec0214aeb5a7f1f1a72fdd846d1d3939d4..848b85086522cc6eeb027869f38c4cb8c7d72632 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 5ff66ccf1e59e25a7765558cdc217ec5c9f5065c..7075332466110c7e03237a0244a3d7b7ea15f143 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 b26dc46d2562e138f3aef2dc552f45b657311f58..65642e460238f76bb5d997cecfa3f73eb0247351 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 592f64c3823fa13b9c5d634f47dc7301b1c08d02..699ff7e6cd3539f2643a3816d488d7e388b2dc85 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 0000000000000000000000000000000000000000..6b2fa7e8d146a296aac989810b0e0f932de93684
--- /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 0000000000000000000000000000000000000000..446840cb33c4ba2f7f9f0bf7585296e50610ef02
--- /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;
+}
+