Skip to content

Commit 13868e8

Browse files
author
Wael Yehia
committed
refactor TOCRestoreNeeded
1 parent 896b543 commit 13868e8

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include "llvm/IR/GlobalValue.h"
4848
#include "llvm/IR/GlobalVariable.h"
4949
#include "llvm/IR/Module.h"
50+
#include "llvm/IR/PatternMatch.h"
5051
#include "llvm/MC/MCAsmInfo.h"
5152
#include "llvm/MC/MCContext.h"
5253
#include "llvm/MC/MCDirectives.h"
@@ -82,6 +83,7 @@
8283

8384
using namespace llvm;
8485
using namespace llvm::XCOFF;
86+
using namespace PatternMatch;
8587

8688
#define DEBUG_TYPE "asmprinter"
8789

@@ -3384,13 +3386,9 @@ void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) {
33843386
OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str());
33853387
}
33863388

3387-
33883389
static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
3389-
auto IsLocalFunc = [&](const Value *V) {
3390-
if (!isa<Function>(V))
3391-
return false;
3392-
auto *F = cast<Function>(V);
3393-
3390+
// Query if the given function is local to the load module.
3391+
auto IsLocalFunc = [](const Function *F) {
33943392
// Static functions are local
33953393
if (F->getLinkage() == GlobalValue::InternalLinkage)
33963394
return true;
@@ -3406,6 +3404,42 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34063404

34073405
return false;
34083406
};
3407+
// Recursive walker that checks if all possible runtime values of the given
3408+
// llvm::Value are addresses of local functions.
3409+
std::function<bool(const Value*)> ValueIsALocalFunc = [&IsLocalFunc, &ValueIsALocalFunc](const Value *V) -> bool{
3410+
if (auto *F = dyn_cast<Function>(V))
3411+
return IsLocalFunc(F);
3412+
if (!isa<Instruction>(V))
3413+
return false;
3414+
3415+
Value *Op;
3416+
auto *I = cast<Instruction>(V);
3417+
// return isP9 ? foo_p9 : foo_default;
3418+
if (auto *SI = dyn_cast<SelectInst>(I))
3419+
return ValueIsALocalFunc(SI->getTrueValue()) && ValueIsALocalFunc(SI->getFalseValue());
3420+
else if (auto *PN = dyn_cast<PHINode>(I)) {
3421+
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
3422+
if (!ValueIsALocalFunc(PN->getIncomingValue(i)))
3423+
return false;
3424+
return true;
3425+
}
3426+
// @switch.table.resolve_foo = private unnamed_addr constant [3 x ptr] [ptr @foo_static, ptr @foo_hidden, ptr @foo_protected]
3427+
// %switch.gep = getelementptr inbounds nuw ptr, ptr @switch.table, i64 %2
3428+
// V = load ptr, ptr %switch.gep,
3429+
else if (match(I, m_Load(m_GEP(m_Value(Op), m_Value())))) {
3430+
if (!isa<GlobalVariable>(Op))
3431+
return false;
3432+
auto *GV = dyn_cast<GlobalVariable>(Op);
3433+
if (!GV->hasInitializer() || !isa<ConstantArray>(GV->getInitializer()))
3434+
return false;
3435+
auto *Initializer = cast<ConstantArray>(GV->getInitializer());
3436+
for (unsigned Idx = 0, End = Initializer->getNumOperands(); Idx != End; ++Idx)
3437+
if (!ValueIsALocalFunc(Initializer->getOperand(Idx)))
3438+
return false;
3439+
return true;
3440+
}
3441+
return false;
3442+
};
34093443

34103444
if (!IFuncLocal.empty()) {
34113445
ArrayRef<std::string> List = IFuncLocal;
@@ -3422,31 +3456,15 @@ static bool TOCRestoreNeededForCallToImplementation(const GlobalIFunc &GI) {
34223456

34233457
auto *Resolver = GI.getResolverFunction();
34243458
// If the resolver is preemptible then we cannot rely on its implementation.
3425-
if (!isLocalFunc(Resolver))
3459+
if (!IsLocalFunc(Resolver))
34263460
return true;
34273461
// If one of the return values of the resolver function is not a
34283462
// local function, then we have to conservatively do a TOC save/restore.
34293463
for (auto &BB : *Resolver) {
34303464
if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
34313465
Value *RV = Ret->getReturnValue();
34323466
assert(RV);
3433-
// return &foo_p9;
3434-
if (auto *F = dyn_cast<Function>(RV)) {
3435-
if (!IsLocalFunc(F))
3436-
return true;
3437-
} else if (auto *I = dyn_cast<Instruction>(RV)) {
3438-
// return isP9 ? foo_p9 : foo_default;
3439-
if (auto *SI = dyn_cast<SelectInst>(I)) {
3440-
if (!IsLocalFunc(SI->getTrueValue()) ||
3441-
!IsLocalFunc(SI->getFalseValue()))
3442-
return true;
3443-
} else if (auto *PN = dyn_cast<PHINode>(I)) {
3444-
for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i)
3445-
if (!IsLocalFunc(PN->getIncomingValue(i)))
3446-
return true;
3447-
} else
3448-
return true;
3449-
} else
3467+
if (!ValueIsALocalFunc(RV))
34503468
return true;
34513469
}
34523470
}

0 commit comments

Comments
 (0)