Commit 15ba5696 by Nick Clifton Committed by Nick Clifton

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
parent 4618de23
2011-01-22 Nick Clifton <nickc@redhat.com>
* 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 <law@redhat.com> 2011-01-21 Jeff Law <law@redhat.com>
PR tree-optimization/47053 PR tree-optimization/47053
......
/* Subroutines used for code generation on Renesas RX processors. /* 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. Contributed by Red Hat.
This file is part of GCC. This file is part of GCC.
...@@ -323,10 +323,20 @@ rx_print_operand_address (FILE * file, rtx addr) ...@@ -323,10 +323,20 @@ rx_print_operand_address (FILE * file, rtx addr)
break; 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 LABEL_REF:
case SYMBOL_REF: case SYMBOL_REF:
case CONST:
fprintf (file, "#"); fprintf (file, "#");
default: default:
output_addr_const (file, addr); output_addr_const (file, addr);
break; break;
...@@ -1281,6 +1291,56 @@ mark_frame_related (rtx insn) ...@@ -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 void
rx_expand_prologue (void) rx_expand_prologue (void)
{ {
...@@ -1370,17 +1430,8 @@ rx_expand_prologue (void) ...@@ -1370,17 +1430,8 @@ rx_expand_prologue (void)
/* If needed, set up the frame pointer. */ /* If needed, set up the frame pointer. */
if (frame_pointer_needed) if (frame_pointer_needed)
{ gen_safe_add (frame_pointer_rtx, stack_pointer_rtx,
if (frame_size) GEN_INT (- (HOST_WIDE_INT) frame_size), true);
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;
/* Allocate space for the outgoing args. /* Allocate space for the outgoing args.
If the stack frame has not already been set up then handle this as well. */ If the stack frame has not already been set up then handle this as well. */
...@@ -1389,29 +1440,26 @@ rx_expand_prologue (void) ...@@ -1389,29 +1440,26 @@ rx_expand_prologue (void)
if (frame_size) if (frame_size)
{ {
if (frame_pointer_needed) if (frame_pointer_needed)
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx, gen_safe_add (stack_pointer_rtx, frame_pointer_rtx,
GEN_INT (- (HOST_WIDE_INT) GEN_INT (- (HOST_WIDE_INT) stack_size), true);
stack_size)));
else else
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- (HOST_WIDE_INT) GEN_INT (- (HOST_WIDE_INT) (frame_size + stack_size)),
(frame_size + stack_size)))); true);
} }
else else
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- (HOST_WIDE_INT) stack_size))); GEN_INT (- (HOST_WIDE_INT) stack_size), true);
} }
else if (frame_size) else if (frame_size)
{ {
if (! frame_pointer_needed) if (! frame_pointer_needed)
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- (HOST_WIDE_INT) frame_size))); GEN_INT (- (HOST_WIDE_INT) frame_size), true);
else 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 static void
...@@ -1589,8 +1637,8 @@ rx_expand_epilogue (bool is_sibcall) ...@@ -1589,8 +1637,8 @@ rx_expand_epilogue (bool is_sibcall)
{ {
/* Cannot use the special instructions - deconstruct by hand. */ /* Cannot use the special instructions - deconstruct by hand. */
if (total_size) if (total_size)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (total_size))); GEN_INT (total_size), false);
if (MUST_SAVE_ACC_REGISTER) if (MUST_SAVE_ACC_REGISTER)
{ {
...@@ -1682,8 +1730,8 @@ rx_expand_epilogue (bool is_sibcall) ...@@ -1682,8 +1730,8 @@ rx_expand_epilogue (bool is_sibcall)
return; return;
} }
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, gen_safe_add (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (total_size))); GEN_INT (total_size), false);
} }
if (low) if (low)
...@@ -2342,8 +2390,6 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED) ...@@ -2342,8 +2390,6 @@ rx_is_ms_bitfield_layout (const_tree record_type ATTRIBUTE_UNUSED)
bool bool
rx_is_legitimate_constant (rtx x) rx_is_legitimate_constant (rtx x)
{ {
HOST_WIDE_INT val;
switch (GET_CODE (x)) switch (GET_CODE (x))
{ {
case CONST: case CONST:
...@@ -2366,7 +2412,9 @@ rx_is_legitimate_constant (rtx x) ...@@ -2366,7 +2412,9 @@ rx_is_legitimate_constant (rtx x)
case SYMBOL_REF: case SYMBOL_REF:
return true; return true;
/* One day we may have to handle UNSPEC constants here. */ case UNSPEC:
return XINT (x, 1) == UNSPEC_CONST;
default: default:
/* FIXME: Can this ever happen ? */ /* FIXME: Can this ever happen ? */
abort (); abort ();
...@@ -2386,17 +2434,7 @@ rx_is_legitimate_constant (rtx x) ...@@ -2386,17 +2434,7 @@ rx_is_legitimate_constant (rtx x)
break; break;
} }
if (rx_max_constant_size == 0 || rx_max_constant_size == 4) return ok_for_max_constant (INTVAL (x));
/* 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)));
} }
static int static int
......
;; Machine Description for Renesas RX processors ;; 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. ;; Contributed by Red Hat.
;; This file is part of GCC. ;; This file is part of GCC.
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
(UNSPEC_RTE 10) (UNSPEC_RTE 10)
(UNSPEC_RTFI 11) (UNSPEC_RTFI 11)
(UNSPEC_NAKED 12) (UNSPEC_NAKED 12)
(UNSPEC_CONST 13)
(UNSPEC_MOVSTR 20) (UNSPEC_MOVSTR 20)
(UNSPEC_MOVMEM 21) (UNSPEC_MOVMEM 21)
...@@ -416,10 +417,12 @@ ...@@ -416,10 +417,12 @@
(set_attr "timings" "55")] (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" (define_insn "deallocate_and_return"
[(set (reg:SI SP_REG) [(set (reg:SI SP_REG)
(plus:SI (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)] (return)]
"" ""
"rtsd\t%0" "rtsd\t%0"
...@@ -431,7 +434,8 @@ ...@@ -431,7 +434,8 @@
[(match_parallel 1 "rx_rtsd_vector" [(match_parallel 1 "rx_rtsd_vector"
[(set (reg:SI SP_REG) [(set (reg:SI SP_REG)
(plus:SI (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" "reload_completed"
{ {
rx_emit_stack_popm (operands, false); rx_emit_stack_popm (operands, false);
...@@ -481,14 +485,14 @@ ...@@ -481,14 +485,14 @@
if (! rx_call_operand (dest, Pmode)) if (! rx_call_operand (dest, Pmode))
dest = force_reg (Pmode, dest); dest = force_reg (Pmode, dest);
emit_call_insn (gen_call_internal (dest, operands[1])); emit_call_insn (gen_call_internal (dest));
DONE; DONE;
} }
) )
(define_insn "call_internal" (define_insn "call_internal"
[(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol")) [(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))] (clobber (reg:CC CC_REG))]
"" ""
"@ "@
...@@ -508,7 +512,7 @@ ...@@ -508,7 +512,7 @@
if (! rx_call_operand (dest, Pmode)) if (! rx_call_operand (dest, Pmode))
dest = force_reg (Pmode, dest); 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; DONE;
} }
) )
...@@ -516,7 +520,7 @@ ...@@ -516,7 +520,7 @@
(define_insn "call_value_internal" (define_insn "call_value_internal"
[(set (match_operand 0 "register_operand" "=r,r") [(set (match_operand 0 "register_operand" "=r,r")
(call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol")) (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))] (clobber (reg:CC CC_REG))]
"" ""
"@ "@
...@@ -540,12 +544,14 @@ ...@@ -540,12 +544,14 @@
{ {
if (MEM_P (operands[0])) if (MEM_P (operands[0]))
operands[0] = XEXP (operands[0], 0); operands[0] = XEXP (operands[0], 0);
emit_call_insn (gen_sibcall_internal (operands[0]));
DONE;
} }
) )
(define_insn "sibcall_internal" (define_insn "sibcall_internal"
[(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol")) [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
(match_operand:SI 1 "general_operand" "g")) (const_int 0))
(return)] (return)]
"" ""
"bra\t%A0" "bra\t%A0"
...@@ -563,13 +569,15 @@ ...@@ -563,13 +569,15 @@
{ {
if (MEM_P (operands[1])) if (MEM_P (operands[1]))
operands[1] = XEXP (operands[1], 0); operands[1] = XEXP (operands[1], 0);
emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
DONE;
} }
) )
(define_insn "sibcall_value_internal" (define_insn "sibcall_value_internal"
[(set (match_operand 0 "register_operand" "=r") [(set (match_operand 0 "register_operand" "=r")
(call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol")) (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
(match_operand:SI 2 "general_operand" "g"))) (const_int 0)))
(return)] (return)]
"" ""
"bra\t%A1" "bra\t%A1"
...@@ -621,6 +629,9 @@ ...@@ -621,6 +629,9 @@
{ {
if (MEM_P (operand0) && MEM_P (operand1)) if (MEM_P (operand0) && MEM_P (operand1))
operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1); operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
if (CONST_INT_P (operand1)
&& ! rx_is_legitimate_constant (operand1))
FAIL;
} }
) )
...@@ -1110,6 +1121,22 @@ ...@@ -1110,6 +1121,22 @@
DONE; 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" (define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") [(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") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
......
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