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 <seg...@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