diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2023-02-14 09:18:07 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2023-02-14 09:18:07 +0000 |
commit | b9c78605039f839f3c79ad8fca4f60ea9a5654ed (patch) | |
tree | 0be016027af538a69102c1df401c67b21290c7ac /gcc/tree-vect-stmts.cc | |
parent | 4f5a1198065dc078f8099db628da7b06a2666f34 (diff) | |
download | gcc-b9c78605039f839f3c79ad8fca4f60ea9a5654ed.zip gcc-b9c78605039f839f3c79ad8fca4f60ea9a5654ed.tar.gz gcc-b9c78605039f839f3c79ad8fca4f60ea9a5654ed.tar.bz2 |
vect: Make partial trapping ops use predication [PR96373]
PR96373 points out that a predicated SVE loop currently converts
trapping unconditional ops into unpredicated vector ops. Doing
the operation on inactive lanes can then raise an exception.
As discussed in the PR trail, we aren't 100% consistent about
whether we preserve traps or not. But the direction of travel
is clearly to improve that rather than live with it. This patch
tries to do that for the SVE case.
Doing this regresses gcc.target/aarch64/sve/fabd_1.c. I've added
-fno-trapping-math for now and filed PR108571 to track it.
A similar problem applies to fsubr_1.c.
I think this is likely to regress Power 10, since conditional
operations are only available for masked loops. I think we'll
need to add -fno-trapping-math to any affected testcases,
but I don't have a Power 10 system to test on.
gcc/
PR tree-optimization/96373
* tree-vect-stmts.cc (vectorizable_operation): Predicate trapping
operations on the loop mask. Reject partial vectors if this isn't
possible.
gcc/testsuite/
PR tree-optimization/96373
PR tree-optimization/108571
* gcc.target/aarch64/sve/fabd_1.c: Add -fno-trapping-math.
* gcc.target/aarch64/sve/fsubr_1.c: Likewise.
* gcc.target/aarch64/sve/fmul_1.c: Expect predicate ops.
* gcc.target/aarch64/sve/fp_arith_1.c: Likewise.
Diffstat (limited to 'gcc/tree-vect-stmts.cc')
-rw-r--r-- | gcc/tree-vect-stmts.cc | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 09b5af6..df6239a 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -6332,6 +6332,7 @@ vectorizable_operation (vec_info *vinfo, int reduc_idx = STMT_VINFO_REDUC_IDX (stmt_info); vec_loop_masks *masks = (loop_vinfo ? &LOOP_VINFO_MASKS (loop_vinfo) : NULL); internal_fn cond_fn = get_conditional_internal_fn (code); + bool could_trap = gimple_could_trap_p (stmt); if (!vec_stmt) /* transformation not required. */ { @@ -6340,7 +6341,7 @@ vectorizable_operation (vec_info *vinfo, keeping the inactive lanes as-is. */ if (loop_vinfo && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) - && reduc_idx >= 0) + && (could_trap || reduc_idx >= 0)) { if (cond_fn == IFN_LAST || !direct_internal_fn_supported_p (cond_fn, vectype, @@ -6483,16 +6484,31 @@ vectorizable_operation (vec_info *vinfo, vop1 = ((op_type == binary_op || op_type == ternary_op) ? vec_oprnds1[i] : NULL_TREE); vop2 = ((op_type == ternary_op) ? vec_oprnds2[i] : NULL_TREE); - if (masked_loop_p && reduc_idx >= 0) + if (masked_loop_p && (reduc_idx >= 0 || could_trap)) { - /* Perform the operation on active elements only and take - inactive elements from the reduction chain input. */ - gcc_assert (!vop2); - vop2 = reduc_idx == 1 ? vop1 : vop0; tree mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies, vectype, i); - gcall *call = gimple_build_call_internal (cond_fn, 4, mask, - vop0, vop1, vop2); + auto_vec<tree> vops (5); + vops.quick_push (mask); + vops.quick_push (vop0); + if (vop1) + vops.quick_push (vop1); + if (vop2) + vops.quick_push (vop2); + if (reduc_idx >= 0) + { + /* Perform the operation on active elements only and take + inactive elements from the reduction chain input. */ + gcc_assert (!vop2); + vops.quick_push (reduc_idx == 1 ? vop1 : vop0); + } + else + { + auto else_value = targetm.preferred_else_value + (cond_fn, vectype, vops.length () - 1, &vops[1]); + vops.quick_push (else_value); + } + gcall *call = gimple_build_call_internal_vec (cond_fn, vops); new_temp = make_ssa_name (vec_dest, call); gimple_call_set_lhs (call, new_temp); gimple_call_set_nothrow (call, true); |