[gcc r17-3258] Add vector integer support to double-conversion patterns
Richard Biener via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:4c136e1d333bc4cf142adbb17d644d5ded5afe63 commit r17-3258-g4c136e1d333bc4cf142adbb17d644d5ded5afe63 Author: Richard Biener <[email protected]> Date: Thu Aug 13 09:24:09 2026 +0200 Add vector integer support to double-conversion patterns The following expands the double-conversion match patterns to also cover integer vectors (it already supports float vectors), adding required guards for supportability. I have simplified supportable_convert_operation by eliding the useless output code argument (it's always the same as the input code). * match.pd ((convert (convert @0))): Allow integer vector types, unify {inside,intrer,final}_vec, guard patterns that are not correct for vectors and those that are with checks the resulting conversion is supported by the target. * optabs-tree.h (supportable_convert_operation): Remove useless last argument. * optabs-tree.cc (supportable_convert_operation): Likewise. (supportable_half_widening_operation): Adjust. * tree-vect-stmts.cc (vectorizable_conversion): Likewise. (supportable_indirect_convert_operation): Likewise. * tree-vect-generic.cc (expand_vector_conversion): Likewise. * tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Likewise. * tree-ssa-forwprop.cc (simplify_vector_constructor): Likewise. Co-Authored-By: H.J. Lu <[email protected]> Diff: --- gcc/match.pd | 38 ++++++++++++++++++++++++-------------- gcc/optabs-tree.cc | 28 ++++++---------------------- gcc/optabs-tree.h | 8 +++----- gcc/tree-ssa-forwprop.cc | 6 ++---- gcc/tree-vect-data-refs.cc | 5 ++--- gcc/tree-vect-generic.cc | 5 ++--- gcc/tree-vect-stmts.cc | 32 ++++++++++++++------------------ 7 files changed, 53 insertions(+), 69 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 3f476cc4baad..5fc89426880d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -5839,24 +5839,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) { tree inside_type = TREE_TYPE (@0); tree inter_type = TREE_TYPE (@1); - int inside_int = INTEGRAL_TYPE_P (inside_type); + int inside_int = ANY_INTEGRAL_TYPE_P (inside_type); int inside_ptr = POINTER_TYPE_P (inside_type); int inside_float = FLOAT_TYPE_P (inside_type); - int inside_vec = VECTOR_TYPE_P (inside_type); unsigned int inside_prec = element_precision (inside_type); int inside_unsignedp = TYPE_UNSIGNED (inside_type); - int inter_int = INTEGRAL_TYPE_P (inter_type); + int inter_int = ANY_INTEGRAL_TYPE_P (inter_type); int inter_ptr = POINTER_TYPE_P (inter_type); int inter_float = FLOAT_TYPE_P (inter_type); - int inter_vec = VECTOR_TYPE_P (inter_type); unsigned int inter_prec = element_precision (inter_type); int inter_unsignedp = TYPE_UNSIGNED (inter_type); - int final_int = INTEGRAL_TYPE_P (type); + int final_int = ANY_INTEGRAL_TYPE_P (type); int final_ptr = POINTER_TYPE_P (type); int final_float = FLOAT_TYPE_P (type); - int final_vec = VECTOR_TYPE_P (type); unsigned int final_prec = element_precision (type); int final_unsignedp = TYPE_UNSIGNED (type); + int is_vec = VECTOR_TYPE_P (type); + gcc_checking_assert (is_vec == VECTOR_TYPE_P (inside_type) + && is_vec == VECTOR_TYPE_P (inter_type)); } (switch /* In addition to the cases of two conversions in a row @@ -5868,7 +5868,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type))) && (((inter_int || inter_ptr) && final_int) || (inter_float && final_float)) - && inter_prec >= final_prec) + && inter_prec >= final_prec + && (! is_vec + || supportable_convert_operation (ocvt, type, TREE_TYPE (@0)))) (ocvt @0)) /* Likewise, if the intermediate and initial types are either both @@ -5879,7 +5881,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (((inter_int && inside_int) || (inter_float && inside_float)) && (final_int || final_float) && inter_prec >= inside_prec - && (inter_float || inter_unsignedp == inside_unsignedp)) + && (inter_float || inter_unsignedp == inside_unsignedp) + && (! is_vec + || supportable_convert_operation (ocvt, type, TREE_TYPE (@0)))) (ocvt @0)) /* If we have a sign-extension of a zero-extended value, we can @@ -5892,7 +5896,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && inside_unsignedp && !inter_unsignedp) || final_prec == inter_prec || (inside_prec < inter_prec && inter_prec > final_prec - && !inside_unsignedp && inter_unsignedp))) + && !inside_unsignedp && inter_unsignedp)) + && (! is_vec + || supportable_convert_operation (ocvt, type, TREE_TYPE (@0)))) (ocvt @0)) /* Two conversions in a row are not needed unless: @@ -5907,7 +5913,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) - the final type is a pointer type and the precisions of the initial and intermediate types differ. */ (if (! inside_float && ! inter_float && ! final_float - && ! inside_vec && ! inter_vec && ! final_vec + && ! is_vec && (inter_prec >= inside_prec || inter_prec >= final_prec) && ! (inside_int && inter_int && inter_unsignedp != inside_unsignedp @@ -5925,13 +5931,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) a sign change of the type. */ (if (inside_int && inter_int && final_int && final_prec <= inside_prec - && inter_prec >= inside_prec) + && inter_prec >= inside_prec + && (! is_vec + || supportable_convert_operation (ocvt, type, TREE_TYPE (@0)))) (convert @0)) /* A truncation to an unsigned type (a zero-extension) should be canonicalized as bitwise and of a mask. */ (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion. */ && final_int && inter_int && inside_int + && ! is_vec && final_prec >= inside_prec && inside_prec > inter_prec && inter_unsignedp) @@ -5944,9 +5953,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) represent it exactly and back to an integer, we can skip the floating-point conversion. */ (if (GIMPLE /* PR66211 */ - && inside_int && inter_float && final_int && - (unsigned) significand_size (TYPE_MODE (inter_type)) - >= inside_prec - !inside_unsignedp) + && inside_int && inter_float && final_int + && ! is_vec + && ((unsigned) significand_size (TYPE_MODE (inter_type)) + >= inside_prec - !inside_unsignedp)) (convert @0))))))) /* (float_type)(integer_type) x -> trunc (x) if the type of x matches diff --git a/gcc/optabs-tree.cc b/gcc/optabs-tree.cc index b7a1cf1f7d8b..5fbdcd3a730d 100644 --- a/gcc/optabs-tree.cc +++ b/gcc/optabs-tree.cc @@ -316,7 +316,6 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out, tree vectype_in, enum tree_code *code1) { machine_mode m1,m2; - enum tree_code dummy_code; optab op; gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in)); @@ -343,8 +342,7 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out, return false; } - if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in, - &dummy_code)) + if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in)) return false; op = optab_for_tree_code (*code1, vectype_out, optab_vector); @@ -360,16 +358,11 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out, Convert operations we currently support directly are FIX_TRUNC and FLOAT. This function checks if these operations are supported - by the target platform directly (via vector tree-codes). - - Output: - - CODE1 is code of vector operation to be used when - vectorizing the operation, if available. */ + by the target platform directly (via vector tree-codes). */ bool supportable_convert_operation (enum tree_code code, - tree vectype_out, tree vectype_in, - enum tree_code *code1) + tree vectype_out, tree vectype_in) { machine_mode m1,m2; bool truncp; @@ -389,24 +382,15 @@ supportable_convert_operation (enum tree_code code, || (code == FLOAT_EXPR && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in)) != CODE_FOR_nothing)) - { - *code1 = code; - return true; - } + return true; if (GET_MODE_UNIT_PRECISION (m1) > GET_MODE_UNIT_PRECISION (m2) && can_extend_p (m1, m2, TYPE_UNSIGNED (vectype_in))) - { - *code1 = code; - return true; - } + return true; if (GET_MODE_UNIT_PRECISION (m1) < GET_MODE_UNIT_PRECISION (m2) && convert_optab_handler (trunc_optab, m1, m2) != CODE_FOR_nothing) - { - *code1 = code; - return true; - } + return true; return false; } diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h index dad9ed9b0bae..fb9469aaece8 100644 --- a/gcc/optabs-tree.h +++ b/gcc/optabs-tree.h @@ -37,11 +37,9 @@ enum optab_subtype the second argument. The third argument distinguishes between the types of vector shifts and rotates. */ optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype); -bool -supportable_half_widening_operation (enum tree_code, tree, tree, - enum tree_code *); -bool supportable_convert_operation (enum tree_code, tree, tree, - enum tree_code *); +bool supportable_half_widening_operation (enum tree_code, tree, tree, + enum tree_code *); +bool supportable_convert_operation (enum tree_code, tree, tree); bool expand_vec_cmp_expr_p (tree, tree, enum tree_code); bool expand_vec_cond_expr_p (tree, tree); void init_tree_optimization_optabs (tree); diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 75f06c6ba410..0531311444b9 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -4112,8 +4112,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (conv_code == ERROR_MARK && nelts != refnelts) conv_src_type = type; if (conv_code != ERROR_MARK - && !supportable_convert_operation (conv_code, type, conv_src_type, - &conv_code)) + && !supportable_convert_operation (conv_code, type, conv_src_type)) { /* Only few targets implement direct conversion patterns so try some simple special cases via VEC_[UN]PACK[_FLOAT]_LO_EXPR. */ @@ -4275,8 +4274,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) tree mask_type, perm_type; perm_type = TREE_TYPE (orig[0]); if (conv_code != ERROR_MARK - && !supportable_convert_operation (conv_code, type, conv_src_type, - &conv_code)) + && !supportable_convert_operation (conv_code, type, conv_src_type)) return false; /* Now that we know the number of elements of the source build the diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index 92aecc656e13..1aa0303d2660 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -4726,7 +4726,6 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, /* Second pass: No direct match. This means we try to find a sign-swapped offset vectype. */ - enum tree_code tmp; for (unsigned int i = 0; i < configs.length (); i++) { unsigned int precision @@ -4735,7 +4734,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, && precision >= needed_precision && (supportable_convert_operation (CONVERT_EXPR, configs[i].offset_vectype, - offset_vectype, &tmp) + offset_vectype) || (needed_precision == offset_precision && tree_nop_conversion_p (configs[i].offset_vectype, offset_vectype)))) @@ -4789,7 +4788,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, && precision >= needed_precision && (supportable_convert_operation (CONVERT_EXPR, configs[i].offset_vectype, - offset_vectype, &tmp) + offset_vectype) || (needed_precision == offset_precision && tree_nop_conversion_p (configs[i].offset_vectype, offset_vectype)))) diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc index a8c319749733..b1491bd39adf 100644 --- a/gcc/tree-vect-generic.cc +++ b/gcc/tree-vect-generic.cc @@ -1929,12 +1929,11 @@ expand_vector_conversion (gimple_stmt_iterator *gsi) { tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts); tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts); - if (supportable_convert_operation (code, ret1_type, arg1_type, - &code1)) + if (supportable_convert_operation (code, ret1_type, arg1_type)) { new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, ret_type, arg1_type, arg, - NULL_TREE, code1, false); + NULL_TREE, code, false); g = gimple_build_assign (lhs, new_rhs); gsi_replace (gsi, g, false); return; diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 50fa0e4bc422..a023977bc51f 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -5554,12 +5554,11 @@ vectorizable_conversion (vec_info *vinfo, if (GET_MODE_SIZE (rhs_mode) == fltsz) { - tc1 = ERROR_MARK; gcc_assert (code.is_tree_code ()); if (!supportable_convert_operation ((tree_code) code, vectype_out, - cvt_type, &tc1)) + cvt_type)) goto unsupported; - codecvt1 = tc1; + codecvt1 = code; } else if (!supportable_widening_operation (code, vectype_out, cvt_type, evenodd_ok, @@ -5610,9 +5609,9 @@ vectorizable_conversion (vec_info *vinfo, cvt_type = get_same_sized_vectype (cvt_type, vectype_in); if (cvt_type == NULL_TREE) goto unsupported; - if (supportable_convert_operation ((tree_code) code, cvt_type, vectype_in, - &tc1)) - codecvt1 = tc1; + if (supportable_convert_operation ((tree_code) code, cvt_type, + vectype_in)) + codecvt1 = code; else goto unsupported; if (supportable_narrowing_operation (NOP_EXPR, vectype_out, cvt_type, @@ -5652,9 +5651,9 @@ vectorizable_conversion (vec_info *vinfo, &interm_types)) goto unsupported; if (supportable_convert_operation ((tree_code) code, vectype_out, - cvt_type, &tc1)) + cvt_type)) { - codecvt1 = tc1; + codecvt1 = code; modifier = NARROW_SRC; break; } @@ -14300,17 +14299,16 @@ supportable_indirect_convert_operation (code_helper code, bool found_mode = false; scalar_mode lhs_mode = GET_MODE_INNER (TYPE_MODE (vectype_out)); scalar_mode rhs_mode = GET_MODE_INNER (TYPE_MODE (vectype_in)); - tree_code tc1, tc2, code1, code2; + tree_code code1, code2; tree cvt_type = NULL_TREE; poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (vectype_in); if (supportable_convert_operation ((tree_code) code, vectype_out, - vectype_in, - &tc1)) + vectype_in)) { - converts.safe_push (std::make_pair (vectype_out, tc1)); + converts.safe_push (std::make_pair (vectype_out, (tree_code) code)); return true; } @@ -14412,11 +14410,9 @@ supportable_indirect_convert_operation (code_helper code, if (cvt_type == NULL_TREE || maybe_ne (TYPE_VECTOR_SUBPARTS (cvt_type), nelts) || !supportable_convert_operation ((tree_code) code1, - vectype_out, - cvt_type, &tc1) + vectype_out, cvt_type) || !supportable_convert_operation ((tree_code) code2, - cvt_type, - vectype_in, &tc2)) + cvt_type, vectype_in)) continue; found_mode = true; @@ -14425,9 +14421,9 @@ supportable_indirect_convert_operation (code_helper code, if (found_mode) { - converts.safe_push (std::make_pair (cvt_type, tc2)); + converts.safe_push (std::make_pair (cvt_type, code2)); if (TYPE_MODE (cvt_type) != TYPE_MODE (vectype_out)) - converts.safe_push (std::make_pair (vectype_out, tc1)); + converts.safe_push (std::make_pair (vectype_out, code1)); return true; } }