[llvm] [LV] Add initial support for vectorizing literal struct return values (PR #109833)

David Sherwood via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 6 05:27:30 PST 2024


================
@@ -0,0 +1,53 @@
+//===----------- VectorUtils.h -  Vector type utility functions -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/DerivedTypes.h"
+
+namespace llvm {
+
+/// A helper function for converting Scalar types to vector types. If
+/// the incoming type is void, we return void. If the EC represents a
+/// scalar, we return the scalar type.
+inline Type *ToVectorTy(Type *Scalar, ElementCount EC) {
+  if (Scalar->isVoidTy() || Scalar->isMetadataTy() || EC.isScalar())
+    return Scalar;
+  return VectorType::get(Scalar, EC);
+}
+
+inline Type *ToVectorTy(Type *Scalar, unsigned VF) {
+  return ToVectorTy(Scalar, ElementCount::getFixed(VF));
+}
+
+/// A helper for converting to wider (vector) types. For scalar types, this is
+/// equivalent to calling `ToVectorTy`. For struct types, this returns a new
+/// struct where each element type has been widened to a vector type. Note: Only
+/// unpacked literal struct types are supported.
+Type *ToWideTy(Type *Ty, ElementCount EC);
----------------
david-arm wrote:

I'm not sure that `ToWideTy`, `ToNarrowTy`, `isWideTy` and `getWideTypeVF `  should really live in the llvm/IR include directory. The widening or narrowing concepts that you're introducing here are really very specific to the use case of loop vectorising a call to a function that returns a structure, but the definition and location of the functions suggest a much wider scope than that. A quick search for VectorUtils.h shows it's included in lib/CodeGen, lib/Transforms/InstCombine, lib/Transforms/Vectorize/SLPVectorizer.cpp, etc. Having said that, it's not immediately obvious where else I'd put it so I'll think about it some more.

I don't think it's actually possible to have a vector of struct types, but I can imagine that for homogenous struct types you could also return a vector with N times the number of elements. For example, { i32, i32 } could be vectorised with a VF of 4 and the return type could just be <8 x i32> where the caller takes responsibility for any deinterleaving into two <4 x i32> types. That's why it feels a bit contentious to tie the widening or narrowing of a struct to a particular format.

I wonder if it would be more acceptable to pass in a flag defining what the behaviour should be for structs? For example, something like:

```
Type *ToWideTy(Type *Ty, ElementCount EC, bool StructMembersAreWidened = false) {
  if (isa<StructType>(Ty) && (!StructMembersAreWidened || !cast<StructType>(Ty)->isHomogenous())
    llvm_unreachable();
  ...
}
```

where you only pass in `true` for the third argument in cases where you can handle structs this way? If something calls ToWideTy on something and didn't expect there to be a struct at least the compiler will blow up with an error.

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


More information about the llvm-commits mailing list