Hi Segher,

on 2019/11/8 上午8:07, Segher Boessenkool wrote:
> Hi!
> 
>>> Half are pretty simple:
>>>
>>> lt(a,b) = gt(b,a)
>>> gt(a,b) = gt(a,b)
>>> eq(a,b) = eq(a,b)
>>> le(a,b) = ge(b,a)
>>> ge(a,b) = ge(a,b)
>>>
>>> ltgt(a,b) = ge(a,b) ^ ge(b,a)
>>> ord(a,b)  = ge(a,b) | ge(b,a)
>>>
>>> The other half are the negations of those:
>>>
>>> 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)
>>>
>>> uneq(a,b) = ~(ge(a,b) ^ ge(b,a))
>>> un(a,b) = ~(ge(a,b) | ge(b,a))
>>
>> Awesome!  Do you suggest refactoring on them?  :)
> 
> I'd do the first five in one pattern (which then swaps two ops and the
> condition in the lt and le case), and the other five in another pattern.
> And the rest in two or four patterns?  Just try it out, see what works
> well.  It helps to do a bunch together in one pattern, but if that then
> turns into special cases for everything, more might be lost than gained.> 

Got it, I'll make a refactoring patch for this part later.

> 
>>> 8 codes, ordered:    never     lt   gt   ltgt eq   le   ge   ordered
>>> 8 codes, unordered:  unordered unlt ungt ne   uneq unle unge always
>>> 8 codes, fast-math:  never     lt   gt   ne   eq   le   ge   always
>>> 8 codes, non-fp:     never     lt   gt   ne   eq   le   ge   always
>>
>> Sorry, I don't quite follow this table.  What's the column heads?
> 
> The first row is the eight possible fp conditions that are not always
> true if unordered is set; the second row is those that *are* always true
> if it is set.  The other two rows (which are the same) is just the eight
> conditions that do not test unordered at all.
> 
> The tricky one is "ne": for FP *with* NaNs, "ne" means "less than, or
> greater than, or unordered", while without NaNs (i.e. -ffast-math) it
> means "less than, or greater than".
> 
> You could write the column heads as
> --/--/--  lt/--/--  --/gt/--  lt/gt/--  --/--/eq  lt/--/eq  --/gt/eq  lt/gt/eq
> if that helps?  Just the eight combinations of the first free flags.
> 

Thanks a lot for the explanation.  It's helpful!
 

>> +;; For signed integer vectors comparison.
>> +(define_expand "vec_cmp<mode><mode>"
>> +  [(set (match_operand:VEC_I 0 "vint_operand")
>> +    (match_operator 1 "signed_or_equality_comparison_operator"
>> +      [(match_operand:VEC_I 2 "vint_operand")
>> +       (match_operand:VEC_I 3 "vint_operand")]))]
>> +  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
>> +{
>> +  enum rtx_code code = GET_CODE (operands[1]);
>> +  rtx tmp = gen_reg_rtx (<MODE>mode);
>> +  switch (code)
>> +    {
>> +    case NE:
>> +      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], 
>> operands[3]));
>> +      emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[0]));
>> +      break;
>> +    case EQ:
>> +      emit_insn (gen_vector_eq<mode> (operands[0], operands[2], 
>> operands[3]));
>> +      break;
>> +    case GE:
>> +      emit_insn (gen_vector_nlt<mode> (operands[0],operands[2], operands[3],
>> +                                   tmp));
>> +      break;
>> +    case GT:
>> +      emit_insn (gen_vector_gt<mode> (operands[0], operands[2], 
>> operands[3]));
>> +      break;
>> +    case LE:
>> +      emit_insn (gen_vector_ngt<mode> (operands[0], operands[2], 
>> operands[3],
>> +                                   tmp));
>> +      break;
>> +    case LT:
>> +      emit_insn (gen_vector_gt<mode> (operands[0], operands[3], 
>> operands[2]));
>> +      break;
>> +    default:
>> +      gcc_unreachable ();
>> +      break;
>> +    }
>> +  DONE;
>> +})
> 
> I would think this can be done easier, but it is alright for now, it can
> be touched up later if we want.
> 
>> +;; For float point vectors comparison.
>> +(define_expand "vec_cmp<mode><VEC_int>"
> 
> This, too.
> 
>> +  [(set (match_operand:<VEC_INT> 0 "vint_operand")
>> +     (match_operator 1 "comparison_operator"
> 
> If you make an iterator for this instead, it is simpler code (you can then
> use <code> to do all these cases in one statement).

If my understanding is correct and based on some tries before, I think we
have to leave these **CASEs** there (at least at the 1st level define_expand
for vec_cmp*), since vec_cmp* doesn't have <code> field in the pattern name.
The code can be only extracted from operator 1.  I tried to add one dummy
operand to hold <code> but it's impractical.

Sorry, I may miss something here, I'm happy to make a subsequent patch to
uniform these cases if there is a good way to run a code iterator on them.

> 
> But that can be done later.  Okay for trunk.  Thanks!
> 

Many thanks for your time!


BR,
Kewen

Reply via email to