On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
<artyom.shinkar...@gmail.com> wrote:
> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
> <richard.guent...@gmail.com> wrote:
>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>> <artyom.shinkar...@gmail.com> wrote:
>>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>> <richard.guent...@gmail.com> wrote:
>>>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>>> <artyom.shinkar...@gmail.com> wrote:
>>>>> Richard
>>>>>
>>>>> I formalized an approach a little-bit, now it works without target
>>>>> hooks, but some polishing is still required. I want you to comment on
>>>>> the several important approaches that I use in the patch.
>>>>>
>>>>> So how does it work.
>>>>> 1) All the vector comparisons at the level of  type-checker are
>>>>> introduced using VEC_COND_EXPR with constant selection operands being
>>>>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR<v0
>>>>>> v1, {-1}, {0}>.
>>>>>
>>>>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>>>>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
>>>>> changes.
>>>>> 2.b) first operand is something else, in that case, we specially mark
>>>>> this case, recognize it in the backend, and do not create a
>>>>> comparison, but use the mask as it was a result of some comparison.
>>>>>
>>>>> 3) In order to make sure that mask in VEC_COND_EXPR<mask, v0, v1> is a
>>>>> vector comparison we use is_vector_comparison function, if it returns
>>>>> false, then we replace mask with mask != {0}.
>>>>>
>>>>> So we end-up with the following functionality:
>>>>> VEC_COND_EXPR<mask, v0,v1> -- if we know that mask is a result of
>>>>> comparison of two vectors, we leave it as it is, otherwise change with
>>>>> mask != {0}.
>>>>>
>>>>> Plain vector comparison a <op> b is represented with VEC_COND_EXPR,
>>>>> which correctly expands, without creating useless masking.
>>>>>
>>>>>
>>>>> Basically for me there are two questions:
>>>>> 1) Can we perform information passing in optabs in a nicer way?
>>>>> 2) How is_vector_comparison could be improved? I have several ideas,
>>>>> like checking if constant vector all consists of 0 and -1, and so on.
>>>>> But first is it conceptually fine.
>>>>>
>>>>> P.S. I tired to put the functionality of is_vector_comparison in
>>>>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>>>>> which I find inappropriate, and the functionality gets more
>>>>> complicated.
>>>>
>>>> Why is it inappropriate to not optimize it at -O0?  If the user
>>>> separates comparison and ?: expression it's his own fault.
>>>
>>> Well, because all the information is there, and I perfectly envision
>>> the case when user expressed comparison separately, just to avoid code
>>> duplication.
>>>
>>> Like:
>>> mask = a > b;
>>> res1 = mask ? v0 : v1;
>>> res2 = mask ? v2 : v3;
>>>
>>> Which in this case would be different from
>>> res1 = a > b ? v0 : v1;
>>> res2 = a > b ? v2 : v3;
>>>
>>>> Btw, the new hook is still in the patch.
>>>>
>>>> I would simply always create != 0 if it isn't and let optimizers
>>>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>>>> non-comparison operands during expansion though, but if
>>>> you always forced a != 0 from the start you can then simply
>>>> interpret it as a proper comparison result (in which case I'd
>>>> modify the backends to have an alternate pattern or directly
>>>> expand to masking operations - using the fake comparison
>>>> RTX is too much of a hack).
>>>
>>> Richard, I think you didn't get the problem.
>>> I really need the way, to pass the information, that the expression
>>> that is in the first operand of vcond is an appropriate mask. I though
>>> for quite a while and this hack is the only answer I found, is there a
>>> better way to do that. I could for example introduce another
>>> tree-node, but it would be overkill as well.
>>>
>>> Now why do I need it so much:
>>> I want to implement the comparison in a way that {1, 5, 0, -1} is
>>> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
>>> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
>>> always). To check the stuff, I use is_vector_comparison in
>>> tree-vect-generic.
>>>
>>> So I really have the difference between mask ? x : y and mask != {0} ?
>>> x : y, otherwise I could treat mask != {0} in the backend as just
>>> mask.
>>>
>>> If this link between optabs and backend breaks, then the patch falls
>>> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
>>> will have to put != {0}. Keep in mind, that I cannot always put the
>>> comparison inside the VEC_COND_EXPR, what if it is defined in a
>>> function-comparison, or somehow else?
>>>
>>> So what would be an appropriate way to connect optabs and the backend?
>>
>> Well, there is no problem in having the only valid mask operand for
>> VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,....} mask.
>> Just the C parser has to transform mask ? vec1 : vec2 to mask != 0 ?
>> vec1 : vec2.
>
> This happens already in the new version of patch (not submitted yet).
>
>> This comparison can be eliminated by optimization passes
>> that
>> either replace it by the real comparison computing the mask or just
>> propagating the information this mask is already {-1,...} / {0,....} by 
>> simply
>> dropping the comparison against zero.
>
> This is not a problem, because the backend recognizes these patterns,
> so no optimization is needed in this part.

I mean for

  mask = v1 < v2 ? {-1,...} : {0,...};
  val = VCOND_EXPR <mask != 0, v3, v4>;

optimizers can see how mask is defined and drop the != 0 test or replace
it by v1 < v2.

>> For the backends I'd have vcond patterns for both an embedded comparison
>> and for a mask.  (Now we can rewind the discussion a bit and allow
>> arbitrary masks and define a vcond with a mask operand to do bitwise
>> selection - what matters is the C frontend semantics which we need to
>> translate to what the middle-end thinks of a VEC_COND_EXPR, they
>> do not have to agree).
>
> But it seems like another combinatorial explosion here. Considering
> what Richard said in his e-mail, in order to support "generic" vcond,
> we just need to enumerate all the possible cases. Or I didn't
> understand right?

Well, the question is still what VCOND_EXPR and thus the vcond pattern
semantically does for a non-comparison operand.  I'd argue that using
the bitwise selection semantic gives us maximum flexibility and a native
instruction with AMD XOP.  This non-comparison VCOND_EXPR is
also easy to implement in the middle-end expansion code if there is
no native instruction for it - by simply emitting the bitwise operations.

But I have the feeling we are talking past each other ...?

> I mean, I don't mind of course, but it seems to me that it would be
> cleaner to have one generic enough pattern.
>
> Is there seriously no way to pass something from optab into the backend??

You can pass operands.  And information is implicitly encoded in the name.

>> If the mask is computed by a function you are of course out of luck,
>> but I don't see how you'd manage to infer knowledge from nowhere either.
>
> Well, take simpler example
>
> a = {0};
> for ( ; *p; p += 16)
>  a &= pattern > (vec)*p;
>
> res = a ? v0 : v1;
>
> In this case it is simple to analyse that a is a comparison, but you
> cannot embed the operations of a into VEC_COND_EXPR.

Sure, but if the above is C source the frontend would generate
res = a != 0 ? v0 : v1; initially.  An optimization pass could still
track this information and replace VEC_COND_EXPR <a != 0, v0, v1>
with VEC_COND_EXPR <a, v0, v1> (no existing one would track
vector contents though).

> Ok, I am testing the patch that removes hooks. Could you push a little
> bit the backend-patterns business?

Well, I suppose we're waiting for Uros here.  I hadn't much luck with
fiddling with the mode-iterator stuff myself.

Richard.

Reply via email to