summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-31 17:04:42 +0000
committerrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-31 17:04:42 +0000
commita39ea4df3097965e689783caa9098d496b837c9f (patch)
treeffcd2f0cd6e20a0379266c1ddc17953d9734dcc9 /gcc/config/rs6000
parented69e50620a42f9b5a5dc320e7ae3091a2f378cd (diff)
downloadgcc-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.h3
-rw-r--r--gcc/config/rs6000/paired.md148
-rw-r--r--gcc/config/rs6000/rs6000-c.c2
-rw-r--r--gcc/config/rs6000/rs6000-protos.h6
-rw-r--r--gcc/config/rs6000/rs6000.c97
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