Index: gcc-head/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-forwprop.c
+++ gcc-head/gcc/tree-ssa-forwprop.c
@@ -1624,30 +1624,56 @@ simplify_bitwise_binary (gimple_stmt_ite
   /* If the first argument is an SSA name that is itself a result of a
      typecast of an ADDR_EXPR to an integer, feed the ADDR_EXPR to the
      folder rather than the ssa name.  */
-  if (code == BIT_AND_EXPR
-      && TREE_CODE (arg2) == INTEGER_CST
+  if (TREE_CODE (arg2) == INTEGER_CST
       && TREE_CODE (arg1) == SSA_NAME)
     {
       gimple def = SSA_NAME_DEF_STMT (arg1);
       tree op = arg1;
+      tree opp = NULL_TREE;
+      tree folded_int = NULL_TREE;
 
-      /* ???  This looks bogus - the conversion could be truncating.  */
       if (is_gimple_assign (def)
 	  && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
 	  && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
 	{
-	  tree opp = gimple_assign_rhs1 (def);
-	  if (TREE_CODE (opp) == ADDR_EXPR)
+	  opp = gimple_assign_rhs1 (def);
+	  folded_int = fold_convert_loc (gimple_location (stmt),
+					 TREE_TYPE (opp), arg2);
+	  /* Check if integer value remains the same on cast back
+	     to original type.  */
+	  if (!operand_equal_p (arg2, fold_convert (TREE_TYPE (arg1),
+						    folded_int), 0))
+	    folded_int = NULL_TREE;
+	  if (TREE_CODE (opp) == ADDR_EXPR && folded_int)
 	    op = opp;
 	}
+      if (code == BIT_AND_EXPR)
+        {
+	  res = fold_binary_loc (gimple_location (stmt),
+				 BIT_AND_EXPR,
+				 TREE_TYPE (gimple_assign_lhs (stmt)),
+				 op, arg2);
+	  if (res && is_gimple_min_invariant (res))
+	    {
+	      gimple_assign_set_rhs_from_tree (gsi, res);
+	      update_stmt (stmt);
+	      return true;
+	    }
+	}
 
-      res = fold_binary_loc (gimple_location (stmt),
-			     BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
-			     op, arg2);
-      if (res && is_gimple_min_invariant (res))
-	{
-	  gimple_assign_set_rhs_from_tree (gsi, res);
-	  update_stmt (stmt);
+      /* Convert (type) X & CST -> (type) (X & (typeof-X) CST),
+         if conversion of CST is reversible.  */
+      if (opp != NULL_TREE && folded_int != NULL_TREE)
+        {
+	  gimple newop;
+	  tree tem = create_tmp_reg (TREE_TYPE (opp), NULL);
+	  newop = gimple_build_assign_with_ops (code, tem, opp, folded_int);
+	  tem = make_ssa_name (tem, newop);
+	  gimple_assign_set_lhs (newop, tem);
+	  gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+	  gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
+					    tem, NULL_TREE, NULL_TREE);
+	  update_stmt (gsi_stmt (*gsi));
 	  return true;
 	}
     }
@@ -1682,10 +1708,11 @@ simplify_bitwise_binary (gimple_stmt_ite
   if (CONVERT_EXPR_CODE_P (def1_code)
       && CONVERT_EXPR_CODE_P (def2_code)
       && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))
-      /* Make sure that the conversion widens the operands or that it
-	 changes the operation to a bitfield precision.  */
+      /* Make sure that the conversion widens the operands, or has same
+	 precision,  or that it changes the operation to a bitfield
+	 precision.  */
       && ((TYPE_PRECISION (TREE_TYPE (def1_arg1))
-	   < TYPE_PRECISION (TREE_TYPE (arg1)))
+	   <= TYPE_PRECISION (TREE_TYPE (arg1)))
 	  || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1)))
 	      != MODE_INT)
 	  || (TYPE_PRECISION (TREE_TYPE (arg1))
Index: gcc-head/gcc/tree-ssa-math-opts.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-math-opts.c
+++ gcc-head/gcc/tree-ssa-math-opts.c
@@ -1785,6 +1785,7 @@ execute_optimize_bswap (void)
   bool bswap32_p, bswap64_p;
   bool changed = false;
   tree bswap32_type = NULL_TREE, bswap64_type = NULL_TREE;
+  int iter = 0;
 
   if (BITS_PER_UNIT != 8)
     return 0;
@@ -1815,108 +1816,123 @@ execute_optimize_bswap (void)
       bswap64_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
     }
 
+  /* Is 64-bit bswap not supported?  */
+  if (!bswap64_p)
+    iter = 1;
+
   memset (&bswap_stats, 0, sizeof (bswap_stats));
 
-  FOR_EACH_BB (bb)
+  /* If iter has value of zero, then seek for 64-bit bswap,
+     If iter has value of one, then seek for 32-bit bswap.  */
+  for (; iter < 2; iter++)
     {
-      gimple_stmt_iterator gsi;
+      FOR_EACH_BB (bb)
+	{
+	  gimple_stmt_iterator gsi;
 
-      for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-        {
-	  gimple stmt = gsi_stmt (gsi);
-	  tree bswap_src, bswap_type;
-	  tree bswap_tmp;
-	  tree fndecl = NULL_TREE;
-	  int type_size;
-	  gimple call;
-
-	  if (!is_gimple_assign (stmt)
-	      || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR)
-	    continue;
+	  for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	    {
+	      gimple stmt = gsi_stmt (gsi);
+	      tree bswap_src, bswap_type;
+	      tree bswap_tmp;
+	      tree fndecl = NULL_TREE;
+	      int type_size;
+	      gimple call;
+
+	      if (!is_gimple_assign (stmt)
+		  || gimple_assign_rhs_code (stmt) != BIT_IOR_EXPR)
+		continue;
 
-	  type_size = TYPE_PRECISION (gimple_expr_type (stmt));
+	      type_size = TYPE_PRECISION (gimple_expr_type (stmt));
 
-	  switch (type_size)
-	    {
-	    case 32:
-	      if (bswap32_p)
+	      switch (type_size)
 		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP32];
-		  bswap_type = bswap32_type;
-		}
-	      break;
-	    case 64:
-	      if (bswap64_p)
-		{
-		  fndecl = built_in_decls[BUILT_IN_BSWAP64];
-		  bswap_type = bswap64_type;
+		case 32:
+		  if (iter != 1)
+		    continue;
+		  if (bswap32_p)
+		    {
+		      fndecl = built_in_decls[BUILT_IN_BSWAP32];
+		      bswap_type = bswap32_type;
+		    }
+		  break;
+		case 64:
+		  if (iter != 0)
+		    continue;
+		  if (bswap64_p)
+		    {
+		      fndecl = built_in_decls[BUILT_IN_BSWAP64];
+		      bswap_type = bswap64_type;
+		    }
+		  break;
+		default:
+		  continue;
 		}
-	      break;
-	    default:
-	      continue;
-	    }
 
-	  if (!fndecl)
-	    continue;
+	      if (!fndecl)
+		continue;
 
-	  bswap_src = find_bswap (stmt);
+	      bswap_src = find_bswap (stmt);
 
-	  if (!bswap_src)
-	    continue;
+	      if (!bswap_src)
+		continue;
 
-	  changed = true;
-	  if (type_size == 32)
-	    bswap_stats.found_32bit++;
-	  else
-	    bswap_stats.found_64bit++;
+	      changed = true;
+	      if (type_size == 32)
+		bswap_stats.found_32bit++;
+	      else
+		bswap_stats.found_64bit++;
 
-	  bswap_tmp = bswap_src;
+	      bswap_tmp = bswap_src;
 
-	  /* Convert the src expression if necessary.  */
-	  if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type))
-	    {
-	      gimple convert_stmt;
+	      /* Convert the src expression if necessary.  */
+	      if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp),
+					      bswap_type))
+		{
+		  gimple convert_stmt;
 
-	      bswap_tmp = create_tmp_var (bswap_type, "bswapsrc");
-	      add_referenced_var (bswap_tmp);
-	      bswap_tmp = make_ssa_name (bswap_tmp, NULL);
-
-	      convert_stmt = gimple_build_assign_with_ops (
-			       CONVERT_EXPR, bswap_tmp, bswap_src, NULL);
-	      gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT);
-	    }
+		  bswap_tmp = create_tmp_var (bswap_type, "bswapsrc");
+		  add_referenced_var (bswap_tmp);
+		  bswap_tmp = make_ssa_name (bswap_tmp, NULL);
+
+		  convert_stmt = gimple_build_assign_with_ops (
+				   CONVERT_EXPR, bswap_tmp, bswap_src, NULL);
+		  gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT);
+		}
 
-	  call = gimple_build_call (fndecl, 1, bswap_tmp);
+	      call = gimple_build_call (fndecl, 1, bswap_tmp);
 
-	  bswap_tmp = gimple_assign_lhs (stmt);
+	      bswap_tmp = gimple_assign_lhs (stmt);
 
-	  /* Convert the result if necessary.  */
-	  if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp), bswap_type))
-	    {
-	      gimple convert_stmt;
+	      /* Convert the result if necessary.  */
+	      if (!useless_type_conversion_p (TREE_TYPE (bswap_tmp),
+					      bswap_type))
+		{
+		  gimple convert_stmt;
 
-	      bswap_tmp = create_tmp_var (bswap_type, "bswapdst");
-	      add_referenced_var (bswap_tmp);
-	      bswap_tmp = make_ssa_name (bswap_tmp, NULL);
-	      convert_stmt = gimple_build_assign_with_ops (
-		               CONVERT_EXPR, gimple_assign_lhs (stmt), bswap_tmp, NULL);
-	      gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
-	    }
+		  bswap_tmp = create_tmp_var (bswap_type, "bswapdst");
+		  add_referenced_var (bswap_tmp);
+		  bswap_tmp = make_ssa_name (bswap_tmp, NULL);
+		  convert_stmt = gimple_build_assign_with_ops (
+				   CONVERT_EXPR, gimple_assign_lhs (stmt),
+				   bswap_tmp, NULL);
+		  gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT);
+		}
 
-	  gimple_call_set_lhs (call, bswap_tmp);
+	      gimple_call_set_lhs (call, bswap_tmp);
 
-	  if (dump_file)
-	    {
-	      fprintf (dump_file, "%d bit bswap implementation found at: ",
-		       (int)type_size);
-	      print_gimple_stmt (dump_file, stmt, 0, 0);
-	    }
+	      if (dump_file)
+		{
+		  fprintf (dump_file, "%d bit bswap implementation found at: ",
+			   (int) type_size);
+		  print_gimple_stmt (dump_file, stmt, 0, 0);
+		}
 
-	  gsi_insert_after (&gsi, call, GSI_SAME_STMT);
-	  gsi_remove (&gsi, true);
+	      gsi_insert_after (&gsi, call, GSI_SAME_STMT);
+	      gsi_remove (&gsi, true);
+	    }
 	}
     }
-
   statistics_counter_event (cfun, "32-bit bswap implementations found",
 			    bswap_stats.found_32bit);
   statistics_counter_event (cfun, "64-bit bswap implementations found",
