Commit 4f031296 authored by Tom Stellard's avatar Tom Stellard
Browse files

Merging r326394:

------------------------------------------------------------------------
r326394 | rnk | 2018-02-28 16:09:35 -0800 (Wed, 28 Feb 2018) | 10 lines

[DAE] don't remove args of musttail target/caller

`musttail` requires identical signatures of caller and callee. Removing
arguments breaks `musttail` semantics.

PR36441

Patch by Fedor Indutny

Differential Revision: https://reviews.llvm.org/D43708
------------------------------------------------------------------------

llvm-svn: 334464
parent f3e10f8b
Loading
Loading
Loading
Loading
+37 −3
Original line number Diff line number Diff line
@@ -507,14 +507,28 @@ 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) {
    DEBUG(dbgs() << "DeadArgumentEliminationPass - " << F.getName()
                 << " has musttail calls\n");
  }

  if (!F.hasLocalLinkage() && (!ShouldHackArguments || F.isIntrinsic())) {
    MarkLive(F);
@@ -526,6 +540,9 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
  // 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 +553,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,6 +602,11 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) {
    }
  }

  if (HasMustTailCallers) {
    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]);
@@ -593,12 +620,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
+16 −0
Original line number Diff line number Diff line
; RUN: opt -deadargelim -S < %s | FileCheck %s
; PR36441
; Dead arguments should not be removed in presence of `musttail` calls.

; CHECK-LABEL: define internal void @test(i32 %a, i32 %b)
; CHECK: musttail call void @foo(i32 %a, i32 0)
; FIXME: we should replace those with `undef`s
define internal void @test(i32 %a, i32 %b) {
  musttail call void @foo(i32 %a, i32 0)
  ret void
}

; CHECK-LABEL: define internal void @foo(i32 %a, i32 %b)
define internal void @foo(i32 %a, i32 %b) {
  ret void
}