This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [split] Add CFI ops, fix call/return prediction, other changes
Richard Henderson <rth@redhat.com> writes:
>> + # Note that %esp is exactly 32 bytes below the CFA -- perfect for
>> + # a 16-byte aligned stack. That said, we still ought to compile
>> + # generic-morestack.c with -mpreferred-stack-boundary=2. FIXME.
>
> Without the ecx push this isn't true. Not that it really matters; if
> the cfa were properly aligned on entry to our caller, we pushed 12
> bytes to get to __morestack, which means our cfa is not aligned.
>
>> + movl -4(%ebp),%eax # Restore registers.
>> + movl -8(%ebp),%edx
>>
>> + movl 4(%ebp),%ecx # Increment the return address
>> + inc %ecx # to skip the ret instruction;
>> + # see above.
>>
>> call *%ecx # Call our caller!
>
> How about using some of that extra space we've got in the frame:
>
> movl -12(%ebp), %ecx # Restore 2 registers
> movl -8(%ebp), %edx
>
> movl 4(%ebp), %eax # Increment return address
> inc %eax
> movl %eax, -8(%ebp) # Store it in an unused slot
>
> movl -4(%ebp), %eax # Restore 3rd register
>
> call *-8(%ebp) # Call our caller via slot
Excellent. Committed to split branch as follows. Thanks.
Ian
libgcc/:
2009-09-30 Ian Lance Taylor <iant@google.com>
Richard Henderson <rth@redhat.com>
* config/i386/morestack.S (__morestack): In 32-bit case, use a
stack slot to hold the incremented return address rather than
trashing %ecx.
gcc/:
2009-09-30 Ian Lance Taylor <iant@google.com>
* config/i386/i386.c (ix86_expand_split_stack_prologue): Never
save %ecx around the call to __morestack.
Index: libgcc/config/i386/morestack.S
===================================================================
--- libgcc/config/i386/morestack.S (revision 152321)
+++ libgcc/config/i386/morestack.S (working copy)
@@ -96,11 +96,11 @@ __morestack:
# In 32-bit mode the registers %eax, %edx, and %ecx may be
# used for parameters, depending on the regparm and fastcall
- # attributes. However, we don't have to worry about %ecx, as
- # the function will have saved it on the stack if necessary.
+ # attributes.
pushl %eax
pushl %edx
+ pushl %ecx
pushl 12(%ebp) # The size of the parameters.
leal 20(%ebp),%eax # Address of caller's parameters.
@@ -122,14 +122,19 @@ __morestack:
# gcc/config/i386/linux.h.
movl %eax,%gs:0x30 # Save the new stack boundary.
- movl -4(%ebp),%eax # Restore registers.
- movl -8(%ebp),%edx
+ movl -8(%ebp),%edx # Restore registers.
+ movl -12(%ebp),%ecx
- movl 4(%ebp),%ecx # Increment the return address
- inc %ecx # to skip the ret instruction;
+ movl 4(%ebp),%eax # Increment the return address
+ inc %eax # to skip the ret instruction;
# see above.
+
+ movl %eax,-8(%ebp) # Store return address in an
+ # unused slot.
- call *%ecx # Call our caller!
+ movl -4(%ebp),%eax # Restore the last register.
+
+ call *-8(%ebp) # Call our caller!
# The caller will return here, as predicted.
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c (revision 152321)
+++ gcc/config/i386/i386.c (working copy)
@@ -9219,13 +9219,6 @@ ix86_expand_split_stack_prologue (void)
call_fusage = NULL_RTX;
if (!TARGET_64BIT)
{
- /* In order to give __morestack a scratch register, we save %ecx
- if necessary. */
- if (is_fastcall || regparm > 2)
- {
- emit_insn (gen_push (gen_rtx_REG (Pmode, CX_REG)));
- args_size += UNITS_PER_WORD;
- }
emit_insn (gen_push (GEN_INT (args_size)));
emit_insn (gen_push (allocate_rtx));
}
@@ -9255,12 +9248,6 @@ ix86_expand_split_stack_prologue (void)
label. Therefore, we use an unspec. */
emit_insn (gen_split_stack_return ());
- if (!TARGET_64BIT && (is_fastcall || regparm > 2))
- {
- /* Restore the scratch register we pushed earlier. */
- emit_insn (gen_popsi1 (gen_rtx_REG (Pmode, CX_REG)));
- }
-
emit_label (label);
LABEL_NUSES (label) = 1;
}