diff options
author | Maciej W. Rozycki <macro@codesourcery.com> | 2014-07-07 15:48:23 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@gcc.gnu.org> | 2014-07-07 15:48:23 +0000 |
commit | 3ca588d3e21439abfa36302defba9aaae83f9860 (patch) | |
tree | 8324bd8033fe2c94fb06a3c775eac47f21722307 | |
parent | e7623929189c96c7e22ec65f3f79cb4987ebd2ed (diff) | |
download | gcc-3ca588d3e21439abfa36302defba9aaae83f9860.zip gcc-3ca588d3e21439abfa36302defba9aaae83f9860.tar.gz gcc-3ca588d3e21439abfa36302defba9aaae83f9860.tar.bz2 |
rs6000.c (output_vec_const_move): Handle little-endian code generation.
gcc/
* config/rs6000/rs6000.c (output_vec_const_move): Handle
little-endian code generation.
* config/rs6000/spe.md (spe_evmergehi): Rename to...
(vec_perm00_v2si): ... this. Handle little-endian code
generation.
(spe_evmergehilo): Rename to...
(vec_perm01_v2si): ... this. Handle little-endian code
generation.
(spe_evmergelo): Rename to...
(vec_perm11_v2si): ... this. Handle little-endian code
generation.
(spe_evmergelohi): Rename to...
(vec_perm10_v2si): ... this. Handle little-endian code
generation.
(spe_evmergehi, spe_evmergehilo): New expanders.
(spe_evmergelo, spe_evmergelohi): Likewise.
(*frob_<SPE64:mode>_<DITI:mode>): Handle little-endian code
generation.
(*frob_tf_ti): Likewise.
(*frob_<mode>_di_2): Likewise.
(*frob_tf_di_8_2): Likewise.
(*frob_di_<mode>): Likewise.
(*frob_ti_tf): Likewise.
(*frob_<DITI:mode>_<SPE64:mode>_2): Likewise.
(*frob_ti_<mode>_8_2): Likewise.
(*frob_ti_tf_2): Likewise.
(mov_si<mode>_e500_subreg0): Rename to...
(mov_si<mode>_e500_subreg0_be): ... this. Restrict to the big
endianness only.
(*mov_si<mode>_e500_subreg0_le): New instruction pattern.
(*mov_si<mode>_e500_subreg0_elf_low): Rename to...
(*mov_si<mode>_e500_subreg0_elf_low_be): ... this. Restrict to
the big endianness only.
(*mov_si<mode>_e500_subreg0_elf_low_le): New instruction pattern.
(*mov_si<mode>_e500_subreg0_2): Rename to...
(*mov_si<mode>_e500_subreg0_2_be): ... this. Restrict to the
big big endianness only.
(*mov_si<mode>_e500_subreg0_2_le): New instruction pattern.
(*mov_si<mode>_e500_subreg4): Rename to...
(*mov_si<mode>_e500_subreg4_be): ... this. Restrict to the big
endianness only.
(mov_si<mode>_e500_subreg4_le): New instruction pattern.
(*mov_si<mode>_e500_subreg4_elf_low): Rename to...
(*mov_si<mode>_e500_subreg4_elf_low_be): ... this. Restrict to
the big endianness only.
(*mov_si<mode>_e500_subreg4_elf_low_le): New instruction/splitter
pattern.
(*mov_si<mode>_e500_subreg4_2): Rename to...
(*mov_si<mode>_e500_subreg4_2_be): ... this. Restrict to the big
endianness only.
(*mov_si<mode>_e500_subreg4_2_le): New instruction pattern.
(*mov_sitf_e500_subreg8): Rename to...
(*mov_sitf_e500_subreg8_be): ... this. Restrict to the big
endianness only.
(*mov_sitf_e500_subreg8_le): New instruction pattern.
(*mov_sitf_e500_subreg8_2): Rename to...
(*mov_sitf_e500_subreg8_2_be): ... this. Restrict to the big
endianness only.
(*mov_sitf_e500_subreg8_2_le): New instruction pattern.
(*mov_sitf_e500_subreg12): Rename to...
(*mov_sitf_e500_subreg12_be): ... this. Restrict to the big
endianness only.
(*mov_sitf_e500_subreg12_le): New instruction pattern.
(*mov_sitf_e500_subreg12_2): Rename to...
(*mov_sitf_e500_subreg12_2_be): ... this. Restrict to the big
endianness only.
(*mov_sitf_e500_subreg12_2_le): New instruction pattern.
gcc/testsuite/
* gcc.target/powerpc/spe-evmerge.c: New file.
From-SVN: r212335
-rw-r--r-- | gcc/ChangeLog | 70 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/spe.md | 395 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/spe-evmerge.c | 71 |
5 files changed, 485 insertions, 59 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1077a65..8eec932 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,73 @@ +2014-07-07 Maciej W. Rozycki <macro@codesourcery.com> + + * config/rs6000/rs6000.c (output_vec_const_move): Handle + little-endian code generation. + * config/rs6000/spe.md (spe_evmergehi): Rename to... + (vec_perm00_v2si): ... this. Handle little-endian code + generation. + (spe_evmergehilo): Rename to... + (vec_perm01_v2si): ... this. Handle little-endian code + generation. + (spe_evmergelo): Rename to... + (vec_perm11_v2si): ... this. Handle little-endian code + generation. + (spe_evmergelohi): Rename to... + (vec_perm10_v2si): ... this. Handle little-endian code + generation. + (spe_evmergehi, spe_evmergehilo): New expanders. + (spe_evmergelo, spe_evmergelohi): Likewise. + (*frob_<SPE64:mode>_<DITI:mode>): Handle little-endian code + generation. + (*frob_tf_ti): Likewise. + (*frob_<mode>_di_2): Likewise. + (*frob_tf_di_8_2): Likewise. + (*frob_di_<mode>): Likewise. + (*frob_ti_tf): Likewise. + (*frob_<DITI:mode>_<SPE64:mode>_2): Likewise. + (*frob_ti_<mode>_8_2): Likewise. + (*frob_ti_tf_2): Likewise. + (mov_si<mode>_e500_subreg0): Rename to... + (mov_si<mode>_e500_subreg0_be): ... this. Restrict to the big + endianness only. + (*mov_si<mode>_e500_subreg0_le): New instruction pattern. + (*mov_si<mode>_e500_subreg0_elf_low): Rename to... + (*mov_si<mode>_e500_subreg0_elf_low_be): ... this. Restrict to + the big endianness only. + (*mov_si<mode>_e500_subreg0_elf_low_le): New instruction pattern. + (*mov_si<mode>_e500_subreg0_2): Rename to... + (*mov_si<mode>_e500_subreg0_2_be): ... this. Restrict to the + big big endianness only. + (*mov_si<mode>_e500_subreg0_2_le): New instruction pattern. + (*mov_si<mode>_e500_subreg4): Rename to... + (*mov_si<mode>_e500_subreg4_be): ... this. Restrict to the big + endianness only. + (mov_si<mode>_e500_subreg4_le): New instruction pattern. + (*mov_si<mode>_e500_subreg4_elf_low): Rename to... + (*mov_si<mode>_e500_subreg4_elf_low_be): ... this. Restrict to + the big endianness only. + (*mov_si<mode>_e500_subreg4_elf_low_le): New instruction/splitter + pattern. + (*mov_si<mode>_e500_subreg4_2): Rename to... + (*mov_si<mode>_e500_subreg4_2_be): ... this. Restrict to the big + endianness only. + (*mov_si<mode>_e500_subreg4_2_le): New instruction pattern. + (*mov_sitf_e500_subreg8): Rename to... + (*mov_sitf_e500_subreg8_be): ... this. Restrict to the big + endianness only. + (*mov_sitf_e500_subreg8_le): New instruction pattern. + (*mov_sitf_e500_subreg8_2): Rename to... + (*mov_sitf_e500_subreg8_2_be): ... this. Restrict to the big + endianness only. + (*mov_sitf_e500_subreg8_2_le): New instruction pattern. + (*mov_sitf_e500_subreg12): Rename to... + (*mov_sitf_e500_subreg12_be): ... this. Restrict to the big + endianness only. + (*mov_sitf_e500_subreg12_le): New instruction pattern. + (*mov_sitf_e500_subreg12_2): Rename to... + (*mov_sitf_e500_subreg12_2_be): ... this. Restrict to the big + endianness only. + (*mov_sitf_e500_subreg12_2_le): New instruction pattern. + 2014-07-07 Max Ostapenko <m.ostapenko@partner.samsung.com> * asan.c (instrument_strlen_call): Do not instrument first byte in strlen diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 215e65b..1c8c992 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -5300,8 +5300,10 @@ output_vec_const_move (rtx *operands) operands[2] = CONST_VECTOR_ELT (vec, 1); if (cst == cst2) return "li %0,%1\n\tevmergelo %0,%0,%0"; - else + else if (WORDS_BIG_ENDIAN) return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2"; + else + return "li %0,%2\n\tevmergelo %0,%0,%0\n\tli %0,%1"; } /* Initialize TARGET of vector PAIRED to VALS. */ diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index ad7eaf0..8eec7b7 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -438,7 +438,12 @@ [(set_attr "type" "vecload") (set_attr "length" "4")]) -(define_insn "spe_evmergehi" +;; Integer vector permutation instructions. The pairs of digits in the +;; names of these instructions indicate the indices, in the memory vector +;; element ordering, of the vector elements permuted to the output vector +;; from the first and the second input vector respectively. + +(define_insn "vec_perm00_v2si" [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") (vec_select:V2SI (vec_concat:V4SI @@ -446,11 +451,16 @@ (match_operand:V2SI 2 "gpc_reg_operand" "r")) (parallel [(const_int 0) (const_int 2)])))] "TARGET_SPE" - "evmergehi %0,%1,%2" +{ + if (WORDS_BIG_ENDIAN) + return "evmergehi %0,%1,%2"; + else + return "evmergelo %0,%2,%1"; +} [(set_attr "type" "vecsimple") (set_attr "length" "4")]) -(define_insn "spe_evmergehilo" +(define_insn "vec_perm01_v2si" [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") (vec_select:V2SI (vec_concat:V4SI @@ -458,11 +468,16 @@ (match_operand:V2SI 2 "gpc_reg_operand" "r")) (parallel [(const_int 0) (const_int 3)])))] "TARGET_SPE" - "evmergehilo %0,%1,%2" +{ + if (WORDS_BIG_ENDIAN) + return "evmergehilo %0,%1,%2"; + else + return "evmergehilo %0,%2,%1"; +} [(set_attr "type" "vecsimple") (set_attr "length" "4")]) -(define_insn "spe_evmergelo" +(define_insn "vec_perm11_v2si" [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") (vec_select:V2SI (vec_concat:V4SI @@ -470,11 +485,16 @@ (match_operand:V2SI 2 "gpc_reg_operand" "r")) (parallel [(const_int 1) (const_int 3)])))] "TARGET_SPE" - "evmergelo %0,%1,%2" +{ + if (WORDS_BIG_ENDIAN) + return "evmergelo %0,%1,%2"; + else + return "evmergehi %0,%2,%1"; +} [(set_attr "type" "vecsimple") (set_attr "length" "4")]) -(define_insn "spe_evmergelohi" +(define_insn "vec_perm10_v2si" [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") (vec_select:V2SI (vec_concat:V4SI @@ -482,7 +502,12 @@ (match_operand:V2SI 2 "gpc_reg_operand" "r")) (parallel [(const_int 1) (const_int 2)])))] "TARGET_SPE" - "evmergelohi %0,%1,%2" +{ + if (WORDS_BIG_ENDIAN) + return "evmergelohi %0,%1,%2"; + else + return "evmergelohi %0,%2,%1"; +} [(set_attr "type" "vecsimple") (set_attr "length" "4")]) @@ -499,6 +524,60 @@ FAIL; }) +(define_expand "spe_evmergehi" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "register_operand" "") + (match_operand:V2SI 2 "register_operand" "")] + "TARGET_SPE" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_perm00_v2si (operands[0], operands[1], operands[2])); + else + emit_insn (gen_vec_perm11_v2si (operands[0], operands[2], operands[1])); + DONE; +}) + +(define_expand "spe_evmergehilo" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "register_operand" "") + (match_operand:V2SI 2 "register_operand" "")] + "TARGET_SPE" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_perm01_v2si (operands[0], operands[1], operands[2])); + else + emit_insn (gen_vec_perm01_v2si (operands[0], operands[2], operands[1])); + DONE; +}) + +(define_expand "spe_evmergelo" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "register_operand" "") + (match_operand:V2SI 2 "register_operand" "")] + "TARGET_SPE" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_perm11_v2si (operands[0], operands[1], operands[2])); + else + emit_insn (gen_vec_perm00_v2si (operands[0], operands[2], operands[1])); + DONE; +}) + +(define_expand "spe_evmergelohi" + [(match_operand:V2SI 0 "register_operand" "") + (match_operand:V2SI 1 "register_operand" "") + (match_operand:V2SI 2 "register_operand" "")] + "TARGET_SPE" +{ + if (BYTES_BIG_ENDIAN) + emit_insn (gen_vec_perm10_v2si (operands[0], operands[1], operands[2])); + else + emit_insn (gen_vec_perm10_v2si (operands[0], operands[2], operands[1])); + DONE; +}) + +;; End of integer vector permutation instructions. + (define_insn "spe_evnand" [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r") (not:V2SI (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r") @@ -2220,15 +2299,31 @@ (subreg:SPE64 (match_operand:DITI 1 "input_operand" "r,m") 0))] "(TARGET_E500_DOUBLE && <SPE64:MODE>mode == DFmode) || (TARGET_SPE && <SPE64:MODE>mode != DFmode)" - "@ - evmergelo %0,%1,%L1 - evldd%X1 %0,%y1") +{ + switch (which_alternative) + { + default: + gcc_unreachable (); + case 0: + if (WORDS_BIG_ENDIAN) + return "evmergelo %0,%1,%L1"; + else + return "evmergelo %0,%L1,%1"; + case 1: + return "evldd%X1 %0,%y1"; + } +}) (define_insn "*frob_tf_ti" [(set (match_operand:TF 0 "gpc_reg_operand" "=r") (subreg:TF (match_operand:TI 1 "gpc_reg_operand" "r") 0))] "TARGET_E500_DOUBLE" - "evmergelo %0,%1,%L1\;evmergelo %L0,%Y1,%Z1" +{ + if (WORDS_BIG_ENDIAN) + return "evmergelo %0,%1,%L1\;evmergelo %L0,%Y1,%Z1"; + else + return "evmergelo %L0,%Z1,%Y1\;evmergelo %0,%L1,%1"; +} [(set_attr "length" "8")]) (define_insn "*frob_<mode>_di_2" @@ -2236,31 +2331,63 @@ (match_operand:DI 1 "input_operand" "r,m"))] "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" - "@ - evmergelo %0,%1,%L1 - evldd%X1 %0,%y1") +{ + switch (which_alternative) + { + default: + gcc_unreachable (); + case 0: + if (WORDS_BIG_ENDIAN) + return "evmergelo %0,%1,%L1"; + else + return "evmergelo %0,%L1,%1"; + case 1: + return "evldd%X1 %0,%y1"; + } +}) (define_insn "*frob_tf_di_8_2" [(set (subreg:DI (match_operand:TF 0 "nonimmediate_operand" "+&r,r") 8) (match_operand:DI 1 "input_operand" "r,m"))] "TARGET_E500_DOUBLE" - "@ - evmergelo %L0,%1,%L1 - evldd%X1 %L0,%y1") +{ + switch (which_alternative) + { + default: + gcc_unreachable (); + case 0: + if (WORDS_BIG_ENDIAN) + return "evmergelo %L0,%1,%L1"; + else + return "evmergelo %L0,%L1,%1"; + case 1: + return "evldd%X1 %L0,%y1"; + } +}) (define_insn "*frob_di_<mode>" [(set (match_operand:DI 0 "nonimmediate_operand" "=&r") (subreg:DI (match_operand:SPE64TF 1 "input_operand" "r") 0))] "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" - "evmergehi %0,%1,%1\;mr %L0,%1" +{ + if (WORDS_BIG_ENDIAN) + return "evmergehi %0,%1,%1\;mr %L0,%1"; + else + return "evmergehi %L0,%1,%1\;mr %0,%1"; +} [(set_attr "length" "8")]) (define_insn "*frob_ti_tf" [(set (match_operand:TI 0 "nonimmediate_operand" "=&r") (subreg:TI (match_operand:TF 1 "input_operand" "r") 0))] "TARGET_E500_DOUBLE" - "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1" +{ + if (WORDS_BIG_ENDIAN) + return "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1"; + else + return "evmergehi %Z0,%L1,%L1\;mr %Y0,%L1\;evmergehi %L0,%1,%1\;mr %0,%1"; +} [(set_attr "length" "16")]) (define_insn "*frob_<DITI:mode>_<SPE64:mode>_2" @@ -2275,22 +2402,40 @@ default: gcc_unreachable (); case 0: - return \"evmergehi %0,%1,%1\;mr %L0,%1\"; + if (WORDS_BIG_ENDIAN) + return \"evmergehi %0,%1,%1\;mr %L0,%1\"; + else + return \"evmergehi %L0,%1,%1\;mr %0,%1\"; case 1: /* If the address is not offsettable we need to load the whole doubleword into a 64-bit register and then copy the high word to form the correct output layout. */ if (!offsettable_nonstrict_memref_p (operands[1])) - return \"evldd%X1 %L0,%y1\;evmergehi %0,%L0,%L0\"; + { + if (WORDS_BIG_ENDIAN) + return \"evldd%X1 %L0,%y1\;evmergehi %0,%L0,%L0\"; + else + return \"evldd%X1 %0,%y1\;evmergehi %L0,%0,%0\"; + } /* If the low-address word is used in the address, we must load it last. Otherwise, load it first. Note that we cannot have auto-increment in that case since the address register is known to be dead. */ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) - return \"lwz %L0,%L1\;lwz %0,%1\"; + { + if (WORDS_BIG_ENDIAN) + return \"lwz %L0,%L1\;lwz %0,%1\"; + else + return \"lwz %0,%1\;lwz %L0,%L1\"; + } else - return \"lwz%U1%X1 %0,%1\;lwz %L0,%L1\"; + { + if (WORDS_BIG_ENDIAN) + return \"lwz%U1%X1 %0,%1\;lwz %L0,%L1\"; + else + return \"lwz%U1%X1 %L0,%L1\;lwz %0,%1\"; + } } }" [(set_attr "length" "8,8")]) @@ -2308,15 +2453,33 @@ default: gcc_unreachable (); case 0: - return \"evmergehi %Y0,%1,%1\;mr %Z0,%1\"; + if (WORDS_BIG_ENDIAN) + return \"evmergehi %Y0,%1,%1\;mr %Z0,%1\"; + else + return \"evmergehi %Z0,%1,%1\;mr %Y0,%1\"; case 1: if (!offsettable_nonstrict_memref_p (operands[1])) - return \"evldd%X1 %Z0,%y1\;evmergehi %Y0,%Z0,%Z0\"; + { + if (WORDS_BIG_ENDIAN) + return \"evldd%X1 %Z0,%y1\;evmergehi %Y0,%Z0,%Z0\"; + else + return \"evldd%X1 %Y0,%y1\;evmergehi %Z0,%Y0,%Y0\"; + } if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) - return \"lwz %Z0,%L1\;lwz %Y0,%1\"; + { + if (WORDS_BIG_ENDIAN) + return \"lwz %Z0,%L1\;lwz %Y0,%1\"; + else + return \"lwz %Y0,%1\;lwz %Z0,%L1\"; + } else - return \"lwz%U1%X1 %Y0,%1\;lwz %Z0,%L1\"; + { + if (WORDS_BIG_ENDIAN) + return \"lwz%U1%X1 %Y0,%1\;lwz %Z0,%L1\"; + else + return \"lwz%U1%X1 %Z0,%L1\;lwz %Y0,%1\"; + } } }" [(set_attr "length" "8,8")]) @@ -2325,110 +2488,226 @@ [(set (subreg:TF (match_operand:TI 0 "gpc_reg_operand" "=&r") 0) (match_operand:TF 1 "input_operand" "r"))] "TARGET_E500_DOUBLE" - "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1" +{ + if (WORDS_BIG_ENDIAN) + return "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1"; + else + return "evmergehi %Z0,%L1,%L1\;mr %Y0,%L1\;evmergehi %L0,%1,%1\;mr %0,%1"; +} [(set_attr "length" "16")]) -(define_insn "mov_si<mode>_e500_subreg0" +(define_insn "mov_si<mode>_e500_subreg0_be" [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 0) (match_operand:SI 1 "input_operand" "r,m"))] - "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" + "WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ evmergelo %0,%1,%0 evmergelohi %0,%0,%0\;lwz%U1%X1 %0,%1\;evmergelohi %0,%0,%0" [(set_attr "length" "4,12")]) -(define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low" +(define_insn "*mov_si<mode>_e500_subreg0_le" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,r") 0) + (match_operand:SI 1 "input_operand" "r,m"))] + "!WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" + "@ + mr %0,%1 + lwz%U1%X1 %0,%1") + +(define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low_be" [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0) (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand 2 "" "")))] - "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) - && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ()" + "WORDS_BIG_ENDIAN + && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ())" "#" "&& 1" [(pc)] { rtx tmp = gen_reg_rtx (SImode); emit_insn (gen_elf_low (tmp, operands[1], operands[2])); - emit_insn (gen_mov_si<mode>_e500_subreg0 (operands[0], tmp)); + emit_insn (gen_mov_si<mode>_e500_subreg0_be (operands[0], tmp)); DONE; } [(set_attr "length" "8")]) +(define_insn "*mov_si<mode>_e500_subreg0_elf_low_le" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0) + (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand 2 "" "")))] + "!WORDS_BIG_ENDIAN + && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT)" + "addic %0,%1,%K2") + ;; ??? Could use evstwwe for memory stores in some cases, depending on ;; the offset. -(define_insn "*mov_si<mode>_e500_subreg0_2" +(define_insn "*mov_si<mode>_e500_subreg0_2_be" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))] - "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" + "WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ evmergehi %0,%0,%1 evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0" [(set_attr "length" "4,8")]) -(define_insn "*mov_si<mode>_e500_subreg4" +(define_insn "*mov_si<mode>_e500_subreg0_2_le" + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") + (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,r") 0))] + "!WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" + "@ + mr %0,%1 + stw%U0%X0 %1,%0") + +(define_insn "*mov_si<mode>_e500_subreg4_be" [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,r") 4) (match_operand:SI 1 "input_operand" "r,m"))] - "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" + "WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ mr %0,%1 lwz%U1%X1 %0,%1") -(define_insn "*mov_si<mode>_e500_subreg4_elf_low" +(define_insn "mov_si<mode>_e500_subreg4_le" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 4) + (match_operand:SI 1 "input_operand" "r,m"))] + "!WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" + "@ + evmergelo %0,%1,%0 + evmergelohi %0,%0,%0\;lwz%U1%X1 %0,%1\;evmergelohi %0,%0,%0" + [(set_attr "length" "4,12")]) + +(define_insn "*mov_si<mode>_e500_subreg4_elf_low_be" [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4) (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand 2 "" "")))] - "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) - && TARGET_ELF && !TARGET_64BIT" + "WORDS_BIG_ENDIAN + && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT)" "addic %0,%1,%K2") -(define_insn "*mov_si<mode>_e500_subreg4_2" +(define_insn_and_split "*mov_si<mode>_e500_subreg4_elf_low_le" + [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4) + (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r") + (match_operand 2 "" "")))] + "!WORDS_BIG_ENDIAN + && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)) + && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ())" + "#" + "&& 1" + [(pc)] +{ + rtx tmp = gen_reg_rtx (SImode); + emit_insn (gen_elf_low (tmp, operands[1], operands[2])); + emit_insn (gen_mov_si<mode>_e500_subreg4_le (operands[0], tmp)); + DONE; +} + [(set_attr "length" "8")]) + +(define_insn "*mov_si<mode>_e500_subreg4_2_be" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 4))] - "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) - || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)" + "WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" "@ mr %0,%1 stw%U0%X0 %1,%0") -(define_insn "*mov_sitf_e500_subreg8" +(define_insn "*mov_si<mode>_e500_subreg4_2_le" + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") + (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 4))] + "!WORDS_BIG_ENDIAN + && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode)) + || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))" + "@ + evmergehi %0,%0,%1 + evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0" + [(set_attr "length" "4,8")]) + +(define_insn "*mov_sitf_e500_subreg8_be" [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,&r") 8) (match_operand:SI 1 "input_operand" "r,m"))] - "TARGET_E500_DOUBLE" + "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" "@ evmergelo %L0,%1,%L0 evmergelohi %L0,%L0,%L0\;lwz%U1%X1 %L0,%1\;evmergelohi %L0,%L0,%L0" [(set_attr "length" "4,12")]) -(define_insn "*mov_sitf_e500_subreg8_2" +(define_insn "*mov_sitf_e500_subreg8_le" + [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,r") 8) + (match_operand:SI 1 "input_operand" "r,m"))] + "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" + "@ + mr %L0,%1 + lwz%U1%X1 %L0,%1") + +(define_insn "*mov_sitf_e500_subreg8_2_be" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:TF 1 "register_operand" "+r,&r") 8))] - "TARGET_E500_DOUBLE" + "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" "@ evmergehi %0,%0,%L1 evmergelohi %L1,%L1,%L1\;stw%U0%X0 %L1,%0" [(set_attr "length" "4,8")]) -(define_insn "*mov_sitf_e500_subreg12" +(define_insn "*mov_sitf_e500_subreg8_2_le" + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") + (subreg:SI (match_operand:TF 1 "register_operand" "r,r") 8))] + "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" + "@ + mr %0,%L1 + stw%U0%X0 %L1,%0") + +(define_insn "*mov_sitf_e500_subreg12_be" [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,r") 12) (match_operand:SI 1 "input_operand" "r,m"))] - "TARGET_E500_DOUBLE" + "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" "@ mr %L0,%1 lwz%U1%X1 %L0,%1") -(define_insn "*mov_sitf_e500_subreg12_2" +(define_insn "*mov_sitf_e500_subreg12_le" + [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,&r") 12) + (match_operand:SI 1 "input_operand" "r,m"))] + "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" + "@ + evmergelo %L0,%1,%L0 + evmergelohi %L0,%L0,%L0\;lwz%U1%X1 %L0,%1\;evmergelohi %L0,%L0,%L0" + [(set_attr "length" "4,12")]) + +(define_insn "*mov_sitf_e500_subreg12_2_be" [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") (subreg:SI (match_operand:TF 1 "register_operand" "r,r") 12))] - "TARGET_E500_DOUBLE" + "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" "@ mr %0,%L1 stw%U0%X0 %L1,%0") +(define_insn "*mov_sitf_e500_subreg12_2_le" + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m") + (subreg:SI (match_operand:TF 1 "register_operand" "+r,&r") 12))] + "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE" + "@ + evmergehi %0,%0,%L1 + evmergelohi %L1,%L1,%L1\;stw%U0%X0 %L1,%0" + [(set_attr "length" "4,8")]) + ;; FIXME: Allow r=CONST0. (define_insn "*movdf_e500_double" [(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bc23150..62b13fc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2014-07-07 Maciej W. Rozycki <macro@codesourcery.com> + + * gcc.target/powerpc/spe-evmerge.c: New file. + 2014-07-07 Paolo Carlini <paolo.carlini@oracle.com> * g++.dg/cpp0x/override1.C: Tweak expected error messages. diff --git a/gcc/testsuite/gcc.target/powerpc/spe-evmerge.c b/gcc/testsuite/gcc.target/powerpc/spe-evmerge.c new file mode 100644 index 0000000..df0a33e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/spe-evmerge.c @@ -0,0 +1,71 @@ +/* Verify SPE vector permute builtins. */ +/* { dg-do run { target { powerpc*-*-* && powerpc_spe } } } */ +/* Remove `-ansi' from options so that <spe.h> compiles. */ +/* { dg-options "" } */ + +#include <spe.h> +#include <stdlib.h> + +#define vector __attribute__ ((vector_size (8))) + +#define WORDS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + +int +main (void) +{ + vector int a = { 0x11111111, 0x22222222 }; + vector int b = { 0x33333333, 0x44444444 }; + vector int c; + + /* c[hi] = a[hi], c[lo] = b[hi] */ + c = __ev_mergehi (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x44444444)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x22222222)) + abort (); + /* c[hi] = a[lo], c[lo] = b[lo] */ + c = __ev_mergelo (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x33333333)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x11111111)) + abort (); + /* c[hi] = a[lo], c[lo] = b[hi] */ + c = __ev_mergelohi (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x44444444)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x11111111)) + abort (); + /* c[hi] = a[hi], c[lo] = b[lo] */ + c = __ev_mergehilo (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x33333333)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x22222222)) + abort (); + + /* c[hi] = a[hi], c[lo] = b[hi] */ + c = __builtin_spe_evmergehi (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x44444444)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x22222222)) + abort (); + /* c[hi] = a[lo], c[lo] = b[lo] */ + c = __builtin_spe_evmergelo (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x33333333)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x11111111)) + abort (); + /* c[hi] = a[lo], c[lo] = b[hi] */ + c = __builtin_spe_evmergelohi (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x44444444)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x11111111)) + abort (); + /* c[hi] = a[hi], c[lo] = b[lo] */ + c = __builtin_spe_evmergehilo (a, b); + if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x33333333)) + abort (); + if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x22222222)) + abort (); + + return 0; +} |