diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b85f8bbbe86..3d1f0188961 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2007-01-10 Sa Liu + Ben Elliston + + * spu.h (STACK_SAVE_AREA): Use VOIDmode for SAVE_FUNCTION, SImode + for SAVE_NONLOCAL and Pmode for any other save level. + * spu-protos.h (spu_restore_stack_block): Declare. + * spu.md (save_stack_block): Remove. + (restore_stack_block): Call spu_restore_stack_block. + * spu.c (spu_restore_stack_block): New function. + (spu_expand_epilogue): Remove old comment. + 2007-01-09 Zdenek Dvorak PR tree-optimization/30322 diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h index 01f5c60c887..6f87ec02581 100644 --- a/gcc/config/spu/spu-protos.h +++ b/gcc/config/spu/spu-protos.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -78,6 +78,7 @@ extern rtx array_to_constant (enum machine_mode mode, unsigned char *arr); extern enum machine_mode spu_eh_return_filter_mode (void); extern void spu_allocate_stack (rtx op0, rtx op1); extern void spu_restore_stack_nonlocal (rtx op0, rtx op1); +extern void spu_restore_stack_block (rtx op0, rtx op1); extern rtx spu_gen_subreg (enum machine_mode mode, rtx x); extern int spu_safe_dma(HOST_WIDE_INT channel); extern void spu_builtin_splats (rtx ops[]); diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index b724b80613e..e30d00e140b 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -1702,8 +1702,6 @@ spu_expand_epilogue (bool sibcall_p) if (total_size > 0) { if (current_function_calls_alloca) - /* Load it from the back chain because our save_stack_block and - restore_stack_block do nothing. */ frame_emit_load (STACK_POINTER_REGNUM, sp_reg, 0); else frame_emit_add_imm (sp_reg, sp_reg, total_size, scratch_reg_0); @@ -4306,6 +4304,32 @@ spu_init_builtins (void) } } +void +spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1) +{ + static unsigned char arr[16] = + { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 }; + + rtx temp = gen_reg_rtx (Pmode); + rtx temp2 = gen_reg_rtx (V4SImode); + rtx temp3 = gen_reg_rtx (V4SImode); + rtx pat = gen_reg_rtx (TImode); + rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM); + + emit_move_insn (pat, array_to_constant (TImode, arr)); + + /* Restore the sp. */ + emit_move_insn (temp, op1); + emit_move_insn (temp2, gen_frame_mem (V4SImode, stack_pointer_rtx)); + + /* Compute available stack size for sp. */ + emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx)); + emit_insn (gen_shufb (temp3, temp, temp, pat)); + + emit_insn (gen_addv4si3 (sp, sp, temp3)); + emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp2); +} + int spu_safe_dma (HOST_WIDE_INT channel) { diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h index 74db2244e32..240d2458995 100644 --- a/gcc/config/spu/spu.h +++ b/gcc/config/spu/spu.h @@ -96,7 +96,10 @@ extern const char *spu_fixed_range_string; #define MAX_FIXED_MODE_SIZE 128 -#define STACK_SAVEAREA_MODE(save_level) SImode +#define STACK_SAVEAREA_MODE(save_level) \ + (save_level == SAVE_FUNCTION ? VOIDmode \ + : save_level == SAVE_NONLOCAL ? SImode \ + : Pmode) #define STACK_SIZE_MODE SImode diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md index 79783615912..8e8fad2d114 100644 --- a/gcc/config/spu/spu.md +++ b/gcc/config/spu/spu.md @@ -1,4 +1,4 @@ -;; Copyright (C) 2006 Free Software Foundation, Inc. +;; Copyright (C) 2006, 2007 Free Software Foundation, Inc. ;; This file is free software; you can redistribute it and/or modify it under ;; the terms of the GNU General Public License as published by the Free @@ -3116,16 +3116,19 @@ selb\t%0,%4,%0,%3" "spu_allocate_stack (operands[0], operands[1]); DONE;") ;; These patterns say how to save and restore the stack pointer. We need not -;; save the stack pointer at function or block level since we are careful to -;; preserve the backchain. Doing nothing at block level means the stack space -;; is allocated until the end of the function. This is currently safe to do -;; because gcc uses the frame pointer for the whole function, so the worst that -;; happens is wasted stack space. That could be bad if a VLA is declared in a -;; loop, because new space will be allocated every iteration, but users can -;; work around that case. Ideally we could detect when we are in a loop and -;; generate the more complicated code in that case. +;; save the stack pointer at function level since we are careful to preserve +;; the backchain. +;; + +;; At block level the stack pointer is saved and restored, so that the +;; stack space allocated within a block is deallocated when leaving +;; block scope. By default, according to the SPU ABI, the stack +;; pointer and available stack size are saved in a register. Upon +;; restoration, the stack pointer is simply copied back, and the +;; current available stack size is calculated against the restored +;; stack pointer. ;; -;; For nonlocal gotos, we must save both the stack pointer and its +;; For nonlocal gotos, we must save the stack pointer and its ;; backchain and restore both. Note that in the nonlocal case, the ;; save area is a memory location. @@ -3141,19 +3144,15 @@ selb\t%0,%4,%0,%3" "" "DONE;") -(define_expand "save_stack_block" - [(match_operand 0 "general_operand" "") - (match_operand 1 "general_operand" "")] - "" - "DONE; ") - (define_expand "restore_stack_block" - [(use (match_operand 0 "spu_reg_operand" "")) - (set (match_dup 2) (match_dup 3)) - (set (match_dup 0) (match_operand 1 "spu_reg_operand" "")) - (set (match_dup 3) (match_dup 2))] + [(match_operand 0 "spu_reg_operand" "") + (match_operand 1 "memory_operand" "")] "" - "DONE;") + " + { + spu_restore_stack_block (operands[0], operands[1]); + DONE; + }") (define_expand "save_stack_nonlocal" [(match_operand 0 "memory_operand" "")