aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/DeadArgumentElimination.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Transforms/IPO/DeadArgumentElimination.cpp
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
downloadsrc-eb11fae6d08f479c0799db45860a98af528fa6e7.tar.gz
src-eb11fae6d08f479c0799db45860a98af528fa6e7.zip
Vendor import of llvm trunk r338150:vendor/llvm/llvm-trunk-r338150
Notes
Notes: svn path=/vendor/llvm/dist/; revision=336809 svn path=/vendor/llvm/llvm-trunk-r338150/; revision=336814; tag=vendor/llvm/llvm-trunk-r338150
Diffstat (limited to 'lib/Transforms/IPO/DeadArgumentElimination.cpp')
-rw-r--r--lib/Transforms/IPO/DeadArgumentElimination.cpp102
1 files changed, 77 insertions, 25 deletions
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp
index 5446541550e5..31e771da3bd3 100644
--- a/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -240,8 +240,11 @@ bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) {
I2->takeName(&*I);
}
- // Patch the pointer to LLVM function in debug info descriptor.
- NF->setSubprogram(Fn.getSubprogram());
+ // Clone metadatas from the old function, including debug info descriptor.
+ SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
+ Fn.getAllMetadata(MDs);
+ for (auto MD : MDs)
+ NF->addMetadata(MD.first, *MD.second);
// Fix up any BlockAddresses that refer to the function.
Fn.replaceAllUsesWith(ConstantExpr::getBitCast(NF, Fn.getType()));
@@ -507,25 +510,43 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
// MaybeLive. Initialized to a list of RetCount empty lists.
RetUses MaybeLiveRetUses(RetCount);
- for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- if (const ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator()))
+ bool HasMustTailCalls = false;
+
+ for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+ if (const ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType()
!= F.getFunctionType()->getReturnType()) {
// We don't support old style multiple return values.
MarkLive(F);
return;
}
+ }
+
+ // If we have any returns of `musttail` results - the signature can't
+ // change
+ if (BB->getTerminatingMustTailCall() != nullptr)
+ HasMustTailCalls = true;
+ }
+
+ if (HasMustTailCalls) {
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - " << F.getName()
+ << " has musttail calls\n");
+ }
if (!F.hasLocalLinkage() && (!ShouldHackArguments || F.isIntrinsic())) {
MarkLive(F);
return;
}
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Inspecting callers for fn: "
- << F.getName() << "\n");
+ LLVM_DEBUG(
+ dbgs() << "DeadArgumentEliminationPass - Inspecting callers for fn: "
+ << F.getName() << "\n");
// Keep track of the number of live retvals, so we can skip checks once all
// of them turn out to be live.
unsigned NumLiveRetVals = 0;
+
+ bool HasMustTailCallers = false;
+
// Loop all uses of the function.
for (const Use &U : F.uses()) {
// If the function is PASSED IN as an argument, its address has been
@@ -536,6 +557,11 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
return;
}
+ // The number of arguments for `musttail` call must match the number of
+ // arguments of the caller
+ if (CS.isMustTailCall())
+ HasMustTailCallers = true;
+
// If this use is anything other than a call site, the function is alive.
const Instruction *TheCall = CS.getInstruction();
if (!TheCall) { // Not a direct call site?
@@ -580,12 +606,17 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
}
}
+ if (HasMustTailCallers) {
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - " << F.getName()
+ << " has musttail callers\n");
+ }
+
// Now we've inspected all callers, record the liveness of our return values.
for (unsigned i = 0; i != RetCount; ++i)
MarkValue(CreateRet(&F, i), RetValLiveness[i], MaybeLiveRetUses[i]);
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Inspecting args for fn: "
- << F.getName() << "\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Inspecting args for fn: "
+ << F.getName() << "\n");
// Now, check all of our arguments.
unsigned i = 0;
@@ -593,12 +624,19 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
for (Function::const_arg_iterator AI = F.arg_begin(),
E = F.arg_end(); AI != E; ++AI, ++i) {
Liveness Result;
- if (F.getFunctionType()->isVarArg()) {
+ if (F.getFunctionType()->isVarArg() || HasMustTailCallers ||
+ HasMustTailCalls) {
// Variadic functions will already have a va_arg function expanded inside
// them, making them potentially very sensitive to ABI changes resulting
// from removing arguments entirely, so don't. For example AArch64 handles
// register and stack HFAs very differently, and this is reflected in the
// IR which has already been generated.
+ //
+ // `musttail` calls to this function restrict argument removal attempts.
+ // The signature of the caller must match the signature of the function.
+ //
+ // `musttail` calls in this function prevents us from changing its
+ // signature
Result = Live;
} else {
// See what the effect of this use is (recording any uses that cause
@@ -637,8 +675,8 @@ void DeadArgumentEliminationPass::MarkValue(const RetOrArg &RA, Liveness L,
/// mark any values that are used as this function's parameters or by its return
/// values (according to Uses) live as well.
void DeadArgumentEliminationPass::MarkLive(const Function &F) {
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Intrinsically live fn: "
- << F.getName() << "\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Intrinsically live fn: "
+ << F.getName() << "\n");
// Mark the function as live.
LiveFunctions.insert(&F);
// Mark all arguments as live.
@@ -659,8 +697,8 @@ void DeadArgumentEliminationPass::MarkLive(const RetOrArg &RA) {
if (!LiveValues.insert(RA).second)
return; // We were already marked Live.
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Marking "
- << RA.getDescription() << " live\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Marking "
+ << RA.getDescription() << " live\n");
PropagateLiveness(RA);
}
@@ -718,9 +756,9 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
HasLiveReturnedArg |= PAL.hasParamAttribute(i, Attribute::Returned);
} else {
++NumArgumentsEliminated;
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing argument " << i
- << " (" << I->getName() << ") from " << F->getName()
- << "\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing argument "
+ << i << " (" << I->getName() << ") from "
+ << F->getName() << "\n");
}
}
@@ -763,8 +801,9 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
NewRetIdxs[i] = RetTypes.size() - 1;
} else {
++NumRetValsEliminated;
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing return value "
- << i << " from " << F->getName() << "\n");
+ LLVM_DEBUG(
+ dbgs() << "DeadArgumentEliminationPass - Removing return value "
+ << i << " from " << F->getName() << "\n");
}
}
if (RetTypes.size() > 1) {
@@ -803,10 +842,14 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
AttributeSet RetAttrs = AttributeSet::get(F->getContext(), RAttrs);
+ // Strip allocsize attributes. They might refer to the deleted arguments.
+ AttributeSet FnAttrs = PAL.getFnAttributes().removeAttribute(
+ F->getContext(), Attribute::AllocSize);
+
// Reconstruct the AttributesList based on the vector we constructed.
assert(ArgAttrVec.size() == Params.size());
- AttributeList NewPAL = AttributeList::get(
- F->getContext(), PAL.getFnAttributes(), RetAttrs, ArgAttrVec);
+ AttributeList NewPAL =
+ AttributeList::get(F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
// Create the new function type based on the recomputed parameters.
FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg());
@@ -875,8 +918,14 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
// Reconstruct the AttributesList based on the vector we constructed.
assert(ArgAttrVec.size() == Args.size());
+
+ // Again, be sure to remove any allocsize attributes, since their indices
+ // may now be incorrect.
+ AttributeSet FnAttrs = CallPAL.getFnAttributes().removeAttribute(
+ F->getContext(), Attribute::AllocSize);
+
AttributeList NewCallPAL = AttributeList::get(
- F->getContext(), CallPAL.getFnAttributes(), RetAttrs, ArgAttrVec);
+ F->getContext(), FnAttrs, RetAttrs, ArgAttrVec);
SmallVector<OperandBundleDef, 1> OpBundles;
CS.getOperandBundlesAsDefs(OpBundles);
@@ -1017,8 +1066,11 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
BB.getInstList().erase(RI);
}
- // Patch the pointer to LLVM function in debug info descriptor.
- NF->setSubprogram(F->getSubprogram());
+ // Clone metadatas from the old function, including debug info descriptor.
+ SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
+ F->getAllMetadata(MDs);
+ for (auto MD : MDs)
+ NF->addMetadata(MD.first, *MD.second);
// Now that the old function is dead, delete it.
F->eraseFromParent();
@@ -1034,7 +1086,7 @@ PreservedAnalyses DeadArgumentEliminationPass::run(Module &M,
// removed. We can do this if they never call va_start. This loop cannot be
// fused with the next loop, because deleting a function invalidates
// information computed while surveying other functions.
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Deleting dead varargs\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Deleting dead varargs\n");
for (Module::iterator I = M.begin(), E = M.end(); I != E; ) {
Function &F = *I++;
if (F.getFunctionType()->isVarArg())
@@ -1045,7 +1097,7 @@ PreservedAnalyses DeadArgumentEliminationPass::run(Module &M,
// We assume all arguments are dead unless proven otherwise (allowing us to
// determine that dead arguments passed into recursive functions are dead).
//
- DEBUG(dbgs() << "DeadArgumentEliminationPass - Determining liveness\n");
+ LLVM_DEBUG(dbgs() << "DeadArgumentEliminationPass - Determining liveness\n");
for (auto &F : M)
SurveyFunction(F);