Skip to content

Commit 8ea858b

Browse files
[CallPromotionUtil] See through function alias when devirtualizing a virtual call on an alloca. (#80736)
- Extract utility function from `DevirtModule::tryFindVirtualCallTargets` [1], which sees through an alias to a function. Call this utility function in the WPD callsite. - For type profiling work, this helper function will be used by indirect-call-promotion pass to find the function pointer at a specified vtable offset (an example in [2]) [1] https://github.com/llvm/llvm-project/blob/b99163fe8feeacba7797d5479bbcd5d8f327dd2d/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp#L1069-L1082 [2] https://github.com/minglotus-6/llvm-project/blob/77a0ef12de82d11f448f7f9de6f2dcf87d9b74af/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp#L347
1 parent a628f68 commit 8ea858b

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

llvm/include/llvm/Analysis/TypeMetadataUtils.h

+9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_ANALYSIS_TYPEMETADATAUTILS_H
1616

1717
#include <cstdint>
18+
#include <utility>
1819

1920
namespace llvm {
2021

@@ -24,6 +25,7 @@ class CallInst;
2425
class Constant;
2526
class Function;
2627
class DominatorTree;
28+
class GlobalVariable;
2729
class Instruction;
2830
class Module;
2931

@@ -77,6 +79,13 @@ void findDevirtualizableCallsForTypeCheckedLoad(
7779
Constant *getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
7880
Constant *TopLevelGlobal = nullptr);
7981

82+
/// Given a vtable and a specified offset, returns the function and the trivial
83+
/// pointer at the specified offset in pair iff the pointer at the specified
84+
/// offset is a function or an alias to a function. Returns a pair of nullptr
85+
/// otherwise.
86+
std::pair<Function *, Constant *>
87+
getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset, Module &M);
88+
8089
/// Finds the same "relative pointer" pattern as described above, where the
8190
/// target is `F`, and replaces the entire pattern with a constant zero.
8291
void replaceRelativePointerUsersWithZero(Function *F);

llvm/lib/Analysis/TypeMetadataUtils.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,26 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
201201
return nullptr;
202202
}
203203

204+
std::pair<Function *, Constant *>
205+
llvm::getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset,
206+
Module &M) {
207+
Constant *Ptr = getPointerAtOffset(GV->getInitializer(), Offset, M, GV);
208+
if (!Ptr)
209+
return std::pair<Function *, Constant *>(nullptr, nullptr);
210+
211+
auto C = Ptr->stripPointerCasts();
212+
// Make sure this is a function or alias to a function.
213+
auto Fn = dyn_cast<Function>(C);
214+
auto A = dyn_cast<GlobalAlias>(C);
215+
if (!Fn && A)
216+
Fn = dyn_cast<Function>(A->getAliasee());
217+
218+
if (!Fn)
219+
return std::pair<Function *, Constant *>(nullptr, nullptr);
220+
221+
return std::pair<Function *, Constant *>(Fn, C);
222+
}
223+
204224
void llvm::replaceRelativePointerUsersWithZero(Function *F) {
205225
for (auto *U : F->users()) {
206226
auto *PtrExpr = dyn_cast<ConstantExpr>(U);

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

+4-11
Original file line numberDiff line numberDiff line change
@@ -1066,17 +1066,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
10661066
GlobalObject::VCallVisibilityPublic)
10671067
return false;
10681068

1069-
Constant *Ptr = getPointerAtOffset(TM.Bits->GV->getInitializer(),
1070-
TM.Offset + ByteOffset, M, TM.Bits->GV);
1071-
if (!Ptr)
1072-
return false;
1073-
1074-
auto C = Ptr->stripPointerCasts();
1075-
// Make sure this is a function or alias to a function.
1076-
auto Fn = dyn_cast<Function>(C);
1077-
auto A = dyn_cast<GlobalAlias>(C);
1078-
if (!Fn && A)
1079-
Fn = dyn_cast<Function>(A->getAliasee());
1069+
Function *Fn = nullptr;
1070+
Constant *C = nullptr;
1071+
std::tie(Fn, C) =
1072+
getFunctionAtVTableOffset(TM.Bits->GV, TM.Offset + ByteOffset, M);
10801073

10811074
if (!Fn)
10821075
return false;

llvm/lib/Transforms/Utils/CallPromotionUtils.cpp

+4-7
Original file line numberDiff line numberDiff line change
@@ -597,16 +597,13 @@ bool llvm::tryPromoteCall(CallBase &CB) {
597597
// Not in the form of a global constant variable with an initializer.
598598
return false;
599599

600-
Constant *VTableGVInitializer = GV->getInitializer();
601600
APInt VTableGVOffset = VTableOffsetGVBase + VTableOffset;
602601
if (!(VTableGVOffset.getActiveBits() <= 64))
603602
return false; // Out of range.
604-
Constant *Ptr = getPointerAtOffset(VTableGVInitializer,
605-
VTableGVOffset.getZExtValue(),
606-
*M);
607-
if (!Ptr)
608-
return false; // No constant (function) pointer found.
609-
Function *DirectCallee = dyn_cast<Function>(Ptr->stripPointerCasts());
603+
604+
Function *DirectCallee = nullptr;
605+
std::tie(DirectCallee, std::ignore) =
606+
getFunctionAtVTableOffset(GV, VTableGVOffset.getZExtValue(), *M);
610607
if (!DirectCallee)
611608
return false; // No function pointer found.
612609

0 commit comments

Comments
 (0)