Skip to content

Commit 29f11b1

Browse files
Simplified createFunctionType method
It accepts ScalarFTy and VecRetTy. As the latter is not kept in VFABI, it should instead come from the original Instruction/Callinst. This change allows further simplification in tests. Also, methods like the test `_ZGVnN3lLRUlnLnRnUn_foo`, which contains only scalar parameters, would still return a valid FunctionType. This is an edge case that will only be encountered in tests though.
1 parent c95fe95 commit 29f11b1

File tree

3 files changed

+28
-75
lines changed

3 files changed

+28
-75
lines changed

llvm/include/llvm/Analysis/VectorUtils.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,10 @@ void getVectorVariantNames(const CallInst &CI,
197197
SmallVectorImpl<std::string> &VariantMappings);
198198

199199
/// Returns a pair of the vectorized FunctionType and the mask's position when
200-
/// there's one, otherwise -1. It rejects any non vectorized calls as this
201-
/// method should be called at a point where the Instruction \p I is already
202-
/// vectorized.
200+
/// there's one, otherwise -1.
203201
std::optional<std::pair<FunctionType *, int>>
204-
createFunctionType(const VFInfo &Info, const Instruction *I, const Module *M);
202+
createFunctionType(const VFInfo &Info, const FunctionType *ScalarFTy,
203+
Type *VecRetTy, const Module *M);
205204
} // end namespace VFABI
206205

207206
/// The Vector Function Database.

llvm/lib/Analysis/VectorUtils.cpp

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,32 +1479,17 @@ void VFABI::getVectorVariantNames(
14791479
}
14801480
}
14811481

1482-
// Returns whether any of the operands or return type of \p I are vectors.
1483-
static bool isVectorized(const Instruction *I) {
1484-
if (I->getType()->isVectorTy())
1485-
return true;
1486-
for (auto &U : I->operands())
1487-
if (U->getType()->isVectorTy())
1488-
return true;
1489-
return false;
1490-
}
1491-
14921482
std::optional<std::pair<FunctionType *, int>>
1493-
VFABI::createFunctionType(const VFInfo &Info, const Instruction *I,
1494-
const Module *M) {
1495-
// only vectorized calls should reach this method
1496-
if (!isVectorized(I))
1497-
return std::nullopt;
1498-
1483+
VFABI::createFunctionType(const VFInfo &Info, const FunctionType *ScalarFTy,
1484+
Type *VecRetTy, const Module *M) {
14991485
ElementCount VF = Info.Shape.VF;
1500-
// get vectorized operands
1501-
const bool IsCall = isa<CallBase>(I);
1502-
SmallVector<Type *, 8> VecParams;
1503-
for (auto [i, U] : enumerate(I->operands())) {
1504-
// ignore the function pointer when the Instruction is a call
1505-
if (IsCall && i == I->getNumOperands() - 1)
1506-
break;
1507-
VecParams.push_back(U->getType());
1486+
// Create vector parameter types
1487+
SmallVector<Type *, 8> VecTypes;
1488+
for (auto [STy, VFParam] : zip(ScalarFTy->params(), Info.Shape.Parameters)) {
1489+
if (VFParam.ParamKind == VFParamKind::Vector)
1490+
VecTypes.push_back(VectorType::get(STy, VF));
1491+
else
1492+
VecTypes.push_back(STy);
15081493
}
15091494

15101495
// Get mask's position mask and append one if not present in the Instruction.
@@ -1515,14 +1500,10 @@ VFABI::createFunctionType(const VFInfo &Info, const Instruction *I,
15151500
return std::nullopt;
15161501

15171502
MaskPos = OptMaskPos.value();
1518-
// append a mask only when it's missing
1519-
if (VecParams.size() == Info.Shape.Parameters.size() - 1) {
1520-
VectorType *MaskTy =
1521-
VectorType::get(Type::getInt1Ty(M->getContext()), VF);
1522-
VecParams.insert(VecParams.begin() + MaskPos, MaskTy);
1523-
}
1503+
VectorType *MaskTy = VectorType::get(Type::getInt1Ty(M->getContext()), VF);
1504+
VecTypes.insert(VecTypes.begin() + MaskPos, MaskTy);
15241505
}
1525-
FunctionType *VecFTy = FunctionType::get(I->getType(), VecParams, false);
1506+
FunctionType *VecFTy = FunctionType::get(VecRetTy, VecTypes, false);
15261507
return std::make_pair(VecFTy, MaskPos);
15271508
}
15281509

llvm/unittests/Analysis/VectorFunctionABITest.cpp

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,9 @@ class VFABIParserTest : public ::testing::Test {
9898
/// number and type of arguments with both the ScalarFTy and the operands of
9999
/// the call.
100100
bool checkFunctionType() {
101-
// Create a mock vectorized CallInst using dummy values and then use it to
102-
// create a vector FunctionType. In the case of scalable ISAs, the created
103-
// vector FunctionType might have a mask parameter Type, however, this input
104-
// CallInst will not have a mask operand.
101+
// For scalable ISAs, the created vector FunctionType might have a mask
102+
// parameter Type, according to VFABI. Regardless, this input CallInst,
103+
// despite being a vectorized call, it will not have a masked operand.
105104
SmallVector<Value *, 8> Args;
106105
SmallVector<Type *, 8> CallTypes;
107106
for (auto [VFParam, STy] :
@@ -117,47 +116,21 @@ class VFABIParserTest : public ::testing::Test {
117116

118117
// Mangled names do not currently encode return Type information. Generally,
119118
// return types are vectors, so use one.
120-
Type *RetTy = ScalarFTy->getReturnType();
121-
if (!RetTy->isVoidTy())
122-
RetTy = VectorType::get(RetTy, Info.Shape.VF);
119+
Type *VecRetTy = ScalarFTy->getReturnType();
120+
if (!VecRetTy->isVoidTy())
121+
VecRetTy = VectorType::get(VecRetTy, Info.Shape.VF);
123122

124123
FunctionCallee F = M->getOrInsertFunction(
125-
VectorName, FunctionType::get(RetTy, CallTypes, false));
124+
VectorName, FunctionType::get(VecRetTy, CallTypes, false));
126125
std::unique_ptr<CallInst> CI(CallInst::Create(F, Args));
127126

128127
// Use VFInfo and the mock CallInst to create a FunctionType that will
129-
// include a mask where relevant.
130-
auto OptVecFTyPos = VFABI::createFunctionType(Info, CI.get(), M.get());
128+
// include a mask when relevant.
129+
auto OptVecFTyPos =
130+
VFABI::createFunctionType(Info, ScalarFTy, VecRetTy, M.get());
131131
if (!OptVecFTyPos)
132132
return false;
133133

134-
// Ensure that masked Instructions are handled
135-
if (isMasked()) {
136-
// In case of a masked call, try creating another mock CallInst that is
137-
// masked. createFunctionType should be able to handle this.
138-
SmallVector<Type *, 8> CallTypesInclMask(CallTypes);
139-
SmallVector<Value *, 8> ArgsInclMask(Args);
140-
Type *MaskTy = VectorType::get(Type::getInt1Ty(M->getContext()), VF);
141-
CallTypesInclMask.push_back(MaskTy);
142-
ArgsInclMask.push_back(Constant::getNullValue(MaskTy));
143-
144-
FunctionCallee FMasked = M->getOrInsertFunction(
145-
VectorName + "_Masked",
146-
FunctionType::get(RetTy, CallTypesInclMask, false));
147-
std::unique_ptr<CallInst> CIMasked(
148-
CallInst::Create(FMasked, ArgsInclMask));
149-
auto OptVecFTyMaskedPos =
150-
VFABI::createFunctionType(Info, CIMasked.get(), M.get());
151-
if (!OptVecFTyMaskedPos)
152-
return false;
153-
154-
// Both FunctionTypes should have the same number of parameters.
155-
assert(
156-
(OptVecFTyPos->first->getNumParams() ==
157-
OptVecFTyMaskedPos->first->getNumParams()) &&
158-
"createFunctionType should accept masked or non masked Instructions");
159-
}
160-
161134
FunctionType *VecFTy = OptVecFTyPos->first;
162135
// Check that vectorized parameters' size match with VFInfo.
163136
// Both may include a mask.
@@ -324,7 +297,7 @@ TEST_F(VFABIParserTest, LinearWithCompileTimeNegativeStep) {
324297
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
325298
EXPECT_FALSE(isMasked());
326299
EXPECT_TRUE(matchParametersNum());
327-
EXPECT_FALSE(checkFunctionType()); // invalid: all operands are scalar
300+
EXPECT_TRUE(checkFunctionType());
328301
EXPECT_EQ(VF, ElementCount::getFixed(2));
329302
EXPECT_EQ(Parameters.size(), (unsigned)4);
330303
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, -1}));
@@ -389,7 +362,7 @@ TEST_F(VFABIParserTest, LinearWithoutCompileTime) {
389362
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
390363
EXPECT_FALSE(isMasked());
391364
EXPECT_TRUE(matchParametersNum());
392-
EXPECT_FALSE(checkFunctionType()); // invalid: all operands are scalar
365+
EXPECT_TRUE(checkFunctionType());
393366
EXPECT_EQ(Parameters.size(), (unsigned)8);
394367
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Linear, 1}));
395368
EXPECT_EQ(Parameters[1], VFParameter({1, VFParamKind::OMP_LinearVal, 1}));
@@ -452,7 +425,7 @@ TEST_F(VFABIParserTest, ParseUniform) {
452425
EXPECT_EQ(ISA, VFISAKind::AdvancedSIMD);
453426
EXPECT_FALSE(isMasked());
454427
EXPECT_TRUE(matchParametersNum());
455-
EXPECT_FALSE(checkFunctionType()); // invalid: all operands are scalar
428+
EXPECT_TRUE(checkFunctionType());
456429
EXPECT_EQ(VF, ElementCount::getFixed(2));
457430
EXPECT_EQ(Parameters.size(), (unsigned)1);
458431
EXPECT_EQ(Parameters[0], VFParameter({0, VFParamKind::OMP_Uniform, 0}));

0 commit comments

Comments
 (0)