Skip to content

Commit 5e92c3d

Browse files
committed
Rework logic to preserve "scalar" operand/return type, even if vector
If isVectorIntrinsicWithScalarOpAtArg() returns true for an argument or return, we should not attempt to modify the type or use the element count, even if it is a vector. This allows the op to be identified as something that doesn't vectorize/scalarize with the width of the intrinsic, but remains the same, even if it is a vector argument. Initial ElementCount will only be the return element count if it's a vector and isVectorIntrinsicWithScalarOpAtArg returns false. This also returns the control flow in the loop to be closer to the original. Remove inconsistent comment about VFABI return type assumption, since we have the accessors that tell us how to handle it for the operation. Fix formatting.
1 parent 2c70285 commit 5e92c3d

File tree

1 file changed

+21
-13
lines changed

1 file changed

+21
-13
lines changed

llvm/lib/CodeGen/ReplaceWithVeclib.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,35 +103,43 @@ static bool replaceWithCallToVeclib(const TargetLibraryInfo &TLI,
103103
Intrinsic::ID IID = II->getIntrinsicID();
104104
if (IID == Intrinsic::not_intrinsic)
105105
return false;
106-
// At the moment VFABI assumes the return type is always widened unless it is
107-
// a void type.
108-
auto *VTy = dyn_cast<VectorType>(II->getType());
109-
ElementCount EC(VTy ? VTy->getElementCount() : ElementCount::getFixed(0));
110-
Type *ScalarRetTy = II->getType()->getScalarType();
106+
107+
// RetIsScalar: Return type is not widened.
108+
bool RetIsScalar = isVectorIntrinsicWithScalarOpAtArg(IID, -1);
109+
Type *RetTy = II->getType();
110+
Type *ScalarRetTy = RetTy->getScalarType();
111+
111112
// Compute the argument types of the corresponding scalar call and check that
112113
// all vector operands match the previously found EC.
113114
SmallVector<Type *, 8> ScalarArgTypes;
115+
auto *VTy = dyn_cast<VectorType>(RetTy);
116+
ElementCount EC(!RetIsScalar && VTy ? VTy->getElementCount()
117+
: ElementCount::getFixed(0));
114118

115119
// OloadTys collects types used in scalar intrinsic overload name.
116120
SmallVector<Type *, 3> OloadTys;
117-
if (!ScalarRetTy->isVoidTy() &&
118-
isVectorIntrinsicWithOverloadTypeAtArg(IID, -1))
119-
OloadTys.push_back(ScalarRetTy);
121+
if (!RetTy->isVoidTy() && isVectorIntrinsicWithOverloadTypeAtArg(IID, -1))
122+
OloadTys.push_back(RetIsScalar ? RetTy : ScalarRetTy);
120123

121124
for (auto Arg : enumerate(II->args())) {
122125
auto *ArgTy = Arg.value()->getType();
123-
auto *ScalarArgTy = ArgTy->getScalarType();
124-
ScalarArgTypes.push_back(ScalarArgTy);
125-
if (isVectorIntrinsicWithOverloadTypeAtArg(IID, Arg.index()))
126+
bool IsOloadTy = isVectorIntrinsicWithOverloadTypeAtArg(IID, Arg.index());
127+
if (isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index())) {
128+
ScalarArgTypes.push_back(ArgTy);
129+
if (IsOloadTy)
130+
OloadTys.push_back(ArgTy);
131+
} else if (auto *VectorArgTy = dyn_cast<VectorType>(ArgTy)) {
132+
auto *ScalarArgTy = VectorArgTy->getElementType();
133+
ScalarArgTypes.push_back(ScalarArgTy);
134+
if (IsOloadTy)
126135
OloadTys.push_back(ScalarArgTy);
127-
if (auto *VectorArgTy = dyn_cast<VectorType>(ArgTy)) {
128136
// When return type is void, set EC to the first vector argument, and
129137
// disallow vector arguments with different ECs.
130138
if (EC.isZero())
131139
EC = VectorArgTy->getElementCount();
132140
else if (EC != VectorArgTy->getElementCount())
133141
return false;
134-
} else if (!isVectorIntrinsicWithScalarOpAtArg(IID, Arg.index()))
142+
} else
135143
// Exit when it is supposed to be a vector argument but it isn't.
136144
return false;
137145
}

0 commit comments

Comments
 (0)