SPV 1.4: Use OpSelect for trivial typed non-scalar/vector expressions.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index fbfb335..d25ccd3 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -2615,6 +2615,19 @@
// next layer copies r-values into memory to use the access-chain mechanism
bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
{
+ // see if OpSelect can handle it
+ const auto isOpSelectable = [&]() {
+ if (node->getBasicType() == glslang::EbtVoid)
+ return false;
+ // OpSelect can do all other types starting with SPV 1.4
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) {
+ // pre-1.4, only scalars and vectors can be handled
+ if ((!node->getType().isScalar() && !node->getType().isVector()))
+ return false;
+ }
+ return true;
+ };
+
// See if it simple and safe, or required, to execute both sides.
// Crucially, side effects must be either semantically required or avoided,
// and there are performance trade-offs.
@@ -2633,9 +2646,7 @@
// if not required to execute both, decide based on performance/practicality...
- // see if OpSelect can handle it
- if ((!node->getType().isScalar() && !node->getType().isVector()) ||
- node->getBasicType() == glslang::EbtVoid)
+ if (!isOpSelectable())
return false;
assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
@@ -2672,14 +2683,16 @@
// emit code to select between trueValue and falseValue
// see if OpSelect can handle it
- if (node->getType().isScalar() || node->getType().isVector()) {
+ if (isOpSelectable()) {
// Emit OpSelect for this selection.
// smear condition to vector, if necessary (AST is always scalar)
- if (builder.isVector(trueValue))
+ // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar
+ if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) {
condition = builder.smearScalar(spv::NoPrecision, condition,
builder.makeVectorType(builder.makeBoolType(),
builder.getNumComponents(trueValue)));
+ }
// OpSelect
result = builder.createTriOp(spv::OpSelect,