https://gcc.gnu.org/g:dbb05d561df3c1a70c23f47a4531abff456e4247
commit r17-5734-gdbb05d561df3c1a70c23f47a4531abff456e4247 Author: liuhongt <[email protected]> Date: Tue Oct 27 20:24:18 2026 -0700 vect: Vectorize exact division by a power of two as a shift vect_recog_divmod_pattern expanded EXACT_DIV_EXPR by a power of two like TRUNC_DIV_EXPR, adding the divisor minus one to negative dividends before the arithmetic shift. The pattern only handles positive divisors, and the dividend of an exact division is a multiple of the divisor, so the arithmetic shift alone gives the result, also for negative dividends: the rounding adjustment only matters when there is a remainder. For pointer differences, which are exact divisions by the element size, this removes a compare, an and and an add per vector. gcc/ChangeLog: * tree-vect-patterns.cc (vect_recog_divmod_pattern): Use a plain arithmetic shift for EXACT_DIV_EXPR by a positive power of two. gcc/testsuite/ChangeLog: * gcc.target/i386/vect-exact-div-pow2.c: New test. Diff: --- gcc/testsuite/gcc.target/i386/vect-exact-div-pow2.c | 16 ++++++++++++++++ gcc/tree-vect-patterns.cc | 14 +++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.target/i386/vect-exact-div-pow2.c b/gcc/testsuite/gcc.target/i386/vect-exact-div-pow2.c new file mode 100644 index 000000000000..374ad2eb81a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-exact-div-pow2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mavx2 -mno-avx512f -fdump-tree-vect-details" } */ + +/* An exact division by a power of two, such as a pointer difference, is + vectorized as an arithmetic shift without the rounding adjustment of + negative dividends needed for truncating division. */ + +void +f (long *__restrict out, int **__restrict p, int **__restrict q) +{ + for (int i = 0; i < 1024; i++) + out[i] = p[i] - q[i]; +} + +/* { dg-final { scan-tree-dump "divmod pattern recognized" "vect" } } */ +/* { dg-final { scan-assembler-not "vpcmp" } } */ diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 49c85c703033..79e984af0244 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -5420,6 +5420,19 @@ vect_recog_divmod_pattern (vec_info *vinfo, *type_out = vectype; + /* OPRND1 is a positive power of two here and the dividend of an + exact division is a multiple of it, so the right shift is exact + also for negative dividends and needs no rounding fixup. */ + if (rhs_code == EXACT_DIV_EXPR) + { + tree shift = build_int_cst (itype, tree_log2 (oprnd1)); + pattern_stmt + = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), + RSHIFT_EXPR, oprnd0, shift); + gimple_set_location (pattern_stmt, gimple_location (last_stmt)); + return pattern_stmt; + } + /* Check if the target supports this internal function. */ internal_fn ifn = IFN_DIV_POW2; if (!TYPE_UNSIGNED (itype) @@ -5465,7 +5478,6 @@ vect_recog_divmod_pattern (vec_info *vinfo, truth_type_for (vectype), itype); tree div_result = NULL_TREE; if (rhs_code == TRUNC_DIV_EXPR - || rhs_code == EXACT_DIV_EXPR || rhs_code == FLOOR_DIV_EXPR || rhs_code == CEIL_DIV_EXPR || rhs_code == ROUND_DIV_EXPR)
