@@ -313,9 +313,10 @@ void wholeprogramdevirt::setAfterReturnValues(
313
313
}
314
314
}
315
315
316
- VirtualCallTarget::VirtualCallTarget (Function *Fn, const TypeMemberInfo *TM)
316
+ VirtualCallTarget::VirtualCallTarget (GlobalValue *Fn, const TypeMemberInfo *TM)
317
317
: Fn(Fn), TM(TM),
318
- IsBigEndian(Fn->getParent ()->getDataLayout().isBigEndian()), WasDevirt(false ) {}
318
+ IsBigEndian(Fn->getParent ()->getDataLayout().isBigEndian()),
319
+ WasDevirt(false ) {}
319
320
320
321
namespace {
321
322
@@ -1009,7 +1010,13 @@ bool DevirtModule::tryFindVirtualCallTargets(
1009
1010
if (!Ptr)
1010
1011
return false ;
1011
1012
1012
- auto Fn = dyn_cast<Function>(Ptr->stripPointerCasts ());
1013
+ auto C = Ptr->stripPointerCasts ();
1014
+ // Make sure this is a function or alias to a function.
1015
+ auto Fn = dyn_cast<Function>(C);
1016
+ auto A = dyn_cast<GlobalAlias>(C);
1017
+ if (!Fn && A)
1018
+ Fn = dyn_cast<Function>(A->getAliasee ());
1019
+
1013
1020
if (!Fn)
1014
1021
return false ;
1015
1022
@@ -1026,7 +1033,11 @@ bool DevirtModule::tryFindVirtualCallTargets(
1026
1033
if (mustBeUnreachableFunction (Fn, ExportSummary))
1027
1034
continue ;
1028
1035
1029
- TargetsForSlot.push_back ({Fn, &TM});
1036
+ // Save the symbol used in the vtable to use as the devirtualization
1037
+ // target.
1038
+ auto GV = dyn_cast<GlobalValue>(C);
1039
+ assert (GV);
1040
+ TargetsForSlot.push_back ({GV, &TM});
1030
1041
}
1031
1042
1032
1043
// Give up if we couldn't find any targets.
@@ -1207,7 +1218,7 @@ bool DevirtModule::trySingleImplDevirt(
1207
1218
WholeProgramDevirtResolution *Res) {
1208
1219
// See if the program contains a single implementation of this virtual
1209
1220
// function.
1210
- Function *TheFn = TargetsForSlot[0 ].Fn ;
1221
+ auto *TheFn = TargetsForSlot[0 ].Fn ;
1211
1222
for (auto &&Target : TargetsForSlot)
1212
1223
if (TheFn != Target.Fn )
1213
1224
return false ;
@@ -1453,23 +1464,30 @@ bool DevirtModule::tryEvaluateFunctionsWithArgs(
1453
1464
// Evaluate each function and store the result in each target's RetVal
1454
1465
// field.
1455
1466
for (VirtualCallTarget &Target : TargetsForSlot) {
1456
- if (Target.Fn ->arg_size () != Args.size () + 1 )
1467
+ // TODO: Skip for now if the vtable symbol was an alias to a function,
1468
+ // need to evaluate whether it would be correct to analyze the aliasee
1469
+ // function for this optimization.
1470
+ auto Fn = dyn_cast<Function>(Target.Fn );
1471
+ if (!Fn)
1472
+ return false ;
1473
+
1474
+ if (Fn->arg_size () != Args.size () + 1 )
1457
1475
return false ;
1458
1476
1459
1477
Evaluator Eval (M.getDataLayout (), nullptr );
1460
1478
SmallVector<Constant *, 2 > EvalArgs;
1461
1479
EvalArgs.push_back (
1462
- Constant::getNullValue (Target. Fn ->getFunctionType ()->getParamType (0 )));
1480
+ Constant::getNullValue (Fn->getFunctionType ()->getParamType (0 )));
1463
1481
for (unsigned I = 0 ; I != Args.size (); ++I) {
1464
- auto *ArgTy = dyn_cast<IntegerType>(
1465
- Target. Fn ->getFunctionType ()->getParamType (I + 1 ));
1482
+ auto *ArgTy =
1483
+ dyn_cast<IntegerType>( Fn->getFunctionType ()->getParamType (I + 1 ));
1466
1484
if (!ArgTy)
1467
1485
return false ;
1468
1486
EvalArgs.push_back (ConstantInt::get (ArgTy, Args[I]));
1469
1487
}
1470
1488
1471
1489
Constant *RetVal;
1472
- if (!Eval.EvaluateFunction (Target. Fn , RetVal, EvalArgs) ||
1490
+ if (!Eval.EvaluateFunction (Fn, RetVal, EvalArgs) ||
1473
1491
!isa<ConstantInt>(RetVal))
1474
1492
return false ;
1475
1493
Target.RetVal = cast<ConstantInt>(RetVal)->getZExtValue ();
@@ -1690,8 +1708,14 @@ void DevirtModule::applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName,
1690
1708
bool DevirtModule::tryVirtualConstProp (
1691
1709
MutableArrayRef<VirtualCallTarget> TargetsForSlot, VTableSlotInfo &SlotInfo,
1692
1710
WholeProgramDevirtResolution *Res, VTableSlot Slot) {
1711
+ // TODO: Skip for now if the vtable symbol was an alias to a function,
1712
+ // need to evaluate whether it would be correct to analyze the aliasee
1713
+ // function for this optimization.
1714
+ auto Fn = dyn_cast<Function>(TargetsForSlot[0 ].Fn );
1715
+ if (!Fn)
1716
+ return false ;
1693
1717
// This only works if the function returns an integer.
1694
- auto RetType = dyn_cast<IntegerType>(TargetsForSlot[ 0 ]. Fn ->getReturnType ());
1718
+ auto RetType = dyn_cast<IntegerType>(Fn->getReturnType ());
1695
1719
if (!RetType)
1696
1720
return false ;
1697
1721
unsigned BitWidth = RetType->getBitWidth ();
@@ -1709,11 +1733,18 @@ bool DevirtModule::tryVirtualConstProp(
1709
1733
// inline all implementations of the virtual function into each call site,
1710
1734
// rather than using function attributes to perform local optimization.
1711
1735
for (VirtualCallTarget &Target : TargetsForSlot) {
1712
- if (Target.Fn ->isDeclaration () ||
1713
- !computeFunctionBodyMemoryAccess (*Target.Fn , AARGetter (*Target.Fn ))
1736
+ // TODO: Skip for now if the vtable symbol was an alias to a function,
1737
+ // need to evaluate whether it would be correct to analyze the aliasee
1738
+ // function for this optimization.
1739
+ auto Fn = dyn_cast<Function>(Target.Fn );
1740
+ if (!Fn)
1741
+ return false ;
1742
+
1743
+ if (Fn->isDeclaration () ||
1744
+ !computeFunctionBodyMemoryAccess (*Fn, AARGetter (*Fn))
1714
1745
.doesNotAccessMemory () ||
1715
- Target. Fn ->arg_empty () || !Target. Fn ->arg_begin ()->use_empty () ||
1716
- Target. Fn ->getReturnType () != RetType)
1746
+ Fn->arg_empty () || !Fn->arg_begin ()->use_empty () ||
1747
+ Fn->getReturnType () != RetType)
1717
1748
return false ;
1718
1749
}
1719
1750
@@ -2221,7 +2252,7 @@ bool DevirtModule::run() {
2221
2252
2222
2253
// For each (type, offset) pair:
2223
2254
bool DidVirtualConstProp = false ;
2224
- std::map<std::string, Function *> DevirtTargets;
2255
+ std::map<std::string, GlobalValue *> DevirtTargets;
2225
2256
for (auto &S : CallSlots) {
2226
2257
// Search each of the members of the type identifier for the virtual
2227
2258
// function implementation at offset S.first.ByteOffset, and add to
@@ -2276,7 +2307,14 @@ bool DevirtModule::run() {
2276
2307
if (RemarksEnabled) {
2277
2308
// Generate remarks for each devirtualized function.
2278
2309
for (const auto &DT : DevirtTargets) {
2279
- Function *F = DT.second ;
2310
+ GlobalValue *GV = DT.second ;
2311
+ auto F = dyn_cast<Function>(GV);
2312
+ if (!F) {
2313
+ auto A = dyn_cast<GlobalAlias>(GV);
2314
+ assert (A && isa<Function>(A->getAliasee ()));
2315
+ F = dyn_cast<Function>(A->getAliasee ());
2316
+ assert (F);
2317
+ }
2280
2318
2281
2319
using namespace ore ;
2282
2320
OREGetter (F).emit (OptimizationRemark (DEBUG_TYPE, " Devirtualized" , F)
0 commit comments