Commit 9e18f575 by Jeff Law

lib2funcs.asm (__outline_prologue): New "function".

        * lib2funcs.asm (__outline_prologue): New "function".
        (__outline_epilogue): New "function".
        * pa.h (TARGET_SPACE): Define.
        (target_flags): Add -mspace and -mno-space.  Enable/disable
        space saving optimizations.
        (FRAME_POINTER_REQUIRED): Frame pointers are always required
        when generating out of line prologues and epilogues.
        * pa.c (compute_frame_size): Handle out of line prologues/epilogues.
        (hppa_expand_prologue): If optimizing for space, emit an out of
        line prologue.
        * pa.c (compute_frame_size): Handle out of line prologues/epilogues.
        (hppa_expand_prologue): If optimizing for space, emit an out of
        line prologue.
        (hppa_expand_epilogue): Similarly.
        (override_options): Optimizing for space is not compatable with
        either profiling or PIC code generation.
        * pa.md (outline_prologue_call): New pattern.
        (outline_epilogue_call): Likewise.

From-SVN: r11438
parent 9ad2334b
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
.SPACE $TEXT$ .SPACE $TEXT$
.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
.SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8
.IMPORT $$dyncall,MILLICODE .IMPORT $$dyncall,MILLICODE
; gcc_compiled.: ; gcc_compiled.:
.SPACE $TEXT$ .SPACE $TEXT$
...@@ -61,3 +63,251 @@ L$foo ...@@ -61,3 +63,251 @@ L$foo
be,n 0(%sr0,%rp) be,n 0(%sr0,%rp)
.EXIT .EXIT
.PROCEND .PROCEND
.SPACE $TEXT$
.SUBSPA $MILLICODE$
; This is an out-of-line prologue.
;
; It performs the following operations:
;
; * Saves the return pointer at sp - 20
;
; * Creates a new stack frame (sp'), size of the frame is passed in %r21
;
; * The old stack pointer is saved at sp
;
; * Saves grs (passed in low 16 bits of %r22 into the stack frame
; at sp' + local_fsize (passed in %r19).
;
; * Saves frs (passed in high 16 bits of %r22) into the stack
; frame at sp' + local_fsize (passed in %r19).
;
; * Sets up a frame pointer (in %r3).
;
; * Returns to the instruction _immediately_ after the call to
; this function.
.align 32
.NSUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
.EXPORT __outline_prologue,MILLICODE
__outline_prologue
.PROC
.CALLINFO FRAME=0,NO_CALLS
.ENTRY
copy %r30,%r20
; Subtract 4 from our return pointer so that we return to
; the right location.
ldo -4(%r31),%r31
; Save off %r2
stw %r2,-20(0,%r30)
; Make our new frame.
add %r21,%r30,%r30
; Save our old stack pointer.
stw %r20,0(0,%r20)
; Add in local_fsize to our frame pointer so we do register
; saves into the right place
add %r20,%r19,%r20
; %r22 tells us what registers we need to save. The upper half
; is for fp registers, the lower half for integer registers.
; We put the lower half in %r1 and the upper half into %r22
; for later use.
extru %r22,31,16,%r1
extrs %r22,15,16,%r22
; %r1 now olds a value 0-18 which corresponds to the number
; of grs we need to save. We need to reverse that value so
; we can just into the table and straight-line execute to the
; end of the gr saves.
comb,= %r0,%r1,L$0000
subi 18,%r1,%r1
blr,n %r1,%r0
b,n L$0000
stws,ma %r18,4(0,%r20)
nop
stws,ma %r17,4(0,%r20)
nop
stws,ma %r16,4(0,%r20)
nop
stws,ma %r15,4(0,%r20)
nop
stws,ma %r14,4(0,%r20)
nop
stws,ma %r13,4(0,%r20)
nop
stws,ma %r12,4(0,%r20)
nop
stws,ma %r11,4(0,%r20)
nop
stws,ma %r10,4(0,%r20)
nop
stws,ma %r9,4(0,%r20)
nop
stws,ma %r8,4(0,%r20)
nop
stws,ma %r7,4(0,%r20)
nop
stws,ma %r6,4(0,%r20)
nop
stws,ma %r5,4(0,%r20)
nop
stws,ma %r4,4(0,%r20)
nop
stws,ma %r3,4(0,%r20)
nop
L$0000
; All gr saves are done. Align the temporary frame pointer and
; do the fr saves.
ldo 7(%r20),%r20
depi 0,31,3,%r20
comb,= %r0,%r22,L$0001
subi 21,%r22,%r22
blr,n %r22,%r0
b,n L$0001
fstws,ma %fr21,8(0,%r20)
nop
fstws,ma %fr20,8(0,%r20)
nop
fstws,ma %fr19,8(0,%r20)
nop
fstws,ma %fr18,8(0,%r20)
nop
fstws,ma %fr17,8(0,%r20)
nop
fstws,ma %fr16,8(0,%r20)
nop
fstws,ma %fr15,8(0,%r20)
nop
fstws,ma %fr14,8(0,%r20)
nop
fstws,ma %fr13,8(0,%r20)
nop
fstws,ma %fr12,8(0,%r20)
nop
L$0001
; Return, setting up a frame pointer in the delay slot
bv 0(%r31)
sub %r30,%r21,%r3
.EXIT
.PROCEND
; This is an out-of-line epilogue. It's operation is basically the reverse
; of the out-of-line prologue.
.align 32
.NSUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
.EXPORT __outline_epilogue,MILLICODE
__outline_epilogue
.PROC
.CALLINFO FRAME=0,NO_CALLS
.ENTRY
; Make a copy of our frame pointer into %r20
copy %r3,%r20
; Subtract 4 from our return pointer so that we return to
; the right location.
ldo -4(%r31),%r31
; Reload %r2
; First save off %r2
ldw -20(0,%r20),%r2
; Load our old stack pointer, save it in %r21.
ldw 0(0,%r20),%r21
; Add in local_fsize (%r19) to the frame pointer to find
; the saved registers.
add %r20,%r19,%r20
; %r22 tells us what registers we need to restore. The upper half
; is for fp registers, the lower half for integer registers.
; We put the lower half in %r1 and the upper half into %r22
; for later use.
extru %r22,31,16,%r1
extrs %r22,15,16,%r22
; %r1 now olds a value 0-18 which corresponds to the number
; of grs we need to restore. We need to reverse that value so
; we can just into the table and straight-line execute to the
; end of the gr restore.
comb,= %r0,%r1,L$0002
subi 18,%r1,%r1
blr,n %r1,%r0
b,n L$0002
ldws,ma 4(0,%r20),%r18
nop
ldws,ma 4(0,%r20),%r17
nop
ldws,ma 4(0,%r20),%r16
nop
ldws,ma 4(0,%r20),%r15
nop
ldws,ma 4(0,%r20),%r14
nop
ldws,ma 4(0,%r20),%r13
nop
ldws,ma 4(0,%r20),%r12
nop
ldws,ma 4(0,%r20),%r11
nop
ldws,ma 4(0,%r20),%r10
nop
ldws,ma 4(0,%r20),%r9
nop
ldws,ma 4(0,%r20),%r8
nop
ldws,ma 4(0,%r20),%r7
nop
ldws,ma 4(0,%r20),%r6
nop
ldws,ma 4(0,%r20),%r5
nop
ldws,ma 4(0,%r20),%r4
nop
ldws,ma 4(0,%r20),%r3
nop
L$0002
; All gr restore are done. Align the temporary frame pointer and
; do the fr restore.
ldo 7(%r20),%r20
depi 0,31,3,%r20
comb,= %r0,%r22,L$0003
subi 21,%r22,%r22
blr,n %r22,%r0
b,n L$0003
fldws,ma 8(0,%r20),%fr21
nop
fldws,ma 8(0,%r20),%fr20
nop
fldws,ma 8(0,%r20),%fr19
nop
fldws,ma 8(0,%r20),%fr18
nop
fldws,ma 8(0,%r20),%fr17
nop
fldws,ma 8(0,%r20),%fr16
nop
fldws,ma 8(0,%r20),%fr15
nop
fldws,ma 8(0,%r20),%fr14
nop
fldws,ma 8(0,%r20),%fr13
nop
fldws,ma 8(0,%r20),%fr12
nop
L$0003
; Return and deallocate our frame.
bv 0(%r31)
copy %r21,%r30
.EXIT
.PROCEND
...@@ -113,6 +113,12 @@ override_options () ...@@ -113,6 +113,12 @@ override_options ()
{ {
warning ("PIC code generation is not compatable with profiling\n"); warning ("PIC code generation is not compatable with profiling\n");
} }
if (TARGET_SPACE && (flag_pic || profile_flag))
{
warning ("Out of line entry/exit sequences are not compatable\n");
warning ("with PIC or profiling\n");
}
} }
...@@ -2039,8 +2045,24 @@ compute_frame_size (size, fregs_live) ...@@ -2039,8 +2045,24 @@ compute_frame_size (size, fregs_live)
for (i = 18; i >= 4; i--) for (i = 18; i >= 4; i--)
{ {
if (regs_ever_live[i]) if (regs_ever_live[i])
{
/* For out of line prologues/epilogues we only need to
compute the highest register number to save and
allocate space for all the callee saved registers
with a lower number. */
if (TARGET_SPACE)
{
fsize += 4 * (i - 3);
break;
}
fsize += 4; fsize += 4;
} }
}
/* We always save %r3, make room for it. */
if (TARGET_SPACE)
fsize += 8;
/* If we don't have a frame pointer, the register normally used for that /* If we don't have a frame pointer, the register normally used for that
purpose is saved just like other registers, not in the "frame marker". */ purpose is saved just like other registers, not in the "frame marker". */
if (! frame_pointer_needed) if (! frame_pointer_needed)
...@@ -2053,9 +2075,19 @@ compute_frame_size (size, fregs_live) ...@@ -2053,9 +2075,19 @@ compute_frame_size (size, fregs_live)
for (i = 66; i >= 48; i -= 2) for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1]) if (regs_ever_live[i] || regs_ever_live[i + 1])
{ {
fsize += 8;
if (fregs_live) if (fregs_live)
*fregs_live = 1; *fregs_live = 1;
/* For out of line prologues/epilogues we only need to
compute the highest register number to save and
allocate space for all the callee saved registers
with a lower number. */
if (TARGET_SPACE)
{
fsize += 4 * (i - 46);
break;
}
fsize += 8;
} }
fsize += current_function_outgoing_args_size; fsize += current_function_outgoing_args_size;
...@@ -2148,6 +2180,47 @@ hppa_expand_prologue() ...@@ -2148,6 +2180,47 @@ hppa_expand_prologue()
tmpreg = gen_rtx (REG, SImode, 1); tmpreg = gen_rtx (REG, SImode, 1);
size_rtx = GEN_INT (actual_fsize); size_rtx = GEN_INT (actual_fsize);
/* Handle out of line prologues and epilogues. */
if (TARGET_SPACE)
{
rtx operands[2];
int saves = 0;
/* Put the local_fisze into %r19. */
operands[0] = gen_rtx (REG, SImode, 19);
operands[1] = GEN_INT (local_fsize);
emit_move_insn (operands[0], operands[1]);
/* Put the stack size into %r21. */
operands[0] = gen_rtx (REG, SImode, 21);
operands[1] = size_rtx;
emit_move_insn (operands[0], operands[1]);
/* Put the register save info into %r22. */
for (i = 18; i >= 3; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
saves = i;
break;
}
for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1])
{
saves |= ((i/2 - 12 ) << 16);
break;
}
operands[0] = gen_rtx (REG, SImode, 22);
operands[1] = GEN_INT (saves);
emit_move_insn (operands[0], operands[1]);
/* Now call the out-of-line prologue. */
emit_insn (gen_outline_prologue_call ());
emit_insn (gen_blockage ());
return;
}
/* Save RP first. The calling conventions manual states RP will /* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp-20. */ always be stored into the caller's frame at sp-20. */
if (regs_ever_live[2] || profile_flag) if (regs_ever_live[2] || profile_flag)
...@@ -2416,6 +2489,43 @@ hppa_expand_epilogue () ...@@ -2416,6 +2489,43 @@ hppa_expand_epilogue ()
int offset,i; int offset,i;
int merge_sp_adjust_with_load = 0; int merge_sp_adjust_with_load = 0;
/* Handle out of line prologues and epilogues. */
if (TARGET_SPACE)
{
int saves = 0;
rtx operands[2];
/* Put the register save info into %r22. */
for (i = 18; i >= 3; i--)
if (regs_ever_live[i] && ! call_used_regs[i])
{
saves = i;
break;
}
for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1])
{
saves |= ((i/2 - 12 ) << 16);
break;
}
emit_insn (gen_blockage ());
/* Put the local_fisze into %r19. */
operands[0] = gen_rtx (REG, SImode, 19);
operands[1] = GEN_INT (local_fsize);
emit_move_insn (operands[0], operands[1]);
operands[0] = gen_rtx (REG, SImode, 22);
operands[1] = GEN_INT (saves);
emit_move_insn (operands[0], operands[1]);
/* Now call the out-of-line epilogue. */
emit_insn (gen_outline_epilogue_call ());
return;
}
/* We will use this often. */ /* We will use this often. */
tmpreg = gen_rtx (REG, SImode, 1); tmpreg = gen_rtx (REG, SImode, 1);
......
...@@ -78,6 +78,10 @@ extern int target_flags; ...@@ -78,6 +78,10 @@ extern int target_flags;
/* Allow unconditional jumps in the delay slots of call instructions. */ /* Allow unconditional jumps in the delay slots of call instructions. */
#define TARGET_JUMP_IN_DELAY (target_flags & 8) #define TARGET_JUMP_IN_DELAY (target_flags & 8)
/* Optimize for space. Currently this only turns on out of line
prologues and epilogues. */
#define TARGET_SPACE (target_flags & 16)
/* Disable indexed addressing modes. */ /* Disable indexed addressing modes. */
#define TARGET_DISABLE_INDEXING (target_flags & 32) #define TARGET_DISABLE_INDEXING (target_flags & 32)
...@@ -119,9 +123,11 @@ extern int target_flags; ...@@ -119,9 +123,11 @@ extern int target_flags;
{"disable-fpregs", 2}, \ {"disable-fpregs", 2}, \
{"no-disable-fpregs", -2}, \ {"no-disable-fpregs", -2}, \
{"no-space-regs", 4}, \ {"no-space-regs", 4}, \
{"space-regs", -4},\ {"space-regs", -4}, \
{"jump-in-delay", 8}, \ {"jump-in-delay", 8}, \
{"no-jump-in-delay", -8}, \ {"no-jump-in-delay", -8}, \
{"space", 16}, \
{"no-space", -16}, \
{"disable-indexing", 32}, \ {"disable-indexing", 32}, \
{"no-disable-indexing", -32},\ {"no-disable-indexing", -32},\
{"portable-runtime", 64}, \ {"portable-runtime", 64}, \
...@@ -554,9 +560,11 @@ do { \ ...@@ -554,9 +560,11 @@ do { \
/* Base register for access to local variables of the function. */ /* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM 3 #define FRAME_POINTER_REGNUM 3
/* Value should be nonzero if functions must have frame pointers. */ /* Value should be nonzero if functions must have frame pointers.
#define FRAME_POINTER_REQUIRED (current_function_calls_alloca) All functions have frame pointers when optimizing for space
(for now).
#define FRAME_POINTER_REQUIRED \
(current_function_calls_alloca || TARGET_SPACE)
/* C statement to store the difference between the frame pointer /* C statement to store the difference between the frame pointer
and the stack pointer values immediately after the function prologue. and the stack pointer values immediately after the function prologue.
......
...@@ -4837,3 +4837,65 @@ ...@@ -4837,3 +4837,65 @@
"mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop" "mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop"
[(set_attr "type" "multi") [(set_attr "type" "multi")
(set_attr "length" "52")]) (set_attr "length" "52")])
;; An out-of-line prologue.
(define_insn "outline_prologue_call"
[(unspec_volatile [(const_int 0)] 0)
(clobber (reg:SI 31))
(clobber (reg:SI 22))
(clobber (reg:SI 21))
(clobber (reg:SI 20))
(clobber (reg:SI 19))
(clobber (reg:SI 1))]
""
"*
{
/* Must import the magic millicode routine. */
output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL);
/* The out-of-line prologue will make sure we return to the right
instruction. */
if (TARGET_PORTABLE_RUNTIME)
{
output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL);
output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL);
}
else
output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL);
return \"\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])
;; An out-of-line epilogue.
(define_insn "outline_epilogue_call"
[(unspec_volatile [(const_int 1)] 0)
(use (reg:SI 29))
(use (reg:SI 28))
(clobber (reg:SI 31))
(clobber (reg:SI 22))
(clobber (reg:SI 21))
(clobber (reg:SI 20))
(clobber (reg:SI 19))
(clobber (reg:SI 2))
(clobber (reg:SI 1))]
""
"*
{
/* Must import the magic millicode routine. */
output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL);
/* The out-of-line prologue will make sure we return to the right
instruction. */
if (TARGET_PORTABLE_RUNTIME)
{
output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL);
output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL);
}
else
output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL);
return \"\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment