From 16afa09ae322b88ad452a08fff984463eb306a2a Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Fri, 6 Dec 2024 14:26:53 +0000 Subject: [PATCH 01/14] [VFABI] Add support for vector functions that return struct types This patch updates the `VFABIDemangler` to support vector functions that return struct types. For example, a vector variant of `sincos` that returns a vector of sine values and a vector of cosine values within a struct. This patch also adds some helpers in `llvm/IR/CallWideningUtils.h` for widening call return types. Some of these are used in the `VFABIDemangler`, and others will be used in subsequent patches, so this patch simply adds tests for them. --- llvm/include/llvm/Analysis/VectorUtils.h | 14 +- llvm/include/llvm/IR/CallWideningUtils.h | 44 ++++++ llvm/include/llvm/IR/VectorUtils.h | 32 +++++ llvm/lib/IR/CMakeLists.txt | 1 + llvm/lib/IR/CallWideningUtils.cpp | 73 ++++++++++ llvm/lib/IR/VFABIDemangler.cpp | 18 ++- llvm/unittests/IR/CMakeLists.txt | 1 + llvm/unittests/IR/CallWideningUtilsTest.cpp | 149 ++++++++++++++++++++ llvm/unittests/IR/VFABIDemanglerTest.cpp | 67 +++++++++ 9 files changed, 379 insertions(+), 20 deletions(-) create mode 100644 llvm/include/llvm/IR/CallWideningUtils.h create mode 100644 llvm/include/llvm/IR/VectorUtils.h create mode 100644 llvm/lib/IR/CallWideningUtils.cpp create mode 100644 llvm/unittests/IR/CallWideningUtilsTest.cpp diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h index c1016dd7bdddb..5433231a1018e 100644 --- a/llvm/include/llvm/Analysis/VectorUtils.h +++ b/llvm/include/llvm/Analysis/VectorUtils.h @@ -18,6 +18,7 @@ #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/IR/Module.h" #include "llvm/IR/VFABIDemangler.h" +#include "llvm/IR/VectorUtils.h" #include "llvm/Support/CheckedArithmetic.h" namespace llvm { @@ -127,19 +128,6 @@ namespace Intrinsic { typedef unsigned ID; } -/// 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)); -} - /// Identify if the intrinsic is trivially vectorizable. /// This method returns true if the intrinsic's argument types are all scalars /// for the scalar form of the intrinsic and all vectors (or scalars handled by diff --git a/llvm/include/llvm/IR/CallWideningUtils.h b/llvm/include/llvm/IR/CallWideningUtils.h new file mode 100644 index 0000000000000..de51c8f6c6ba1 --- /dev/null +++ b/llvm/include/llvm/IR/CallWideningUtils.h @@ -0,0 +1,44 @@ +//===---- CallWideningUtils.h - Utils for widening scalar to vector calls --==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_CALLWIDENINGUTILS_H +#define LLVM_IR_CALLWIDENINGUTILS_H + +#include "llvm/IR/DerivedTypes.h" + +namespace llvm { + +/// 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); + +/// A helper for converting wide types to narrow (non-vector) types. For vector +/// types, this is equivalent to calling .getScalarType(). For struct types, +/// this returns a new struct where each element type has been converted to a +/// scalar type. Note: Only unpacked literal struct types are supported. +Type *ToNarrowTy(Type *Ty); + +/// Returns the types contained in `Ty`. For struct types, it returns the +/// elements, all other types are returned directly. +SmallVector getContainedTypes(Type *Ty); + +/// Returns true if `Ty` is a vector type or a struct of vector types where all +/// vector types share the same VF. +bool isWideTy(Type *Ty); + +/// Returns the vectorization factor for a widened type. +inline ElementCount getWideTypeVF(Type *Ty) { + assert(isWideTy(Ty) && "expected widened type"); + return cast(getContainedTypes(Ty).front())->getElementCount(); +} + +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h new file mode 100644 index 0000000000000..a2e34a02e08a6 --- /dev/null +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -0,0 +1,32 @@ +//===----------- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_VECTORUTILS_H +#define LLVM_IR_VECTORUTILS_H + +#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)); +} + +} // namespace llvm + +#endif diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 544f4ea9223d0..874ee8c4795a9 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMCore AutoUpgrade.cpp BasicBlock.cpp BuiltinGCs.cpp + CallWideningUtils.cpp Comdat.cpp ConstantFold.cpp ConstantFPRange.cpp diff --git a/llvm/lib/IR/CallWideningUtils.cpp b/llvm/lib/IR/CallWideningUtils.cpp new file mode 100644 index 0000000000000..ec0bc6e3baa46 --- /dev/null +++ b/llvm/lib/IR/CallWideningUtils.cpp @@ -0,0 +1,73 @@ +//===----------- VectorUtils.cpp - Vector type utility functions ----------===// +// +// 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/IR/CallWideningUtils.h" +#include "llvm/ADT/SmallVectorExtras.h" +#include "llvm/IR/VectorUtils.h" + +using namespace llvm; + +/// 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 *llvm::ToWideTy(Type *Ty, ElementCount EC) { + if (EC.isScalar()) + return Ty; + auto *StructTy = dyn_cast(Ty); + if (!StructTy) + return ToVectorTy(Ty, EC); + assert(StructTy->isLiteral() && !StructTy->isPacked() && + "expected unpacked struct literal"); + return StructType::get( + Ty->getContext(), + map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * { + return VectorType::get(ElTy, EC); + })); +} + +/// A helper for converting wide types to narrow (non-vector) types. For vector +/// types, this is equivalent to calling .getScalarType(). For struct types, +/// this returns a new struct where each element type has been converted to a +/// scalar type. Note: Only unpacked literal struct types are supported. +Type *llvm::ToNarrowTy(Type *Ty) { + auto *StructTy = dyn_cast(Ty); + if (!StructTy) + return Ty->getScalarType(); + assert(StructTy->isLiteral() && !StructTy->isPacked() && + "expected unpacked struct literal"); + return StructType::get( + Ty->getContext(), + map_to_vector(StructTy->elements(), [](Type *ElTy) -> Type * { + return ElTy->getScalarType(); + })); +} + +/// Returns the types contained in `Ty`. For struct types, it returns the +/// elements, all other types are returned directly. +SmallVector llvm::getContainedTypes(Type *Ty) { + auto *StructTy = dyn_cast(Ty); + if (StructTy) + return to_vector<2>(StructTy->elements()); + return {Ty}; +} + +/// Returns true if `Ty` is a vector type or a struct of vector types where all +/// vector types share the same VF. +bool llvm::isWideTy(Type *Ty) { + auto *StructTy = dyn_cast(Ty); + if (StructTy && (!StructTy->isLiteral() || StructTy->isPacked())) + return false; + auto ContainedTys = getContainedTypes(Ty); + if (ContainedTys.empty() || !ContainedTys.front()->isVectorTy()) + return false; + ElementCount VF = cast(ContainedTys.front())->getElementCount(); + return all_of(ContainedTys, [&](Type *Ty) { + return Ty->isVectorTy() && cast(Ty)->getElementCount() == VF; + }); +} diff --git a/llvm/lib/IR/VFABIDemangler.cpp b/llvm/lib/IR/VFABIDemangler.cpp index 897583084bf38..19c922c8bf035 100644 --- a/llvm/lib/IR/VFABIDemangler.cpp +++ b/llvm/lib/IR/VFABIDemangler.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/IR/CallWideningUtils.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -346,12 +347,15 @@ getScalableECFromSignature(const FunctionType *Signature, const VFISAKind ISA, // Also check the return type if not void. Type *RetTy = Signature->getReturnType(); if (!RetTy->isVoidTy()) { - std::optional ReturnEC = getElementCountForTy(ISA, RetTy); - // If we have an unknown scalar element type we can't find a reasonable VF. - if (!ReturnEC) - return std::nullopt; - if (ElementCount::isKnownLT(*ReturnEC, MinEC)) - MinEC = *ReturnEC; + for (Type *RetTy : getContainedTypes(RetTy)) { + std::optional ReturnEC = getElementCountForTy(ISA, RetTy); + // If we have an unknown scalar element type we can't find a reasonable + // VF. + if (!ReturnEC) + return std::nullopt; + if (ElementCount::isKnownLT(*ReturnEC, MinEC)) + MinEC = *ReturnEC; + } } // The SVE Vector function call ABI bases the VF on the widest element types @@ -566,7 +570,7 @@ FunctionType *VFABI::createFunctionType(const VFInfo &Info, auto *RetTy = ScalarFTy->getReturnType(); if (!RetTy->isVoidTy()) - RetTy = VectorType::get(RetTy, VF); + RetTy = ToWideTy(RetTy, VF); return FunctionType::get(RetTy, VecTypes, false); } diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt index ed93ee547d223..c4cc1bd78403a 100644 --- a/llvm/unittests/IR/CMakeLists.txt +++ b/llvm/unittests/IR/CMakeLists.txt @@ -15,6 +15,7 @@ add_llvm_unittest(IRTests AttributesTest.cpp BasicBlockTest.cpp BasicBlockDbgInfoTest.cpp + CallWideningUtilsTest.cpp CFGBuilder.cpp ConstantFPRangeTest.cpp ConstantRangeTest.cpp diff --git a/llvm/unittests/IR/CallWideningUtilsTest.cpp b/llvm/unittests/IR/CallWideningUtilsTest.cpp new file mode 100644 index 0000000000000..939806212eee6 --- /dev/null +++ b/llvm/unittests/IR/CallWideningUtilsTest.cpp @@ -0,0 +1,149 @@ +//===------- CallWideningUtilsTest.cpp - Call widening utils tests --------===// +// +// 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/IR/CallWideningUtils.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class CallWideningUtilsTest : public ::testing::Test {}; + +TEST(CallWideningUtilsTest, TestToWideTy) { + LLVMContext C; + + Type *ITy = Type::getInt32Ty(C); + Type *FTy = Type::getFloatTy(C); + Type *HomogeneousStructTy = StructType::get(FTy, FTy, FTy); + Type *MixedStructTy = StructType::get(FTy, ITy); + Type *VoidTy = Type::getVoidTy(C); + + for (ElementCount VF : + {ElementCount::getFixed(4), ElementCount::getScalable(2)}) { + Type *IntVec = ToWideTy(ITy, VF); + EXPECT_TRUE(isa(IntVec)); + EXPECT_EQ(IntVec, VectorType::get(ITy, VF)); + + Type *FloatVec = ToWideTy(FTy, VF); + EXPECT_TRUE(isa(FloatVec)); + EXPECT_EQ(FloatVec, VectorType::get(FTy, VF)); + + Type *WideHomogeneousStructTy = ToWideTy(HomogeneousStructTy, VF); + EXPECT_TRUE(isa(WideHomogeneousStructTy)); + EXPECT_TRUE( + cast(WideHomogeneousStructTy)->containsHomogeneousTypes()); + EXPECT_TRUE(cast(WideHomogeneousStructTy)->getNumElements() == + 3); + EXPECT_TRUE(cast(WideHomogeneousStructTy)->getElementType(0) == + VectorType::get(FTy, VF)); + + Type *WideMixedStructTy = ToWideTy(MixedStructTy, VF); + EXPECT_TRUE(isa(WideMixedStructTy)); + EXPECT_TRUE(cast(WideMixedStructTy)->getNumElements() == 2); + EXPECT_TRUE(cast(WideMixedStructTy)->getElementType(0) == + VectorType::get(FTy, VF)); + EXPECT_TRUE(cast(WideMixedStructTy)->getElementType(1) == + VectorType::get(ITy, VF)); + + EXPECT_EQ(ToWideTy(VoidTy, VF), VoidTy); + } + + ElementCount ScalarVF = ElementCount::getFixed(1); + for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy, VoidTy}) { + EXPECT_EQ(ToWideTy(Ty, ScalarVF), Ty); + } +} + +TEST(CallWideningUtilsTest, TestToNarrowTy) { + LLVMContext C; + + Type *ITy = Type::getInt32Ty(C); + Type *FTy = Type::getFloatTy(C); + Type *HomogeneousStructTy = StructType::get(FTy, FTy, FTy); + Type *MixedStructTy = StructType::get(FTy, ITy); + Type *VoidTy = Type::getVoidTy(C); + + for (ElementCount VF : {ElementCount::getFixed(1), ElementCount::getFixed(4), + ElementCount::getScalable(2)}) { + for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy, VoidTy}) { + // ToNarrowTy should be the inverse of ToWideTy. + EXPECT_EQ(ToNarrowTy(ToWideTy(Ty, VF)), Ty); + }; + } +} + +TEST(CallWideningUtilsTest, TestGetContainedTypes) { + LLVMContext C; + + Type *ITy = Type::getInt32Ty(C); + Type *FTy = Type::getFloatTy(C); + Type *HomogeneousStructTy = StructType::get(FTy, FTy, FTy); + Type *MixedStructTy = StructType::get(FTy, ITy); + Type *VoidTy = Type::getVoidTy(C); + + EXPECT_EQ(getContainedTypes(ITy), SmallVector({ITy})); + EXPECT_EQ(getContainedTypes(FTy), SmallVector({FTy})); + EXPECT_EQ(getContainedTypes(VoidTy), SmallVector({VoidTy})); + EXPECT_EQ(getContainedTypes(HomogeneousStructTy), + SmallVector({FTy, FTy, FTy})); + EXPECT_EQ(getContainedTypes(MixedStructTy), SmallVector({FTy, ITy})); +} + +TEST(CallWideningUtilsTest, TestIsWideTy) { + LLVMContext C; + + Type *ITy = Type::getInt32Ty(C); + Type *FTy = Type::getFloatTy(C); + Type *NarrowStruct = StructType::get(FTy, ITy); + Type *VoidTy = Type::getVoidTy(C); + + EXPECT_FALSE(isWideTy(ITy)); + EXPECT_FALSE(isWideTy(NarrowStruct)); + EXPECT_FALSE(isWideTy(VoidTy)); + + ElementCount VF = ElementCount::getFixed(4); + EXPECT_TRUE(isWideTy(ToWideTy(ITy, VF))); + EXPECT_TRUE(isWideTy(ToWideTy(NarrowStruct, VF))); + + Type *MixedVFStruct = + StructType::get(VectorType::get(ITy, ElementCount::getFixed(2)), + VectorType::get(ITy, ElementCount::getFixed(4))); + EXPECT_FALSE(isWideTy(MixedVFStruct)); + + // Currently only literals types are considered wide. + Type *NamedWideStruct = StructType::create("Named", VectorType::get(ITy, VF), + VectorType::get(ITy, VF)); + EXPECT_FALSE(isWideTy(NamedWideStruct)); + + // Currently only unpacked types are considered wide. + Type *PackedWideStruct = StructType::get( + C, ArrayRef{VectorType::get(ITy, VF), VectorType::get(ITy, VF)}, + /*isPacked=*/true); + EXPECT_FALSE(isWideTy(PackedWideStruct)); +} + +TEST(CallWideningUtilsTest, TestGetWideTypeVF) { + LLVMContext C; + + Type *ITy = Type::getInt32Ty(C); + Type *FTy = Type::getFloatTy(C); + Type *HomogeneousStructTy = StructType::get(FTy, FTy, FTy); + Type *MixedStructTy = StructType::get(FTy, ITy); + + for (ElementCount VF : + {ElementCount::getFixed(4), ElementCount::getScalable(2)}) { + for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy}) { + EXPECT_EQ(getWideTypeVF(ToWideTy(Ty, VF)), VF); + }; + } +} + +} // namespace diff --git a/llvm/unittests/IR/VFABIDemanglerTest.cpp b/llvm/unittests/IR/VFABIDemanglerTest.cpp index 07bff16df4933..896cd48ad11d6 100644 --- a/llvm/unittests/IR/VFABIDemanglerTest.cpp +++ b/llvm/unittests/IR/VFABIDemanglerTest.cpp @@ -753,6 +753,73 @@ TEST_F(VFABIParserTest, ParseVoidReturnTypeSVE) { EXPECT_EQ(VectorName, "vector_foo"); } +TEST_F(VFABIParserTest, ParseWideStructReturnTypeSVE) { + EXPECT_TRUE( + invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, double}(float)")); + EXPECT_EQ(ISA, VFISAKind::SVE); + EXPECT_TRUE(isMasked()); + FunctionType *FTy = FunctionType::get( + StructType::get( + VectorType::get(Type::getDoubleTy(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getDoubleTy(Ctx), + ElementCount::getScalable(2))), + { + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)), + }, + false); + EXPECT_EQ(getFunctionType(), FTy); + EXPECT_EQ(Parameters.size(), 2U); + EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); + EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); + EXPECT_EQ(VF, ElementCount::getScalable(2)); + EXPECT_EQ(ScalarName, "foo"); + EXPECT_EQ(VectorName, "vector_foo"); +} + +TEST_F(VFABIParserTest, ParseWideStructMixedReturnTypeSVE) { + EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "{float, i64}(float)")); + EXPECT_EQ(ISA, VFISAKind::SVE); + EXPECT_TRUE(isMasked()); + FunctionType *FTy = FunctionType::get( + StructType::get( + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getInt64Ty(Ctx), ElementCount::getScalable(2))), + { + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)), + }, + false); + EXPECT_EQ(getFunctionType(), FTy); + EXPECT_EQ(Parameters.size(), 2U); + EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); + EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); + EXPECT_EQ(VF, ElementCount::getScalable(2)); + EXPECT_EQ(ScalarName, "foo"); + EXPECT_EQ(VectorName, "vector_foo"); +} + +TEST_F(VFABIParserTest, ParseWideStructReturnTypeNEON) { + EXPECT_TRUE( + invokeParser("_ZGVnN2v_foo(vector_foo)", "{float, float}(float)")); + EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); + EXPECT_FALSE(isMasked()); + FunctionType *FTy = FunctionType::get( + StructType::get( + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2)), + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2))), + { + VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2)), + }, + false); + EXPECT_EQ(getFunctionType(), FTy); + EXPECT_EQ(Parameters.size(), 1U); + EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); + EXPECT_EQ(VF, ElementCount::getFixed(2)); + EXPECT_EQ(ScalarName, "foo"); + EXPECT_EQ(VectorName, "vector_foo"); +} + // Make sure we reject unsupported parameter types. TEST_F(VFABIParserTest, ParseUnsupportedElementTypeSVE) { EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i128)")); From 349b678f7553f0b25e9dd85cde7230da2db2e75c Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 12 Dec 2024 17:18:37 +0000 Subject: [PATCH 02/14] Fixups --- llvm/include/llvm/IR/CallWideningUtils.h | 44 ----------- llvm/include/llvm/IR/StructWideningUtils.h | 32 ++++++++ llvm/include/llvm/IR/VectorUtils.h | 46 +++++++++++- llvm/lib/IR/CMakeLists.txt | 2 +- llvm/lib/IR/CallWideningUtils.cpp | 73 ------------------- llvm/lib/IR/StructWideningUtils.cpp | 57 +++++++++++++++ llvm/lib/IR/VFABIDemangler.cpp | 2 +- llvm/unittests/IR/CMakeLists.txt | 2 +- ...eningUtilsTest.cpp => VectorUtilsTest.cpp} | 26 +++---- 9 files changed, 149 insertions(+), 135 deletions(-) delete mode 100644 llvm/include/llvm/IR/CallWideningUtils.h create mode 100644 llvm/include/llvm/IR/StructWideningUtils.h delete mode 100644 llvm/lib/IR/CallWideningUtils.cpp create mode 100644 llvm/lib/IR/StructWideningUtils.cpp rename llvm/unittests/IR/{CallWideningUtilsTest.cpp => VectorUtilsTest.cpp} (86%) diff --git a/llvm/include/llvm/IR/CallWideningUtils.h b/llvm/include/llvm/IR/CallWideningUtils.h deleted file mode 100644 index de51c8f6c6ba1..0000000000000 --- a/llvm/include/llvm/IR/CallWideningUtils.h +++ /dev/null @@ -1,44 +0,0 @@ -//===---- CallWideningUtils.h - Utils for widening scalar to vector calls --==// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_CALLWIDENINGUTILS_H -#define LLVM_IR_CALLWIDENINGUTILS_H - -#include "llvm/IR/DerivedTypes.h" - -namespace llvm { - -/// 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); - -/// A helper for converting wide types to narrow (non-vector) types. For vector -/// types, this is equivalent to calling .getScalarType(). For struct types, -/// this returns a new struct where each element type has been converted to a -/// scalar type. Note: Only unpacked literal struct types are supported. -Type *ToNarrowTy(Type *Ty); - -/// Returns the types contained in `Ty`. For struct types, it returns the -/// elements, all other types are returned directly. -SmallVector getContainedTypes(Type *Ty); - -/// Returns true if `Ty` is a vector type or a struct of vector types where all -/// vector types share the same VF. -bool isWideTy(Type *Ty); - -/// Returns the vectorization factor for a widened type. -inline ElementCount getWideTypeVF(Type *Ty) { - assert(isWideTy(Ty) && "expected widened type"); - return cast(getContainedTypes(Ty).front())->getElementCount(); -} - -} // namespace llvm - -#endif diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h new file mode 100644 index 0000000000000..b1b922f2b5d8b --- /dev/null +++ b/llvm/include/llvm/IR/StructWideningUtils.h @@ -0,0 +1,32 @@ +//===---- StructWideningUtils.h - Utils for widening scalar to vector calls +//--==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_STRUCTWIDENINGUTILS_H +#define LLVM_IR_STRUCTWIDENINGUTILS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DerivedTypes.h" + +namespace llvm { + +/// A helper for converting structs of scalar types to structs of vector types. +/// Note: Only unpacked literal struct types are supported. +Type *ToWideStructTy(StructType *StructTy, ElementCount EC); + +/// A helper for converting structs of vector types to structs of scalar types. +/// Note: Only unpacked literal struct types are supported. +Type *ToNarrowStructTy(StructType *StructTy); + +/// Returns true if `StructTy` is an unpacked literal struct where all elements +/// are vectors of matching element count. This does not include empty structs. +bool isWideStructTy(StructType *StructTy); + +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h index a2e34a02e08a6..89c8dc2911c50 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -1,4 +1,4 @@ -//===----------- VectorUtils.h - Vector type utility functions -*- C++ -*-===// +//===----------- 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. @@ -9,8 +9,8 @@ #ifndef LLVM_IR_VECTORUTILS_H #define LLVM_IR_VECTORUTILS_H -#include "llvm/ADT/SmallVector.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/StructWideningUtils.h" namespace llvm { @@ -27,6 +27,48 @@ 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. +inline Type *ToWideTy(Type *Ty, ElementCount EC) { + if (StructType *StructTy = dyn_cast(Ty)) + return ToWideStructTy(StructTy, EC); + return ToVectorTy(Ty, EC); +} + +/// A helper for converting wide types to narrow (non-vector) types. For vector +/// types, this is equivalent to calling .getScalarType(). For struct types, +/// this returns a new struct where each element type has been converted to a +/// scalar type. Note: Only unpacked literal struct types are supported. +inline Type *ToNarrowTy(Type *Ty) { + if (StructType *StructTy = dyn_cast(Ty)) + return ToNarrowStructTy(StructTy); + return Ty->getScalarType(); +} + +/// Returns true if `Ty` is a vector type or a struct of vector types where all +/// vector types share the same VF. +inline bool isWideTy(Type *Ty) { + if (StructType *StructTy = dyn_cast(Ty)) + return isWideStructTy(StructTy); + return Ty->isVectorTy(); +} + +/// Returns the types contained in `Ty`. For struct types, it returns the +/// elements, all other types are returned directly. +inline ArrayRef getContainedTypes(Type *const &Ty) { + if (auto *StructTy = dyn_cast(Ty)) + return StructTy->elements(); + return ArrayRef{&Ty, 1}; +} + +/// Returns the vectorization factor for a widened type. +inline ElementCount getWideTypeVF(Type *Ty) { + assert(isWideTy(Ty) && "expected widened type"); + return cast(getContainedTypes(Ty).front())->getElementCount(); +} + } // namespace llvm #endif diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 874ee8c4795a9..42aceadde5922 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -6,7 +6,6 @@ add_llvm_component_library(LLVMCore AutoUpgrade.cpp BasicBlock.cpp BuiltinGCs.cpp - CallWideningUtils.cpp Comdat.cpp ConstantFold.cpp ConstantFPRange.cpp @@ -65,6 +64,7 @@ add_llvm_component_library(LLVMCore PseudoProbe.cpp ReplaceConstant.cpp Statepoint.cpp + StructWideningUtils.cpp StructuralHash.cpp Type.cpp TypedPointerType.cpp diff --git a/llvm/lib/IR/CallWideningUtils.cpp b/llvm/lib/IR/CallWideningUtils.cpp deleted file mode 100644 index ec0bc6e3baa46..0000000000000 --- a/llvm/lib/IR/CallWideningUtils.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===----------- VectorUtils.cpp - Vector type utility functions ----------===// -// -// 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/IR/CallWideningUtils.h" -#include "llvm/ADT/SmallVectorExtras.h" -#include "llvm/IR/VectorUtils.h" - -using namespace llvm; - -/// 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 *llvm::ToWideTy(Type *Ty, ElementCount EC) { - if (EC.isScalar()) - return Ty; - auto *StructTy = dyn_cast(Ty); - if (!StructTy) - return ToVectorTy(Ty, EC); - assert(StructTy->isLiteral() && !StructTy->isPacked() && - "expected unpacked struct literal"); - return StructType::get( - Ty->getContext(), - map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * { - return VectorType::get(ElTy, EC); - })); -} - -/// A helper for converting wide types to narrow (non-vector) types. For vector -/// types, this is equivalent to calling .getScalarType(). For struct types, -/// this returns a new struct where each element type has been converted to a -/// scalar type. Note: Only unpacked literal struct types are supported. -Type *llvm::ToNarrowTy(Type *Ty) { - auto *StructTy = dyn_cast(Ty); - if (!StructTy) - return Ty->getScalarType(); - assert(StructTy->isLiteral() && !StructTy->isPacked() && - "expected unpacked struct literal"); - return StructType::get( - Ty->getContext(), - map_to_vector(StructTy->elements(), [](Type *ElTy) -> Type * { - return ElTy->getScalarType(); - })); -} - -/// Returns the types contained in `Ty`. For struct types, it returns the -/// elements, all other types are returned directly. -SmallVector llvm::getContainedTypes(Type *Ty) { - auto *StructTy = dyn_cast(Ty); - if (StructTy) - return to_vector<2>(StructTy->elements()); - return {Ty}; -} - -/// Returns true if `Ty` is a vector type or a struct of vector types where all -/// vector types share the same VF. -bool llvm::isWideTy(Type *Ty) { - auto *StructTy = dyn_cast(Ty); - if (StructTy && (!StructTy->isLiteral() || StructTy->isPacked())) - return false; - auto ContainedTys = getContainedTypes(Ty); - if (ContainedTys.empty() || !ContainedTys.front()->isVectorTy()) - return false; - ElementCount VF = cast(ContainedTys.front())->getElementCount(); - return all_of(ContainedTys, [&](Type *Ty) { - return Ty->isVectorTy() && cast(Ty)->getElementCount() == VF; - }); -} diff --git a/llvm/lib/IR/StructWideningUtils.cpp b/llvm/lib/IR/StructWideningUtils.cpp new file mode 100644 index 0000000000000..5c325c7cbdafc --- /dev/null +++ b/llvm/lib/IR/StructWideningUtils.cpp @@ -0,0 +1,57 @@ +//===-- CallWideningUtils.cpp - Utils for widening scalar to vector calls --==// +// +// 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/IR/StructWideningUtils.h" +#include "llvm/ADT/SmallVectorExtras.h" +#include "llvm/IR/VectorUtils.h" + +using namespace llvm; + +static bool isUnpackedStructLiteral(StructType *StructTy) { + return StructTy->isLiteral() && !StructTy->isPacked(); +} + +/// A helper for converting structs of scalar types to structs of vector types. +/// Note: Only unpacked literal struct types are supported. +Type *llvm::ToWideStructTy(StructType *StructTy, ElementCount EC) { + if (EC.isScalar()) + return StructTy; + assert(isUnpackedStructLiteral(StructTy) && + "expected unpacked struct literal"); + return StructType::get( + StructTy->getContext(), + map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * { + return VectorType::get(ElTy, EC); + })); +} + +/// A helper for converting structs of vector types to structs of scalar types. +/// Note: Only unpacked literal struct types are supported. +Type *llvm::ToNarrowStructTy(StructType *StructTy) { + assert(isUnpackedStructLiteral(StructTy) && + "expected unpacked struct literal"); + return StructType::get( + StructTy->getContext(), + map_to_vector(StructTy->elements(), [](Type *ElTy) -> Type * { + return ElTy->getScalarType(); + })); +} + +/// Returns true if `StructTy` is an unpacked literal struct where all elements +/// are vectors of matching element count. This does not include empty structs. +bool llvm::isWideStructTy(StructType *StructTy) { + if (!isUnpackedStructLiteral(StructTy)) + return false; + auto ElemTys = StructTy->elements(); + if (ElemTys.empty() || !ElemTys.front()->isVectorTy()) + return false; + ElementCount VF = cast(ElemTys.front())->getElementCount(); + return all_of(ElemTys, [&](Type *Ty) { + return Ty->isVectorTy() && cast(Ty)->getElementCount() == VF; + }); +} diff --git a/llvm/lib/IR/VFABIDemangler.cpp b/llvm/lib/IR/VFABIDemangler.cpp index 19c922c8bf035..b7559e2f4108a 100644 --- a/llvm/lib/IR/VFABIDemangler.cpp +++ b/llvm/lib/IR/VFABIDemangler.cpp @@ -10,8 +10,8 @@ #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/IR/CallWideningUtils.h" #include "llvm/IR/Module.h" +#include "llvm/IR/VectorUtils.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt index c4cc1bd78403a..efbe710987a48 100644 --- a/llvm/unittests/IR/CMakeLists.txt +++ b/llvm/unittests/IR/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_unittest(IRTests AttributesTest.cpp BasicBlockTest.cpp BasicBlockDbgInfoTest.cpp - CallWideningUtilsTest.cpp CFGBuilder.cpp ConstantFPRangeTest.cpp ConstantRangeTest.cpp @@ -53,6 +52,7 @@ add_llvm_unittest(IRTests ValueTest.cpp VectorBuilderTest.cpp VectorTypesTest.cpp + VectorUtilsTest.cpp VerifierTest.cpp VFABIDemanglerTest.cpp VPIntrinsicTest.cpp diff --git a/llvm/unittests/IR/CallWideningUtilsTest.cpp b/llvm/unittests/IR/VectorUtilsTest.cpp similarity index 86% rename from llvm/unittests/IR/CallWideningUtilsTest.cpp rename to llvm/unittests/IR/VectorUtilsTest.cpp index 939806212eee6..b70cd2f511df4 100644 --- a/llvm/unittests/IR/CallWideningUtilsTest.cpp +++ b/llvm/unittests/IR/VectorUtilsTest.cpp @@ -1,4 +1,4 @@ -//===------- CallWideningUtilsTest.cpp - Call widening utils tests --------===// +//===------- VectorUtilsTest.cpp - Vector utils tests ---------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/CallWideningUtils.h" +#include "llvm/IR/VectorUtils.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "gtest/gtest.h" @@ -15,9 +15,9 @@ using namespace llvm; namespace { -class CallWideningUtilsTest : public ::testing::Test {}; +class VectorUtilsTest : public ::testing::Test {}; -TEST(CallWideningUtilsTest, TestToWideTy) { +TEST(VectorUtilsTest, TestToWideTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -62,7 +62,7 @@ TEST(CallWideningUtilsTest, TestToWideTy) { } } -TEST(CallWideningUtilsTest, TestToNarrowTy) { +TEST(VectorUtilsTest, TestToNarrowTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -80,7 +80,7 @@ TEST(CallWideningUtilsTest, TestToNarrowTy) { } } -TEST(CallWideningUtilsTest, TestGetContainedTypes) { +TEST(VectorUtilsTest, TestGetContainedTypes) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -89,15 +89,15 @@ TEST(CallWideningUtilsTest, TestGetContainedTypes) { Type *MixedStructTy = StructType::get(FTy, ITy); Type *VoidTy = Type::getVoidTy(C); - EXPECT_EQ(getContainedTypes(ITy), SmallVector({ITy})); - EXPECT_EQ(getContainedTypes(FTy), SmallVector({FTy})); - EXPECT_EQ(getContainedTypes(VoidTy), SmallVector({VoidTy})); + EXPECT_EQ(getContainedTypes(ITy), ArrayRef({ITy})); + EXPECT_EQ(getContainedTypes(FTy), ArrayRef({FTy})); + EXPECT_EQ(getContainedTypes(VoidTy), ArrayRef({VoidTy})); EXPECT_EQ(getContainedTypes(HomogeneousStructTy), - SmallVector({FTy, FTy, FTy})); - EXPECT_EQ(getContainedTypes(MixedStructTy), SmallVector({FTy, ITy})); + ArrayRef({FTy, FTy, FTy})); + EXPECT_EQ(getContainedTypes(MixedStructTy), ArrayRef({FTy, ITy})); } -TEST(CallWideningUtilsTest, TestIsWideTy) { +TEST(VectorUtilsTest, TestIsWideTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -130,7 +130,7 @@ TEST(CallWideningUtilsTest, TestIsWideTy) { EXPECT_FALSE(isWideTy(PackedWideStruct)); } -TEST(CallWideningUtilsTest, TestGetWideTypeVF) { +TEST(VectorUtilsTest, TestGetWideTypeVF) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); From 8199c2366ae344d6dcec56c962106b7d4539b72a Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 12 Dec 2024 17:20:54 +0000 Subject: [PATCH 03/14] Rm include --- llvm/include/llvm/IR/StructWideningUtils.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h index b1b922f2b5d8b..a5b1238244bfd 100644 --- a/llvm/include/llvm/IR/StructWideningUtils.h +++ b/llvm/include/llvm/IR/StructWideningUtils.h @@ -10,7 +10,6 @@ #ifndef LLVM_IR_STRUCTWIDENINGUTILS_H #define LLVM_IR_STRUCTWIDENINGUTILS_H -#include "llvm/ADT/SmallVector.h" #include "llvm/IR/DerivedTypes.h" namespace llvm { From 7b2339741deb3765615b01ebf64ebe3d2e1ec475 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Thu, 12 Dec 2024 17:24:49 +0000 Subject: [PATCH 04/14] Update comment --- llvm/include/llvm/IR/StructWideningUtils.h | 3 +-- llvm/lib/IR/StructWideningUtils.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h index a5b1238244bfd..3044f3b4658d0 100644 --- a/llvm/include/llvm/IR/StructWideningUtils.h +++ b/llvm/include/llvm/IR/StructWideningUtils.h @@ -1,5 +1,4 @@ -//===---- StructWideningUtils.h - Utils for widening scalar to vector calls -//--==// +//===--- StructWideningUtils.h - Utils for widening/narrowing struct types ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/lib/IR/StructWideningUtils.cpp b/llvm/lib/IR/StructWideningUtils.cpp index 5c325c7cbdafc..b97b1e0a3da0e 100644 --- a/llvm/lib/IR/StructWideningUtils.cpp +++ b/llvm/lib/IR/StructWideningUtils.cpp @@ -1,4 +1,4 @@ -//===-- CallWideningUtils.cpp - Utils for widening scalar to vector calls --==// +//===- StructWideningUtils.cpp - Utils for widening/narrowing struct types ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. From 0bb3c80a1355c1da0b0051b5547dc8501fad08b9 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Fri, 13 Dec 2024 12:31:01 +0000 Subject: [PATCH 05/14] Fixups --- llvm/include/llvm/IR/StructWideningUtils.h | 8 +++- llvm/include/llvm/IR/VectorUtils.h | 8 ++-- llvm/lib/IR/StructWideningUtils.cpp | 10 ++-- llvm/lib/IR/VFABIDemangler.cpp | 5 ++ llvm/unittests/IR/VFABIDemanglerTest.cpp | 56 ++++++++++++++-------- 5 files changed, 55 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h index 3044f3b4658d0..3067ab88435ae 100644 --- a/llvm/include/llvm/IR/StructWideningUtils.h +++ b/llvm/include/llvm/IR/StructWideningUtils.h @@ -13,13 +13,17 @@ namespace llvm { +inline bool isUnpackedStructLiteral(StructType *StructTy) { + return StructTy->isLiteral() && !StructTy->isPacked(); +} + /// A helper for converting structs of scalar types to structs of vector types. /// Note: Only unpacked literal struct types are supported. -Type *ToWideStructTy(StructType *StructTy, ElementCount EC); +Type *toWideStructTy(StructType *StructTy, ElementCount EC); /// A helper for converting structs of vector types to structs of scalar types. /// Note: Only unpacked literal struct types are supported. -Type *ToNarrowStructTy(StructType *StructTy); +Type *toNarrowStructTy(StructType *StructTy); /// Returns true if `StructTy` is an unpacked literal struct where all elements /// are vectors of matching element count. This does not include empty structs. diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h index 89c8dc2911c50..4ddf721e3a829 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -33,7 +33,7 @@ inline Type *ToVectorTy(Type *Scalar, unsigned VF) { /// unpacked literal struct types are supported. inline Type *ToWideTy(Type *Ty, ElementCount EC) { if (StructType *StructTy = dyn_cast(Ty)) - return ToWideStructTy(StructTy, EC); + return toWideStructTy(StructTy, EC); return ToVectorTy(Ty, EC); } @@ -43,7 +43,7 @@ inline Type *ToWideTy(Type *Ty, ElementCount EC) { /// scalar type. Note: Only unpacked literal struct types are supported. inline Type *ToNarrowTy(Type *Ty) { if (StructType *StructTy = dyn_cast(Ty)) - return ToNarrowStructTy(StructTy); + return toNarrowStructTy(StructTy); return Ty->getScalarType(); } @@ -60,10 +60,10 @@ inline bool isWideTy(Type *Ty) { inline ArrayRef getContainedTypes(Type *const &Ty) { if (auto *StructTy = dyn_cast(Ty)) return StructTy->elements(); - return ArrayRef{&Ty, 1}; + return ArrayRef(&Ty, 1); } -/// Returns the vectorization factor for a widened type. +/// Returns the number of vector elements for a widened type. inline ElementCount getWideTypeVF(Type *Ty) { assert(isWideTy(Ty) && "expected widened type"); return cast(getContainedTypes(Ty).front())->getElementCount(); diff --git a/llvm/lib/IR/StructWideningUtils.cpp b/llvm/lib/IR/StructWideningUtils.cpp index b97b1e0a3da0e..72f442a9bf04c 100644 --- a/llvm/lib/IR/StructWideningUtils.cpp +++ b/llvm/lib/IR/StructWideningUtils.cpp @@ -12,17 +12,15 @@ using namespace llvm; -static bool isUnpackedStructLiteral(StructType *StructTy) { - return StructTy->isLiteral() && !StructTy->isPacked(); -} - /// A helper for converting structs of scalar types to structs of vector types. /// Note: Only unpacked literal struct types are supported. -Type *llvm::ToWideStructTy(StructType *StructTy, ElementCount EC) { +Type *llvm::toWideStructTy(StructType *StructTy, ElementCount EC) { if (EC.isScalar()) return StructTy; assert(isUnpackedStructLiteral(StructTy) && "expected unpacked struct literal"); + assert(all_of(StructTy->elements(), VectorType::isValidElementType) && + "expected all element types to be valid vector element types"); return StructType::get( StructTy->getContext(), map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * { @@ -32,7 +30,7 @@ Type *llvm::ToWideStructTy(StructType *StructTy, ElementCount EC) { /// A helper for converting structs of vector types to structs of scalar types. /// Note: Only unpacked literal struct types are supported. -Type *llvm::ToNarrowStructTy(StructType *StructTy) { +Type *llvm::toNarrowStructTy(StructType *StructTy) { assert(isUnpackedStructLiteral(StructTy) && "expected unpacked struct literal"); return StructType::get( diff --git a/llvm/lib/IR/VFABIDemangler.cpp b/llvm/lib/IR/VFABIDemangler.cpp index b7559e2f4108a..e7e080038e74c 100644 --- a/llvm/lib/IR/VFABIDemangler.cpp +++ b/llvm/lib/IR/VFABIDemangler.cpp @@ -347,6 +347,11 @@ getScalableECFromSignature(const FunctionType *Signature, const VFISAKind ISA, // Also check the return type if not void. Type *RetTy = Signature->getReturnType(); if (!RetTy->isVoidTy()) { + // If the return type is a struct, only allow unpacked struct literals. + StructType *StructTy = dyn_cast(RetTy); + if (StructTy && !isUnpackedStructLiteral(StructTy)) + return std::nullopt; + for (Type *RetTy : getContainedTypes(RetTy)) { std::optional ReturnEC = getElementCountForTy(ISA, RetTy); // If we have an unknown scalar element type we can't find a reasonable diff --git a/llvm/unittests/IR/VFABIDemanglerTest.cpp b/llvm/unittests/IR/VFABIDemanglerTest.cpp index 896cd48ad11d6..0e62082e07c7d 100644 --- a/llvm/unittests/IR/VFABIDemanglerTest.cpp +++ b/llvm/unittests/IR/VFABIDemanglerTest.cpp @@ -40,7 +40,9 @@ class VFABIParserTest : public ::testing::Test { VFInfo Info; /// Reset the data needed for the test. void reset(const StringRef ScalarFTyStr) { - M = parseAssemblyString("declare void @dummy()", Err, Ctx); + M = parseAssemblyString("%dummy_named_struct = type { double, double }\n" + "declare void @dummy()", + Err, Ctx); EXPECT_NE(M.get(), nullptr) << "Loading an invalid module.\n " << Err.getMessage() << "\n"; Type *Ty = parseType(ScalarFTyStr, Err, *(M)); @@ -758,21 +760,20 @@ TEST_F(VFABIParserTest, ParseWideStructReturnTypeSVE) { invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, double}(float)")); EXPECT_EQ(ISA, VFISAKind::SVE); EXPECT_TRUE(isMasked()); + ElementCount NXV2 = ElementCount::getScalable(2); FunctionType *FTy = FunctionType::get( - StructType::get( - VectorType::get(Type::getDoubleTy(Ctx), ElementCount::getScalable(2)), - VectorType::get(Type::getDoubleTy(Ctx), - ElementCount::getScalable(2))), + StructType::get(VectorType::get(Type::getDoubleTy(Ctx), NXV2), + VectorType::get(Type::getDoubleTy(Ctx), NXV2)), { - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), - VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getFloatTy(Ctx), NXV2), + VectorType::get(Type::getInt1Ty(Ctx), NXV2), }, false); EXPECT_EQ(getFunctionType(), FTy); EXPECT_EQ(Parameters.size(), 2U); EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); - EXPECT_EQ(VF, ElementCount::getScalable(2)); + EXPECT_EQ(VF, NXV2); EXPECT_EQ(ScalarName, "foo"); EXPECT_EQ(VectorName, "vector_foo"); } @@ -781,45 +782,60 @@ TEST_F(VFABIParserTest, ParseWideStructMixedReturnTypeSVE) { EXPECT_TRUE(invokeParser("_ZGVsMxv_foo(vector_foo)", "{float, i64}(float)")); EXPECT_EQ(ISA, VFISAKind::SVE); EXPECT_TRUE(isMasked()); + ElementCount NXV2 = ElementCount::getScalable(2); FunctionType *FTy = FunctionType::get( - StructType::get( - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), - VectorType::get(Type::getInt64Ty(Ctx), ElementCount::getScalable(2))), + StructType::get(VectorType::get(Type::getFloatTy(Ctx), NXV2), + VectorType::get(Type::getInt64Ty(Ctx), NXV2)), { - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getScalable(2)), - VectorType::get(Type::getInt1Ty(Ctx), ElementCount::getScalable(2)), + VectorType::get(Type::getFloatTy(Ctx), NXV2), + VectorType::get(Type::getInt1Ty(Ctx), NXV2), }, false); EXPECT_EQ(getFunctionType(), FTy); EXPECT_EQ(Parameters.size(), 2U); EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::GlobalPredicate})); - EXPECT_EQ(VF, ElementCount::getScalable(2)); + EXPECT_EQ(VF, NXV2); EXPECT_EQ(ScalarName, "foo"); EXPECT_EQ(VectorName, "vector_foo"); } TEST_F(VFABIParserTest, ParseWideStructReturnTypeNEON) { EXPECT_TRUE( - invokeParser("_ZGVnN2v_foo(vector_foo)", "{float, float}(float)")); + invokeParser("_ZGVnN4v_foo(vector_foo)", "{float, float}(float)")); EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD); EXPECT_FALSE(isMasked()); + ElementCount V4 = ElementCount::getFixed(4); FunctionType *FTy = FunctionType::get( - StructType::get( - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2)), - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2))), + StructType::get(VectorType::get(Type::getFloatTy(Ctx), V4), + VectorType::get(Type::getFloatTy(Ctx), V4)), { - VectorType::get(Type::getFloatTy(Ctx), ElementCount::getFixed(2)), + VectorType::get(Type::getFloatTy(Ctx), V4), }, false); EXPECT_EQ(getFunctionType(), FTy); EXPECT_EQ(Parameters.size(), 1U); EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::Vector})); - EXPECT_EQ(VF, ElementCount::getFixed(2)); + EXPECT_EQ(VF, V4); EXPECT_EQ(ScalarName, "foo"); EXPECT_EQ(VectorName, "vector_foo"); } +TEST_F(VFABIParserTest, ParseUnsupportedStructReturnTypesSVE) { + // Struct with array element type. + EXPECT_FALSE( + invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, [4 x f32]}(float)")); + // Nested struct type. + EXPECT_FALSE( + invokeParser("_ZGVsMxv_foo(vector_foo)", "{{float, float}}(float)")); + // Packed struct type. + EXPECT_FALSE( + invokeParser("_ZGVsMxv_foo(vector_foo)", "<{double, float}>(float)")); + // Named struct type. + EXPECT_FALSE( + invokeParser("_ZGVsMxv_foo(vector_foo)", "%dummy_named_struct(float)")); +} + // Make sure we reject unsupported parameter types. TEST_F(VFABIParserTest, ParseUnsupportedElementTypeSVE) { EXPECT_FALSE(invokeParser("_ZGVsMxv_foo(vector_foo)", "void(i128)")); From 54c624490e9aff94fd3f386fe131ebfc83fb4ea0 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Fri, 13 Dec 2024 14:47:11 +0000 Subject: [PATCH 06/14] Fix typo --- llvm/unittests/IR/VFABIDemanglerTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/IR/VFABIDemanglerTest.cpp b/llvm/unittests/IR/VFABIDemanglerTest.cpp index 0e62082e07c7d..e30e0f865f719 100644 --- a/llvm/unittests/IR/VFABIDemanglerTest.cpp +++ b/llvm/unittests/IR/VFABIDemanglerTest.cpp @@ -824,7 +824,7 @@ TEST_F(VFABIParserTest, ParseWideStructReturnTypeNEON) { TEST_F(VFABIParserTest, ParseUnsupportedStructReturnTypesSVE) { // Struct with array element type. EXPECT_FALSE( - invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, [4 x f32]}(float)")); + invokeParser("_ZGVsMxv_foo(vector_foo)", "{double, [4 x float]}(float)")); // Nested struct type. EXPECT_FALSE( invokeParser("_ZGVsMxv_foo(vector_foo)", "{{float, float}}(float)")); From 91085c669b2072cd0b05d38062ece968ac8d5fa9 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Fri, 13 Dec 2024 16:58:46 +0000 Subject: [PATCH 07/14] Fixups --- llvm/include/llvm/IR/StructWideningUtils.h | 8 ++--- llvm/include/llvm/IR/VectorUtils.h | 28 +++++++-------- llvm/lib/IR/StructWideningUtils.cpp | 8 ++--- llvm/lib/IR/VFABIDemangler.cpp | 2 +- llvm/unittests/IR/VectorUtilsTest.cpp | 42 +++++++++++----------- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h index 3067ab88435ae..8c3cb9f5192cd 100644 --- a/llvm/include/llvm/IR/StructWideningUtils.h +++ b/llvm/include/llvm/IR/StructWideningUtils.h @@ -1,4 +1,4 @@ -//===--- StructWideningUtils.h - Utils for widening/narrowing struct types ===// +//===--- StructWideningUtils.h - Utils for vectorizing struct types -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -19,15 +19,15 @@ inline bool isUnpackedStructLiteral(StructType *StructTy) { /// A helper for converting structs of scalar types to structs of vector types. /// Note: Only unpacked literal struct types are supported. -Type *toWideStructTy(StructType *StructTy, ElementCount EC); +Type *toVectorizedStructTy(StructType *StructTy, ElementCount EC); /// A helper for converting structs of vector types to structs of scalar types. /// Note: Only unpacked literal struct types are supported. -Type *toNarrowStructTy(StructType *StructTy); +Type *toScalarizedStructTy(StructType *StructTy); /// Returns true if `StructTy` is an unpacked literal struct where all elements /// are vectors of matching element count. This does not include empty structs. -bool isWideStructTy(StructType *StructTy); +bool isVectorizedStructTy(StructType *StructTy); } // namespace llvm diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h index 4ddf721e3a829..49409f7ea26ce 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -27,31 +27,31 @@ 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 +/// A helper for converting to vectorized 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. -inline Type *ToWideTy(Type *Ty, ElementCount EC) { +inline Type *toVectorizedTy(Type *Ty, ElementCount EC) { if (StructType *StructTy = dyn_cast(Ty)) - return toWideStructTy(StructTy, EC); + return toVectorizedStructTy(StructTy, EC); return ToVectorTy(Ty, EC); } -/// A helper for converting wide types to narrow (non-vector) types. For vector -/// types, this is equivalent to calling .getScalarType(). For struct types, -/// this returns a new struct where each element type has been converted to a -/// scalar type. Note: Only unpacked literal struct types are supported. -inline Type *ToNarrowTy(Type *Ty) { +/// A helper for converting vectorized types to scalarized (non-vector) types. +/// For vector types, this is equivalent to calling .getScalarType(). For struct +/// types, this returns a new struct where each element type has been converted +/// to a scalar type. Note: Only unpacked literal struct types are supported. +inline Type *toScalarizedTy(Type *Ty) { if (StructType *StructTy = dyn_cast(Ty)) - return toNarrowStructTy(StructTy); + return toScalarizedStructTy(StructTy); return Ty->getScalarType(); } /// Returns true if `Ty` is a vector type or a struct of vector types where all /// vector types share the same VF. -inline bool isWideTy(Type *Ty) { +inline bool isVectorizedTy(Type *Ty) { if (StructType *StructTy = dyn_cast(Ty)) - return isWideStructTy(StructTy); + return isVectorizedStructTy(StructTy); return Ty->isVectorTy(); } @@ -63,9 +63,9 @@ inline ArrayRef getContainedTypes(Type *const &Ty) { return ArrayRef(&Ty, 1); } -/// Returns the number of vector elements for a widened type. -inline ElementCount getWideTypeVF(Type *Ty) { - assert(isWideTy(Ty) && "expected widened type"); +/// Returns the number of vector elements for a vectorized type. +inline ElementCount getVectorizedTypeVF(Type *Ty) { + assert(isVectorizedTy(Ty) && "expected widened type"); return cast(getContainedTypes(Ty).front())->getElementCount(); } diff --git a/llvm/lib/IR/StructWideningUtils.cpp b/llvm/lib/IR/StructWideningUtils.cpp index 72f442a9bf04c..372db086fe761 100644 --- a/llvm/lib/IR/StructWideningUtils.cpp +++ b/llvm/lib/IR/StructWideningUtils.cpp @@ -1,4 +1,4 @@ -//===- StructWideningUtils.cpp - Utils for widening/narrowing struct types ===// +//===- StructWideningUtils.cpp - Utils for vectorizing struct types------- ===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,7 +14,7 @@ using namespace llvm; /// A helper for converting structs of scalar types to structs of vector types. /// Note: Only unpacked literal struct types are supported. -Type *llvm::toWideStructTy(StructType *StructTy, ElementCount EC) { +Type *llvm::toVectorizedStructTy(StructType *StructTy, ElementCount EC) { if (EC.isScalar()) return StructTy; assert(isUnpackedStructLiteral(StructTy) && @@ -30,7 +30,7 @@ Type *llvm::toWideStructTy(StructType *StructTy, ElementCount EC) { /// A helper for converting structs of vector types to structs of scalar types. /// Note: Only unpacked literal struct types are supported. -Type *llvm::toNarrowStructTy(StructType *StructTy) { +Type *llvm::toScalarizedStructTy(StructType *StructTy) { assert(isUnpackedStructLiteral(StructTy) && "expected unpacked struct literal"); return StructType::get( @@ -42,7 +42,7 @@ Type *llvm::toNarrowStructTy(StructType *StructTy) { /// Returns true if `StructTy` is an unpacked literal struct where all elements /// are vectors of matching element count. This does not include empty structs. -bool llvm::isWideStructTy(StructType *StructTy) { +bool llvm::isVectorizedStructTy(StructType *StructTy) { if (!isUnpackedStructLiteral(StructTy)) return false; auto ElemTys = StructTy->elements(); diff --git a/llvm/lib/IR/VFABIDemangler.cpp b/llvm/lib/IR/VFABIDemangler.cpp index e7e080038e74c..a61eae6d478c3 100644 --- a/llvm/lib/IR/VFABIDemangler.cpp +++ b/llvm/lib/IR/VFABIDemangler.cpp @@ -575,7 +575,7 @@ FunctionType *VFABI::createFunctionType(const VFInfo &Info, auto *RetTy = ScalarFTy->getReturnType(); if (!RetTy->isVoidTy()) - RetTy = ToWideTy(RetTy, VF); + RetTy = toVectorizedTy(RetTy, VF); return FunctionType::get(RetTy, VecTypes, false); } diff --git a/llvm/unittests/IR/VectorUtilsTest.cpp b/llvm/unittests/IR/VectorUtilsTest.cpp index b70cd2f511df4..aac3bf1817f92 100644 --- a/llvm/unittests/IR/VectorUtilsTest.cpp +++ b/llvm/unittests/IR/VectorUtilsTest.cpp @@ -17,7 +17,7 @@ namespace { class VectorUtilsTest : public ::testing::Test {}; -TEST(VectorUtilsTest, TestToWideTy) { +TEST(VectorUtilsTest, TestToVectorizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -28,15 +28,15 @@ TEST(VectorUtilsTest, TestToWideTy) { for (ElementCount VF : {ElementCount::getFixed(4), ElementCount::getScalable(2)}) { - Type *IntVec = ToWideTy(ITy, VF); + Type *IntVec = toVectorizedTy(ITy, VF); EXPECT_TRUE(isa(IntVec)); EXPECT_EQ(IntVec, VectorType::get(ITy, VF)); - Type *FloatVec = ToWideTy(FTy, VF); + Type *FloatVec = toVectorizedTy(FTy, VF); EXPECT_TRUE(isa(FloatVec)); EXPECT_EQ(FloatVec, VectorType::get(FTy, VF)); - Type *WideHomogeneousStructTy = ToWideTy(HomogeneousStructTy, VF); + Type *WideHomogeneousStructTy = toVectorizedTy(HomogeneousStructTy, VF); EXPECT_TRUE(isa(WideHomogeneousStructTy)); EXPECT_TRUE( cast(WideHomogeneousStructTy)->containsHomogeneousTypes()); @@ -45,7 +45,7 @@ TEST(VectorUtilsTest, TestToWideTy) { EXPECT_TRUE(cast(WideHomogeneousStructTy)->getElementType(0) == VectorType::get(FTy, VF)); - Type *WideMixedStructTy = ToWideTy(MixedStructTy, VF); + Type *WideMixedStructTy = toVectorizedTy(MixedStructTy, VF); EXPECT_TRUE(isa(WideMixedStructTy)); EXPECT_TRUE(cast(WideMixedStructTy)->getNumElements() == 2); EXPECT_TRUE(cast(WideMixedStructTy)->getElementType(0) == @@ -53,16 +53,16 @@ TEST(VectorUtilsTest, TestToWideTy) { EXPECT_TRUE(cast(WideMixedStructTy)->getElementType(1) == VectorType::get(ITy, VF)); - EXPECT_EQ(ToWideTy(VoidTy, VF), VoidTy); + EXPECT_EQ(toVectorizedTy(VoidTy, VF), VoidTy); } ElementCount ScalarVF = ElementCount::getFixed(1); for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy, VoidTy}) { - EXPECT_EQ(ToWideTy(Ty, ScalarVF), Ty); + EXPECT_EQ(toVectorizedTy(Ty, ScalarVF), Ty); } } -TEST(VectorUtilsTest, TestToNarrowTy) { +TEST(VectorUtilsTest, TestToScalarizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -74,8 +74,8 @@ TEST(VectorUtilsTest, TestToNarrowTy) { for (ElementCount VF : {ElementCount::getFixed(1), ElementCount::getFixed(4), ElementCount::getScalable(2)}) { for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy, VoidTy}) { - // ToNarrowTy should be the inverse of ToWideTy. - EXPECT_EQ(ToNarrowTy(ToWideTy(Ty, VF)), Ty); + // toScalarizedTy should be the inverse of toVectorizedTy. + EXPECT_EQ(toScalarizedTy(toVectorizedTy(Ty, VF)), Ty); }; } } @@ -97,7 +97,7 @@ TEST(VectorUtilsTest, TestGetContainedTypes) { EXPECT_EQ(getContainedTypes(MixedStructTy), ArrayRef({FTy, ITy})); } -TEST(VectorUtilsTest, TestIsWideTy) { +TEST(VectorUtilsTest, TestIsVectorizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -105,32 +105,32 @@ TEST(VectorUtilsTest, TestIsWideTy) { Type *NarrowStruct = StructType::get(FTy, ITy); Type *VoidTy = Type::getVoidTy(C); - EXPECT_FALSE(isWideTy(ITy)); - EXPECT_FALSE(isWideTy(NarrowStruct)); - EXPECT_FALSE(isWideTy(VoidTy)); + EXPECT_FALSE(isVectorizedTy(ITy)); + EXPECT_FALSE(isVectorizedTy(NarrowStruct)); + EXPECT_FALSE(isVectorizedTy(VoidTy)); ElementCount VF = ElementCount::getFixed(4); - EXPECT_TRUE(isWideTy(ToWideTy(ITy, VF))); - EXPECT_TRUE(isWideTy(ToWideTy(NarrowStruct, VF))); + EXPECT_TRUE(isVectorizedTy(toVectorizedTy(ITy, VF))); + EXPECT_TRUE(isVectorizedTy(toVectorizedTy(NarrowStruct, VF))); Type *MixedVFStruct = StructType::get(VectorType::get(ITy, ElementCount::getFixed(2)), VectorType::get(ITy, ElementCount::getFixed(4))); - EXPECT_FALSE(isWideTy(MixedVFStruct)); + EXPECT_FALSE(isVectorizedTy(MixedVFStruct)); // Currently only literals types are considered wide. Type *NamedWideStruct = StructType::create("Named", VectorType::get(ITy, VF), VectorType::get(ITy, VF)); - EXPECT_FALSE(isWideTy(NamedWideStruct)); + EXPECT_FALSE(isVectorizedTy(NamedWideStruct)); // Currently only unpacked types are considered wide. Type *PackedWideStruct = StructType::get( C, ArrayRef{VectorType::get(ITy, VF), VectorType::get(ITy, VF)}, /*isPacked=*/true); - EXPECT_FALSE(isWideTy(PackedWideStruct)); + EXPECT_FALSE(isVectorizedTy(PackedWideStruct)); } -TEST(VectorUtilsTest, TestGetWideTypeVF) { +TEST(VectorUtilsTest, TestGetVectorizedTypeVF) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -141,7 +141,7 @@ TEST(VectorUtilsTest, TestGetWideTypeVF) { for (ElementCount VF : {ElementCount::getFixed(4), ElementCount::getScalable(2)}) { for (Type *Ty : {ITy, FTy, HomogeneousStructTy, MixedStructTy}) { - EXPECT_EQ(getWideTypeVF(ToWideTy(Ty, VF)), VF); + EXPECT_EQ(getVectorizedTypeVF(toVectorizedTy(Ty, VF)), VF); }; } } From 899f19a6f33febcbad98251d38970d3ee5bb6b3d Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 10:29:46 +0000 Subject: [PATCH 08/14] Move helpers --- llvm/include/llvm/IR/StructWideningUtils.h | 34 ------------------- llvm/include/llvm/IR/VectorUtils.h | 17 +++++++++- llvm/lib/IR/CMakeLists.txt | 2 +- ...tructWideningUtils.cpp => VectorUtils.cpp} | 5 ++- 4 files changed, 19 insertions(+), 39 deletions(-) delete mode 100644 llvm/include/llvm/IR/StructWideningUtils.h rename llvm/lib/IR/{StructWideningUtils.cpp => VectorUtils.cpp} (94%) diff --git a/llvm/include/llvm/IR/StructWideningUtils.h b/llvm/include/llvm/IR/StructWideningUtils.h deleted file mode 100644 index 8c3cb9f5192cd..0000000000000 --- a/llvm/include/llvm/IR/StructWideningUtils.h +++ /dev/null @@ -1,34 +0,0 @@ -//===--- StructWideningUtils.h - Utils for vectorizing struct types -------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_STRUCTWIDENINGUTILS_H -#define LLVM_IR_STRUCTWIDENINGUTILS_H - -#include "llvm/IR/DerivedTypes.h" - -namespace llvm { - -inline bool isUnpackedStructLiteral(StructType *StructTy) { - return StructTy->isLiteral() && !StructTy->isPacked(); -} - -/// A helper for converting structs of scalar types to structs of vector types. -/// Note: Only unpacked literal struct types are supported. -Type *toVectorizedStructTy(StructType *StructTy, ElementCount EC); - -/// A helper for converting structs of vector types to structs of scalar types. -/// Note: Only unpacked literal struct types are supported. -Type *toScalarizedStructTy(StructType *StructTy); - -/// Returns true if `StructTy` is an unpacked literal struct where all elements -/// are vectors of matching element count. This does not include empty structs. -bool isVectorizedStructTy(StructType *StructTy); - -} // namespace llvm - -#endif diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h index 49409f7ea26ce..3396bba64cc53 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -10,7 +10,6 @@ #define LLVM_IR_VECTORUTILS_H #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/StructWideningUtils.h" namespace llvm { @@ -27,6 +26,18 @@ inline Type *ToVectorTy(Type *Scalar, unsigned VF) { return ToVectorTy(Scalar, ElementCount::getFixed(VF)); } +/// A helper for converting structs of scalar types to structs of vector types. +/// Note: Only unpacked literal struct types are supported. +Type *toVectorizedStructTy(StructType *StructTy, ElementCount EC); + +/// A helper for converting structs of vector types to structs of scalar types. +/// Note: Only unpacked literal struct types are supported. +Type *toScalarizedStructTy(StructType *StructTy); + +/// Returns true if `StructTy` is an unpacked literal struct where all elements +/// are vectors of matching element count. This does not include empty structs. +bool isVectorizedStructTy(StructType *StructTy); + /// A helper for converting to vectorized 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 @@ -69,6 +80,10 @@ inline ElementCount getVectorizedTypeVF(Type *Ty) { return cast(getContainedTypes(Ty).front())->getElementCount(); } +inline bool isUnpackedStructLiteral(StructType *StructTy) { + return StructTy->isLiteral() && !StructTy->isPacked(); +} + } // namespace llvm #endif diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 42aceadde5922..7eaf35e10ebc6 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -64,7 +64,6 @@ add_llvm_component_library(LLVMCore PseudoProbe.cpp ReplaceConstant.cpp Statepoint.cpp - StructWideningUtils.cpp StructuralHash.cpp Type.cpp TypedPointerType.cpp @@ -74,6 +73,7 @@ add_llvm_component_library(LLVMCore Value.cpp ValueSymbolTable.cpp VectorBuilder.cpp + VectorUtils.cpp Verifier.cpp VFABIDemangler.cpp RuntimeLibcalls.cpp diff --git a/llvm/lib/IR/StructWideningUtils.cpp b/llvm/lib/IR/VectorUtils.cpp similarity index 94% rename from llvm/lib/IR/StructWideningUtils.cpp rename to llvm/lib/IR/VectorUtils.cpp index 372db086fe761..7a7ef2796a2a0 100644 --- a/llvm/lib/IR/StructWideningUtils.cpp +++ b/llvm/lib/IR/VectorUtils.cpp @@ -1,4 +1,4 @@ -//===- StructWideningUtils.cpp - Utils for vectorizing struct types------- ===// +//===- VectorUtils.cpp - Vector type utility functions --------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/StructWideningUtils.h" -#include "llvm/ADT/SmallVectorExtras.h" #include "llvm/IR/VectorUtils.h" +#include "llvm/ADT/SmallVectorExtras.h" using namespace llvm; From ee19f4e20ac123c8442959974dbf5e9923a5d569 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 14:10:39 +0000 Subject: [PATCH 09/14] Fixups --- llvm/include/llvm/IR/VectorUtils.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorUtils.h index 3396bba64cc53..47ff1bbc98ebc 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorUtils.h @@ -27,7 +27,9 @@ inline Type *ToVectorTy(Type *Scalar, unsigned VF) { } /// A helper for converting structs of scalar types to structs of vector types. -/// Note: Only unpacked literal struct types are supported. +/// Note: +/// - If \p EC is scalar, \p StructTy is returned unchanged +/// - Only unpacked literal struct types are supported Type *toVectorizedStructTy(StructType *StructTy, ElementCount EC); /// A helper for converting structs of vector types to structs of scalar types. @@ -40,8 +42,11 @@ bool isVectorizedStructTy(StructType *StructTy); /// A helper for converting to vectorized 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. +/// struct where each element type has been widened to a vector type. +/// Note: +/// - If the he incoming type is void, we return void +/// - If \p EC is scalar, \p Ty is returned unchanged +/// - Only unpacked literal struct types are supported inline Type *toVectorizedTy(Type *Ty, ElementCount EC) { if (StructType *StructTy = dyn_cast(Ty)) return toVectorizedStructTy(StructTy, EC); From b0ff8df1e1987c10302d22b7e87b2a19347e77f6 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 19:05:01 +0000 Subject: [PATCH 10/14] RM --- llvm/include/llvm/Analysis/VectorUtils.h | 2 +- llvm/include/llvm/IR/{VectorUtils.h => VectorTypeUtils.h} | 2 +- llvm/lib/IR/CMakeLists.txt | 2 +- llvm/lib/IR/VFABIDemangler.cpp | 2 +- llvm/lib/IR/{VectorUtils.cpp => VectorTypeUtils.cpp} | 4 ++-- llvm/unittests/IR/CMakeLists.txt | 2 +- .../IR/{VectorUtilsTest.cpp => VectorTypeUtilsTest.cpp} | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) rename llvm/include/llvm/IR/{VectorUtils.h => VectorTypeUtils.h} (98%) rename llvm/lib/IR/{VectorUtils.cpp => VectorTypeUtils.cpp} (94%) rename llvm/unittests/IR/{VectorUtilsTest.cpp => VectorTypeUtilsTest.cpp} (98%) diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h index 5433231a1018e..7f8a0c9c0af7b 100644 --- a/llvm/include/llvm/Analysis/VectorUtils.h +++ b/llvm/include/llvm/Analysis/VectorUtils.h @@ -18,7 +18,7 @@ #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/IR/Module.h" #include "llvm/IR/VFABIDemangler.h" -#include "llvm/IR/VectorUtils.h" +#include "llvm/IR/VectorTypeUtils.h" #include "llvm/Support/CheckedArithmetic.h" namespace llvm { diff --git a/llvm/include/llvm/IR/VectorUtils.h b/llvm/include/llvm/IR/VectorTypeUtils.h similarity index 98% rename from llvm/include/llvm/IR/VectorUtils.h rename to llvm/include/llvm/IR/VectorTypeUtils.h index 47ff1bbc98ebc..ed838c05ba03a 100644 --- a/llvm/include/llvm/IR/VectorUtils.h +++ b/llvm/include/llvm/IR/VectorTypeUtils.h @@ -1,4 +1,4 @@ -//===----------- VectorUtils.h - Vector type utility functions -*- C++ -*-====// +//===------- VectorTypeUtils.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. diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt index 7eaf35e10ebc6..5f6254b231318 100644 --- a/llvm/lib/IR/CMakeLists.txt +++ b/llvm/lib/IR/CMakeLists.txt @@ -73,7 +73,7 @@ add_llvm_component_library(LLVMCore Value.cpp ValueSymbolTable.cpp VectorBuilder.cpp - VectorUtils.cpp + VectorTypeUtils.cpp Verifier.cpp VFABIDemangler.cpp RuntimeLibcalls.cpp diff --git a/llvm/lib/IR/VFABIDemangler.cpp b/llvm/lib/IR/VFABIDemangler.cpp index a61eae6d478c3..62f96b10cea4a 100644 --- a/llvm/lib/IR/VFABIDemangler.cpp +++ b/llvm/lib/IR/VFABIDemangler.cpp @@ -11,7 +11,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/IR/Module.h" -#include "llvm/IR/VectorUtils.h" +#include "llvm/IR/VectorTypeUtils.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/llvm/lib/IR/VectorUtils.cpp b/llvm/lib/IR/VectorTypeUtils.cpp similarity index 94% rename from llvm/lib/IR/VectorUtils.cpp rename to llvm/lib/IR/VectorTypeUtils.cpp index 7a7ef2796a2a0..e6e265414a2b8 100644 --- a/llvm/lib/IR/VectorUtils.cpp +++ b/llvm/lib/IR/VectorTypeUtils.cpp @@ -1,4 +1,4 @@ -//===- VectorUtils.cpp - Vector type utility functions --------------------===// +//===------- VectorTypeUtils.cpp - Vector type utility functions ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/VectorUtils.h" +#include "llvm/IR/VectorTypeUtils.h" #include "llvm/ADT/SmallVectorExtras.h" using namespace llvm; diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt index efbe710987a48..b3dfe3d72fd38 100644 --- a/llvm/unittests/IR/CMakeLists.txt +++ b/llvm/unittests/IR/CMakeLists.txt @@ -51,8 +51,8 @@ add_llvm_unittest(IRTests ValueMapTest.cpp ValueTest.cpp VectorBuilderTest.cpp + VectorTypeUtilsTest.cpp VectorTypesTest.cpp - VectorUtilsTest.cpp VerifierTest.cpp VFABIDemanglerTest.cpp VPIntrinsicTest.cpp diff --git a/llvm/unittests/IR/VectorUtilsTest.cpp b/llvm/unittests/IR/VectorTypeUtilsTest.cpp similarity index 98% rename from llvm/unittests/IR/VectorUtilsTest.cpp rename to llvm/unittests/IR/VectorTypeUtilsTest.cpp index aac3bf1817f92..00ae6bbdcd3ac 100644 --- a/llvm/unittests/IR/VectorUtilsTest.cpp +++ b/llvm/unittests/IR/VectorTypeUtilsTest.cpp @@ -1,4 +1,4 @@ -//===------- VectorUtilsTest.cpp - Vector utils tests ---------------------===// +//===------- VectorTypeUtilsTest.cpp - Vector utils tests -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/VectorUtils.h" +#include "llvm/IR/VectorTypeUtils.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" #include "gtest/gtest.h" From 5c155cefc1fa7ff691a3eb1536238da4e6d93e18 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 19:07:08 +0000 Subject: [PATCH 11/14] RM --- llvm/include/llvm/IR/VectorTypeUtils.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/IR/VectorTypeUtils.h b/llvm/include/llvm/IR/VectorTypeUtils.h index ed838c05ba03a..756eed63fae49 100644 --- a/llvm/include/llvm/IR/VectorTypeUtils.h +++ b/llvm/include/llvm/IR/VectorTypeUtils.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_VECTORUTILS_H -#define LLVM_IR_VECTORUTILS_H +#ifndef LLVM_IR_VECTORTYPEUTILS_H +#define LLVM_IR_VECTORTYPEUTILS_H #include "llvm/IR/DerivedTypes.h" From dd90ff4460172021fba065eda20dfc1d3fe3bd8f Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 19:15:11 +0000 Subject: [PATCH 12/14] RM --- llvm/unittests/IR/VectorTypeUtilsTest.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/unittests/IR/VectorTypeUtilsTest.cpp b/llvm/unittests/IR/VectorTypeUtilsTest.cpp index 00ae6bbdcd3ac..c77f183e921de 100644 --- a/llvm/unittests/IR/VectorTypeUtilsTest.cpp +++ b/llvm/unittests/IR/VectorTypeUtilsTest.cpp @@ -15,9 +15,9 @@ using namespace llvm; namespace { -class VectorUtilsTest : public ::testing::Test {}; +class VectorTypeUtilsTest : public ::testing::Test {}; -TEST(VectorUtilsTest, TestToVectorizedTy) { +TEST(VectorTypeUtilsTest, TestToVectorizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -62,7 +62,7 @@ TEST(VectorUtilsTest, TestToVectorizedTy) { } } -TEST(VectorUtilsTest, TestToScalarizedTy) { +TEST(VectorTypeUtilsTest, TestToScalarizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -80,7 +80,7 @@ TEST(VectorUtilsTest, TestToScalarizedTy) { } } -TEST(VectorUtilsTest, TestGetContainedTypes) { +TEST(VectorTypeUtilsTest, TestGetContainedTypes) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -97,7 +97,7 @@ TEST(VectorUtilsTest, TestGetContainedTypes) { EXPECT_EQ(getContainedTypes(MixedStructTy), ArrayRef({FTy, ITy})); } -TEST(VectorUtilsTest, TestIsVectorizedTy) { +TEST(VectorTypeUtilsTest, TestIsVectorizedTy) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); @@ -130,7 +130,7 @@ TEST(VectorUtilsTest, TestIsVectorizedTy) { EXPECT_FALSE(isVectorizedTy(PackedWideStruct)); } -TEST(VectorUtilsTest, TestGetVectorizedTypeVF) { +TEST(VectorTypeUtilsTest, TestGetVectorizedTypeVF) { LLVMContext C; Type *ITy = Type::getInt32Ty(C); From cbf5ff970c687cd72f8858628f317b68ea9fbeab Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 20:48:17 +0000 Subject: [PATCH 13/14] fix typo --- llvm/include/llvm/IR/VectorTypeUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/VectorTypeUtils.h b/llvm/include/llvm/IR/VectorTypeUtils.h index 756eed63fae49..4a48663911ed4 100644 --- a/llvm/include/llvm/IR/VectorTypeUtils.h +++ b/llvm/include/llvm/IR/VectorTypeUtils.h @@ -44,7 +44,7 @@ bool isVectorizedStructTy(StructType *StructTy); /// equivalent to calling `ToVectorTy`. For struct types, this returns a new /// struct where each element type has been widened to a vector type. /// Note: -/// - If the he incoming type is void, we return void +/// - If the incoming type is void, we return void /// - If \p EC is scalar, \p Ty is returned unchanged /// - Only unpacked literal struct types are supported inline Type *toVectorizedTy(Type *Ty, ElementCount EC) { From 39c5bc4434ebf22416544c8bd47c948a95bcece4 Mon Sep 17 00:00:00 2001 From: Benjamin Maxwell Date: Tue, 17 Dec 2024 20:57:12 +0000 Subject: [PATCH 14/14] widened type -> vectorized type --- llvm/include/llvm/IR/VectorTypeUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/VectorTypeUtils.h b/llvm/include/llvm/IR/VectorTypeUtils.h index 4a48663911ed4..f30bf9ee9240b 100644 --- a/llvm/include/llvm/IR/VectorTypeUtils.h +++ b/llvm/include/llvm/IR/VectorTypeUtils.h @@ -81,7 +81,7 @@ inline ArrayRef getContainedTypes(Type *const &Ty) { /// Returns the number of vector elements for a vectorized type. inline ElementCount getVectorizedTypeVF(Type *Ty) { - assert(isVectorizedTy(Ty) && "expected widened type"); + assert(isVectorizedTy(Ty) && "expected vectorized type"); return cast(getContainedTypes(Ty).front())->getElementCount(); }