Skip to content

Commit e846778

Browse files
committed
[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.
1 parent b88d211 commit e846778

File tree

5 files changed

+71
-36
lines changed

5 files changed

+71
-36
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8272,6 +8272,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
82728272
return nullptr;
82738273

82748274
SmallVector<VPValue *, 4> Ops(Operands.take_front(CI->arg_size()));
8275+
Ops.push_back(Operands.back());
82758276

82768277
// Is it beneficial to perform intrinsic call compared to lib call?
82778278
bool ShouldUseVectorIntrinsic =
@@ -8282,7 +8283,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
82828283
},
82838284
Range);
82848285
if (ShouldUseVectorIntrinsic)
8285-
return new VPWidenCallRecipe(*CI, make_range(Ops.begin(), Ops.end()), ID,
8286+
return new VPWidenCallRecipe(CI, make_range(Ops.begin(), Ops.end()), ID,
82868287
CI->getDebugLoc());
82878288

82888289
Function *Variant = nullptr;
@@ -8335,7 +8336,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI,
83358336
Ops.insert(Ops.begin() + *MaskPos, Mask);
83368337
}
83378338

8338-
return new VPWidenCallRecipe(*CI, make_range(Ops.begin(), Ops.end()),
8339+
return new VPWidenCallRecipe(CI, make_range(Ops.begin(), Ops.end()),
83398340
Intrinsic::not_intrinsic, CI->getDebugLoc(),
83408341
Variant);
83418342
}

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,25 +1458,39 @@ class VPWidenCallRecipe : public VPSingleDefRecipe {
14581458

14591459
public:
14601460
template <typename IterT>
1461-
VPWidenCallRecipe(CallInst &I, iterator_range<IterT> CallArguments,
1461+
VPWidenCallRecipe(Value *UV, iterator_range<IterT> CallArguments,
14621462
Intrinsic::ID VectorIntrinsicID, DebugLoc DL = {},
14631463
Function *Variant = nullptr)
1464-
: VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, &I, DL),
1465-
VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {}
1464+
: VPSingleDefRecipe(VPDef::VPWidenCallSC, CallArguments, UV, DL),
1465+
VectorIntrinsicID(VectorIntrinsicID), Variant(Variant) {
1466+
assert(
1467+
isa<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue()) &&
1468+
"last operand must be the called function");
1469+
}
14661470

14671471
~VPWidenCallRecipe() override = default;
14681472

14691473
VPWidenCallRecipe *clone() override {
1470-
return new VPWidenCallRecipe(*cast<CallInst>(getUnderlyingInstr()),
1471-
operands(), VectorIntrinsicID, getDebugLoc(),
1472-
Variant);
1474+
return new VPWidenCallRecipe(getUnderlyingValue(), operands(),
1475+
VectorIntrinsicID, getDebugLoc(), Variant);
14731476
}
14741477

14751478
VP_CLASSOF_IMPL(VPDef::VPWidenCallSC)
14761479

14771480
/// Produce a widened version of the call instruction.
14781481
void execute(VPTransformState &State) override;
14791482

1483+
Function *getCalledScalarFunction() const {
1484+
return cast<Function>(getOperand(getNumOperands() - 1)->getLiveInIRValue());
1485+
}
1486+
1487+
operand_range arg_operands() {
1488+
return make_range(op_begin(), op_begin() + getNumOperands() - 1);
1489+
}
1490+
const_operand_range arg_operands() const {
1491+
return make_range(op_begin(), op_begin() + getNumOperands() - 1);
1492+
}
1493+
14801494
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
14811495
/// Print the recipe.
14821496
void print(raw_ostream &O, const Twine &Indent,

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ bool VPRecipeBase::mayWriteToMemory() const {
5151
case VPWidenStoreSC:
5252
return true;
5353
case VPReplicateSC:
54-
case VPWidenCallSC:
5554
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
5655
->mayWriteToMemory();
56+
case VPWidenCallSC:
57+
return !cast<VPWidenCallRecipe>(this)
58+
->getCalledScalarFunction()
59+
->onlyReadsMemory();
5760
case VPBranchOnMaskSC:
5861
case VPScalarIVStepsSC:
5962
case VPPredInstPHISC:
@@ -87,9 +90,12 @@ bool VPRecipeBase::mayReadFromMemory() const {
8790
case VPWidenLoadSC:
8891
return true;
8992
case VPReplicateSC:
90-
case VPWidenCallSC:
9193
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
9294
->mayReadFromMemory();
95+
case VPWidenCallSC:
96+
return !cast<VPWidenCallRecipe>(this)
97+
->getCalledScalarFunction()
98+
->onlyWritesMemory();
9399
case VPBranchOnMaskSC:
94100
case VPPredInstPHISC:
95101
case VPScalarIVStepsSC:
@@ -136,9 +142,10 @@ bool VPRecipeBase::mayHaveSideEffects() const {
136142
default:
137143
return true;
138144
}
139-
case VPWidenCallSC:
140-
return cast<Instruction>(getVPSingleValue()->getUnderlyingValue())
141-
->mayHaveSideEffects();
145+
case VPWidenCallSC: {
146+
Function *Fn = cast<VPWidenCallRecipe>(this)->getCalledScalarFunction();
147+
return mayWriteToMemory() || !Fn->doesNotThrow() || !Fn->willReturn();
148+
}
142149
case VPBlendSC:
143150
case VPReductionSC:
144151
case VPScalarIVStepsSC:
@@ -702,8 +709,8 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
702709

703710
void VPWidenCallRecipe::execute(VPTransformState &State) {
704711
assert(State.VF.isVector() && "not widening");
705-
auto &CI = *cast<CallInst>(getUnderlyingInstr());
706-
assert(!isa<DbgInfoIntrinsic>(CI) &&
712+
Function *CalledScalarFn = getCalledScalarFunction();
713+
assert(!isDbgInfoIntrinsic(CalledScalarFn->getIntrinsicID()) &&
707714
"DbgInfoIntrinsic should have been dropped during VPlan construction");
708715
State.setDebugLocFrom(getDebugLoc());
709716

@@ -716,10 +723,10 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
716723
// Add return type if intrinsic is overloaded on it.
717724
if (UseIntrinsic &&
718725
isVectorIntrinsicWithOverloadTypeAtArg(VectorIntrinsicID, -1))
719-
TysForDecl.push_back(
720-
VectorType::get(CI.getType()->getScalarType(), State.VF));
726+
TysForDecl.push_back(VectorType::get(
727+
CalledScalarFn->getReturnType()->getScalarType(), State.VF));
721728
SmallVector<Value *, 4> Args;
722-
for (const auto &I : enumerate(operands())) {
729+
for (const auto &I : enumerate(arg_operands())) {
723730
// Some intrinsics have a scalar argument - don't replace it with a
724731
// vector.
725732
Value *Arg;
@@ -752,16 +759,19 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
752759
VectorF = Variant;
753760
}
754761

762+
auto *CI = cast_or_null<CallInst>(getUnderlyingInstr());
755763
SmallVector<OperandBundleDef, 1> OpBundles;
756-
CI.getOperandBundlesAsDefs(OpBundles);
764+
if (CI)
765+
CI->getOperandBundlesAsDefs(OpBundles);
766+
757767
CallInst *V = State.Builder.CreateCall(VectorF, Args, OpBundles);
758768

759769
if (isa<FPMathOperator>(V))
760-
V->copyFastMathFlags(&CI);
770+
V->copyFastMathFlags(CI);
761771

762772
if (!V->getType()->isVoidTy())
763773
State.set(this, V, Part);
764-
State.addMetadata(V, &CI);
774+
State.addMetadata(V, CI);
765775
}
766776
}
767777

@@ -770,16 +780,18 @@ void VPWidenCallRecipe::print(raw_ostream &O, const Twine &Indent,
770780
VPSlotTracker &SlotTracker) const {
771781
O << Indent << "WIDEN-CALL ";
772782

773-
auto *CI = cast<CallInst>(getUnderlyingInstr());
774-
if (CI->getType()->isVoidTy())
783+
Function *CalledFn = getCalledScalarFunction();
784+
if (CalledFn->getReturnType()->isVoidTy())
775785
O << "void ";
776786
else {
777787
printAsOperand(O, SlotTracker);
778788
O << " = ";
779789
}
780790

781-
O << "call @" << CI->getCalledFunction()->getName() << "(";
782-
printOperands(O, SlotTracker);
791+
O << "call @" << CalledFn->getName() << "(";
792+
interleaveComma(arg_operands(), O, [&O, &SlotTracker](VPValue *Op) {
793+
Op->printAsOperand(O, SlotTracker);
794+
});
783795
O << ")";
784796

785797
if (VectorIntrinsicID)

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ void VPlanTransforms::VPInstructionsToVPRecipes(
7575
NewRecipe = new VPWidenGEPRecipe(GEP, Ingredient.operands());
7676
} else if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
7777
NewRecipe = new VPWidenCallRecipe(
78-
*CI, drop_end(Ingredient.operands()),
79-
getVectorIntrinsicIDForCall(CI, &TLI), CI->getDebugLoc());
78+
CI, Ingredient.operands(), getVectorIntrinsicIDForCall(CI, &TLI),
79+
CI->getDebugLoc());
8080
} else if (SelectInst *SI = dyn_cast<SelectInst>(Inst)) {
8181
NewRecipe = new VPWidenSelectRecipe(*SI, Ingredient.operands());
8282
} else if (auto *CI = dyn_cast<CastInst>(Inst)) {

llvm/unittests/Transforms/Vectorize/VPlanTest.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -895,13 +895,16 @@ TEST(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
895895

896896
IntegerType *Int32 = IntegerType::get(C, 32);
897897
FunctionType *FTy = FunctionType::get(Int32, false);
898-
auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
898+
Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0);
899+
auto *Call = CallInst::Create(FTy, Fn);
899900
VPValue Op1;
900901
VPValue Op2;
902+
VPValue CalledFn(Call->getCalledFunction());
901903
SmallVector<VPValue *, 2> Args;
902904
Args.push_back(&Op1);
903905
Args.push_back(&Op2);
904-
VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()), false);
906+
Args.push_back(&CalledFn);
907+
VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
905908
EXPECT_TRUE(isa<VPUser>(&Recipe));
906909
VPRecipeBase *BaseR = &Recipe;
907910
EXPECT_TRUE(isa<VPUser>(BaseR));
@@ -912,6 +915,7 @@ TEST(VPRecipeTest, CastVPWidenCallRecipeToVPUserAndVPDef) {
912915
EXPECT_EQ(&Recipe, VPV->getDefiningRecipe());
913916

914917
delete Call;
918+
delete Fn;
915919
}
916920

917921
TEST(VPRecipeTest, CastVPWidenSelectRecipeToVPUserAndVPDef) {
@@ -1157,19 +1161,22 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
11571161

11581162
{
11591163
FunctionType *FTy = FunctionType::get(Int32, false);
1160-
auto *Call = CallInst::Create(FTy, UndefValue::get(FTy));
1164+
Function *Fn = Function::Create(FTy, GlobalValue::ExternalLinkage, 0);
1165+
auto *Call = CallInst::Create(FTy, Fn);
11611166
VPValue Op1;
11621167
VPValue Op2;
1163-
SmallVector<VPValue *, 2> Args;
1168+
VPValue CalledFn(Call->getCalledFunction());
1169+
SmallVector<VPValue *, 3> Args;
11641170
Args.push_back(&Op1);
11651171
Args.push_back(&Op2);
1166-
VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()),
1167-
false);
1172+
Args.push_back(&CalledFn);
1173+
VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
11681174
EXPECT_TRUE(Recipe.mayHaveSideEffects());
11691175
EXPECT_TRUE(Recipe.mayReadFromMemory());
11701176
EXPECT_TRUE(Recipe.mayWriteToMemory());
11711177
EXPECT_TRUE(Recipe.mayReadOrWriteMemory());
11721178
delete Call;
1179+
delete Fn;
11731180
}
11741181

11751182
{
@@ -1181,11 +1188,12 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) {
11811188
auto *Call = CallInst::Create(TheFn->getFunctionType(), TheFn);
11821189
VPValue Op1;
11831190
VPValue Op2;
1184-
SmallVector<VPValue *, 2> Args;
1191+
VPValue CalledFn(TheFn);
1192+
SmallVector<VPValue *, 3> Args;
11851193
Args.push_back(&Op1);
11861194
Args.push_back(&Op2);
1187-
VPWidenCallRecipe Recipe(*Call, make_range(Args.begin(), Args.end()),
1188-
false);
1195+
Args.push_back(&CalledFn);
1196+
VPWidenCallRecipe Recipe(Call, make_range(Args.begin(), Args.end()), false);
11891197
EXPECT_FALSE(Recipe.mayHaveSideEffects());
11901198
EXPECT_FALSE(Recipe.mayReadFromMemory());
11911199
EXPECT_FALSE(Recipe.mayWriteToMemory());

0 commit comments

Comments
 (0)