With some changes I was working on, I produced a situation where one of
the x86 peepholes made an incorrect transformation. In the prologue
expansion code, we have
/* When using red zone we may start register saving before allocating
the stack frame saving one cycle of the prologue. However, avoid
doing this if we have to probe the stack; at least on x86_64 the
stack probe can turn into a call that clobbers a red zone location.
So, we can in some situations produce something like:
mov %ebx, -8(%rsp)
mov %edi, -16(%rsp)
subl $16, %rsp
which is fine if using a redzone. The problem is that there are
peepholes which convert sp subtractions into pushes, clobbering the
saved registers.
I've made these peepholes conditional on !x86_using_red_zone.
Bootstrapped and tested on x86_64-linux, ok (now or later)?
Bernd
* config/i386/i386-protos.h (ix86_using_red_zone): Declare.
* config/i386/i386.c (ix86_using_red_zone): No longer static.
* config/i386/i386.md (stack decrement to push peepholes): Guard
with !x86_using_red_zone ().
testsuite/
* gcc.target/i386/pr46470.c: Add -mno-red-zone to dg-optios for
x86_64.
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h (revision 234831)
+++ gcc/config/i386/i386-protos.h (working copy)
@@ -44,6 +44,8 @@ extern bool ix86_use_pseudo_pic_reg (voi
extern void ix86_reset_previous_fndecl (void);
+extern bool ix86_using_red_zone (void);
+
#ifdef RTX_CODE
extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c (revision 234831)
+++ gcc/config/i386/i386.c (working copy)
@@ -3709,7 +3709,7 @@ make_pass_stv (gcc::context *ctxt)
/* Return true if a red-zone is in use. */
-static inline bool
+bool
ix86_using_red_zone (void)
{
return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md (revision 234831)
+++ gcc/config/i386/i386.md (working copy)
@@ -18240,7 +18240,8 @@ (define_peephole2
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
@@ -18253,7 +18254,8 @@ (define_peephole2
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
@@ -18267,7 +18269,8 @@ (define_peephole2
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
@@ -18278,7 +18281,8 @@ (define_peephole2
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
Index: gcc/testsuite/gcc.target/i386/pr46470.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr46470.c (revision 234831)
+++ gcc/testsuite/gcc.target/i386/pr46470.c (working copy)
@@ -4,7 +4,7 @@
/* These options are selected to ensure 1 word needs to be allocated
on the stack to maintain alignment for the call. This should be
transformed to push+pop. We also want to force unwind info updates. */
-/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables" } */
+/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables -mno-red-zone" } */
/* { dg-options "-Os -fomit-frame-pointer -mpreferred-stack-boundary=3 -fasynchronous-unwind-tables" { target ia32 } } */
/* ms_abi has reserved stack-region. */
/* { dg-skip-if "" { x86_64-*-mingw* } { "*" } { "" } } */