forked from OSchip/llvm-project
[VFDatabase] Scalar functions are vector functions with VF =1
Summary: Return scalar function when VF==1. The new trivial mapping scalar --> scalar when VF==1 to prevent false positive for "isVectorizable" query. Author: masoud.ataei (Masoud Ataei) Reviewers: Whitney (Whitney Tsang), fhahn (Florian Hahn), pjeeva01 (Jeeva P.), fpetrogalli (Francesco Petrogalli), rengolin (Renato Golin) Reviewed By: fpetrogalli (Francesco Petrogalli) Subscribers: hiraditya (Aditya Kumar), llvm-commits, LLVM Tag: LLVM Differential Revision: https://reviews.llvm.org/D78054
This commit is contained in:
parent
1c12a95d9c
commit
c7878ad231
|
@ -96,6 +96,12 @@ struct VFShape {
|
|||
assert(hasValidParameterList() && "Invalid parameter list");
|
||||
}
|
||||
|
||||
// Retrieve the VFShape that can be used to map a (scalar) function to itself,
|
||||
// with VF = 1.
|
||||
static VFShape getScalarShape(const CallInst &CI) {
|
||||
return VFShape::get(CI, /*EC*/ {1, false}, /*HasGlobalPredicate*/ false);
|
||||
}
|
||||
|
||||
// Retrieve the basic vectorization shape of the function, where all
|
||||
// parameters are mapped to VFParamKind::Vector with \p EC
|
||||
// lanes. Specifies whether the function has a Global Predicate
|
||||
|
@ -186,6 +192,8 @@ void getVectorVariantNames(const CallInst &CI,
|
|||
class VFDatabase {
|
||||
/// The Module of the CallInst CI.
|
||||
const Module *M;
|
||||
/// The CallInst instance being queried for scalar to vector mappings.
|
||||
const CallInst &CI;
|
||||
/// List of vector functions descritors associated to the call
|
||||
/// instruction.
|
||||
const SmallVector<VFInfo, 8> ScalarToVectorMappings;
|
||||
|
@ -233,13 +241,16 @@ public:
|
|||
|
||||
/// Constructor, requires a CallInst instance.
|
||||
VFDatabase(CallInst &CI)
|
||||
: M(CI.getModule()), ScalarToVectorMappings(VFDatabase::getMappings(CI)) {
|
||||
}
|
||||
: M(CI.getModule()), CI(CI),
|
||||
ScalarToVectorMappings(VFDatabase::getMappings(CI)) {}
|
||||
/// \defgroup VFDatabase query interface.
|
||||
///
|
||||
/// @{
|
||||
/// Retrieve the Function with VFShape \p Shape.
|
||||
Function *getVectorizedFunction(const VFShape &Shape) const {
|
||||
if (Shape == VFShape::getScalarShape(CI))
|
||||
return CI.getCalledFunction();
|
||||
|
||||
for (const auto &Info : ScalarToVectorMappings)
|
||||
if (Info.Shape == Shape)
|
||||
return M->getFunction(Info.VectorName);
|
||||
|
|
|
@ -4384,22 +4384,17 @@ void InnerLoopVectorizer::widenCallInstruction(CallInst &I, VPUser &ArgOperands,
|
|||
if (VF > 1)
|
||||
TysForDecl[0] = VectorType::get(CI->getType()->getScalarType(), VF);
|
||||
VectorF = Intrinsic::getDeclaration(M, ID, TysForDecl);
|
||||
assert(VectorF && "Can't retrieve vector intrinsic.");
|
||||
} else {
|
||||
// Use vector version of the function call.
|
||||
const VFShape Shape =
|
||||
VFShape::get(*CI, {VF, false} /*EC*/, false /*HasGlobalPred*/);
|
||||
#ifndef NDEBUG
|
||||
const SmallVector<VFInfo, 8> Infos = VFDatabase::getMappings(*CI);
|
||||
assert(std::find_if(Infos.begin(), Infos.end(),
|
||||
[&Shape](const VFInfo &Info) {
|
||||
return Info.Shape == Shape;
|
||||
}) != Infos.end() &&
|
||||
"Vector function shape is missing from the database.");
|
||||
assert(VFDatabase(*CI).getVectorizedFunction(Shape) != nullptr &&
|
||||
"Can't create vector function.");
|
||||
#endif
|
||||
VectorF = VFDatabase(*CI).getVectorizedFunction(Shape);
|
||||
}
|
||||
assert(VectorF && "Can't create vector function.");
|
||||
|
||||
SmallVector<OperandBundleDef, 1> OpBundles;
|
||||
CI->getOperandBundlesAsDefs(OpBundles);
|
||||
CallInst *V = Builder.CreateCall(VectorF, Args, OpBundles);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
; RUN: opt < %s -passes=loop-vectorize -S 2>&1 | FileCheck %s
|
||||
|
||||
target triple = "powerpc64le-unknown-linux-gnu"
|
||||
%type = type { [3 x double] }
|
||||
|
||||
define void @getScalarFunc(double* %A, double* %C, %type* %B) #0 {
|
||||
; CHECK-LABEL: getScalarFunc
|
||||
; This check will catch also the massv version of the function.
|
||||
; CHECK-NOT: call fast <{{[0-9]+}} x double> @{{.*}}atan{{.*}}(<{{[0-9]+}} x double> %{{[0-9]+}})
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body:
|
||||
%i = phi i64 [ %inc, %for.body ], [ 0, %entry ]
|
||||
%dummyload2 = load double, double* %A, align 8
|
||||
%arrayidx.i24 = getelementptr inbounds %type, %type* %B, i64 %i, i32 0, i32 0
|
||||
%_15 = load double, double* %arrayidx.i24, align 8
|
||||
%call10 = tail call fast double @atan(double %_15) #1
|
||||
%inc = add i64 %i, 1
|
||||
%cmp = icmp ugt i64 1000, %inc
|
||||
br i1 %cmp, label %for.body, label %for.end
|
||||
|
||||
for.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare double @atan(double) local_unnamed_addr
|
||||
declare <2 x double> @__atand2_massv(<2 x double>) #1
|
||||
attributes #0 = { "target-cpu"="pwr9" }
|
||||
attributes #1 = { nounwind readnone "vector-function-abi-variant"="_ZGV_LLVM_N2v_atan(__atand2_massv)" }
|
|
@ -536,6 +536,24 @@ TEST_F(VFShapeAPITest, API_buildVFShape) {
|
|||
EXPECT_EQ(Shape, Expected);
|
||||
}
|
||||
|
||||
TEST_F(VFShapeAPITest, API_getScalarShape) {
|
||||
buildShape(/*VF*/ 1, /*IsScalable*/ false, /*HasGlobalPred*/ false);
|
||||
EXPECT_EQ(VFShape::getScalarShape(*CI), Shape);
|
||||
}
|
||||
|
||||
TEST_F(VFShapeAPITest, API_getVectorizedFunction) {
|
||||
VFShape ScalarShape = VFShape::getScalarShape(*CI);
|
||||
EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(ScalarShape),
|
||||
M->getFunction("g"));
|
||||
|
||||
buildShape(/*VF*/ 1, /*IsScalable*/ true, /*HasGlobalPred*/ false);
|
||||
EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
|
||||
buildShape(/*VF*/ 1, /*IsScalable*/ false, /*HasGlobalPred*/ true);
|
||||
EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
|
||||
buildShape(/*VF*/ 1, /*IsScalable*/ true, /*HasGlobalPred*/ true);
|
||||
EXPECT_EQ(VFDatabase(*CI).getVectorizedFunction(Shape), nullptr);
|
||||
}
|
||||
|
||||
TEST_F(VFShapeAPITest, API_updateVFShape) {
|
||||
|
||||
buildShape(/*VF*/ 2, /*IsScalable*/ false, /*HasGlobalPred*/ false);
|
||||
|
|
Loading…
Reference in New Issue