diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7bd222e353e53f2ae5655aa813c00a80b065ea37..94ba6516bb02a59ec72aa4a8d1fe2aa8147f9c26 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2006-05-21  Kazu Hirata  <kazu@codesourcery.com>
+
+	PR rtl-optimization/27671
+	* simplify-rtx.c (simplify_relational_operation_1): Fix
+	simplifications of (eq/ne (xor x y) y) and
+	(eq/ne (xor x y) x).
+
 2006-05-21  Bernhard Fischer  <aldot@gcc.gnu.org>
 
 	* tree-cfg.c: Prune whitespace.
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 962c2de5840cbbca2cd189bbe712e57ef1816b4d..6ab5cb753c697790ef8b017188e7299811992dbf 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -3604,18 +3604,21 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
     return simplify_gen_relational (code, mode, cmp_mode,
 				    XEXP (op0, 0), XEXP (op0, 1));
 
-  /* (eq/ne (xor x y) x) simplifies to (eq/ne x 0).  */
+  /* (eq/ne (xor x y) x) simplifies to (eq/ne y 0).  */
   if ((code == EQ || code == NE)
       && op0code == XOR
       && rtx_equal_p (XEXP (op0, 0), op1)
-      && !side_effects_p (XEXP (op0, 1)))
-    return simplify_gen_relational (code, mode, cmp_mode, op1, const0_rtx);
-  /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne y 0).  */
+      && !side_effects_p (XEXP (op0, 0)))
+    return simplify_gen_relational (code, mode, cmp_mode,
+				    XEXP (op0, 1), const0_rtx);
+
+  /* Likewise (eq/ne (xor x y) y) simplifies to (eq/ne x 0).  */
   if ((code == EQ || code == NE)
       && op0code == XOR
       && rtx_equal_p (XEXP (op0, 1), op1)
-      && !side_effects_p (XEXP (op0, 0)))
-    return simplify_gen_relational (code, mode, cmp_mode, op1, const0_rtx);
+      && !side_effects_p (XEXP (op0, 1)))
+    return simplify_gen_relational (code, mode, cmp_mode,
+				    XEXP (op0, 0), const0_rtx);
 
   /* (eq/ne (xor x C1) C2) simplifies to (eq/ne x (C1^C2)).  */
   if ((code == EQ || code == NE)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 13713e64087d6147d7835e9e46c1e21a491a5230..11e358a67a18d40d835b74df6f0d789ba901aae9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-05-21  Kazu Hirata  <kazu@codesourcery.com>
+
+	PR rtl-optimization/27671
+	* gcc.c-torture/execute/pr27671-1.c: New.
+	* gcc.dg/pr27671-2.c: Likewise.
+
 2006-05-21  Paul Thomas  <pault@gcc.gnu.org>
 
 	PR fortran/27613
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr27671-1.c b/gcc/testsuite/gcc.c-torture/execute/pr27671-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd2982cc843da958f03b37694897a0ea4b6d3f34
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr27671-1.c
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/27671.
+   The combiner used to simplify "a ^ b == a" to "a" via
+   simplify_relational_operation_1 in simplify-rtx.c.  */
+
+extern void abort (void) __attribute__ ((noreturn));
+extern void exit (int) __attribute__ ((noreturn));
+
+static int __attribute__((noinline))
+foo (int a, int b)
+{
+  int c = a ^ b;
+  if (c == a)
+    abort ();
+}
+
+int
+main (void)
+{
+  foo (0, 1);
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/pr27671-2.c b/gcc/testsuite/gcc.dg/pr27671-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..78820427b7b6d56392e7d42331febc4cf0ec95d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr27671-2.c
@@ -0,0 +1,24 @@
+/* PR rtl-optimization/27671.
+   The combiner used to simplify "a ^ b == a" to "a" via
+   simplify_relational_operation_1 in simplify-rtx.c.  */
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+/* { dg-options "-O1 -march=pentium4" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+
+extern void abort (void) __attribute__ ((noreturn));
+extern void exit (int) __attribute__ ((noreturn));
+
+static void __attribute__ ((noinline))
+bar (int k)
+{
+  int n = k % 2;
+  if (n == 0)
+    abort ();
+}
+
+int
+main (void)
+{  
+  bar (1);
+  exit (0);
+}