> -----Original Message----- > From: Andrea Pinski <[email protected]> > Sent: 23 September 2026 18:47 > To: Tamar Christina <[email protected]> > Cc: [email protected]; nd <[email protected]>; [email protected]; > [email protected] > Subject: Re: [patch 9/14][isel]: form conditional vector compare IFNs > > On Mon, Sep 14, 2026 at 2:32 AM Tamar Christina > <[email protected]> wrote: > > > > This patch forms conditional vector compare IFNs during gimple isel. > > > > The match.pd rules recognize integer vector compare idioms where a > compare is > > guarded by another vector predicate. gimple isel then lowers those idioms > to > > IFN_COND_VEC_CMP or IFN_COND_LEN_VEC_CMP when the target reports > support for > > the corresponding optab. If the original compare was only used by the > > converted statement, the patch removes that now-dead definition. > > > > The tests for this lowering are kept with the later AArch64 SVE expander > > patch, since they require the SVE cond_vec_cmp target support added there. > > > > Bootstrapped Regtested on aarch64-none-linux-gnu, > > arm-none-linux-gnueabihf, x86_64-pc-linux-gnu > > -m32, -m64 and no issues. > > > > -O3, profiled, profiled -O3 and -O3 -LTO bootstrap tested and no issues. > > > > Also SPECCPU 2017 and SPECCPU 2026 tested. > > > > OK for master? > > > > gcc/ChangeLog: > > * gimple-isel.cc (gimple_convert_conditional_compare): Declare. > > (gimple_convert_conditional_len_compare): Likewise. > > (maybe_duplicate_comparison): Fix comment. > > (gimple_expand_conditional_compare): New function. > > (pass_gimple_isel::execute): Use it. > > * match.pd (convert_conditional_compare): New match. > > (convert_conditional_len_compare): Likewise. > > > > --- > > diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc > > index > 1d346ee124ffdfdccf658ea79cc72cbf80240f81..9bd523cd81be541383ea9c9 > 62a9180565cea9f0d 100644 > > --- a/gcc/gimple-isel.cc > > +++ b/gcc/gimple-isel.cc > > @@ -327,8 +327,8 @@ maybe_duplicate_comparison (gassign *stmt, > basic_block bb) > > tree lhs = gimple_assign_lhs (stmt); > > unsigned cnt = 0; > > > > - /* This is should not be used for -O0 nor it is not useful > > - when ter is turned off. */ > > + /* This should not be used for -O0 and is not useful when TER is turned > > + off. */ > > if (!optimize || !flag_tree_ter) > > return; > > > > @@ -376,6 +376,9 @@ maybe_duplicate_comparison (gassign *stmt, > basic_block bb) > > extern bool gimple_nop_atomic_bit_test_and_p (tree, tree *, > > tree (*) (tree)); > > extern bool gimple_nop_convert (tree, tree*, tree (*) (tree)); > > +extern bool gimple_convert_conditional_compare (tree, tree *, tree (*) > (tree)); > > +extern bool gimple_convert_conditional_len_compare (tree, tree *, > > + tree (*) (tree)); > > > > namespace { > > > > @@ -488,6 +491,74 @@ convert_atomic_bit_not (enum internal_fn fn, > gimple *use_stmt, > > return use_stmt; > > } > > > > +/* Try to replace STMT with a conditional vector comparison internal > function. > > + The generated matchers recognize the source patterns and capture the > mask, > > + operands and original comparison SSA name. If the original comparison > > is > > + used only by STMT, store its defining statement in *DEAD_CMP_DEF so > that the > > + caller can remove it after replacing STMT. */ > > + > > +static gimple * > > +gimple_expand_conditional_compare (gimple_stmt_iterator *gsi, > > + gassign **dead_cmp_def) > > +{ > > + gimple *stmt = gsi_stmt (*gsi); > > + *dead_cmp_def = nullptr; > > + tree lhs = gimple_get_lhs (stmt); > > + > > + if (!lhs || TREE_CODE (lhs) != SSA_NAME) > > + return nullptr; > > + > > + tree ops[6] = {}; > > + location_t loc = gimple_location (stmt); > > + bool len_p = false; > > + if (!gimple_convert_conditional_compare (lhs, ops, nullptr) > > + && !gimple_convert_conditional_len_compare (lhs, ops, nullptr)) > > + return nullptr; > > + len_p = ops[4] != NULL_TREE; > > + > > + unsigned int cmp_opno = len_p ? 5 : 3; > > + tree cmp_name = ops[cmp_opno]; > > + if (TREE_CODE (cmp_name) != SSA_NAME) > > + return nullptr; > > + > > + gassign *cmp_def = dyn_cast<gassign *> (SSA_NAME_DEF_STMT > (cmp_name)); > > + if (!cmp_def) > > + return nullptr; > > + > > + tree_code code = gimple_assign_rhs_code (cmp_def); > > + if (TREE_CODE_CLASS (code) != tcc_comparison) > > + return nullptr; > > + > > + internal_fn ifn = len_p ? IFN_COND_LEN_VEC_CMP : > IFN_COND_VEC_CMP; > > + bool supported_p > > + = (len_p > > + ? expand_cond_len_vec_cmp_p (code, ops[0], ops[1], ops[2], > > + ops[3], ops[4]) > > + : expand_cond_vec_cmp_p (code, ops[0], ops[1], ops[2])); > > + if (!supported_p) > > + return nullptr; > > + > > + auto_vec<tree, 6> args; > > + args.quick_push (build_int_cst (integer_type_node, code)); > > + args.quick_push (ops[0]); > > + args.quick_push (ops[1]); > > + args.quick_push (ops[2]); > > + if (len_p) > > + { > > + args.quick_push (ops[3]); > > + args.quick_push (ops[4]); > > + } > > + > > + gcall *call = gimple_build_call_internal_vec (ifn, args); > > + gimple_call_set_lhs (call, lhs); > > + gimple_set_location (call, loc); > > + use_operand_p use_p; > > + gimple *use_stmt; > > + if (single_imm_use (cmp_name, &use_p, &use_stmt) && use_stmt == > stmt) > > + *dead_cmp_def = cmp_def; > > + return call; > > +} > > + > > /* Optimize > > mask_2 = 1 << cnt_1; > > _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3); > > @@ -1369,6 +1440,20 @@ pass_gimple_isel::execute (struct function *fun) > > /* Give the target first try at replacing the instruction. */ > > cfg_changed |= targetm.instruction_selection (fun, &gsi); > > > > + gimple *isel_stmt = NULL; > > + gassign *dead_cmp_def = NULL; > > + if (!gsi_end_p (gsi)) > > + isel_stmt = gimple_expand_conditional_compare (&gsi, > &dead_cmp_def); > > + if (isel_stmt) > > + { > > + gsi_replace (&gsi, isel_stmt, true); > > + if (dead_cmp_def) > > + { > > + gimple_stmt_iterator cmp_gsi = gsi_for_stmt > > (dead_cmp_def); > > + gsi_remove (&cmp_gsi, true); > > + } > > + } > > + > > /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function > > calls mapping to supported optabs. */ > > gimple *g = gimple_expand_vec_cond_expr (&gsi); > > @@ -1411,4 +1496,3 @@ make_pass_gimple_isel (gcc::context *ctxt) > > { > > return new pass_gimple_isel (ctxt); > > } > > - > > diff --git a/gcc/match.pd b/gcc/match.pd > > index > c1aba410b66e38c947a4d52064fda1594934f297..db5038b7dccd030a09b6 > 7d5070a2ce2b74651184 100644 > > --- a/gcc/match.pd > > +++ b/gcc/match.pd > > @@ -13364,3 +13364,20 @@ and, > > (if (INTEGRAL_TYPE_P (type)) > > (with { tree itype = TREE_TYPE (@2); } > > (convert (minus @2 (convert:itype @1)))))) > > + > > +#if GIMPLE > > + > > +(for cmp (tcc_comparison) > > + (match (convert_conditional_compare @0 @1 @2 @3) > > + (bit_and:c @0 (cmp@3 @1 @2)) > > + (if (VECTOR_BOOLEAN_TYPE_P (type) > > + && !FLOAT_TYPE_P (TREE_TYPE (@1))))) > > Just a minor thing here. You don't need to use a for loop, you can > use tcc_comparison directly. > So this becomes: > (match (convert_conditional_compare @0 @1 @2 @3) > (bit_and:c @0 (tcc_comparison@3 @1 @2)) > (if (VECTOR_BOOLEAN_TYPE_P (type) > && !FLOAT_TYPE_P (TREE_TYPE (@1))))) > > > + > > +/* Transform .VCOND_MASK_LEN (a `cmp` b, {-1, ...}, {0, ...}, len, bias) > > + into cond_len_vec_cmp (cmp, mask, a, b, len, bias). */ > > + (match (convert_conditional_len_compare @0 @1 @2 @3 @4 @5) > > + (IFN_VCOND_MASK_LEN @0 (cmp@5 @1 @2) integer_minus_onep > integer_zerop @3 @4) > > + (if (VECTOR_BOOLEAN_TYPE_P (type) > > + && !FLOAT_TYPE_P (TREE_TYPE (@1)))))) > > Likewise.
Thanks, I learned something new :) Cheers, Tamar > > Thanks, > Andrea > > > + > > +#endif > > > > > > --
