diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-01 14:13:44 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-01 14:13:44 +0000 |
commit | b8d2bcdd743853cfef58c1c0d7ee7f518c098416 (patch) | |
tree | 366fcb1b6390ba0ac365092bc3e6aee1326879fc /gcc/expmed.c | |
parent | 99cf25d08b422ccf718a05f484e1be90f533ab63 (diff) | |
download | gcc-b8d2bcdd743853cfef58c1c0d7ee7f518c098416.tar.gz |
* expmed.c (store_bit_field, extract_bit_field): Use new named patterns
* expr.c (store_constructor): Use vec_init pattern.
* genopinit.c (optabs): Initailize vec_set/vec_extract/vec_init.
* optabs.h (optab_index): ADD OTI_vec_set/OTI_vec_extract/OTI_vec_init
(vec_set_optab, vec_extract_optab, vec_init_optab): New.
* i386.md (vec_setv2df, vec_extractv2df, vec_setv4sf, vec_extractv4sf):
New patterns.
(sse2_unpc?pd): Fix pattern.
(sse2_movlpd): Kill.
(sse2_movsd): Deal with movlpd too.
* i386.c (ix86_expand_builtin): Use sse2_movsd instead of sse2_movlpd.
(ix86_expand_vector_init): New.
* emmintrin.h (__mm_set_pd, __mm_set_ps): Use vector extensions.
* md.texi (vec_set, vec_extract): Document
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75304 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 98a26a14c1e..8ebfb487552 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -313,6 +313,53 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, value = protect_from_queue (value, 0); + /* Use vec_extract patterns for extracting parts of vectors whenever + available. */ + if (VECTOR_MODE_P (GET_MODE (op0)) + && GET_CODE (op0) != MEM + && (vec_set_optab->handlers[(int)GET_MODE (op0)].insn_code + != CODE_FOR_nothing) + && fieldmode == GET_MODE_INNER (GET_MODE (op0)) + && bitsize == GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0))) + && !(bitnum % GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0))))) + { + enum machine_mode outermode = GET_MODE (op0); + enum machine_mode innermode = GET_MODE_INNER (outermode); + int icode = (int) vec_set_optab->handlers[(int) outermode].insn_code; + int pos = bitnum / GET_MODE_BITSIZE (innermode); + rtx rtxpos = GEN_INT (pos); + rtx src = value; + rtx dest = op0; + rtx pat, seq; + enum machine_mode mode0 = insn_data[icode].operand[0].mode; + enum machine_mode mode1 = insn_data[icode].operand[1].mode; + enum machine_mode mode2 = insn_data[icode].operand[2].mode; + + start_sequence (); + + if (! (*insn_data[icode].operand[1].predicate) (src, mode1)) + src = copy_to_mode_reg (mode1, src); + + if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2)) + rtxpos = copy_to_mode_reg (mode1, rtxpos); + + /* We could handle this, but we should always be called with a pseudo + for our targets and all insns should take them as outputs. */ + if (! (*insn_data[icode].operand[0].predicate) (dest, mode0) + || ! (*insn_data[icode].operand[1].predicate) (src, mode1) + || ! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2)) + abort (); + pat = GEN_FCN (icode) (dest, src, rtxpos); + seq = get_insns (); + end_sequence (); + if (pat) + { + emit_insn (seq); + emit_insn (pat); + return dest; + } + } + if (flag_force_mem) { int old_generating_concat_p = generating_concat_p; @@ -1035,6 +1082,62 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, return op0; } + /* Use vec_extract patterns for extracting parts of vectors whenever + available. */ + if (VECTOR_MODE_P (GET_MODE (op0)) + && GET_CODE (op0) != MEM + && (vec_extract_optab->handlers[(int)GET_MODE (op0)].insn_code + != CODE_FOR_nothing) + && ((bitsize + bitnum) / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0))) + == bitsize / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0))))) + { + enum machine_mode outermode = GET_MODE (op0); + enum machine_mode innermode = GET_MODE_INNER (outermode); + int icode = (int) vec_extract_optab->handlers[(int) outermode].insn_code; + int pos = bitnum / GET_MODE_BITSIZE (innermode); + rtx rtxpos = GEN_INT (pos); + rtx src = op0; + rtx dest = NULL, pat, seq; + enum machine_mode mode0 = insn_data[icode].operand[0].mode; + enum machine_mode mode1 = insn_data[icode].operand[1].mode; + enum machine_mode mode2 = insn_data[icode].operand[2].mode; + + if (innermode == tmode || innermode == mode) + dest = target; + + if (!dest) + dest = gen_reg_rtx (innermode); + + start_sequence (); + + if (! (*insn_data[icode].operand[0].predicate) (dest, mode0)) + dest = copy_to_mode_reg (mode0, dest); + + if (! (*insn_data[icode].operand[1].predicate) (src, mode1)) + src = copy_to_mode_reg (mode1, src); + + if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2)) + rtxpos = copy_to_mode_reg (mode1, rtxpos); + + /* We could handle this, but we should always be called with a pseudo + for our targets and all insns should take them as outputs. */ + if (! (*insn_data[icode].operand[0].predicate) (dest, mode0) + || ! (*insn_data[icode].operand[1].predicate) (src, mode1) + || ! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2)) + abort (); + pat = GEN_FCN (icode) (dest, src, rtxpos); + seq = get_insns (); + end_sequence (); + if (pat) + { + emit_insn (seq); + emit_insn (pat); + return extract_bit_field (dest, bitsize, + bitnum - pos * GET_MODE_BITSIZE (innermode), + unsignedp, target, mode, tmode, total_size); + } + } + /* Make sure we are playing with integral modes. Pun with subregs if we aren't. */ { |