summaryrefslogtreecommitdiff
path: root/meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch')
-rw-r--r--meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch314
1 files changed, 314 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch b/meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch
new file mode 100644
index 000000000..23f41ccd9
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-4.5.1/pr44618.patch
@@ -0,0 +1,314 @@
+Upstream-Status: Pending
+
+Backport of bugfix in gcc-4.6.x and mainline that address bug 44618 in
+which we get wrong code generation with -Os -frename-registers.
+
+ 2011-06-13 Edmar Wienskoski <edmar@freescale.com>
+
+ PR target/44618
+ * config/rs6000/rs6000.md (save_gpregs_<mode>): Replaced pattern
+ with a set of similar patterns, where the MATCH_OPERAND for the
+ function argument is replaced with individual references to hardware
+ registers.
+ (save_fpregs_<mode>): Ditto
+ (restore_gpregs_<mode>): Ditto
+ (return_and_restore_gpregs_<mode>): Ditto
+ (return_and_restore_fpregs_<mode>): Ditto
+ (return_and_restore_fpregs_aix_<mode>): Ditto
+
+ * gcc.target/powerpc/outofline_rnreg.c: New testcase.
+
+Index: gcc-4.5.1/gcc/config/rs6000/rs6000.md
+===================================================================
+--- gcc-4.5.1.orig/gcc/config/rs6000/rs6000.md
++++ gcc-4.5.1/gcc/config/rs6000/rs6000.md
+@@ -15256,25 +15256,88 @@
+ "{stm|stmw} %2,%1"
+ [(set_attr "type" "store_ux")])
+
+-(define_insn "*save_gpregs_<mode>"
++; The following comment applies to:
++; save_gpregs_*
++; save_fpregs_*
++; restore_gpregs*
++; return_and_restore_gpregs*
++; return_and_restore_fpregs*
++; return_and_restore_fpregs_aix*
++;
++; The out-of-line save / restore functions expects one input argument.
++; Since those are not standard call_insn's, we must avoid using
++; MATCH_OPERAND for that argument. That way the register rename
++; optimization will not try to rename this register.
++; Each pattern is repeated for each possible register number used in
++; various ABIs (r11, r1, and for some functions r12)
++
++(define_insn "*save_gpregs_<mode>_r11"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (reg:P 65))
++ (use (match_operand:P 1 "symbol_ref_operand" "s"))
++ (use (reg:P 11))
++ (set (match_operand:P 2 "memory_operand" "=m")
++ (match_operand:P 3 "gpc_reg_operand" "r"))])]
++ ""
++ "bl %1"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*save_gpregs_<mode>_r12"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (reg:P 65))
++ (use (match_operand:P 1 "symbol_ref_operand" "s"))
++ (use (reg:P 12))
++ (set (match_operand:P 2 "memory_operand" "=m")
++ (match_operand:P 3 "gpc_reg_operand" "r"))])]
++ ""
++ "bl %1"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*save_gpregs_<mode>_r1"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (reg:P 65))
++ (use (match_operand:P 1 "symbol_ref_operand" "s"))
++ (use (reg:P 1))
++ (set (match_operand:P 2 "memory_operand" "=m")
++ (match_operand:P 3 "gpc_reg_operand" "r"))])]
++ ""
++ "bl %1"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*save_fpregs_<mode>_r11"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (reg:P 65))
++ (use (match_operand:P 1 "symbol_ref_operand" "s"))
++ (use (reg:P 11))
++ (set (match_operand:DF 2 "memory_operand" "=m")
++ (match_operand:DF 3 "gpc_reg_operand" "d"))])]
++ ""
++ "bl %1"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*save_fpregs_<mode>_r12"
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (reg:P 65))
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+- (use (match_operand:P 2 "gpc_reg_operand" "r"))
+- (set (match_operand:P 3 "memory_operand" "=m")
+- (match_operand:P 4 "gpc_reg_operand" "r"))])]
++ (use (reg:P 12))
++ (set (match_operand:DF 2 "memory_operand" "=m")
++ (match_operand:DF 3 "gpc_reg_operand" "d"))])]
+ ""
+ "bl %1"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+-(define_insn "*save_fpregs_<mode>"
++(define_insn "*save_fpregs_<mode>_r1"
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (reg:P 65))
+ (use (match_operand:P 1 "symbol_ref_operand" "s"))
+- (use (match_operand:P 2 "gpc_reg_operand" "r"))
+- (set (match_operand:DF 3 "memory_operand" "=m")
+- (match_operand:DF 4 "gpc_reg_operand" "d"))])]
++ (use (reg:P 1))
++ (set (match_operand:DF 2 "memory_operand" "=m")
++ (match_operand:DF 3 "gpc_reg_operand" "d"))])]
+ ""
+ "bl %1"
+ [(set_attr "type" "branch")
+@@ -15372,52 +15435,156 @@
+ ; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
+ ; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...
+
+-(define_insn "*restore_gpregs_<mode>"
++; The following comment applies to:
++; save_gpregs_*
++; save_fpregs_*
++; restore_gpregs*
++; return_and_restore_gpregs*
++; return_and_restore_fpregs*
++; return_and_restore_fpregs_aix*
++;
++; The out-of-line save / restore functions expects one input argument.
++; Since those are not standard call_insn's, we must avoid using
++; MATCH_OPERAND for that argument. That way the register rename
++; optimization will not try to rename this register.
++; Each pattern is repeated for each possible register number used in
++; various ABIs (r11, r1, and for some functions r12)
++
++(define_insn "*restore_gpregs_<mode>_r11"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 11))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
++ ""
++ "bl %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*restore_gpregs_<mode>_r12"
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+- (use (match_operand:P 3 "gpc_reg_operand" "r"))
+- (set (match_operand:P 4 "gpc_reg_operand" "=r")
+- (match_operand:P 5 "memory_operand" "m"))])]
++ (use (reg:P 12))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
+ ""
+ "bl %2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+-(define_insn "*return_and_restore_gpregs_<mode>"
++(define_insn "*restore_gpregs_<mode>_r1"
++ [(match_parallel 0 "any_parallel_operand"
++ [(clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 1))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
++ ""
++ "bl %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_gpregs_<mode>_r11"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 11))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
++ ""
++ "b %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_gpregs_<mode>_r12"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 12))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
++ ""
++ "b %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_gpregs_<mode>_r1"
+ [(match_parallel 0 "any_parallel_operand"
+ [(return)
+ (clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+- (use (match_operand:P 3 "gpc_reg_operand" "r"))
+- (set (match_operand:P 4 "gpc_reg_operand" "=r")
+- (match_operand:P 5 "memory_operand" "m"))])]
++ (use (reg:P 1))
++ (set (match_operand:P 3 "gpc_reg_operand" "=r")
++ (match_operand:P 4 "memory_operand" "m"))])]
+ ""
+ "b %2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+-(define_insn "*return_and_restore_fpregs_<mode>"
++(define_insn "*return_and_restore_fpregs_<mode>_r11"
+ [(match_parallel 0 "any_parallel_operand"
+ [(return)
+ (clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+- (use (match_operand:P 3 "gpc_reg_operand" "r"))
+- (set (match_operand:DF 4 "gpc_reg_operand" "=d")
+- (match_operand:DF 5 "memory_operand" "m"))])]
++ (use (reg:P 11))
++ (set (match_operand:DF 3 "gpc_reg_operand" "=d")
++ (match_operand:DF 4 "memory_operand" "m"))])]
++ ""
++ "b %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_fpregs_<mode>_r12"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 12))
++ (set (match_operand:DF 3 "gpc_reg_operand" "=d")
++ (match_operand:DF 4 "memory_operand" "m"))])]
++ ""
++ "b %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_fpregs_<mode>_r1"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (clobber (match_operand:P 1 "register_operand" "=l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 1))
++ (set (match_operand:DF 3 "gpc_reg_operand" "=d")
++ (match_operand:DF 4 "memory_operand" "m"))])]
++ ""
++ "b %2"
++ [(set_attr "type" "branch")
++ (set_attr "length" "4")])
++
++(define_insn "*return_and_restore_fpregs_aix_<mode>_r11"
++ [(match_parallel 0 "any_parallel_operand"
++ [(return)
++ (use (match_operand:P 1 "register_operand" "l"))
++ (use (match_operand:P 2 "symbol_ref_operand" "s"))
++ (use (reg:P 11))
++ (set (match_operand:DF 3 "gpc_reg_operand" "=d")
++ (match_operand:DF 4 "memory_operand" "m"))])]
+ ""
+ "b %2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+-(define_insn "*return_and_restore_fpregs_aix_<mode>"
++(define_insn "*return_and_restore_fpregs_aix_<mode>_r1"
+ [(match_parallel 0 "any_parallel_operand"
+ [(return)
+ (use (match_operand:P 1 "register_operand" "l"))
+ (use (match_operand:P 2 "symbol_ref_operand" "s"))
+- (use (match_operand:P 3 "gpc_reg_operand" "r"))
+- (set (match_operand:DF 4 "gpc_reg_operand" "=d")
+- (match_operand:DF 5 "memory_operand" "m"))])]
++ (use (reg:P 1))
++ (set (match_operand:DF 3 "gpc_reg_operand" "=d")
++ (match_operand:DF 4 "memory_operand" "m"))])]
+ ""
+ "b %2"
+ [(set_attr "type" "branch")
+Index: gcc-4.5.1/gcc/testsuite/gcc.target/powerpc/outofline_rnreg.c
+===================================================================
+--- /dev/null
++++ gcc-4.5.1/gcc/testsuite/gcc.target/powerpc/outofline_rnreg.c
+@@ -0,0 +1,15 @@
++/* Test that registers used by out of line restore functions does not get renamed.
++ AIX, and 64 bit targets uses r1, which rnreg stays away from.
++ Linux 32 bits targets uses r11, which is susceptible to be renamed */
++/* { dg-do compile } */
++/* { dg-require-effective-target ilp32 } */
++/* { dg-options "-Os -frename-registers -fdump-rtl-rnreg" } */
++/* "* renamed" or "* no available better choice" results are not acceptable */
++/* { dg-final { scan-rtl-dump-not "Register 11 in insn *" "rnreg" { target powerpc*-*-linux* } } } */
++/* { dg-final { cleanup-rtl-dump "rnreg" } } */
++int
++calc (int j)
++{
++ if (j<=1) return 1;
++ return calc(j-1)*(j+1);
++}