--- gcc/tree-vrp.c.jj	2012-09-17 11:13:12.000000000 +0200
+++ gcc/tree-vrp.c	2012-09-24 10:06:10.814376659 +0200
@@ -501,8 +501,19 @@ set_and_canonicalize_value_range (value_
      to adjust them.  */
   if (tree_int_cst_lt (max, min))
     {
-      tree one = build_int_cst (TREE_TYPE (min), 1);
-      tree tmp = int_const_binop (PLUS_EXPR, max, one);
+      tree one, tmp;
+
+      /* For one bit precision if max < min, then the swapped
+	 range covers all values, so for VR_RANGE it is varying and
+	 for VR_ANTI_RANGE empty range, so drop to varying as well.  */
+      if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
+	{
+	  set_value_range_to_varying (vr);
+	  return;
+	}
+
+      one = build_int_cst (TREE_TYPE (min), 1);
+      tmp = int_const_binop (PLUS_EXPR, max, one);
       max = int_const_binop (MINUS_EXPR, min, one);
       min = tmp;
 
@@ -531,6 +542,24 @@ set_and_canonicalize_value_range (value_
 	  set_value_range_to_varying (vr);
 	  return;
 	}
+      else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
+	       && !TYPE_UNSIGNED (TREE_TYPE (min))
+	       && (is_min || is_max))
+	{
+	  /* For signed 1-bit precision, one is not in-range and
+	     thus adding/subtracting it would result in overflows.  */
+	  if (operand_equal_p (min, max, 0))
+	    {
+	      min = max = is_min ? vrp_val_max (TREE_TYPE (min))
+				 : vrp_val_min (TREE_TYPE (min));
+	      t = VR_RANGE;
+	    }
+	  else
+	    {
+	      set_value_range_to_varying (vr);
+	      return;
+	    }
+	}
       else if (is_min
 	       /* As a special exception preserve non-null ranges.  */
 	       && !(TYPE_UNSIGNED (TREE_TYPE (min))
--- gcc/testsuite/gcc.dg/pr54676.c.jj	2012-09-24 10:52:48.911691835 +0200
+++ gcc/testsuite/gcc.dg/pr54676.c	2012-09-24 10:52:30.000000000 +0200
@@ -0,0 +1,23 @@
+/* PR tree-optimization/54676 */
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-ccp -fno-tree-copy-prop -fno-tree-fre -ftree-vrp" } */
+
+struct S
+{
+  int s:1;
+};
+
+struct S bar (void);
+
+int a;
+
+void
+foo (int x)
+{
+  struct S s = bar ();
+  while (!a)
+    {
+      int l = 94967295;
+      a = x || (s.s &= l);
+    }
+}
