Fix FunctionPropertiesAnalysis updating callsite in 1-BB loop

If the callsite is in a single BB loop, we need to exclude the BB from
the successor set (in which it'd be a member), because that set forms a
boundary at which we stop traversing the CFG, when re-ingesting BBs
after inlining; but after inlining, the callsite BB's new successors
should be visited.

Reviewed By: kazu

Differential Revision: https://reviews.llvm.org/D127178
This commit is contained in:
Mircea Trofin 2022-06-08 14:30:43 -07:00
parent f6b1bfb7d5
commit b8c39eb275
2 changed files with 75 additions and 0 deletions

View File

@ -134,6 +134,14 @@ FunctionPropertiesUpdater::FunctionPropertiesUpdater(
// We track successors separately, too, because they form a boundary, together
// with the CB BB ('Entry') between which the inlined callee will be pasted.
Successors.insert(succ_begin(&CallSiteBB), succ_end(&CallSiteBB));
// Exclude the CallSiteBB, if it happens to be its own successor (1-BB loop).
// We are only interested in BBs the graph moves past the callsite BB to
// define the frontier past which we don't want to re-process BBs. Including
// the callsite BB in this case would prematurely stop the traversal in
// finish().
Successors.erase(&CallSiteBB);
for (const auto *BB : Successors)
LikelyToChangeBBs.insert(BB);

View File

@ -543,4 +543,71 @@ lpad:
EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, LINew));
}
TEST_F(FunctionPropertiesAnalysisTest, InlineSameLoopBB) {
LLVMContext C;
std::unique_ptr<Module> M = makeLLVMModule(C,
R"IR(
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
declare i32 @a()
declare i32 @b()
define i32 @f1(i32 %a) {
entry:
br label %loop
loop:
%i = call i32 @f2(i32 %a)
%c = icmp slt i32 %i, %a
br i1 %c, label %loop, label %end
end:
%r = phi i32 [%i, %loop], [%a, %entry]
ret i32 %r
}
define i32 @f2(i32 %a) {
%cnd = icmp slt i32 %a, 0
br i1 %cnd, label %then, label %else
then:
%r1 = call i32 @a()
br label %end
else:
%r2 = call i32 @b()
br label %end
end:
%r = phi i32 [%r1, %then], [%r2, %else]
ret i32 %r
}
)IR");
Function *F1 = M->getFunction("f1");
CallBase *CB = findCall(*F1);
EXPECT_NE(CB, nullptr);
FunctionPropertiesInfo ExpectedInitial;
ExpectedInitial.BasicBlockCount = 3;
ExpectedInitial.TotalInstructionCount = 6;
ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;
ExpectedInitial.Uses = 1;
ExpectedInitial.DirectCallsToDefinedFunctions = 1;
ExpectedInitial.MaxLoopDepth = 1;
ExpectedInitial.TopLevelLoopCount = 1;
FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
ExpectedFinal.BasicBlockCount = 6;
ExpectedFinal.DirectCallsToDefinedFunctions = 0;
ExpectedFinal.BlocksReachedFromConditionalInstruction = 4;
ExpectedFinal.TotalInstructionCount = 12;
auto FPI = buildFPI(*F1);
EXPECT_EQ(FPI, ExpectedInitial);
FunctionPropertiesUpdater FPU(FPI, *CB);
InlineFunctionInfo IFI;
auto IR = llvm::InlineFunction(*CB, IFI);
EXPECT_TRUE(IR.isSuccess());
FPU.finish(*LI);
EXPECT_EQ(FPI, ExpectedFinal);
}
} // end anonymous namespace