diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac116172052d4a2296f3f472046bee702365bc1c..dd1b4b49581f10ace3490cce19778121bf8f7ab6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2012-11-12  Steven Bosscher  <steven@gcc.gnu.org>
+	    Jakub Jelinek  <jakub@redhat.com>
+
+	PR rtl-optimization/51447
+	* df-scan.c (df_get_entry_block_def_set): Add global regs to the set.
+	* df-problems.c (df_lr_local_compute): Make global regs always live.
+	* dce.c (deletable_insn_p): Make insns setting a global reg
+	inherently necessary.
+
 2012-11-12  Ian Bolton  <ian.bolton@arm.com>
 
 	* config/aarch64/aarch64.md (cmov<mode>_insn): Emit CSINC when
@@ -362,7 +371,7 @@
 2012-11-09  Kenneth Zadeck <zadeck@naturalbridge.com>
 
 	* rtl.h (CONST_SCALAR_INT_P): New macro.
-   	* cfgexpand.c (expand_debug_locations): Changed to use
+	* cfgexpand.c (expand_debug_locations): Changed to use
 	CONST_SCALAR_INT_P macro.
 	* combine.c (try_combine, subst, make_extraction,
 	gen_lowpart_for_combine): Ditto.
@@ -725,7 +734,7 @@
 	is_tm_ending_fndecl calls as mergable.
 
 2012-11-06  Sterling Augustine <saugustine@google.com>
-            Cary Coutant <ccoutant@google.com>
+	    Cary Coutant <ccoutant@google.com>
 
 	* common.opt (gno-split-dwarf, gsplit-dwarf): New switches.
 	* doc/invoke.texi (Debugging Options): Document them.
@@ -1254,7 +1263,7 @@
 	(make_extraction): Adjust head comment and move up canonicalization.
 
 2012-11-04  Alexandre Oliva <aoliva@redhat.com>
-            Jakub Jelinek <jakub@redhat.com>
+	    Jakub Jelinek <jakub@redhat.com>
 
 	PR debug/54693
 	* tree-ssa-loop-ivopts.c (remove_unused_ivs): Emit debug temps
@@ -1541,9 +1550,9 @@
 	(symtab_node_def::try_variable): New.  Change most calls to
 	symtab_variable_p with calls to dyn_cast <varpool_node> (p).
 	(symtab_function_p): Remove.  Change callers to use
-        is_a <cgraph_node> (p) instead.
+	is_a <cgraph_node> (p) instead.
 	(symtab_variable_p): Remove.  Change callers to use
-        is_a <varpool_node> (p) instead.
+	is_a <varpool_node> (p) instead.
 	* cgraph.c (cgraph_node_for_asm): Remove redundant call to
 	symtab_node_for_asm.
 	* cgraphunit.c (symbol_finalized_and_needed): New.
@@ -2333,7 +2342,7 @@
 2012-10-24  Sharad Singhai  <singhai@google.com>
 
 	* config/rs6000/rs6000.c (rs6000_density_test): Use dump_enabled_p
-          instead of dump_kind_p.
+	instead of dump_kind_p.
 
 2012-10-24  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
@@ -3478,7 +3487,7 @@
 	(TARGET_FSGSBASE): Likewise.
 	(TARGET_RDRND): Likewise.
 	(TARGET_F16C): Likewise.
-	(TARGET_RTM     ): Likewise.
+	(TARGET_RTM): Likewise.
 	(TARGET_HLE): Likewise.
 	(TARGET_RDSEED): Likewise.
 	(TARGET_PRFCHW): Likewise.
diff --git a/gcc/dce.c b/gcc/dce.c
index 9a87677dc630d8815a040aef479498ab7ef16f9c..7e4addaef3a747ed763a6a7071300575374091ab 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -121,6 +121,12 @@ deletable_insn_p (rtx insn, bool fast, bitmap arg_stores)
       && !insn_nothrow_p (insn))
     return false;
 
+  /* If INSN sets a global_reg, leave it untouched.  */
+  for (df_ref *def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
+    if (HARD_REGISTER_NUM_P (DF_REF_REGNO (*def_rec))
+	&& global_regs[DF_REF_REGNO (*def_rec)])
+      return false;
+
   body = PATTERN (insn);
   switch (GET_CODE (body))
     {
diff --git a/gcc/df-problems.c b/gcc/df-problems.c
index 3f9228dc53ad7e3a4930cc49ea086e8ac45d216f..452926128fcd0bf7da87af9a75b490a3793d8b0a 100644
--- a/gcc/df-problems.c
+++ b/gcc/df-problems.c
@@ -931,7 +931,7 @@ df_lr_bb_local_compute (unsigned int bb_index)
 static void
 df_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED)
 {
-  unsigned int bb_index;
+  unsigned int bb_index, i;
   bitmap_iterator bi;
 
   bitmap_clear (&df->hardware_regs_used);
@@ -939,6 +939,11 @@ df_lr_local_compute (bitmap all_blocks ATTRIBUTE_UNUSED)
   /* The all-important stack pointer must always be live.  */
   bitmap_set_bit (&df->hardware_regs_used, STACK_POINTER_REGNUM);
 
+  /* Global regs are always live, too.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (global_regs[i])
+      bitmap_set_bit (&df->hardware_regs_used, i);
+
   /* Before reload, there are a few registers that must be forced
      live everywhere -- which might not already be the case for
      blocks within infinite loops.  */
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 23da115f1789d26e6f6e4792f00a8f3a471e588b..566f2375be5e9a0057b5f64451040565682737e1 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -3790,8 +3790,12 @@ df_get_entry_block_def_set (bitmap entry_block_defs)
   bitmap_clear (entry_block_defs);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (FUNCTION_ARG_REGNO_P (i))
-      bitmap_set_bit (entry_block_defs, INCOMING_REGNO (i));
+    {
+      if (global_regs[i])
+	bitmap_set_bit (entry_block_defs, i);
+      if (FUNCTION_ARG_REGNO_P (i))
+	bitmap_set_bit (entry_block_defs, INCOMING_REGNO (i));
+    }
 
   /* The always important stack pointer.  */
   bitmap_set_bit (entry_block_defs, STACK_POINTER_REGNUM);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9c933702cb331289e7f725dc6b66dd10e51f632c..f236a2f4d1b0aa94d01e74d0b4f72c6f70f99290 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2012-11-12  Steven Bosscher  <steven@gcc.gnu.org>
+	    Jakub Jelinek  <jakub@redhat.com>
+
+	PR rtl-optimization/51447
+	* gcc.c-torture/execute/pr51447.c: New test.
+
 2012-11-12  Ian Bolton  <ian.bolton@arm.com>
 
 	* gcc.target/aarch64/csinc-2.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr51447.c b/gcc/testsuite/gcc.c-torture/execute/pr51447.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b71a2642ad40ca6f1db28b72facc200a41c2848
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr51447.c
@@ -0,0 +1,27 @@
+/* PR rtl-optimization/51447 */
+
+extern void abort (void);
+
+#ifdef __x86_64__
+register void *ptr asm ("rbx");
+#else
+void *ptr;
+#endif
+
+int
+main (void)
+{
+  __label__ nonlocal_lab;
+  __attribute__((noinline, noclone)) void
+    bar (void *func)
+      {
+	ptr = func;
+	goto nonlocal_lab;
+      }
+  bar (&&nonlocal_lab);
+  return 1;
+nonlocal_lab:
+  if (ptr != &&nonlocal_lab)
+    abort ();
+  return 0;
+}