diff options
author | Jan Hubicka <hubicka@freesoft.cz> | 1999-11-18 20:10:44 +0100 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1999-11-18 11:10:44 -0800 |
commit | 2450a057297b5bf665b98e9594ac6799c8a7e5fb (patch) | |
tree | 33ca9fa73edbb3730b350af5f3ed0a6b7c85eccf /gcc | |
parent | 4a6ef811c845111d1988d027ec7c5fd3e787fdd3 (diff) | |
download | gcc-2450a057297b5bf665b98e9594ac6799c8a7e5fb.zip gcc-2450a057297b5bf665b98e9594ac6799c8a7e5fb.tar.gz gcc-2450a057297b5bf665b98e9594ac6799c8a7e5fb.tar.bz2 |
i386-protos.h (split_xf, [...]): Remove.
* i386-protos.h (split_xf, ix86_split_movdi): Remove.
(ix86_split_long_move): Declare.
* i386.c (split_xf, ix86_split_movdi): Remove.
(ix86_split_to_parts, ix86_split_long_move): New.
* i386.md (dimode move splitters): Use ix86_split_long_move.
(dfmode move splitters): Likewise.
(xfmode move splitters): Likewise.
(movsf_1): Allow F->r.
(movdf_1, movxf_1): Allow F->ro.
Co-Authored-By: Richard Henderson <rth@cygnus.com>
From-SVN: r30578
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 234 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 86 |
4 files changed, 251 insertions, 85 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f8fe6c5..66758cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +Thu Nov 18 11:10:03 1999 Jan Hubicka <hubicka@freesoft.cz> + Richard Henderson <rth@cygnus.com> + + * i386-protos.h (split_xf, ix86_split_movdi): Remove. + (ix86_split_long_move): Declare. + * i386.c (split_xf, ix86_split_movdi): Remove. + (ix86_split_to_parts, ix86_split_long_move): New. + * i386.md (dimode move splitters): Use ix86_split_long_move. + (dfmode move splitters): Likewise. + (xfmode move splitters): Likewise. + (movsf_1): Allow F->r. + (movdf_1, movxf_1): Allow F->ro. + 1999-11-17 Mark Mitchell <mark@codesourcery.com> * except.h (struct eh_entry): Add goto_entry_p. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 7468ce8..a8e16b5 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -73,7 +73,6 @@ extern void print_operand PROTO((FILE*, rtx, int)); extern void print_operand_address PROTO((FILE*, rtx)); extern void split_di PROTO((rtx[], int, rtx[], rtx[])); -extern void split_xf PROTO((rtx, rtx[3])); extern char *output_387_binary_op PROTO((rtx, rtx*)); extern char *output_fix_trunc PROTO((rtx, rtx*)); @@ -92,7 +91,7 @@ extern void ix86_expand_branch PROTO((enum rtx_code, int, rtx)); extern int ix86_expand_setcc PROTO((enum rtx_code, int, rtx)); extern int ix86_expand_int_movcc PROTO((rtx[])); extern int ix86_expand_fp_movcc PROTO((rtx[])); -extern int ix86_split_movdi PROTO((rtx[])); +extern int ix86_split_long_move PROTO((rtx[])); extern void ix86_split_ashldi PROTO((rtx *, rtx)); extern void ix86_split_ashrdi PROTO((rtx *, rtx)); extern void ix86_split_lshrdi PROTO((rtx *, rtx)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 9228970..c8e8995 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2996,26 +2996,6 @@ split_di (operands, num, lo_half, hi_half) abort(); } } - -void -split_xf (orig, out) - rtx orig; - rtx out[3]; -{ - if (REG_P (orig)) - { - int regno = REGNO (orig); - out[0] = gen_rtx_REG (SImode, regno); - out[1] = gen_rtx_REG (SImode, regno + 1); - out[2] = gen_rtx_REG (SImode, regno + 2); - } - else - { - out[0] = change_address (orig, SImode, NULL_RTX); - out[1] = adj_offsettable_operand (out[0], 4); - out[2] = adj_offsettable_operand (out[0], 8); - } -} /* Output code to perform a 387 binary operation in INSN, one of PLUS, MINUS, MULT or DIV. OPERANDS are the insn operands, where operands[3] @@ -4643,27 +4623,211 @@ ix86_expand_fp_movcc (operands) return 1; } -int -ix86_split_movdi (operands) - rtx operands[]; +/* Split operands 0 and 1 into SImode parts. Similar to split_di, but + works for floating pointer parameters and nonoffsetable memories. + For pushes, it returns just stack offsets; the values will be saved + in the right order. Maximally three parts are generated. */ + +static void +ix86_split_to_parts (operand, parts, mode) + rtx operand; + rtx *parts; + enum machine_mode mode; { - split_di (operands+0, 1, operands+2, operands+3); - split_di (operands+1, 1, operands+4, operands+5); - if (reg_overlap_mentioned_p (operands[2], operands[1])) + int size = GET_MODE_SIZE (mode) / 4; + + if (size < 2 || size > 3) + abort (); + + if (GET_CODE (operand) == MEM && !offsettable_memref_p (operand)) { - rtx tmp; - if (!reg_overlap_mentioned_p (operands[3], operands[4])) + /* The only non-offsetable memories we handle are pushes. */ + 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]); + else { - tmp = operands[2], operands[2] = operands[3], operands[3] = tmp; - tmp = operands[4], operands[4] = operands[5], operands[5] = tmp; + if (REG_P (operand)) + { + if (!reload_completed) + abort (); + parts[0] = gen_rtx_REG (SImode, REGNO (operand) + 0); + parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1); + if (size == 3) + parts[2] = gen_rtx_REG (SImode, REGNO (operand) + 2); + } + else if (offsettable_memref_p (operand)) + { + PUT_MODE (operand, SImode); + parts[0] = operand; + parts[1] = adj_offsettable_operand (operand, 4); + if (size == 3) + parts[2] = adj_offsettable_operand (operand, 8); + } + else if (GET_CODE (operand) == CONST_DOUBLE) + { + REAL_VALUE_TYPE r; + long l[3]; + + REAL_VALUE_FROM_CONST_DOUBLE (r, operand); + switch (mode) + { + case XFmode: + REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l); + parts[2] = GEN_INT (l[2]); + break; + case DFmode: + REAL_VALUE_TO_TARGET_DOUBLE (r, l); + break; + default: + abort (); + } + parts[1] = GEN_INT (l[1]); + parts[0] = GEN_INT (l[0]); + } + else + abort (); } - else + } + + return; +} + +/* Emit insns to perform a move or push of DI, DF, and XF values. + Return false when normal moves are needed; true when all required + 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 = GET_MODE_SIZE (GET_MODE (operands1[0])) / 4; + 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]); + + if (size < 2 || size > 3) + abort (); + + /* The only non-offsettable memory we handle is push. */ + if (push_operand (operands[0], VOIDmode)) + push = 1; + else if (GET_CODE (operands[0]) == MEM + && ! offsettable_memref_p (operands[0])) + abort (); + + 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]; + } + + /* We need to do copy in the right order in case an address register + of the source overlaps the destination. */ + if (REG_P (part[0][0]) && GET_CODE (part[1][0]) == MEM) + { + if (reg_overlap_mentioned_p (part[0][0], XEXP (part[1][0], 0))) + 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))) { - emit_insn (gen_push (operands[4])); - emit_insn (gen_rtx_SET (VOIDmode, operands[3], operands[5])); - emit_insn (gen_popsi1 (operands[2])); + rtx tmp; + tmp = part[0][1]; part[0][1] = part[0][2]; part[0][2] = tmp; + tmp = part[1][1]; part[1][1] = part[1][2]; part[1][2] = tmp; + } - return 1; /* DONE */ + /* If there are more collisions, we can't handle it by reordering. + Do an lea to the last part and use only one colliding move. */ + 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) + 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]; + operands1[4] = part[0][0]; + operands1[5] = part[1][2]; + operands1[6] = part[1][1]; + operands1[7] = part[1][0]; + } + else + { + operands1[2] = part[0][1]; + operands1[3] = part[0][0]; + operands1[5] = part[1][1]; + operands1[6] = part[1][0]; + } + } + else + { + if (size == 3) + { + operands1[2] = part[0][0]; + operands1[3] = part[0][1]; + operands1[4] = part[0][2]; + operands1[5] = part[1][0]; + operands1[6] = part[1][1]; + operands1[7] = part[1][2]; + } + else + { + operands1[2] = part[0][0]; + operands1[3] = part[0][1]; + operands1[5] = part[1][0]; + operands1[6] = part[1][1]; } } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 82553cf..eb08227 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1665,17 +1665,9 @@ (define_split [(set (match_operand:DI 0 "push_operand" "") (match_operand:DI 1 "general_operand" ""))] - "" - [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 3)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 2))] - " -{ - split_di (operands+1, 1, operands+2, operands+3); - /* Compensate for the fact that we're changing stack offsets in - the middle of this operation. */ - if (reg_mentioned_p (stack_pointer_rtx, operands[2])) - operands[2] = adj_offsettable_operand (operands[2], 4); -}") + "reload_completed" + [(const_int 0)] + "if (!ix86_split_long_move (operands)) abort (); DONE;") ;; %%% This multiword shite has got to go. (define_split @@ -1683,19 +1675,19 @@ (match_operand:DI 1 "general_operand" "")) (clobber (reg:CC 17))] "reload_completed" - [(parallel [(set (match_dup 2) (match_dup 4)) + [(parallel [(set (match_dup 2) (match_dup 5)) (clobber (reg:CC 17))]) - (parallel [(set (match_dup 3) (match_dup 5)) + (parallel [(set (match_dup 3) (match_dup 6)) (clobber (reg:CC 17))])] - "if (ix86_split_movdi (operands)) DONE;") + "if (ix86_split_long_move (operands)) DONE;") (define_split [(set (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "general_operand" ""))] "reload_completed" - [(set (match_dup 2) (match_dup 4)) - (set (match_dup 3) (match_dup 5))] - "if (ix86_split_movdi (operands)) DONE;") + [(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 "general_operand" "") @@ -1740,7 +1732,7 @@ (define_insn "*movsf_1" [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,f,*r,m,*r") - (match_operand:SF 1 "general_operand" "fm,f,G,*rm,*r,G"))] + (match_operand:SF 1 "general_operand" "fm,f,G,*rm,F*r,GF"))] "" "* { @@ -1843,20 +1835,12 @@ [(set (match_operand:DF 0 "push_operand" "") (match_operand:DF 1 "general_operand" ""))] "reload_completed" - [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 1)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))] - " -{ - split_di (operands+1, 1, operands+0, operands+1); - /* Compensate for the fact that we're changing stack offsets in - the middle of this operation. */ - if (reg_mentioned_p (stack_pointer_rtx, operands[0])) - operands[0] = adj_offsettable_operand (operands[0], 4); -}") + [(const_int 0)] + "if (!ix86_split_long_move (operands)) abort (); DONE;") (define_insn "*movdf_1" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,f,*&r,m,*r") - (match_operand:DF 1 "general_operand" "fm,f,G,*rm,*r,G"))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,f,*r,o") + (match_operand:DF 1 "general_operand" "fm,f,G,*roF,F*r"))] "" "* { @@ -1889,14 +1873,13 @@ case 3: case 4: - case 5: return \"#\"; default: abort(); } }" - [(set_attr "type" "fmov,fmov,fmov,multi,multi,multi")]) + [(set_attr "type" "fmov,fmov,fmov,multi,multi")]) (define_split [(set (match_operand:DF 0 "nonimmediate_operand" "") @@ -1909,10 +1892,9 @@ && ! (FP_REG_P (operands[1]) || (GET_CODE (operands[1]) == SUBREG && FP_REG_P (SUBREG_REG (operands[1]))))" - [(set (match_dup 0) (match_dup 2)) - (set (match_dup 1) (match_dup 3))] - "split_di (operands+1, 1, operands+2, operands+3); - split_di (operands+0, 1, operands+0, 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") @@ -1936,8 +1918,8 @@ "ix86_expand_move (XFmode, operands); DONE;") (define_insn "*pushxf" - [(set (match_operand:XF 0 "push_operand" "=<") - (match_operand:XF 1 "register_operand" "f"))] + [(set (match_operand:XF 0 "push_operand" "=<,<") + (match_operand:XF 1 "register_operand" "f,oF*r"))] "" "* { @@ -1954,6 +1936,14 @@ (define_split [(set (match_operand:XF 0 "push_operand" "") + (match_operand:XF 1 "general_operand" ""))] + "reload_completed + && (!REG_P (operands[1]) || !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" "") (match_operand:XF 1 "register_operand" ""))] "FP_REGNO_P (REGNO (operands[1]))" [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) @@ -1980,8 +1970,8 @@ }") (define_insn "*movxf_1" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*&r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,*ro,*r"))] + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") + (match_operand:XF 1 "general_operand" "fm,f,G,*roF,*r"))] "" "* { @@ -2023,14 +2013,14 @@ (define_split [(set (match_operand:XF 0 "nonimmediate_operand" "") - (match_operand:XF 1 "nonimmediate_operand" ""))] - "(REG_P (operands[0]) && ! FP_REGNO_P (REGNO (operands[0]))) - || (REG_P (operands[1]) && ! FP_REGNO_P (REGNO (operands[1])))" - [(set (match_dup 0) (match_dup 3)) - (set (match_dup 1) (match_dup 4)) - (set (match_dup 2) (match_dup 5))] - "split_xf (operands[1], &operands[3]); - split_xf (operands[0], &operands[0]);") + (match_operand:XF 1 "general_operand" ""))] + "reload_completed + && ((REG_P (operands[0]) && ! FP_REGNO_P (REGNO (operands[0]))) + || (REG_P (operands[1]) && ! FP_REGNO_P (REGNO (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_insn "swapxf" [(set (match_operand:XF 0 "register_operand" "+f") |