Hi! On Mon, Nov 11, 2019 at 03:40:51PM +0800, Kewen.Lin wrote: > This is a subsequent patch to refactor the existing float point > vector comparison operator supports. The patch to fix PR92132 > supplemented vector float point comparison by exposing the names > for unordered/ordered/uneq/ltgt and adding ungt/unge/unlt/unle/ > ne. As Segher pointed out, some patterns can be refactored > together. The main link on this is: > https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00452.html > > > The refactoring mainly follows the below patterns: > > pattern 1: > lt(a,b) = gt(b,a) > le(a,b) = ge(b,a)
This is done by swap_condition normally. > pattern 2: > unge(a,b) = ~gt(b,a) > unle(a,b) = ~gt(a,b) > ne(a,b) = ~eq(a,b) > ungt(a,b) = ~ge(b,a) > unlt(a,b) = ~ge(a,b) This is reverse_condition_maybe_unordered (and a swap, in two cases). > pattern 3: > ltgt: gt(a,b) | gt(b,a) > ordered: ge(a,b) | ge(b,a) That's the only interesting one :-) > pattern 4: > uneq: ~gt(a,b) & ~gt(b,a) > unordered: ~ge(a,b) & ~ge(b,a) That is 3, reversed. > Naming the code iterators and attributes are really knotty for me :(. Maybe the above helps :-) > (vector_<code><mode> for VEC_F and vec_fp_cmp1): New > define_and_split. > +;; code iterators and attributes for vector FP comparison operators: > + > +;; 1. lt and le. > +(define_code_iterator vec_fp_cmp1 [lt le]) > +(define_code_attr vec_fp_cmp1_attr [(lt "gt") > + (le "ge")]) So this is just (a subset of) swap_condition. (I'm reordering stuff) > +; 1. For lt and le: > +; lt(a,b) = gt(b,a) > +; le(a,b) = ge(b,a) > +(define_insn_and_split "vector_<code><mode>" > [(set (match_operand:VEC_F 0 "vfloat_operand") > + (vec_fp_cmp1:VEC_F (match_operand:VEC_F 1 "vfloat_operand") > + (match_operand:VEC_F 2 "vfloat_operand")))] > "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" > "#" > "" > + [(set (match_dup 0) > + (<vec_fp_cmp1_attr>:VEC_F (match_dup 2) > + (match_dup 1)))] > { > }) Empty preparation statements (the {}) can just be left out completely. The split condition "" is incorrect, it should be "&& 1": if it starts with "&&", the insn condition is included. > +; 2. unge, unle, ne, ungt and unlt. > +(define_code_iterator vec_fp_cmp2 [unge unle ne ungt unlt]) > +(define_code_attr vec_fp_cmp2_attr [(unge "gt") > + (unle "gt") > + (ne "eq") > + (ungt "ge") > + (unlt "ge")]) > +; 2. For unge, unle, ne, ungt and unlt: > +; unge(a,b) = ~gt(b,a) > +; unle(a,b) = ~gt(a,b) > +; ne(a,b) = ~eq(a,b) > +; ungt(a,b) = ~ge(b,a) > +; unlt(a,b) = ~ge(a,b) > +(define_insn_and_split "vector_<code><mode>" > [(set (match_operand:VEC_F 0 "vfloat_operand") > + (vec_fp_cmp2:VEC_F (match_operand:VEC_F 1 "vfloat_operand") > + (match_operand:VEC_F 2 "vfloat_operand")))] > "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)" > "#" > "" > [(set (match_dup 3) > + (<vec_fp_cmp2_attr>:VEC_F (match_dup 1) > + (match_dup 2))) > (set (match_dup 0) > + (not:VEC_F (match_dup 3)))] > { > operands[3] = gen_reg_rtx (<MODE>mode); > + > + if (<CODE> == UNGE || <CODE> == UNGT) > + std::swap (operands[1], operands[2]); > }) So maybe it is simplest to *do* use match_operator here, handle all of lt gt le ge eq unge unle ungt unlt ne in one define_expand, which then swaps the condition and the args, and expand the extra not for the five where that is needed? > +;; 3. ltgt and ordered. > +(define_code_iterator vec_fp_cmp3 [ltgt ordered]) > +(define_code_attr vec_fp_cmp3_attr [(ltgt "gt") > + (ordered "ge")]) > + > +;; 4. uneq and unordered. > +(define_code_iterator vec_fp_cmp4 [uneq unordered]) > +(define_code_attr vec_fp_cmp4_attr [(uneq "gt") > + (unordered "ge")]) And then another one for ltgt uneq ordered unordered perhaps? So you'll need to define two new predicates then. Something like vector_fp_comparison_operator and, erm, vector_fp_extra_comparison_operator, which kind of sucks as a name, but there is only one ;-) Sorry for sending you first one way, and then back the other. Segher