[cfe-dev] [PATCH] [OpenCL] Conversions for ternary operations between scalar and vector

Sahasrabuddhe, Sameer sameer.sahasrabuddhe at amd.com
Fri Dec 12 02:50:20 PST 2014


On 12/11/2014 5:47 PM, Colin Riddell wrote:
> Yes, this is a good exercise for me as well. It's really forcing me to 
> question my understanding, rather than just hacking something together 
> to make it work. I agree we need more tests, so I will work on a 
> larger set of both positive and negative tests once we have solidified 
> our understanding.

Good to know that. It definitely affects AMD's frontend and I am 
guessing that it also affects the Khronos SPIR generator.

> I reviewed your document and moved it around slightly to fit with my 
> understanding of the spec. In summary, my changes are:

Thanks for looking into it! I have replied below by copying relevant 
parts from the file.

>   * Select rules about bits can be simplified down to something very 
> succinct like: 'use select when exp1 result is a vector. When using 
> select, exp2 and exp3 must match.' (and conversion rules apply to make 
> them match detailed in 4.2). This is because, beyond checking these 
> types, at this stage in the compilation we have no other control.. 
> which is what the checkConditionalConvertScalarsToVectors() function 
> is attempting to do (though this may be incorrect).
>
> I think these changes are more around the order and organization of 
> the rules, rather than the actual rules themselves and think we are 
> starting to come to agreement on them. Let me know what you think of 
> my changes to your document..

Sure, but one motivation for writing this document was to identify gray 
areas, where Clang is following conventions in the absence of rules. See 
below regarding point (6) from my original writeup.

Pasting some of the lines from your attached file:

>       1. exp2 and exp3 can be any type, as long as they match
>
>       2. If exp2 and exp3 don't match, then one of either exp2 or exp3
>          can be converted using the arithmetic conversion rules for 
> vectors
>          ("both" rules, in your wording):
>              1. If one is a vector and the other a scalar, the scalar
>                 may be converted to the base type, and expanded to the 
> vec
>                 type.
>              2. If both are vectors of the same type and size, no implicit
>                 conversion is required.
>              3. If both are vectors of different type or size, no implicit
>                 conversion is ALLOWED
>       3. For *scalars*, the result type is obtained by implicit
>          conversion on exp2 *or* exp3. (section 6.2.1 of CL Spec). Which
>          comes under the "either" rules, by your wording.

We don't actually need to say all this. It's enough to just cite Section 
6.2.6. This was my intention in point (5):

> -5. The result type is obtained by usual arithmetic conversions on exp2
> -   and exp3, as specified in Section 6.2.6.

Aside: Does the minus (-) sign mean that you think this should be deleted?

Also, I think that Section 6.2.1 is not really necessary in this 
situation, the way it occurs on page 220 of the spec:

     ... or there is a conversion in section 6.2.1 Implicit Conversions that
     can be applied to one of the expressions to make their types match, ...

Which expression should be implicitly converted? As far as I can make 
out, there was no need to mention Section 6.2.1 at this point in the 
spec itself, especially because Section 6.2.6 is meant to clarify 
exactly this choice: "The purpose is to determine a common real type for 
the operands and result.". This section cites the C99 spec when both 
operands are scalars: "Otherwise, if all operands are scalar, the usual 
arithmetic conversions apply, per section 6.3.1.8 of the C99 standard."

> (I suppose, technically they are both evaulated, but one converted to the
> other. Covered in 4)
> -   2. Both exp2 and exp3 are evaluated.

Yeah, if we have already said that the vector operator behaves like the 
select function call, then it implies that both are evaluated. But I 
thought it would be good to make this an explicit point because it was 
the first thing that tripped me up when I first encountered the ternary 
operator long ago! :)

> - 6. If exp1 is a vector, and the result type is a scalar, then

This is an important point; it covers exactly the part that caused the 
original bug. By "result type", I meant the one obtained by usual 
arithmetic conversions on LHS and RHS. It is the same as ResTy in the 
code. If we had stopped at saying that the ternary operator behaves like 
the select function, then it would be illegal to have an expression like 
"int2 ? float : float". The vector expansion required is not specified 
anywhere --- we want to promote ResTy (scalar float) to a vector that 
matches the length of CondTy, but we do not want to change its element 
type.

 1. CondTy is vector, RHS is scalar and LHS is scalar.
 2. Current behaviour: Use usual arithmetic conversions to cast both RHS
    and LHS to CondTy. Very buggy because it performs illegal
    conversions from scalar to vector.
 3. Expected behaviour: Use usual arithmetic conversions to determine
    ResTy from RHS and LHS, then expand it to match CondTy in length.
    Actually, only one of RHS and LHS will be casted.

Going by the letter of the spec, it is difficult to say whether the 
situation itself is illegal or undefined. Note that a similar situation 
with the select builtin will result in a signature mismatch. Clang 
currently implements the first version, but at least you and I agree 
that the second version is more useful. There is no reason to say that 
one behaviour is correct and the other is not.

Sameer.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141212/b7af60c4/attachment.html>


More information about the cfe-dev mailing list