[llvm] [Scalarizer][DirectX] support structs return types (PR #111569)

Tex Riddell via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 17 16:19:42 PDT 2024


================
@@ -667,14 +686,26 @@ bool ScalarizerVisitor::splitBinary(Instruction &I, const Splitter &Split) {
 bool ScalarizerVisitor::isTriviallyScalarizable(Intrinsic::ID ID) {
   if (isTriviallyVectorizable(ID))
     return true;
+  // TODO: Move frexp to isTriviallyVectorizable.
+  // https://github.com/llvm/llvm-project/issues/112408
+  switch (ID) {
+  case Intrinsic::frexp:
+    return true;
+  }
   return Intrinsic::isTargetIntrinsic(ID) &&
          TTI->isTargetIntrinsicTriviallyScalarizable(ID);
 }
 
 /// If a call to a vector typed intrinsic function, split into a scalar call per
 /// element if possible for the intrinsic.
 bool ScalarizerVisitor::splitCall(CallInst &CI) {
-  std::optional<VectorSplit> VS = getVectorSplit(CI.getType());
+  Type *CallType = CI.getType();
+  bool AreAllMatchingVectors = isStructOfMatchingFixedVectors(CallType);
+  std::optional<VectorSplit> VS;
+  if (AreAllMatchingVectors)
+    VS = getVectorSplit(CallType->getContainedType(0));
----------------
tex3d wrote:

> I think that limiting our handling to cases where all of the vector types nested in the struct type of the return type match is pretty reasonable.

As Farzon points out, the `frexp` example has mismatching vector types in the return struct.  My initial assumption about how this was going to work was incorrect, so this thread may have started out with a bit of confusion.

For `frexp`, each of these are involved in the overload type for the intrinsic, so each must be captured.  The way it works in this PR now is that it captures the first field only if `isVectorIntrinsicWithOverloadTypeAtArg` called with `-1` returns true, then it captures each field after that if it differs from the prior field.  This second part sounds basically like a heuristic, not an explicit property describing a specific intrinsic.

That seems fragile, and it would be easy to break if some intrinsic required something different (even if you think that will never come up).  It's certainly possible, though likely rare, that one of the returned vectors does not contribute to the overload type, even if it differs from the other type.  Other possible scenarios couldn't be handled by this as well.

The compromise Farzon came to, after we met earlier, was to add a different query function for struct return argument fields.  At least it makes things explicit, though it means yet another function needs to be plumbed through TTI as well.

https://github.com/llvm/llvm-project/pull/111569


More information about the llvm-commits mailing list