diff mbox

rs6000: Don't add an immediate to r0 (PR80966)

Message ID 31f559b621b855a23783a9b616316026b16a4570.1496976652.git.segher@kernel.crashing.org
State New
Headers show

Commit Message

Segher Boessenkool June 9, 2017, 3:40 a.m. UTC
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 mbox

Patch

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;
+}