This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] rs6000: Don't add an immediate to r0 (PR80966)
- From: Segher Boessenkool <segher at kernel dot crashing dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dje dot gcc at gmail dot com, ebotcazou at libertysurf dot fr, Segher Boessenkool <segher at kernel dot crashing dot org>
- Date: Fri, 9 Jun 2017 03:40:51 +0000
- Subject: [PATCH] rs6000: Don't add an immediate to r0 (PR80966)
- Authentication-results: sourceware.org; auth=none
If there is a large stack frame the rs6000 -fstack-limit code would
calculate the new stack pointer value using two insns (an addis and
an addi), with r0 as temporary. Such instructions do not exist.
This patch changes add<mode>3 to expand using a different strategy in
such cases; to FAIL if there is no way to do it (namely, if the source
is r0 and there is no way to get a temporary reg); and it changes
rs6000_emit_allocate_stack to assert gen_add3_insn did in fact emit
instructions.
Tested on powerpc64-linux {-m32,-m64}; committing to trunk.
Segher
2017-06-09 Segher Boessenkool <segher@kernel.crashing.org>
PR target/80966
* config/rs6000/rs6000.c (rs6000_emit_allocate_stack): Assert that
gen_add3_insn did not fail.
* config/rs6000/rs6000.md (add<mode>3): If asked to add a constant to
r0, construct that number in a temporary reg and add that reg to r0.
If asked to put the result in r0 as well, fail.
gcc/testsuite/
* gcc.target/powerpc/stack-limit.c: New testcase.
---
gcc/config/rs6000/rs6000.c | 8 +++++---
gcc/config/rs6000/rs6000.md | 11 +++++++++++
gcc/testsuite/gcc.target/powerpc/stack-limit.c | 10 ++++++++++
3 files changed, 26 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/powerpc/stack-limit.c
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ad52eee..32c84cd 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -26940,9 +26940,11 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
&& REGNO (stack_limit_rtx) > 1
&& REGNO (stack_limit_rtx) <= 31)
{
- emit_insn (gen_add3_insn (tmp_reg, stack_limit_rtx, GEN_INT (size)));
- emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
- const0_rtx));
+ rtx_insn *insn
+ = gen_add3_insn (tmp_reg, stack_limit_rtx, GEN_INT (size));
+ gcc_assert (insn);
+ emit_insn (insn);
+ emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg, const0_rtx));
}
else if (GET_CODE (stack_limit_rtx) == SYMBOL_REF
&& TARGET_32BIT
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 08d3e1b..bb505c5 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1629,6 +1629,17 @@ (define_expand "add<mode>3"
|| rtx_equal_p (operands[0], operands[1]))
? operands[0] : gen_reg_rtx (<MODE>mode));
+ /* Adding a constant to r0 is not a valid insn, so use a different
+ strategy in that case. */
+ if (REGNO (operands[1]) == 0 || REGNO (tmp) == 0)
+ {
+ if (operands[0] == operands[1])
+ FAIL;
+ rs6000_emit_move (operands[0], operands[2], <MODE>mode);
+ emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[0]));
+ DONE;
+ }
+
HOST_WIDE_INT val = INTVAL (operands[2]);
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
diff --git a/gcc/testsuite/gcc.target/powerpc/stack-limit.c b/gcc/testsuite/gcc.target/powerpc/stack-limit.c
new file mode 100644
index 0000000..e676c96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/stack-limit.c
@@ -0,0 +1,10 @@
+/* { dg-options "-O0 -fstack-limit-register=r14" } */
+
+// PR80966
+
+int foo (int i)
+{
+ char arr[135000];
+
+ arr[i] = 0;
+}
--
1.9.3