This is an archive of the discontinued LLVM Phabricator instance.

Implement VectorType conditional operator GNU extension.
ClosedPublic

Authored by erichkeane on Dec 13 2019, 6:27 AM.

Details

Summary

GCC supports the conditional operator on VectorTypes that acts as a
'select' in C++ mode. This patch implements the support. Types are
converted as closely to GCC's behavior as possible, though in a few
places consistency with our existing vector type support was preferred.

Note that this implementation is different from the OpenCL version in a
number of ways, so it unfortunately required a different implementation.

First, the SEMA rules and promotion rules are significantly different.

Secondly, GCC implements COND[i] != 0 ? LHS[i] : RHS[i] (where i is in
the range 0- VectorSize, for each element). In OpenCL, the condition is
COND[i] < 0 ? LHS[i]: RHS[i].

In the process of implementing this, it was also required to make the
expression COND ? LHS : RHS type dependent if COND is type dependent,
since the type is now dependent on the condition. For example:

T ? 1 : 2;

Is not typically type dependent, since the result can be deduced from
the operands. HOWEVER, if T is a VectorType now, it could change this
to a 'select' (basically a swizzle with a non-constant mask) with the 1
and 2 being promoted to vectors themselves.

While this is a change, it is NOT a standards incompatible change. Based
on my (and D. Gregor's, at the time of writing the code) reading of the
standard, the expression is supposed to be type dependent if ANY
sub-expression is type dependent.

Diff Detail

Event Timeline

erichkeane created this revision.Dec 13 2019, 6:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 13 2019, 6:27 AM
Herald added a subscriber: Anastasia. · View Herald Transcript

Sorry in advance for the reviewer choices... Blame got me you all for all touching these things in the early 2010s. Since then, Richard and I seem to be the only one to have touched these types.

Can you update https://clang.llvm.org/docs/LanguageExtensions.html#langext-vectors with a description of the interaction between the different language features here?

It's unfortunate that the gcc extension is explicitly incompatible with OpenCL, but I guess we're stuck with it.

clang/include/clang/AST/Expr.h
3747

You can just refer to [temp.dep.expr] here; the type does in fact "depend" on the type of the condition. I'm a little concerned that the C++ standard might not preserve this guarantee in the future.

clang/lib/Sema/SemaExpr.cpp
8981 ↗(On Diff #233791)

Can you separate this out into an independent patch?

clang/lib/Sema/SemaExprCXX.cpp
5826

I'm not completely sure this works the way you want it to... in particular, if the types don't match, and both operands can be promoted to int, you end up with an int vector.

erichkeane marked 5 inline comments as done.Dec 13 2019, 1:13 PM

Can you update https://clang.llvm.org/docs/LanguageExtensions.html#langext-vectors with a description of the interaction between the different language features here?

Done, see the next patch.

It's unfortunate that the gcc extension is explicitly incompatible with OpenCL, but I guess we're stuck with it.

I think it is the other way around actually. The GCC extension predates the OpenCL one from what I can tell.

clang/include/clang/AST/Expr.h
3747

I wasn't able to find a bug report in the core issues list, and this has been known about by Doug for ~15 years now. I'm somewhat less concerned, particularly since GCC has this issue as well.

clang/lib/Sema/SemaExpr.cpp
8981 ↗(On Diff #233791)
clang/lib/Sema/SemaExprCXX.cpp
5826

I think I'm OK with that... GCC does allow some promotions here (a short and a ushort act as an int). I tried a bunch of cases and couldn't come up with a case where this didn't work in the 2 scalar versions. You wouldn't happen to have something in mind, would you?

erichkeane marked 2 inline comments as done.

Rebase + @eli.friedman s comments.

aaron.ballman added inline comments.Dec 20 2019, 12:54 PM
clang/docs/LanguageExtensions.rst
467–468

Do these columns line up in the actual source file? They don't appear to line up in the Phab viewer, but I don't know if that's an artifact of Phab or not.

clang/include/clang/Basic/DiagnosticSemaKinds.td
6950

We don't actually use enumeral in diagnostics anywhere -- I think that should be enumeration instead.

clang/lib/CodeGen/CGExprScalar.cpp
4322

auto *

Also, should these three variables have identifiers starting with an uppercase like CondV et al?

clang/lib/Sema/SemaExprCXX.cpp
5757

Do you actually need the getTypePtr() bit, or will the cast<> suffice to trigger the cast through Type*?

5761–5762

If these checks are redundant, would you prefer to assert them?

5779

const auto * (same elsewhere in the function where the type is spelled out in the initialization)

5793

Shouldn't this pass in the LHSType instead because that's what's being tested?

5799

And this one do the RHSType?

5805

Do you need to canonicalize these types before comparing them?

erichkeane marked 13 inline comments as done.Dec 20 2019, 1:46 PM

New patch coming as soon as my build finishes.

clang/docs/LanguageExtensions.rst
467–468

They don't, I had misread the sphinx doc it seems and was doing footnotes incorrectly. A coworker shared the live-sphinx viewer so I corrected this. See next patch.

clang/lib/CodeGen/CGExprScalar.cpp
4322

Probably, I just C&P'ed this code from the above group :/

clang/lib/Sema/SemaExprCXX.cpp
5757

TIL!

5793

Yep!

5805

No, both versions of this function canonicalize for me: https://clang.llvm.org/doxygen/ASTContext_8h_source.html#l02305

erichkeane marked 4 inline comments as done.

@aaron.ballman s comments done.

@eli.friedman @rjmccall Do you have further comments on these?

It looks good, I was just thinking whether it would be possible to share more common infrastructure. There is Sema::CheckVectorOperands that corresponding OpenCL methods are using internally. Do you think it is possible to share the code more?

clang/include/clang/Basic/DiagnosticSemaKinds.td
6948

Would this only apply to GNU extension? I am just wondering if this can be generalized.

clang/lib/Sema/SemaExprCXX.cpp
5797

Don't we already have a diagnostic for this used in OpenCL?

erichkeane marked 2 inline comments as done.Dec 27 2019, 9:09 AM

It looks good, I was just thinking whether it would be possible to share more common infrastructure. There is Sema::CheckVectorOperands that corresponding OpenCL methods are using internally. Do you think it is possible to share the code more?

I tried in my initial implementation. Unfortunately CheckVectorOperands and the OpenCL vectors have significantly different semantic rules from this, these aren't even consistent with the normal GCC vector conversion rules. The similarities/differences between all of these are frustrating, any attempt I made at unifying the logic made both really difficult to follow.

clang/include/clang/Basic/DiagnosticSemaKinds.td
6948

To be honest, I limited the scope of this a bit since the ext_vector type isn't something I have a great knowledge of. The OpenCL vector types end up having frustratingly similar/different behavior that it required significant differences in logic.

Does OpenCL prohibit void/throw expressions in their vector conditionals?

clang/lib/Sema/SemaExprCXX.cpp
5797

The one I found was less specific than just 'mismatched'. It ended up containing info about not convertible. I tried a set of 'selects' on it but it ended up getting hacked up more than I was comfortable with. Unless you're referring to a different one that I missed?

This revision is now accepted and ready to land.Jan 13 2020, 1:05 PM
This revision was automatically updated to reflect the committed changes.