diff options
author | revitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-31 17:04:42 +0000 |
---|---|---|
committer | revitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-31 17:04:42 +0000 |
commit | a39ea4df3097965e689783caa9098d496b837c9f (patch) | |
tree | ffcd2f0cd6e20a0379266c1ddc17953d9734dcc9 /gcc/config/rs6000 | |
parent | ed69e50620a42f9b5a5dc320e7ae3091a2f378cd (diff) | |
download | gcc-a39ea4df3097965e689783caa9098d496b837c9f.tar.gz |
Enable auto-vectorization for PowerPC 750CL paired-single instructions
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129803 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r-- | gcc/config/rs6000/750cl.h | 3 | ||||
-rw-r--r-- | gcc/config/rs6000/paired.md | 148 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-c.c | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 97 |
5 files changed, 256 insertions, 0 deletions
diff --git a/gcc/config/rs6000/750cl.h b/gcc/config/rs6000/750cl.h index d01761b2ae2..b88a1942685 100644 --- a/gcc/config/rs6000/750cl.h +++ b/gcc/config/rs6000/750cl.h @@ -21,3 +21,6 @@ #undef TARGET_PAIRED_FLOAT #define TARGET_PAIRED_FLOAT rs6000_paired_float +#undef ASM_CPU_SPEC +#define ASM_CPU_SPEC "-m750cl" + diff --git a/gcc/config/rs6000/paired.md b/gcc/config/rs6000/paired.md index 67eee233c5e..4e41359d014 100644 --- a/gcc/config/rs6000/paired.md +++ b/gcc/config/rs6000/paired.md @@ -21,6 +21,12 @@ ;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, ;; MA 02110-1301, USA. +(define_constants +[(UNSPEC_INTERHI_V2SF 330) + (UNSPEC_INTERLO_V2SF 331) + (UNSPEC_EXTEVEN_V2SF 332) + (UNSPEC_EXTODD_V2SF 333) +]) (define_insn "negv2sf2" [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") @@ -370,3 +376,145 @@ "ps_merge00 %0, %1, %2" [(set_attr "type" "fp")]) +(define_expand "sminv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (smin:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" +{ + rtx tmp = gen_reg_rtx (V2SFmode); + + emit_insn (gen_subv2sf3 (tmp, operands[1], operands[2])); + emit_insn (gen_selv2sf4 (operands[0], tmp, operands[2], operands[1], CONST0_RTX (SFmode))); + DONE; +}) + +(define_expand "smaxv2sf3" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (smax:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT" +{ + rtx tmp = gen_reg_rtx (V2SFmode); + + emit_insn (gen_subv2sf3 (tmp, operands[1], operands[2])); + emit_insn (gen_selv2sf4 (operands[0], tmp, operands[1], operands[2], CONST0_RTX (SFmode))); + DONE; +}) + +(define_expand "reduc_smax_v2sf" + [(match_operand:V2SF 0 "gpc_reg_operand" "=f") + (match_operand:V2SF 1 "gpc_reg_operand" "f")] + "TARGET_PAIRED_FLOAT" +{ + rtx tmp_swap = gen_reg_rtx (V2SFmode); + rtx tmp = gen_reg_rtx (V2SFmode); + + emit_insn (gen_paired_merge10 (tmp_swap, operands[1], operands[1])); + emit_insn (gen_subv2sf3 (tmp, operands[1], tmp_swap)); + emit_insn (gen_selv2sf4 (operands[0], tmp, operands[1], tmp_swap, CONST0_RTX (SFmode))); + + DONE; +}) + +(define_expand "reduc_smin_v2sf" + [(match_operand:V2SF 0 "gpc_reg_operand" "=f") + (match_operand:V2SF 1 "gpc_reg_operand" "f")] + "TARGET_PAIRED_FLOAT" +{ + rtx tmp_swap = gen_reg_rtx (V2SFmode); + rtx tmp = gen_reg_rtx (V2SFmode); + + emit_insn (gen_paired_merge10 (tmp_swap, operands[1], operands[1])); + emit_insn (gen_subv2sf3 (tmp, operands[1], tmp_swap)); + emit_insn (gen_selv2sf4 (operands[0], tmp, tmp_swap, operands[1], CONST0_RTX (SFmode))); + + DONE; +}) + +(define_expand "vec_interleave_highv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")] + UNSPEC_INTERHI_V2SF))] + "TARGET_PAIRED_FLOAT" + " +{ + emit_insn (gen_paired_merge00 (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_expand "vec_interleave_lowv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")] + UNSPEC_INTERLO_V2SF))] + "TARGET_PAIRED_FLOAT" + " +{ + emit_insn (gen_paired_merge11 (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_expand "vec_extract_evenv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")] + UNSPEC_EXTEVEN_V2SF))] + "TARGET_PAIRED_FLOAT" + " +{ + emit_insn (gen_paired_merge00 (operands[0], operands[1], operands[2])); + DONE; +}") + +(define_expand "vec_extract_oddv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")] + UNSPEC_EXTODD_V2SF))] + "TARGET_PAIRED_FLOAT" + " +{ + emit_insn (gen_paired_merge11 (operands[0], operands[1], operands[2])); + DONE; +}") + + +(define_expand "reduc_splus_v2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (match_operand:V2SF 1 "gpc_reg_operand" "f"))] + "TARGET_PAIRED_FLOAT" + " +{ + emit_insn (gen_paired_sum1 (operands[0], operands[1], operands[1], operands[1])); + DONE; +}") + +(define_expand "movmisalignv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (match_operand:V2SF 1 "gpc_reg_operand" "f"))] + "TARGET_PAIRED_FLOAT" +{ + paired_expand_vector_move (operands); + DONE; +}) + +(define_expand "vcondv2sf" + [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f") + (if_then_else:V2SF + (match_operator 3 "gpc_reg_operand" + [(match_operand:V2SF 4 "gpc_reg_operand" "f") + (match_operand:V2SF 5 "gpc_reg_operand" "f")]) + (match_operand:V2SF 1 "gpc_reg_operand" "f") + (match_operand:V2SF 2 "gpc_reg_operand" "f")))] + "TARGET_PAIRED_FLOAT && flag_unsafe_math_optimizations" + " +{ + if (paired_emit_vector_cond_expr (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5])) + DONE; + else + FAIL; +}") + diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index f2a5061abc4..336eceef7b2 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -123,6 +123,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) } if (TARGET_SPE) builtin_define ("__SPE__"); + if (TARGET_PAIRED_FLOAT) + builtin_define ("__PAIRED__"); if (TARGET_SOFT_FLOAT) builtin_define ("_SOFT_FLOAT"); if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE))) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 8c9eb0696c1..56bb376a77d 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -65,6 +65,12 @@ extern int mems_ok_for_quad_peep (rtx, rtx); extern bool gpr_or_gpr_p (rtx, rtx); extern enum reg_class rs6000_secondary_reload_class (enum reg_class, enum machine_mode, rtx); + +extern int paired_emit_vector_cond_expr (rtx, rtx, rtx, + rtx, rtx, rtx); +extern void paired_expand_vector_move (rtx operands[]); + + extern int ccr_bit (rtx, int); extern int extract_MB (rtx); extern int extract_ME (rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index cbbb8a84a81..3dc6c15ad56 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2773,6 +2773,103 @@ paired_expand_vector_init (rtx target, rtx vals) emit_move_insn (target, new); } +void +paired_expand_vector_move (rtx operands[]) +{ + rtx op0 = operands[0], op1 = operands[1]; + + emit_move_insn (op0, op1); +} + +/* Emit vector compare for code RCODE. DEST is destination, OP1 and + OP2 are two VEC_COND_EXPR operands, CC_OP0 and CC_OP1 are the two + operands for the relation operation COND. This is a recursive + function. */ + +static void +paired_emit_vector_compare (enum rtx_code rcode, + rtx dest, rtx op0, rtx op1, + rtx cc_op0, rtx cc_op1) +{ + rtx tmp = gen_reg_rtx (V2SFmode); + rtx tmp1, max, min, equal_zero; + + gcc_assert (TARGET_PAIRED_FLOAT); + gcc_assert (GET_MODE (op0) == GET_MODE (op1)); + + switch (rcode) + { + case LT: + case LTU: + paired_emit_vector_compare (GE, dest, op1, op0, cc_op0, cc_op1); + return; + case GE: + case GEU: + emit_insn (gen_subv2sf3 (tmp, cc_op0, cc_op1)); + emit_insn (gen_selv2sf4 (dest, tmp, op0, op1, CONST0_RTX (SFmode))); + return; + case LE: + case LEU: + paired_emit_vector_compare (GE, dest, op0, op1, cc_op1, cc_op0); + return; + case GT: + paired_emit_vector_compare (LE, dest, op1, op0, cc_op0, cc_op1); + return; + case EQ: + tmp1 = gen_reg_rtx (V2SFmode); + max = gen_reg_rtx (V2SFmode); + min = gen_reg_rtx (V2SFmode); + equal_zero = gen_reg_rtx (V2SFmode); + + emit_insn (gen_subv2sf3 (tmp, cc_op0, cc_op1)); + emit_insn (gen_selv2sf4 + (max, tmp, cc_op0, cc_op1, CONST0_RTX (SFmode))); + emit_insn (gen_subv2sf3 (tmp, cc_op1, cc_op0)); + emit_insn (gen_selv2sf4 + (min, tmp, cc_op0, cc_op1, CONST0_RTX (SFmode))); + emit_insn (gen_subv2sf3 (tmp1, min, max)); + emit_insn (gen_selv2sf4 (dest, tmp1, op0, op1, CONST0_RTX (SFmode))); + return; + case NE: + paired_emit_vector_compare (EQ, dest, op1, op0, cc_op0, cc_op1); + return; + case UNLE: + paired_emit_vector_compare (LE, dest, op1, op0, cc_op0, cc_op1); + return; + case UNLT: + paired_emit_vector_compare (LT, dest, op1, op0, cc_op0, cc_op1); + return; + case UNGE: + paired_emit_vector_compare (GE, dest, op1, op0, cc_op0, cc_op1); + return; + case UNGT: + paired_emit_vector_compare (GT, dest, op1, op0, cc_op0, cc_op1); + return; + default: + gcc_unreachable (); + } + + return; +} + +/* Emit vector conditional expression. + DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands. + CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */ + +int +paired_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2, + rtx cond, rtx cc_op0, rtx cc_op1) +{ + enum rtx_code rcode = GET_CODE (cond); + + if (!TARGET_PAIRED_FLOAT) + return 0; + + paired_emit_vector_compare (rcode, dest, op1, op2, cc_op0, cc_op1); + + return 1; +} + /* Initialize vector TARGET to VALS. */ void |