[patches] Re: x86_64 merger part 17 - split-long-move update
Jan Hubicka
jh@suse.cz
Wed Mar 21 02:31:00 GMT 2001
>
> I'd prefer you used change_address instead of PUT_MODE throughout.
> I know that existing code in this function does it, but I don't
> like that either.
>
> Again, please use UNITS_PER_WORD. It's more concise than the
> explicit conditional, and it documents exactly what you want.
>
> > + /* In 64bit mode we don't have 32bit push available. In case this is
> > + register, it is OK - we will just use larger counterpart. We also
> > + retype memory - these comes from attempt to avoid REX prefix on
> > + moving of second half of TFmode value. */
> > + if (TARGET_64BIT && GET_MODE (part[1][1]) == SImode)
>
> This part is confusingly arranged with multiple tests for TARGET_64BIT.
>
> > [(const_int 0)]
> > ! "ix86_split_long_move (operands);")
>
> You've lost the DONE.
Hi
I am just testing following updated version of the patch. OK assuming
that it passes bootstrap/testsuite?
Wed Mar 14 18:51:04 CET 2001 Jan Hubicka <jh@suse.cz>
* i386-protos.h (ix86_split_long_move): Return void.
* i386.c (ix86_split_to_parts): Handle 64bit target.
(ix86_split_long_move): Likewise.
* i386.md (all calls to ix86_split_long_move): Update.
Index: i386-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386-protos.h,v
retrieving revision 1.46
diff -c -3 -p -r1.46 i386-protos.h
*** i386-protos.h 2001/03/21 10:12:19 1.46
--- i386-protos.h 2001/03/21 10:26:50
*************** extern void ix86_expand_branch PARAMS ((
*** 115,121 ****
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 int ix86_split_long_move PARAMS ((rtx[]));
extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
--- 115,121 ----
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_split_long_move PARAMS ((rtx[]));
extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
Index: i386.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.237
diff -c -3 -p -r1.237 i386.c
*** i386.c 2001/03/21 10:12:19 1.237
--- i386.c 2001/03/21 10:27:01
*************** ix86_split_to_parts (operand, parts, mod
*** 6579,6588 ****
if (! push_operand (operand, VOIDmode))
abort ();
! PUT_MODE (operand, SImode);
parts[0] = parts[1] = parts[2] = operand;
}
! else
{
if (mode == DImode)
split_di (&operand, 1, &parts[0], &parts[1]);
--- 6579,6588 ----
if (! push_operand (operand, VOIDmode))
abort ();
! operand = change_address (operand, SImode, operand);
parts[0] = parts[1] = parts[2] = operand;
}
! else if (!TARGET_64BIT)
{
if (mode == DImode)
split_di (&operand, 1, &parts[0], &parts[1]);
*************** ix86_split_to_parts (operand, parts, mod
*** 6599,6605 ****
}
else if (offsettable_memref_p (operand))
{
! PUT_MODE (operand, SImode);
parts[0] = operand;
parts[1] = adj_offsettable_operand (operand, 4);
if (size == 3)
--- 6599,6605 ----
}
else if (offsettable_memref_p (operand))
{
! operand = change_address (operand, SImode, operand);
parts[0] = operand;
parts[1] = adj_offsettable_operand (operand, 4);
if (size == 3)
*************** ix86_split_to_parts (operand, parts, mod
*** 6631,6636 ****
--- 6631,6672 ----
abort ();
}
}
+ else
+ {
+ if (mode == XFmode || mode == TFmode)
+ {
+ if (REG_P (operand))
+ {
+ if (!reload_completed)
+ abort ();
+ parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
+ parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
+ }
+ else if (offsettable_memref_p (operand))
+ {
+ operand = change_address (operand, DImode, operand);
+ parts[0] = operand;
+ parts[1] = adj_offsettable_operand (operand, 8);
+ parts[1] = change_address (parts[1], SImode, operand);
+ }
+ else if (GET_CODE (operand) == CONST_DOUBLE)
+ {
+ REAL_VALUE_TYPE r;
+ long l[3];
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
+ #if HOST_BITS_PER_WIDE_INT >= 64
+ parts[0] = GEN_INT (l[0] + (l[1] << 32));
+ #else
+ parts[0] = immed_double_const (l[0], l[1], DImode);
+ #endif
+ parts[1] = GEN_INT (l[2]);
+ }
+ else
+ abort ();
+ }
+ }
return size;
}
*************** ix86_split_to_parts (operand, parts, mod
*** 6640,6655 ****
insns have been emitted. Operands 2-4 contain the input values
int the correct order; operands 5-7 contain the output values. */
! int
ix86_split_long_move (operands1)
rtx operands1[];
{
rtx part[2][3];
rtx operands[2];
! int size;
int push = 0;
int collisions = 0;
/* Make our own copy to avoid clobbering the operands. */
operands[0] = copy_rtx (operands1[0]);
operands[1] = copy_rtx (operands1[1]);
--- 6676,6717 ----
insns have been emitted. Operands 2-4 contain the input values
int the correct order; operands 5-7 contain the output values. */
! void
ix86_split_long_move (operands1)
rtx operands1[];
{
rtx part[2][3];
rtx operands[2];
! int nparts;
int push = 0;
int collisions = 0;
+ /* The DFmode expanders may ask us to move double.
+ For 64bit target this is single move. By hiding the fact
+ here we simplify i386.md splitters. */
+ if (GET_MODE_SIZE (GET_MODE (operands1[0])) == 8 && TARGET_64BIT)
+ {
+ /* Optimize constant pool reference to immediates. This is used by fp moves,
+ that force all constants to memory to allow combining. */
+
+ if (GET_CODE (operands1[1]) == MEM
+ && GET_CODE (XEXP (operands1[1], 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands1[1], 0)))
+ operands[1] = get_pool_constant (XEXP (operands1[1], 0));
+ else
+ operands[1] = operands1[1];
+ if (push_operand (operands1[0], VOIDmode))
+ {
+ operands[0] = copy_rtx (operands1[0]);
+ operands[0] = change_address (operands[0], DImode, operands[0]);
+ }
+ else
+ operands[0] = gen_lowpart (DImode, operands1[0]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ emit_move_insn (operands[0], operands[1]);
+ return;
+ }
+
/* Make our own copy to avoid clobbering the operands. */
operands[0] = copy_rtx (operands1[0]);
operands[1] = copy_rtx (operands1[1]);
*************** ix86_split_long_move (operands1)
*** 6661,6674 ****
&& ! offsettable_memref_p (operands[0]))
abort ();
! size = ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
! ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
/* When emitting push, take care for source operands on the stack. */
if (push && GET_CODE (operands[1]) == MEM
&& reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
{
! if (size == 3)
part[1][1] = part[1][2];
part[1][0] = part[1][1];
}
--- 6723,6736 ----
&& ! offsettable_memref_p (operands[0]))
abort ();
! nparts = ix86_split_to_parts (operands[1], part[1], GET_MODE (operands1[0]));
! ix86_split_to_parts (operands[0], part[0], GET_MODE (operands1[0]));
/* When emitting push, take care for source operands on the stack. */
if (push && GET_CODE (operands[1]) == MEM
&& reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
{
! if (nparts == 3)
part[1][1] = part[1][2];
part[1][0] = part[1][1];
}
*************** ix86_split_long_move (operands1)
*** 6681,6692 ****
collisions++;
if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
collisions++;
! if (size == 3
&& reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
collisions++;
/* Collision in the middle part can be handled by reordering. */
! if (collisions == 1 && size == 3
&& reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
{
rtx tmp;
--- 6743,6754 ----
collisions++;
if (reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
collisions++;
! if (nparts == 3
&& reg_overlap_mentioned_p (part[0][2], XEXP (part[1][0], 0)))
collisions++;
/* Collision in the middle part can be handled by reordering. */
! if (collisions == 1 && nparts == 3
&& reg_overlap_mentioned_p (part[0][1], XEXP (part[1][0], 0)))
{
rtx tmp;
*************** ix86_split_long_move (operands1)
*** 6699,6740 ****
else if (collisions > 1)
{
collisions = 1;
! emit_insn (gen_rtx_SET (VOIDmode, part[0][size - 1],
XEXP (part[1][0], 0)));
! part[1][0] = change_address (part[1][0], SImode, part[0][size - 1]);
! part[1][1] = adj_offsettable_operand (part[1][0], 4);
! if (size == 3)
part[1][2] = adj_offsettable_operand (part[1][0], 8);
}
}
if (push)
{
! if (size == 3)
{
! /* We use only first 12 bytes of TFmode value, but for pushing we
! are required to adjust stack as if we were pushing real 16byte
! value. */
! if (GET_MODE (operands1[0]) == TFmode)
! emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! GEN_INT (-4)));
! emit_insn (gen_push (part[1][2]));
}
emit_insn (gen_push (part[1][1]));
emit_insn (gen_push (part[1][0]));
! return 1;
}
/* Choose correct order to not overwrite the source before it is copied. */
if ((REG_P (part[0][0])
&& REG_P (part[1][1])
&& (REGNO (part[0][0]) == REGNO (part[1][1])
! || (size == 3
&& REGNO (part[0][0]) == REGNO (part[1][2]))))
|| (collisions > 0
&& reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
{
! if (size == 3)
{
operands1[2] = part[0][2];
operands1[3] = part[0][1];
--- 6761,6825 ----
else if (collisions > 1)
{
collisions = 1;
! emit_insn (gen_rtx_SET (VOIDmode, part[0][nparts - 1],
XEXP (part[1][0], 0)));
! part[1][0] = change_address (part[1][0],
! TARGET_64BIT ? DImode : SImode,
! part[0][nparts - 1]);
! part[1][1] = adj_offsettable_operand (part[1][0],
! UNITS_PER_WORD);
! part[1][1] = change_address (part[1][1], SImode, part[1][1]);
! if (nparts == 3)
part[1][2] = adj_offsettable_operand (part[1][0], 8);
}
}
if (push)
{
! if (!TARGET_64BIT)
! {
! if (nparts == 3)
! {
! /* We use only first 12 bytes of TFmode value, but for pushing we
! are required to adjust stack as if we were pushing real 16byte
! value. */
! if (GET_MODE (operands1[0]) == TFmode && !TARGET_64BIT)
! emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
! GEN_INT (-4)));
! emit_insn (gen_push (part[1][2]));
! }
! }
! else
{
! /* In 64bit mode we don't have 32bit push available. In case this is
! register, it is OK - we will just use larger counterpart. We also
! retype memory - these comes from attempt to avoid REX prefix on
! moving of second half of TFmode value. */
! if (GET_MODE (part[1][1]) == SImode)
! {
! if (GET_CODE (part[1][1]) == MEM)
! part[1][1] = change_address (part[1][1], DImode, part[1][1]);
! else if (REG_P (part[1][1]))
! part[1][1] = gen_rtx_REG (DImode, REGNO (part[1][1]));
! else
! abort();
! }
}
emit_insn (gen_push (part[1][1]));
emit_insn (gen_push (part[1][0]));
! return;
}
/* Choose correct order to not overwrite the source before it is copied. */
if ((REG_P (part[0][0])
&& REG_P (part[1][1])
&& (REGNO (part[0][0]) == REGNO (part[1][1])
! || (nparts == 3
&& REGNO (part[0][0]) == REGNO (part[1][2]))))
|| (collisions > 0
&& reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))))
{
! if (nparts == 3)
{
operands1[2] = part[0][2];
operands1[3] = part[0][1];
*************** ix86_split_long_move (operands1)
*** 6753,6759 ****
}
else
{
! if (size == 3)
{
operands1[2] = part[0][0];
operands1[3] = part[0][1];
--- 6838,6844 ----
}
else
{
! if (nparts == 3)
{
operands1[2] = part[0][0];
operands1[3] = part[0][1];
*************** ix86_split_long_move (operands1)
*** 6770,6777 ****
operands1[6] = part[1][1];
}
}
! return 0;
}
void
--- 6855,6873 ----
operands1[6] = part[1][1];
}
}
+ if (nparts == 3)
+ {
+ emit_move_insn (operands1[2], operands1[5]);
+ emit_move_insn (operands1[3], operands1[6]);
+ emit_move_insn (operands1[4], operands1[7]);
+ }
+ else
+ {
+ emit_move_insn (operands1[2], operands1[5]);
+ emit_move_insn (operands1[3], operands1[6]);
+ }
! return;
}
void
Index: i386.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.240
diff -c -3 -p -r1.240 i386.md
*** i386.md 2001/03/21 10:12:20 1.240
--- i386.md 2001/03/21 10:27:17
***************
*** 2177,2192 ****
(match_operand:DI 1 "general_operand" ""))]
"reload_completed && ! MMX_REG_P (operands[1]) && !TARGET_64BIT"
[(const_int 0)]
! "if (!ix86_split_long_move (operands)) abort (); DONE;")
;; %%% This multiword shite has got to go.
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"reload_completed && ! MMX_REG_P (operands[0]) && ! MMX_REG_P (operands[1])"
! [(set (match_dup 2) (match_dup 5))
! (set (match_dup 3) (match_dup 6))]
! "if (ix86_split_long_move (operands)) DONE;")
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
--- 2177,2191 ----
(match_operand:DI 1 "general_operand" ""))]
"reload_completed && ! MMX_REG_P (operands[1]) && !TARGET_64BIT"
[(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
;; %%% This multiword shite has got to go.
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"reload_completed && ! MMX_REG_P (operands[0]) && ! MMX_REG_P (operands[1])"
! [(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
(define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "")
***************
*** 2401,2407 ****
(match_operand:DF 1 "general_operand" ""))]
"reload_completed"
[(const_int 0)]
! "if (!ix86_split_long_move (operands)) abort (); DONE;")
;; Moving is usually shorter when only FP registers are used. This separate
;; movdf pattern avoids the use of integer registers for FP operations
--- 2400,2406 ----
(match_operand:DF 1 "general_operand" ""))]
"reload_completed"
[(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
;; Moving is usually shorter when only FP registers are used. This separate
;; movdf pattern avoids the use of integer registers for FP operations
***************
*** 2535,2543 ****
&& ! (ANY_FP_REG_P (operands[1]) ||
(GET_CODE (operands[1]) == SUBREG
&& ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
! [(set (match_dup 2) (match_dup 5))
! (set (match_dup 3) (match_dup 6))]
! "if (ix86_split_long_move (operands)) DONE;")
(define_insn "*swapdf"
[(set (match_operand:DF 0 "register_operand" "+f")
--- 2534,2541 ----
&& ! (ANY_FP_REG_P (operands[1]) ||
(GET_CODE (operands[1]) == SUBREG
&& ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
! [(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
(define_insn "*swapdf"
[(set (match_operand:DF 0 "register_operand" "+f")
***************
*** 2697,2703 ****
|| GET_MODE (operands[0]) == DFmode)
&& (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
[(const_int 0)]
! "if (!ix86_split_long_move (operands)) abort (); DONE;")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
--- 2695,2701 ----
|| GET_MODE (operands[0]) == DFmode)
&& (!REG_P (operands[1]) || !ANY_FP_REGNO_P (REGNO (operands[1])))"
[(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
(define_split
[(set (match_operand:XF 0 "push_operand" "")
***************
*** 2916,2925 ****
&& ! (ANY_FP_REG_P (operands[1]) ||
(GET_CODE (operands[1]) == SUBREG
&& ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
! [(set (match_dup 2) (match_dup 5))
! (set (match_dup 3) (match_dup 6))
! (set (match_dup 4) (match_dup 7))]
! "if (ix86_split_long_move (operands)) DONE;")
(define_split
[(set (match_operand 0 "register_operand" "")
--- 2914,2921 ----
&& ! (ANY_FP_REG_P (operands[1]) ||
(GET_CODE (operands[1]) == SUBREG
&& ANY_FP_REG_P (SUBREG_REG (operands[1]))))"
! [(const_int 0)]
! "ix86_split_long_move (operands); DONE;")
(define_split
[(set (match_operand 0 "register_operand" "")
More information about the Gcc-patches
mailing list