Patchwork Fix vec_perm_expr for fp-only targets

login
register
mail settings
Submitter Richard Henderson
Date Dec. 10, 2011, 8:49 p.m.
Message ID <4EE3C5DE.7080204@redhat.com>
Download mbox | patch
Permalink /patch/130565/
State New
Headers show

Comments

Richard Henderson - Dec. 10, 2011, 8:49 p.m.
Targets like mips -mpaired-single which have support for V2SF vectors,
but no support for V2SI vectors, will expand the V2SI constant parameter
to VEC_PERM_EXPR in DImode.  Which is absolutely not what we expect in
expand_vec_perm, and is somewhat less than useful.

Tested on x86_64-linux (where it doesn't fire, of course), and lightly
tested on mips64-elf.


r~
commit d9198d8536af4470fffc9d1e70626d106d8a8ac7
Author: rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Sat Dec 10 20:43:03 2011 +0000

    Force the creation of a CONST_VECTOR for expand_vec_perm.
    
            * expr.c (expand_expr_real_2) [VEC_PERM_EXPR]: Avoid passing a
            CONST_INT to expand_vec_perm as the selector.
            * optabs.c (expand_vec_perm): Assert the selector is of a proper mode.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182192 138bc75d-0d04-0410-961f-82ee72b054a4

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3490874..885f535 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,11 @@ 
 2011-12-10  Richard Henderson  <rth@redhat.com>
 
+	* expr.c (expand_expr_real_2) [VEC_PERM_EXPR]: Avoid passing a
+	CONST_INT to expand_vec_perm as the selector.
+	* optabs.c (expand_vec_perm): Assert the selector is of a proper mode.
+
+2011-12-10  Richard Henderson  <rth@redhat.com>
+
 	* genmodes.c (struct mode_data): Remove wider_2x member.
 	(blank_mode): Adjust initializer.
 	(calc_wider_mode): Use XALLOCAVEC.
diff --git a/gcc/expr.c b/gcc/expr.c
index b2166bd..aa78468 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8716,6 +8716,23 @@  expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
     case VEC_PERM_EXPR:
       expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
       op2 = expand_normal (treeop2);
+
+      /* Careful here: if the target doesn't support integral vector modes,
+	 a constant selection vector could wind up smooshed into a normal
+	 integral constant.  */
+      if (CONSTANT_P (op2) && GET_CODE (op2) != CONST_VECTOR)
+	{
+	  tree sel_type = TREE_TYPE (treeop2);
+	  enum machine_mode vmode
+	    = mode_for_vector (TYPE_MODE (TREE_TYPE (sel_type)),
+			       TYPE_VECTOR_SUBPARTS (sel_type));
+	  gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
+	  op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
+	  gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
+	}
+      else
+        gcc_assert (GET_MODE_CLASS (GET_MODE (op2)) == MODE_VECTOR_INT);
+
       temp = expand_vec_perm (mode, op0, op1, op2, target);
       gcc_assert (temp);
       return temp;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 3f50177..2c3a640 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -7038,7 +7038,8 @@  expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
     }
 
   /* If the input is a constant, expand it specially.  */
-  if (CONSTANT_P (sel))
+  gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
+  if (GET_CODE (sel) == CONST_VECTOR)
     {
       icode = direct_optab_handler (vec_perm_const_optab, mode);
       if (icode != CODE_FOR_nothing)
@@ -7056,7 +7057,7 @@  expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
 	    {
 	      unsigned int j, this_e;
 
-	      this_e = INTVAL (XVECEXP (sel, 0, i));
+	      this_e = INTVAL (CONST_VECTOR_ELT (sel, i));
 	      this_e &= 2 * e - 1;
 	      this_e *= u;