Don't defer choice of vector type for bools (PR 92596)
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 29 Nov 2019 14:47:44 +0000 (14:47 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 29 Nov 2019 14:47:44 +0000 (14:47 +0000)
commit02d895504cc59be06fc3f7ec0cfd4eb160561211
treef5842a2462cf34f8b20f78ac536079cf262b7675
parent0c3ea6b3424ee4d32d97ca5d7453891b587b3132
Don't defer choice of vector type for bools (PR 92596)

Now that stmt_vec_info records the choice between vector mask
types and normal nonmask types, we can use that information in
vect_get_vector_types_for_stmt instead of deferring the choice
of vector type till later.

vect_get_mask_type_for_stmt used to check whether the boolean inputs
to an operation:
(a) consistently used mask types or consistently used nonmask types; and
(b) agreed on the number of elements.

(b) shouldn't be a problem when (a) is met.  If the operation
consistently uses mask types, tree-vect-patterns.c will have corrected
any mismatches in mask precision.  (This is because we only use mask
types for a small well-known set of operations and tree-vect-patterns.c
knows how to handle any that could have different mask precisions.)
And if the operation consistently uses normal nonmask types, there's
no reason why booleans should need extra vector compatibility checks
compared to ordinary integers.

So the potential difficulties all seem to come from (a).  Now that
we've chosen the result type ahead of time, we also have to consider
whether the outputs and inputs consistently use mask types.

Taking each vectorizable_* routine in turn:

- vectorizable_call

    vect_get_vector_types_for_stmt only handled booleans specially
    for gassigns, so vect_get_mask_type_for_stmt never had chance to
    handle calls.  I'm not sure we support any calls that operate on
    booleans, but as things stand, a boolean result would always have
    a nonmask type.  Presumably any vector argument would also need to
    use nonmask types, unless it corresponds to internal_fn_mask_index
    (which is already a special case).

    For safety, I've added a check for mask/nonmask combinations here
    even though we didn't check this previously.

- vectorizable_simd_clone_call

    Again, vect_get_mask_type_for_stmt never had chance to handle calls.
    The result of the call will always be a nonmask type and the patch
    for PR 92710 rejects mask arguments.  So all booleans should
    consistently use nonmask types here.

- vectorizable_conversion

    The function already rejects any conversion between booleans in which
    one type isn't a mask type.

- vectorizable_operation

    This function definitely needs a consistency check, e.g. to handle
    & and | in which one operand is loaded from memory and the other is
    a comparison result.  Ideally we'd handle this via pattern stmts
    instead (like we do for the all-mask case), but that's future work.

- vectorizable_assignment

    VECT_SCALAR_BOOLEAN_TYPE_P requires single-bit precision, so the
    current code already rejects problematic cases.

- vectorizable_load

    Loads always produce nonmask types and there are no relevant inputs
    to check against.

- vectorizable_store

    vect_check_store_rhs already rejects mask/nonmask combinations
    via useless_type_conversion_p.

- vectorizable_reduction
- vectorizable_lc_phi

    PHIs always have nonmask types.  After the change above, attempts
    to combine the PHI result with a mask type would be rejected by
    vectorizable_operation.  (Again, it would be better to handle
    this using pattern stmts.)

- vectorizable_induction

    We don't generate inductions for booleans.

- vectorizable_shift

    The function already rejects boolean shifts via type_has_mode_precision_p.

- vectorizable_condition

    The function already rejects mismatches via useless_type_conversion_p.

- vectorizable_comparison

    The function already rejects comparisons between mask and nonmask types.
    The result is always a mask type.

2019-11-29  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
PR tree-optimization/92596
* tree-vect-stmts.c (vectorizable_call): Punt on hybrid mask/nonmask
operations.
(vectorizable_operation): Likewise, instead of relying on
vect_get_mask_type_for_stmt to do this.
(vect_get_vector_types_for_stmt): Always return a vector type
immediately, rather than deferring the choice for boolean results.
Use a vector mask type instead of a normal vector if
vect_use_mask_type_p.
(vect_get_mask_type_for_stmt): Delete.
* tree-vect-loop.c (vect_determine_vf_for_stmt_1): Remove
mask_producers argument and special boolean_type_node handling.
(vect_determine_vf_for_stmt): Remove mask_producers argument and
update calls to vect_determine_vf_for_stmt_1.  Remove doubled call.
(vect_determine_vectorization_factor): Update call accordingly.
* tree-vect-slp.c (vect_build_slp_tree_1): Remove special
boolean_type_node handling.
(vect_slp_analyze_node_operations_1): Likewise.

gcc/testsuite/
PR tree-optimization/92596
* gcc.dg/vect/bb-slp-pr92596.c: New test.
* gcc.dg/vect/bb-slp-43.c: Likewise.

From-SVN: r278851
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/bb-slp-43.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c [new file with mode: 0644]
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c
gcc/tree-vect-stmts.c