-/* Return true if we can implement with VEC_PERM_EXPR for this target.
- If PSEL is non-null, return the selector for the permutation. */
-
-bool
-can_vec_perm_for_code_p (enum tree_code code, enum machine_mode mode,
- rtx *psel)
-{
- bool need_sel_test = false;
- enum insn_code icode;
-
- /* If the target doesn't implement a vector mode for the vector type,
- then no operations are supported. */
- if (!VECTOR_MODE_P (mode))
- return false;
-
- /* Do as many tests as possible without reqiring the selector. */
- icode = direct_optab_handler (vec_perm_optab, mode);
- if (icode == CODE_FOR_nothing && GET_MODE_INNER (mode) != QImode)
- {
- enum machine_mode qimode
- = mode_for_vector (QImode, GET_MODE_SIZE (mode));
- if (VECTOR_MODE_P (qimode))
- icode = direct_optab_handler (vec_perm_optab, qimode);
- }
- if (icode == CODE_FOR_nothing)
- {
- icode = direct_optab_handler (vec_perm_const_optab, mode);
- if (icode != CODE_FOR_nothing
- && targetm.vectorize.vec_perm_const_ok != NULL)
- need_sel_test = true;
- }
- if (icode == CODE_FOR_nothing)
- return false;
-
- /* If the selector is required, or if we need to test it, build it. */
- if (psel || need_sel_test)
- {
- int i, nelt = GET_MODE_NUNITS (mode), alt = 0;
- unsigned char *data = XALLOCAVEC (unsigned char, nelt);
-
- switch (code)
- {
- case VEC_EXTRACT_ODD_EXPR:
- alt = 1;
- /* FALLTHRU */
- case VEC_EXTRACT_EVEN_EXPR:
- for (i = 0; i < nelt; ++i)
- data[i] = i * 2 + alt;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- if (need_sel_test
- && !targetm.vectorize.vec_perm_const_ok (mode, data))
- return false;
-
- if (psel)
- {
- rtvec vec = rtvec_alloc (nelt);
- enum machine_mode imode = mode;
-
- for (i = 0; i < nelt; ++i)
- RTVEC_ELT (vec, i) = GEN_INT (data[i]);
-
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
- {
- imode = int_mode_for_mode (GET_MODE_INNER (mode));
- imode = mode_for_vector (imode, nelt);
- gcc_assert (GET_MODE_CLASS (imode) == MODE_VECTOR_INT);
- }
-
- *psel = gen_rtx_CONST_VECTOR (imode, vec);
- }
- }
-
- return true;
-}
-