summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2024-05-01 20:48:22 +0100
committerFlorian Hahn <flo@fhahn.com>2024-05-01 20:48:22 +0100
commite846778e52f8586b5092c2fd4cdbec2334e31770 (patch)
tree0bf7c91746f81f4d613e03788b9d17a3e95c85f3
parentb88d21127f31c04139281de49dc7be7671bf47d8 (diff)
[VPlan] Make CallInst optional for VPWidenCallRecipe (NFCI).
Replace relying on the underling CallInst for looking up the called function and its types by instead adding the called function as operand, in line with how called functions are handled in CallInst. Operand bundles, metadata and fast-math flags are optionally used if there's an underlying CallInst. This enables creating VPWidenCallRecipes without requiring an underlying IR instruction.
-rw-r--r--llvm/lib/Transforms/Vectorize/LoopVectorize.cpp5
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlan.h26
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp46
-rw-r--r--llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp4
-rw-r--r--llvm/unittests/Transforms/Vectorize/VPlanTest.cpp26
5 files changed, 71 insertions, 36 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index c44d90f0998e..d1c54b928f9f 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8272,6 +8272,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
return nullptr;
SmallVector<VPValue *, 4> Ops(Operands.take_front(CI->arg_size()));
+ Ops.push_back(Operands.back());
// Is it beneficial to perform intrinsic call compared to lib call?
bool ShouldUseVectorIntrinsic =
@@ -8282,7 +8283,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
},
Range);
if (ShouldUseVectorIntrinsic)
- return new VPWidenCallRecipe(*CI, make_range(Ops.begin(), Ops.end()), ID,
+ return new VPWidenCallRecipe(CI, make_range(Ops.begin(), Ops.end()), ID,
CI->getDebugLoc());
Function *Variant = nullptr;
@@ -8335,7 +8336,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
Ops.insert(Ops.begin() + *MaskPos, Mask);
}
- return new VPWidenCallRecipe(*CI, make_range(Ops.begin(), Ops.end()),
+ return new VPWidenCallRecipe(CI, make_range(Ops.begin(), Ops.end()),
Intrinsic::not_intrinsic, CI->getDebugLoc(),
Variant);
}
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 71387bf5b7e9..71594be2b965 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -1458,18 +1458,21 @@ class VPWidenCallRecipe : public VPSingleDefRecipe {
public:
template <typename IterT>
- VPWidenCallRecipe(CallInst &I, iterator_range<IterT> CallArguments,
+ VPWidenCallRecipe(Value *UV, iterator_range<IterT> CallArguments,
Intrinsic::ID VectorIntrinsicID, DebugLoc DL = {},
Function *Variant = nullptr)
- : VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, &I, DL),
- VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {}
+ : VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, UV, DL),
+ VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {
+ assert(
+ isa<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue()) &&
+ "last operand must be the called function");
+ }
~VPWidenCallRecipe() override = default;
VPWidenCallRecipe *clone() override {
- return new VPWidenCallRecipe(*cast<CallInst>(getUnderlyingInstr()),
- operands(), VectorIntrinsicID, getDebugLoc(),
- Variant);
+ return new VPWidenCallRecipe(getUnderlyingValue(), operands(),
+ VectorIntrinsicID, getDebugLoc(), Variant);
}
VP_CLASSOF_IMPL(VPDef::VPWidenCallSC)
@@ -1477,6 +1480,17 @@ public:
/// Produce a widened version of the call instruction.
void execute(VPTransformState &State) override;
+ Function *getCalledScalarFunction() const {
+ return cast<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue());
+ }
+
+ operand_range arg_operands() {
+ return make_range(op_begin(), op_begin() + getNumOperands() - 1);
+ }
+ const_operand_range arg_operands() const {
+ return make_range(op_begin(), op_begin() + getNumOperands() - 1);
+ }
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Print the recipe.
void print(raw_ostream &O, const Twine &Indent,
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index 9ec422ec002c..29ed001ccd2c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -51,9 +51,12 @@ bool VPRecipeBase::mayWriteToMemory() const {
case VPWidenStoreSC:
return true;
case VPReplicateSC:
- case VPWidenCallSC:
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
->mayWriteToMemory();
+ case VPWidenCallSC:
+ return !cast<VPWidenCallRecipe>(this)
+ ->getCalledScalarFunction()
+ ->onlyReadsMemory();
case VPBranchOnMaskSC:
case VPScalarIVStepsSC:
case VPPredInstPHISC:
@@ -87,9 +90,12 @@ bool VPRecipeBase::mayReadFromMemory() const {
case VPWidenLoadSC:
return true;
case VPReplicateSC:
- case VPWidenCallSC:
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
->mayReadFromMemory();
+ case VPWidenCallSC:
+ return !cast<VPWidenCallRecipe>(this)
+ ->getCalledScalarFunction()
+ ->onlyWritesMemory();
case VPBranchOnMaskSC:
case VPPredInstPHISC:
case VPScalarIVStepsSC:
@@ -136,9 +142,10 @@ bool VPRecipeBase::mayHaveSideEffects() const {
default:
return true;
}
- case VPWidenCallSC:
- return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
- ->mayHaveSideEffects();
+ case VPWidenCallSC: {
+ Function *Fn = cast<VPWidenCallRecipe>(this)->getCalledScalarFunction();
+ return mayWriteToMemory() || !Fn->doesNotThrow() || !Fn->willReturn();
+ }
case VPBlendSC:
case VPReductionSC:
case VPScalarIVStepsSC:
@@ -702,8 +709,8 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
void VPWidenCallRecipe::execute(VPTransformState &State) {
assert(State.VF.isVector() && "not widening");
- auto &CI = *cast<CallInst>(getUnderlyingInstr());
- assert(!isa<DbgInfoIntrinsic>(CI) &&
+ Function *CalledScalarFn = getCalledScalarFunction();
+ assert(!isDbgInfoIntrinsic(CalledScalarFn->getIntrinsicID()) &&
"DbgInfoIntrinsic should have been dropped during VPlan construction");
State.setDebugLocFrom(getDebugLoc());
@@ -716,10 +723,10 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
// Add return type if intrinsic is overloaded on it.
if (UseIntrinsic &&
isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1))
- TysForDecl.push_back(
- VectorType::get(CI.getType()->getScalarType(), State.VF));
+ TysForDecl.push_back(VectorType::get(
+ CalledScalarFn->getReturnType()->getScalarType(), State.VF));
SmallVector<Value *, 4> Args;
- for (const auto &I : enumerate(operands())) {
+ for (const auto &I : enumerate(arg_operands())) {
// Some intrinsics have a scalar argument - don't replace it with a
// vector.
Value *Arg;
@@ -752,16 +759,19 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
VectorF = Variant;
}
+ auto *CI = cast_or_null<CallInst>(getUnderlyingInstr());
SmallVector<OperandBundleDef, 1> OpBundles;
- CI.getOperandBundlesAsDefs(OpBundles);
+ if (CI)
+ CI->getOperandBundlesAsDefs(OpBundles);
+
CallInst *V = State.Builder.CreateCall(VectorF, Args, OpBundles);
if (isa<FPMathOperator>(V))
- V->copyFastMathFlags(&CI);
+ V->copyFastMathFlags(CI);
if (!V->getType()->isVoidTy())
State.set(this, V, Part);
- State.addMetadata(V, &CI);
+ State.addMetadata(V, CI);
}
}
@@ -770,16 +780,18 @@ void VPWidenCallRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
O << Indent << "WIDEN-CALL ";
- auto *CI = cast<CallInst>(getUnderlyingInstr());
- if (CI->getType()->isVoidTy())
+ Function *CalledFn = getCalledScalarFunction();
+ if (CalledFn->getReturnType()->isVoidTy())
O << "void ";
else {
printAsOperand(O, SlotTracker);
O << " = ";
}
- O << "call @" << CI->getCalledFunction()->getName() << "(";
- printOperands(O, SlotTracker);
+ O << "call @" << CalledFn->getName() << "(";
+ interleaveComma(arg_operands(), O, [&O, &SlotTracker](VPValue *Op) {
+ Op->printAsOperand(O, SlotTracker);
+ });
O << ")";
if (VectorIntrinsicID)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index a7337f7aa94d..017b00c042f4 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -75,8 +75,8 @@ void VPlanTransforms::VPInstructionsToVPRecipes(
NewRecipe = new VPWidenGEPRecipe(GEP, Ingredient.operands());
} else if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
NewRecipe = new VPWidenCallRecipe(
- *CI, drop_end(Ingredient.operands()),
- getVectorIntrinsicIDForCall(CI, &TLI), CI->getDebugLoc());
+ CI, Ingredient.operands(), getVectorIntrinsicIDForCall(CI, &TLI),
+ CI->getDebugLoc());
} else if (SelectInst *SI = dyn_cast<SelectInst>(Inst)) {
NewRecipe = new VPWidenSelectRecipe(*SI, Ingredient.operands());
} else if (auto *CI = dyn_cast<CastInst>(Inst)) {
diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
index 64e9c06db3fe..eda4723f67b2 100644
--- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
+++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp
@@ -895,13 +895,16 @@ TEST(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
IntegerType *Int32 = IntegerType::get(C, 32);
FunctionType *FTy = FunctionType::get(Int32, false);
- auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
+ Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0);
+ auto *Call = CallInst::Create(FTy, Fn);
VPValue Op1;
VPValue Op2;
+ VPValue CalledFn(Call->getCalledFunction());
SmallVector<VPValue *, 2> Args;
Args.push_back(&Op1);
Args.push_back(&Op2);
- VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()), false);
+ Args.push_back(&CalledFn);
+ VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
EXPECT_TRUE(isa<VPUser>(&Recipe));
VPRecipeBase *BaseR = &Recipe;
EXPECT_TRUE(isa<VPUser>(BaseR));
@@ -912,6 +915,7 @@ TEST(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
EXPECT_EQ(&Recipe, VPV->getDefiningRecipe());
delete Call;
+ delete Fn;
}
TEST(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) {
@@ -1157,19 +1161,22 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
{
FunctionType *FTy = FunctionType::get(Int32, false);
- auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
+ Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0);
+ auto *Call = CallInst::Create(FTy, Fn);
VPValue Op1;
VPValue Op2;
- SmallVector<VPValue *, 2> Args;
+ VPValue CalledFn(Call->getCalledFunction());
+ SmallVector<VPValue *, 3> Args;
Args.push_back(&Op1);
Args.push_back(&Op2);
- VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()),
- false);
+ Args.push_back(&CalledFn);
+ VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
EXPECT_TRUE(Recipe.mayHaveSideEffects());
EXPECT_TRUE(Recipe.mayReadFromMemory());
EXPECT_TRUE(Recipe.mayWriteToMemory());
EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
delete Call;
+ delete Fn;
}
{
@@ -1181,11 +1188,12 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
auto *Call = CallInst::Create(TheFn->getFunctionType(), TheFn);
VPValue Op1;
VPValue Op2;
- SmallVector<VPValue *, 2> Args;
+ VPValue CalledFn(TheFn);
+ SmallVector<VPValue *, 3> Args;
Args.push_back(&Op1);
Args.push_back(&Op2);
- VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()),
- false);
+ Args.push_back(&CalledFn);
+ VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
EXPECT_FALSE(Recipe.mayHaveSideEffects());
EXPECT_FALSE(Recipe.mayReadFromMemory());
EXPECT_FALSE(Recipe.mayWriteToMemory());