This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
clean up x86 call patterns
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 May 2002 22:22:47 -0700
- Subject: clean up x86 call patterns
Pulls out all the duplicated code into an external function.
Adds %ebx to CALL_INSN_FUNCTION_USAGE when it's used by the
PLT thunk. The reason will become apparent in the next patch;
for now it has no effect.
r~
* config/i386/i386.c (ix86_expand_call): New function, extracted
from md call patterns. Add pic_offset_table_rtx to
CALL_INSN_FUNCTION_USAGE when needed.
* config/i386/i386.md (call_pop, call): Use ix86_expand_call.
(call_value_pop, call_value, untyped_call): Likewise.
(call_exp, call_value_exp): Remove.
* config/i386/i386-protos.h: Update.
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.71
diff -c -p -d -r1.71 i386-protos.h
*** config/i386/i386-protos.h 19 May 2002 08:31:50 -0000 1.71
--- config/i386/i386-protos.h 23 May 2002 05:15:57 -0000
*************** extern void ix86_expand_branch PARAMS ((
*** 121,126 ****
--- 121,127 ----
extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
extern int ix86_expand_int_movcc PARAMS ((rtx[]));
extern int ix86_expand_fp_movcc PARAMS ((rtx[]));
+ extern void ix86_expand_call PARAMS ((rtx, rtx, rtx, rtx, rtx));
extern void x86_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern rtx ix86_zero_extend_to_Pmode PARAMS ((rtx));
extern void ix86_split_long_move PARAMS ((rtx[]));
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.403
diff -c -p -d -r1.403 i386.c
*** config/i386/i386.c 21 May 2002 23:51:59 -0000 1.403
--- config/i386/i386.c 23 May 2002 05:15:57 -0000
*************** ix86_expand_strlensi_unroll_1 (out, alig
*** 9850,9855 ****
--- 9850,9904 ----
emit_label (end_0_label);
}
+
+ void
+ ix86_expand_call (retval, fnaddr, callarg1, callarg2, pop)
+ rtx retval, fnaddr, callarg1, callarg2, pop;
+ {
+ rtx use = NULL, call;
+
+ if (pop == const0_rtx)
+ pop = NULL;
+ if (TARGET_64BIT && pop)
+ abort ();
+
+ /* Static functions and indirect calls don't need the pic register. */
+ if (! TARGET_64BIT && flag_pic
+ && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
+ && ! SYMBOL_REF_FLAG (XEXP (fnaddr, 0)))
+ {
+ current_function_uses_pic_offset_table = 1;
+ use_reg (&use, pic_offset_table_rtx);
+ }
+
+ if (TARGET_64BIT && INTVAL (callarg2) >= 0)
+ {
+ rtx al = gen_rtx_REG (QImode, 0);
+ emit_move_insn (al, callarg2);
+ use_reg (&use, al);
+ }
+
+ if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
+ {
+ fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
+ fnaddr = gen_rtx_MEM (QImode, fnaddr);
+ }
+
+ call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
+ if (retval)
+ call = gen_rtx_SET (VOIDmode, retval, call);
+ if (pop)
+ {
+ pop = gen_rtx_PLUS (Pmode, stack_pointer_rtx, pop);
+ pop = gen_rtx_SET (VOIDmode, stack_pointer_rtx, pop);
+ call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, call, pop));
+ }
+
+ call = emit_call_insn (call);
+ if (use)
+ CALL_INSN_FUNCTION_USAGE (call) = use;
+ }
+
/* Clear stack slot assignments remembered from previous functions.
This is called from INIT_EXPANDERS once before RTL is emitted for each
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.362
diff -c -p -d -r1.362 i386.md
*** config/i386/i386.md 18 May 2002 22:26:33 -0000 1.362
--- config/i386/i386.md 23 May 2002 05:15:57 -0000
***************
*** 12891,12911 ****
(match_operand:SI 3 "" "")))])]
"!TARGET_64BIT"
{
! if (operands[3] == const0_rtx)
! {
! emit_insn (gen_call (operands[0], operands[1], constm1_rtx));
! DONE;
! }
! /* Static functions and indirect calls don't need
! current_function_uses_pic_offset_table. */
! if (flag_pic
! && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
! && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
! current_function_uses_pic_offset_table = 1;
! if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
! XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
! if (TARGET_64BIT)
! abort();
})
(define_insn "*call_pop_0"
--- 12891,12898 ----
(match_operand:SI 3 "" "")))])]
"!TARGET_64BIT"
{
! ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]);
! DONE;
})
(define_insn "*call_pop_0"
***************
*** 12947,12983 ****
[(call (match_operand:QI 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))]
- ;; Operand 1 not used on the i386.
""
{
! rtx insn;
! /* Static functions and indirect calls don't need
! current_function_uses_pic_offset_table. */
! if (flag_pic
! && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
! && ! SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
! current_function_uses_pic_offset_table = 1;
!
! if (! call_insn_operand (XEXP (operands[0], 0), Pmode))
! XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
! if (TARGET_64BIT && INTVAL (operands[2]) >= 0)
! {
! rtx reg = gen_rtx_REG (QImode, 0);
! emit_move_insn (reg, operands[2]);
! insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
! use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
! DONE;
! }
! insn = emit_call_insn (gen_call_exp (operands[0], operands[1]));
! DONE;
})
- (define_expand "call_exp"
- [(call (match_operand:QI 0 "" "")
- (match_operand 1 "" ""))]
- ""
- "")
-
(define_insn "*call_0"
[(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
(match_operand 1 "" ""))]
--- 12934,12945 ----
[(call (match_operand:QI 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))]
""
{
! ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL);
! DONE;
})
(define_insn "*call_0"
[(call (mem:QI (match_operand 0 "constant_call_address_operand" ""))
(match_operand 1 "" ""))]
***************
*** 13029,13035 ****
[(set_attr "type" "call")])
;; Call subroutine, returning value in operand 0
- ;; (which must be a hard register).
(define_expand "call_value_pop"
[(parallel [(set (match_operand 0 "" "")
--- 12991,12996 ----
***************
*** 13040,13059 ****
(match_operand:SI 4 "" "")))])]
"!TARGET_64BIT"
{
! if (operands[4] == const0_rtx)
! {
! emit_insn (gen_call_value (operands[0], operands[1], operands[2],
! constm1_rtx));
! DONE;
! }
! /* Static functions and indirect calls don't need
! current_function_uses_pic_offset_table. */
! if (flag_pic
! && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
! && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
! current_function_uses_pic_offset_table = 1;
! if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
! XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
})
(define_expand "call_value"
--- 13001,13009 ----
(match_operand:SI 4 "" "")))])]
"!TARGET_64BIT"
{
! ix86_expand_call (operands[0], operands[1], operands[2],
! operands[3], operands[4]);
! DONE;
})
(define_expand "call_value"
***************
*** 13064,13099 ****
;; Operand 2 not used on the i386.
""
{
! rtx insn;
! /* Static functions and indirect calls don't need
! current_function_uses_pic_offset_table. */
! if (flag_pic
! && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
! && ! SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
! current_function_uses_pic_offset_table = 1;
! if (! call_insn_operand (XEXP (operands[1], 0), Pmode))
! XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
! if (TARGET_64BIT && INTVAL (operands[3]) >= 0)
! {
! rtx reg = gen_rtx_REG (QImode, 0);
! emit_move_insn (reg, operands[3]);
! insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
! operands[2]));
! use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
! DONE;
! }
! insn = emit_call_insn (gen_call_value_exp (operands[0], operands[1],
! operands[2]));
DONE;
})
- (define_expand "call_value_exp"
- [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "" "")
- (match_operand:SI 2 "" "")))]
- ""
- "")
-
;; Call subroutine returning any type.
(define_expand "untyped_call"
--- 13014,13023 ----
;; Operand 2 not used on the i386.
""
{
! ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL);
DONE;
})
;; Call subroutine returning any type.
(define_expand "untyped_call"
***************
*** 13110,13121 ****
simply pretend the untyped call returns a complex long double
value. */
! emit_call_insn (TARGET_FLOAT_RETURNS_IN_80387
! ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
! operands[0], const0_rtx,
! GEN_INT (SSE_REGPARM_MAX - 1))
! : gen_call (operands[0], const0_rtx,
! GEN_INT (SSE_REGPARM_MAX - 1)));
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
--- 13034,13043 ----
simply pretend the untyped call returns a complex long double
value. */
! ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387
! ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL),
! operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1),
! NULL);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{