aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/frv/frv.md
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2004-05-02 04:57:47 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2004-05-02 04:57:47 +0000
commit764678d17d7e22a3b5d087b3f3e1d9a518df9a22 (patch)
tree1d04e1233f03f836fa8708f2a315b1ba2834a01c /gcc/config/frv/frv.md
parentafbe7e61febc8df565418161787af714550c8244 (diff)
downloadgcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.zip
gcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.tar.gz
gcc-764678d17d7e22a3b5d087b3f3e1d9a518df9a22.tar.bz2
frv-protos.h (frv_expand_epilogue, [...]): Add bool argument.
* config/frv/frv-protos.h (frv_expand_epilogue, frv_expand_fdpic_call): Add bool argument. * config/frv/frv.c (frv_function_ok_for_sibcall): New. (TARGET_FUNCTION_OK_FOR_SIBCALL): Define to it. (frv_expand_epilogue): Use new argument to decide whether to emit return instruction or copy the return address to LR. (frv_expand_fdpic_call): Inline PLT entry when emitting direct sibcalls. (sibcall_operand): New. * config/frv/frv.h (PREDICATE_CODES): call_operand doesn't match PLUS nor LABEL_REF. Add sibcall_operand. * config/frv/frv.md (call, call_value): Pass false to frv_expand_fdpic_call. (call_fdpicdi, call_value_fdpicdi): Insert %i0 in calll. (sibcall, sibcall_internal, sibcall_fdpicdi, sibcall_value, sibcall_value_internal, sibcall_value_fdpicdi): New. (return_unsigned_true, return_unsigned_false): New. (epilogue): Adjust call to frv_expand_epilogue. (sibcall_epilogue): New. From-SVN: r81405
Diffstat (limited to 'gcc/config/frv/frv.md')
-rw-r--r--gcc/config/frv/frv.md145
1 files changed, 139 insertions, 6 deletions
diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md
index 20170bd..36b6d8e 100644
--- a/gcc/config/frv/frv.md
+++ b/gcc/config/frv/frv.md
@@ -5260,7 +5260,7 @@
operands[2] = const0_rtx;
if (TARGET_FDPIC)
- frv_expand_fdpic_call (operands, 0);
+ frv_expand_fdpic_call (operands, false, false);
else
emit_call_insn (gen_call_internal (addr, operands[1], operands[2], lr));
@@ -5308,7 +5308,7 @@
(match_operand 1 "" ""))
(clobber (match_operand:SI 2 "lr_operand" "=l"))]
"TARGET_FDPIC"
- "calll %M0"
+ "call%i0l %M0"
[(set_attr "length" "4")
(set_attr "type" "jumpl")])
@@ -5325,6 +5325,65 @@
[(set_attr "length" "4")
(set_attr "type" "call,jumpl")])
+(define_expand "sibcall"
+ [(use (match_operand:QI 0 "" ""))
+ (use (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))]
+ ""
+ "
+{
+ rtx addr;
+
+ if (GET_CODE (operands[0]) != MEM)
+ abort ();
+
+ addr = XEXP (operands[0], 0);
+ if (! sibcall_operand (addr, Pmode))
+ addr = force_reg (Pmode, addr);
+
+ if (! operands[2])
+ operands[2] = const0_rtx;
+
+ if (TARGET_FDPIC)
+ frv_expand_fdpic_call (operands, false, true);
+ else
+ emit_call_insn (gen_sibcall_internal (addr, operands[1], operands[2]));
+
+ DONE;
+}")
+
+;; It might seem that these sibcall patterns are missing references to
+;; LR, but they're not necessary because sibcall_epilogue will make
+;; sure LR is restored, and having LR here will set
+;; regs_ever_used[REG_LR], forcing it to be saved on the stack, and
+;; then restored in sibcalls and regular return code paths, even if
+;; the function becomes a leaf function after tail-call elimination.
+
+;; We must not use a call-saved register here. `W' limits ourselves
+;; to gr14 or gr15, but since we're almost running out of constraint
+;; letters, and most other call-clobbered registers are often used for
+;; argument-passing, this will do.
+(define_insn "sibcall_internal"
+ [(call (mem:QI (match_operand:SI 0 "sibcall_operand" "WNOP"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (return)]
+ "! TARGET_FDPIC"
+ "jmp%i0l %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl")])
+
+(define_insn "sibcall_fdpicdi"
+ [(call (mem:QI (match_operand:DI 0 "fdpic_fptr_operand" "W"))
+ (match_operand 1 "" ""))
+ (return)]
+ "TARGET_FDPIC"
+ "jmp%i0l %M0"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl")])
+
+
;; Subroutine call instruction returning a value. Operand 0 is the hard
;; register in which the value is returned. There are three more operands, the
;; same as the three operands of the `call' instruction (but with numbers
@@ -5355,7 +5414,7 @@
operands[3] = const0_rtx;
if (TARGET_FDPIC)
- frv_expand_fdpic_call (operands, 1);
+ frv_expand_fdpic_call (operands, true, false);
else
emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2],
operands[3], lr));
@@ -5382,7 +5441,7 @@
(match_operand 2 "" "")))
(clobber (match_operand:SI 3 "lr_operand" "=l"))]
"TARGET_FDPIC"
- "calll %M1"
+ "call%i1l %M1"
[(set_attr "length" "4")
(set_attr "type" "jumpl")])
@@ -5400,6 +5459,56 @@
[(set_attr "length" "4")
(set_attr "type" "call,jumpl")])
+(define_expand "sibcall_value"
+ [(use (match_operand 0 "" ""))
+ (use (match_operand:QI 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))]
+ ""
+ "
+{
+ rtx addr;
+
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
+
+ addr = XEXP (operands[1], 0);
+ if (! sibcall_operand (addr, Pmode))
+ addr = force_reg (Pmode, addr);
+
+ if (! operands[3])
+ operands[3] = const0_rtx;
+
+ if (TARGET_FDPIC)
+ frv_expand_fdpic_call (operands, true, true);
+ else
+ emit_call_insn (gen_sibcall_value_internal (operands[0], addr, operands[2],
+ operands[3]));
+ DONE;
+}")
+
+(define_insn "sibcall_value_internal"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:QI (match_operand:SI 1 "sibcall_operand" "WNOP"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (return)]
+ "! TARGET_FDPIC"
+ "jmp%i1l %M1"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl")])
+
+(define_insn "sibcall_value_fdpicdi"
+ [(set (match_operand 0 "register_operand" "=d")
+ (call (mem:QI (match_operand:DI 1 "fdpic_fptr_operand" "W"))
+ (match_operand 2 "" "")))
+ (return)]
+ "TARGET_FDPIC"
+ "jmp%i1l %M1"
+ [(set_attr "length" "4")
+ (set_attr "type" "jumpl")])
+
;; return instruction generated instead of jmp to epilog
(define_expand "return"
[(parallel [(return)
@@ -5430,6 +5539,30 @@
[(set_attr "length" "4")
(set_attr "type" "jump,jumpl")])
+(define_insn "*return_unsigned_true"
+ [(set (pc)
+ (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (return)
+ (pc)))]
+ "direct_return_p ()"
+ "b%c0lr %1,%#"
+ [(set_attr "length" "4")
+ (set_attr "type" "jump")])
+
+(define_insn "*return_unsigned_false"
+ [(set (pc)
+ (if_then_else (match_operator:CC_UNS 0 "unsigned_relational_operator"
+ [(match_operand 1 "icc_operand" "t")
+ (const_int 0)])
+ (pc)
+ (return)))]
+ "direct_return_p ()"
+ "b%C0lr %1,%#"
+ [(set_attr "length" "4")
+ (set_attr "type" "jump")])
+
;; A version of addsi3 for deallocating stack space at the end of the
;; epilogue. The addition is done in parallel with an (unspec_volatile),
;; which represents the clobbering of the deallocated space.
@@ -5634,7 +5767,7 @@
""
"
{
- frv_expand_epilogue (FALSE);
+ frv_expand_epilogue (true);
DONE;
}")
@@ -5650,7 +5783,7 @@
""
"
{
- frv_expand_epilogue (TRUE);
+ frv_expand_epilogue (false);
DONE;
}")