llvm/llvm-project

Unnecessary return statement in unreachable block generated by EmitFunctionEpilog in musttail cases.

Open

#104,770 建立於 2024年8月19日

在 GitHub 查看
 (6 留言) (0 反應) (2 負責人)C++ (10,782 fork)batch import
clang:codegengood first issue

倉庫指標

Star
 (26,378 star)
PR 合併指標
 (平均合併 1天 2小時) (30 天內合併 1,000 個 PR)

描述

When clang::musttail is used, and -O is not set, an extra "function epiloge" return case is generated. This seems to be optimized out at any -O level, and automatially optimized out by the backend. I believe this is the case for all musttail calls, but I have attatched a repro example for conveniance.

Reproduce:

int F1(signed short P0);
int F2(signed short P0) {
  [[clang::musttail]] return F1(2);
}
clang -S -emit-llvm
define dso_local noundef i32 @_Z2F2s(i16 noundef signext %P0) #0 {
entry:
  %P0.addr = alloca i16, align 2
  store i16 %P0, ptr %P0.addr, align 2
  %call = musttail call noundef i32 @_Z2F1s(i16 noundef signext 2)
  ret i32 %call

0:                                                ; No predecessors!
  ret i32 undef
}

The two calls to CreateRet are here: CodeGenFunction::EmitCall

  // If this is a musttail call, return immediately. We do not branch to the
  // epilogue in this case.
  if (IsMustTail) {
    for (auto it = EHStack.find(CurrentCleanupScopeDepth); it != EHStack.end();
         ++it) {
      EHCleanupScope *Cleanup = dyn_cast<EHCleanupScope>(&*it);
      if (!(Cleanup && Cleanup->getCleanup()->isRedundantBeforeReturn()))
        CGM.ErrorUnsupported(MustTailCall, "tail call skipping over cleanups");
    }
    if (CI->getType()->isVoidTy())
      Builder.CreateRetVoid();
    else
      Builder.CreateRet(CI);
    Builder.ClearInsertionPoint();
    EnsureInsertPoint();
    return GetUndefRValue(RetTy);
  }

Note how the insert point is unset here, as no more code should be generated for this function and here CodeGenFunction::EmitFunctionEpilog

case ABIArgInfo::IndirectAliased:
    llvm_unreachable("Invalid ABI kind for return argument");
  }

  llvm::Instruction *Ret;
  if (RV) {
    if (CurFuncDecl && CurFuncDecl->hasAttr<CmseNSEntryAttr>()) {
      // For certain return types, clear padding bits, as they may reveal
      // sensitive information.
      // Small struct/union types are passed as integers.
      auto *ITy = dyn_cast<llvm::IntegerType>(RV->getType());
      if (ITy != nullptr && isa<RecordType>(RetTy.getCanonicalType()))
        RV = EmitCMSEClearRecord(RV, ITy, RetTy);
    }
    EmitReturnValueCheck(RV);
    Ret = Builder.CreateRet(RV);
  } else {
    Ret = Builder.CreateRetVoid();
  }

I suggest that EmitFunctionEpilog should not be called for a musttail function, as the body definitely already contains a return.

貢獻者指南