From: Nick Clifton Date: Sat, 22 Jan 2011 16:05:49 +0000 (+0000) Subject: rx.md (UNSPEC_CONST): New. X-Git-Tag: upstream/12.2.0~86909 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=15ba56964dee4136423c2d8534698013663fb8df;p=platform%2Fupstream%2Fgcc.git rx.md (UNSPEC_CONST): New. * config/rx/rx.md (UNSPEC_CONST): New. (deallocate_and_return): Wrap the amount popped off the stack in an UNSPEC_CONST in order to stop it being rejected by -mmax-constant-size. (pop_and_return): Add a "(return)" rtx. (call): Drop the immediate operand. (call_internal): Likewise. (call_value): Likewise. (call_value_internal): Likewise. (sibcall_internal): Likewise. (sibcall_value_internal): Likewise. (sibcall): Likewise. Generate an explicit call using sibcall_internal. (sibcall_value): Likewise. (mov<>): FAIL if a constant operand is not legitimate. (addsi3_unpsec): New pattern. * config/rx/rx.c (rx_print_operand_address): Handle UNPSEC CONSTs. (ok_for_max_constant): New function. (gen_safe_add): New function. (rx_expand_prologue): Use gen_safe_add. (rx_expand_epilogue): Likewise. (rx_is_legitimate_constant): Use ok_for_max_constant. Handle UNSPEC CONSTs. From-SVN: r169128 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9aba03d..b0edbea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2011-01-22 Nick Clifton + + * config/rx/rx.md (UNSPEC_CONST): New. + (deallocate_and_return): Wrap the amount popped off the stack in + an UNSPEC_CONST in order to stop it being rejected by + -mmax-constant-size. + (pop_and_return): Add a "(return)" rtx. + (call): Drop the immediate operand. + (call_internal): Likewise. + (call_value): Likewise. + (call_value_internal): Likewise. + (sibcall_internal): Likewise. + (sibcall_value_internal): Likewise. + (sibcall): Likewise. Generate an explicit call using + sibcall_internal. + (sibcall_value): Likewise. + (mov<>): FAIL if a constant operand is not legitimate. + (addsi3_unpsec): New pattern. + * config/rx/rx.c (rx_print_operand_address): Handle UNPSEC + CONSTs. + (ok_for_max_constant): New function. + (gen_safe_add): New function. + (rx_expand_prologue): Use gen_safe_add. + (rx_expand_epilogue): Likewise. + (rx_is_legitimate_constant): Use ok_for_max_constant. Handle + UNSPEC CONSTs. + 2011-01-21 Jeff Law PR tree-optimization/47053 diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 0179b1f..54cb737 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -1,5 +1,5 @@ /* Subroutines used for code generation on Renesas RX processors. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Red Hat. This file is part of GCC. @@ -323,10 +323,20 @@ rx_print_operand_address (FILE * file, rtx addr) break; } + case CONST: + if (GET_CODE (XEXP (addr, 0)) == UNSPEC) + { + addr = XEXP (addr, 0); + gcc_assert (XINT (addr, 1) == UNSPEC_CONST); + + addr = XVECEXP (addr, 0, 0); + gcc_assert (CONST_INT_P (addr)); + } + /* Fall through. */ case LABEL_REF: case SYMBOL_REF: - case CONST: fprintf (file, "#"); + default: output_addr_const (file, addr); break; @@ -1281,6 +1291,56 @@ mark_frame_related (rtx insn) } } +static bool +ok_for_max_constant (HOST_WIDE_INT val) +{ + if (rx_max_constant_size == 0 || rx_max_constant_size == 4) + /* If there is no constraint on the size of constants + used as operands, then any value is legitimate. */ + return true; + + /* rx_max_constant_size specifies the maximum number + of bytes that can be used to hold a signed value. */ + return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)), + ( 1 << (rx_max_constant_size * 8))); +} + +/* Generate an ADD of SRC plus VAL into DEST. + Handles the case where VAL is too big for max_constant_value. + Sets FRAME_RELATED_P on the insn if IS_FRAME_RELATED is true. */ + +static void +gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related) +{ + rtx insn; + + if (val == NULL_RTX || INTVAL (val) == 0) + { + gcc_assert (dest != src); + + insn = emit_move_insn (dest, src); + } + else if (ok_for_max_constant (INTVAL (val))) + insn = emit_insn (gen_addsi3 (dest, src, val)); + else + { + insn = emit_insn (gen_addsi3_unspec (dest, src, val)); + + if (is_frame_related) + /* We have to provide our own frame related note here + as the dwarf2out code cannot be expected to grok + our unspec. */ + add_reg_note (insn, REG_FRAME_RELATED_EXPR, + gen_rtx_SET (SImode, dest, + gen_rtx_PLUS (SImode, src, val))); + return; + } + + if (is_frame_related) + RTX_FRAME_RELATED_P (insn) = 1; + return; +} + void rx_expand_prologue (void) { @@ -1370,17 +1430,8 @@ rx_expand_prologue (void) /* If needed, set up the frame pointer. */ if (frame_pointer_needed) - { - if (frame_size) - insn = emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx, - GEN_INT (- (HOST_WIDE_INT) frame_size))); - else - insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx); - - RTX_FRAME_RELATED_P (insn) = 1; - } - - insn = NULL_RTX; + gen_safe_add (frame_pointer_rtx, stack_pointer_rtx, + GEN_INT (- (HOST_WIDE_INT) frame_size), true); /* Allocate space for the outgoing args. If the stack frame has not already been set up then handle this as well. */ @@ -1389,29 +1440,26 @@ rx_expand_prologue (void) if (frame_size) { if (frame_pointer_needed) - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx, - GEN_INT (- (HOST_WIDE_INT) - stack_size))); + gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, + GEN_INT (- (HOST_WIDE_INT) stack_size), true); else - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (- (HOST_WIDE_INT) - (frame_size + stack_size)))); + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)), + true); } else - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (- (HOST_WIDE_INT) stack_size))); + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (- (HOST_WIDE_INT) stack_size), true); } else if (frame_size) { if (! frame_pointer_needed) - insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (- (HOST_WIDE_INT) frame_size))); + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (- (HOST_WIDE_INT) frame_size), true); else - insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); + gen_safe_add (stack_pointer_rtx, frame_pointer_rtx, NULL_RTX, + true); } - - if (insn != NULL_RTX) - RTX_FRAME_RELATED_P (insn) = 1; } static void @@ -1589,8 +1637,8 @@ rx_expand_epilogue (bool is_sibcall) { /* Cannot use the special instructions - deconstruct by hand. */ if (total_size) - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (total_size))); + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (total_size), false); if (MUST_SAVE_ACC_REGISTER) { @@ -1682,8 +1730,8 @@ rx_expand_epilogue (bool is_sibcall) return; } - emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (total_size))); + gen_safe_add (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (total_size), false); } if (low) @@ -2342,8 +2390,6 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED) bool rx_is_legitimate_constant (rtx x) { - HOST_WIDE_INT val; - switch (GET_CODE (x)) { case CONST: @@ -2366,7 +2412,9 @@ rx_is_legitimate_constant (rtx x) case SYMBOL_REF: return true; - /* One day we may have to handle UNSPEC constants here. */ + case UNSPEC: + return XINT (x, 1) == UNSPEC_CONST; + default: /* FIXME: Can this ever happen ? */ abort (); @@ -2386,17 +2434,7 @@ rx_is_legitimate_constant (rtx x) break; } - if (rx_max_constant_size == 0 || rx_max_constant_size == 4) - /* If there is no constraint on the size of constants - used as operands, then any value is legitimate. */ - return true; - - val = INTVAL (x); - - /* rx_max_constant_size specifies the maximum number - of bytes that can be used to hold a signed value. */ - return IN_RANGE (val, (-1 << (rx_max_constant_size * 8)), - ( 1 << (rx_max_constant_size * 8))); + return ok_for_max_constant (INTVAL (x)); } static int diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index d8cd66d..1ae42cb 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -1,5 +1,5 @@ ;; Machine Description for Renesas RX processors -;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +;; Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. ;; Contributed by Red Hat. ;; This file is part of GCC. @@ -50,6 +50,7 @@ (UNSPEC_RTE 10) (UNSPEC_RTFI 11) (UNSPEC_NAKED 12) + (UNSPEC_CONST 13) (UNSPEC_MOVSTR 20) (UNSPEC_MOVMEM 21) @@ -416,10 +417,12 @@ (set_attr "timings" "55")] ) +;; Unspec used so that the constant will not be invalid +;; if -mmax-constant-size has been specified. (define_insn "deallocate_and_return" [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 0 "immediate_operand" "i"))) + (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST)))) (return)] "" "rtsd\t%0" @@ -431,7 +434,8 @@ [(match_parallel 1 "rx_rtsd_vector" [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) - (match_operand:SI 0 "const_int_operand" "n")))])] + (match_operand:SI 0 "const_int_operand" "n")))]) + (return)] "reload_completed" { rx_emit_stack_popm (operands, false); @@ -481,14 +485,14 @@ if (! rx_call_operand (dest, Pmode)) dest = force_reg (Pmode, dest); - emit_call_insn (gen_call_internal (dest, operands[1])); + emit_call_insn (gen_call_internal (dest)); DONE; } ) (define_insn "call_internal" [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol")) - (match_operand:SI 1 "general_operand" "g,g")) + (const_int 0)) (clobber (reg:CC CC_REG))] "" "@ @@ -508,7 +512,7 @@ if (! rx_call_operand (dest, Pmode)) dest = force_reg (Pmode, dest); - emit_call_insn (gen_call_value_internal (operands[0], dest, operands[2])); + emit_call_insn (gen_call_value_internal (operands[0], dest)); DONE; } ) @@ -516,7 +520,7 @@ (define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=r,r") (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol")) - (match_operand:SI 2 "general_operand" "g,g"))) + (const_int 0))) (clobber (reg:CC CC_REG))] "" "@ @@ -540,12 +544,14 @@ { if (MEM_P (operands[0])) operands[0] = XEXP (operands[0], 0); + emit_call_insn (gen_sibcall_internal (operands[0])); + DONE; } ) (define_insn "sibcall_internal" [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol")) - (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) (return)] "" "bra\t%A0" @@ -563,13 +569,15 @@ { if (MEM_P (operands[1])) operands[1] = XEXP (operands[1], 0); + emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1])); + DONE; } ) (define_insn "sibcall_value_internal" [(set (match_operand 0 "register_operand" "=r") (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol")) - (match_operand:SI 2 "general_operand" "g"))) + (const_int 0))) (return)] "" "bra\t%A1" @@ -621,6 +629,9 @@ { if (MEM_P (operand0) && MEM_P (operand1)) operands[1] = copy_to_mode_reg (mode, operand1); + if (CONST_INT_P (operand1) + && ! rx_is_legitimate_constant (operand1)) + FAIL; } ) @@ -1110,6 +1121,22 @@ DONE; }) +;; A pattern to add an integer to a register, regardless of the +;; setting of the -mmax-constant-size command line switch. +;; See rx.c:gen_safe_add() for more details. +(define_insn "addsi3_unspec" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,r") + (const:SI (unspec:SI [(match_operand 2 "const_int_operand" "n,n")] UNSPEC_CONST)))) + (clobber (reg:CC CC_REG))] + "" + "@ + add\t%2, %0 + add\t%2, %1, %0" + [(set_attr "timings" "11") + (set_attr "length" "6")] +) + (define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")