--- gcc/fold-const.c.jj	2013-01-11 09:02:35.000000000 +0100
+++ gcc/fold-const.c	2013-01-20 17:37:45.787761247 +0100
@@ -13560,6 +13560,11 @@ fold_binary_loc (location_t loc,
 	  && TYPE_UNSIGNED (TREE_TYPE (arg0))
 	  && CONVERT_EXPR_P (arg1)
 	  && TREE_CODE (TREE_OPERAND (arg1, 0)) == LSHIFT_EXPR
+	  && (TYPE_PRECISION (TREE_TYPE (arg1))
+	      >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0))))
+	  && (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg1, 0)))
+	      || (TYPE_PRECISION (TREE_TYPE (arg1))
+		  == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg1, 0)))))
 	  && integer_onep (TREE_OPERAND (TREE_OPERAND (arg1, 0), 0)))
 	{
 	  tem = build2 (RSHIFT_EXPR, TREE_TYPE (arg0), arg0,
--- gcc/testsuite/gcc.c-torture/execute/pr56051.c.jj	2013-01-20 17:40:09.070945296 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr56051.c	2013-01-20 17:38:31.000000000 +0100
@@ -0,0 +1,32 @@
+/* PR tree-optimization/56051 */
+
+extern void abort (void);
+
+int
+main ()
+{
+  unsigned char x1[1] = { 0 };
+  unsigned int s1 = __CHAR_BIT__;
+  int a1 = x1[0] < (unsigned char) (1 << s1);
+  unsigned char y1 = (unsigned char) (1 << s1);
+  int b1 = x1[0] < y1;
+  if (a1 != b1)
+    abort ();
+#if __SIZEOF_LONG_LONG__ > __SIZEOF_INT__
+  unsigned long long x2[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) };
+  unsigned int s2 = sizeof (int) * __CHAR_BIT__ - 1;
+  int a2 = x2[0] >= (unsigned long long) (1 << s2);
+  unsigned long long y2 = 1 << s2;
+  int b2 = x2[0] >= y2;
+  if (a2 != b2)
+    abort ();
+  unsigned long long x3[1] = { 2ULL << (sizeof (int) * __CHAR_BIT__) };
+  unsigned int s3 = sizeof (int) * __CHAR_BIT__ - 1;
+  int a3 = x3[0] >= (unsigned long long) (1U << s3);
+  unsigned long long y3 = 1U << s3;
+  int b3 = x3[0] >= y3;
+  if (a3 != b3)
+    abort ();
+#endif
+  return 0;
+}
