As implemented before r202131, all the code that checked for AlwaysInline also checked for ForceInline and treated it identically.<div><br></div><div>This commit, r202131, does nothing to change the semantics of how clang feels about ForceInline.  It is just as correct or wrong as it was before.</div>
<div><br></div><div>Quite frankly, many of the limitations that __forceinline is documented to have are ridiculous, it seems like their implementation is incredibly dependent on the frontend being able to do some analysis.</div>
<div><br></div><div>For example, they mention that they won't inline if the function has a variable argument list.  That just seems like a bug, I don't see why we would need to mimic that behavior.</div><div><br></div>
<div>MSVC has /Ob0, which we bind to -fno-inline.  I don't think we have this on by default, they do. The two flags don't have quite the same semantics. I think if there is something to fix, it should be done by fixing /Ob0.</div>
<div><br></div><div>-- </div><div>David Majnemer<br><div><br><div>On Tue Feb 25 2014 at 5:24:05 AM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I don't believe the semantics for __forceinline and always_inline<br>
really match up. As best I can tell, always_inline will *always*<br>
inline the function, regardless of optimization level, which is not<br>
something that __forceinline does. As a simple example:<br>
<br>
__forceinline int i() { return 9; }<br>
<br>
int main(void) {<br>
  int j = i();<br>
  return 0;<br>
}<br>
<br>
In debug mode in MSVC 2013, this produces (in part):<br>
<br>
; 3    : int main(void) {<br>
<br>
push ebp<br>
mov ebp, esp<br>
sub esp, 204 ; 000000ccH<br>
push ebx<br>
push esi<br>
push edi<br>
lea edi, DWORD PTR [ebp-204]<br>
mov ecx, 51 ; 00000033H<br>
mov eax, -858993460 ; ccccccccH<br>
rep stosd<br>
<br>
; 4    :   int j = i();<br>
<br>
call ?i@@YAHXZ ; i<br>
mov DWORD PTR _j$[ebp], eax<br>
<br>
; 5    :   return 0;<br>
<br>
xor eax, eax<br>
<br>
; 6    : }<br>
<br>
When I compile in GCC (using always_inline) at -O0, I get:<br>
<br>
main:<br>
push rbp<br>
mov rbp, rsp<br>
mov eax, 9<br>
mov DWORD PTR [rbp-4], eax<br>
mov eax, 0<br>
pop rbp<br>
ret<br>
<br>
Clang may not support __forceinline semantics properly yet, but I am<br>
not keen on this behavior change. It also deviates from the<br>
documentation for both (gcc claims "this attribute inlines the<br>
function even if no optimization level was specified." and msvc claims<br>
"You cannot force the compiler to inline a particular function, even<br>
with the __forceinline keyword.").<br>
<br>
~Aaron<br>
<br>
On Tue, Feb 25, 2014 at 4:53 AM, David Majnemer<br>
<<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>> wrote:<br>
> Author: majnemer<br>
> Date: Tue Feb 25 03:53:29 2014<br>
> New Revision: 202131<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=202131&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=202131&view=rev</a><br>
> Log:<br>
> Attr: Remove ForceInline<br>
><br>
> The __forceinline keyword's semantics are now recast as AlwaysInline and<br>
> the kw___forceinline token has its language mode set for KEYMS.<br>
><br>
> This preserves the semantics of the previous implementation but with<br>
> less duplication of code.<br>
><br>
> Modified:<br>
>     cfe/trunk/include/clang/Basic/<u></u>Attr.td<br>
>     cfe/trunk/include/clang/Basic/<u></u>TokenKinds.def<br>
>     cfe/trunk/lib/CodeGen/<u></u>CodeGenFunction.cpp<br>
>     cfe/trunk/lib/CodeGen/<u></u>CodeGenModule.cpp<br>
>     cfe/trunk/lib/Sema/<u></u>SemaDeclAttr.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/<u></u>Attr.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=202131&r1=202130&r2=202131&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Basic/Attr.td?rev=<u></u>202131&r1=202130&r2=202131&<u></u>view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- cfe/trunk/include/clang/Basic/<u></u>Attr.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/<u></u>Attr.td Tue Feb 25 03:53:29 2014<br>
> @@ -357,7 +357,7 @@ def AlignMac68k : InheritableAttr {<br>
>  }<br>
><br>
>  def AlwaysInline : InheritableAttr {<br>
> -  let Spellings = [GCC<"always_inline">];<br>
> +  let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">];<br>
>    let Subjects = SubjectList<[Function]>;<br>
>    let Documentation = [Undocumented];<br>
>  }<br>
> @@ -1676,12 +1676,6 @@ def DLLImport : InheritableAttr, TargetS<br>
>    let Documentation = [Undocumented];<br>
>  }<br>
><br>
> -def ForceInline : InheritableAttr {<br>
> -  let Spellings = [Keyword<"__forceinline">];<br>
> -  let LangOpts = [MicrosoftExt];<br>
> -  let Documentation = [Undocumented];<br>
> -}<br>
> -<br>
>  def SelectAny : InheritableAttr {<br>
>    let Spellings = [Declspec<"selectany">];<br>
>    let LangOpts = [MicrosoftExt];<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/<u></u>TokenKinds.def<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=202131&r1=202130&r2=202131&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/include/<u></u>clang/Basic/TokenKinds.def?<u></u>rev=202131&r1=202130&r2=<u></u>202131&view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- cfe/trunk/include/clang/Basic/<u></u>TokenKinds.def (original)<br>
> +++ cfe/trunk/include/clang/Basic/<u></u>TokenKinds.def Tue Feb 25 03:53:29 2014<br>
> @@ -455,7 +455,7 @@ KEYWORD(__cdecl                     , KE<br>
>  KEYWORD(__stdcall                   , KEYALL)<br>
>  KEYWORD(__fastcall                  , KEYALL)<br>
>  KEYWORD(__thiscall                  , KEYALL)<br>
> -KEYWORD(__forceinline               , KEYALL)<br>
> +KEYWORD(__forceinline               , KEYMS)<br>
>  KEYWORD(__unaligned                 , KEYMS)<br>
><br>
>  // OpenCL address space qualifiers<br>
><br>
> Modified: cfe/trunk/lib/CodeGen/<u></u>CodeGenFunction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=202131&r1=202130&r2=202131&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/CodeGen/<u></u>CodeGenFunction.cpp?rev=<u></u>202131&r1=202130&r2=202131&<u></u>view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- cfe/trunk/lib/CodeGen/<u></u>CodeGenFunction.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/<u></u>CodeGenFunction.cpp Tue Feb 25 03:53:29 2014<br>
> @@ -527,8 +527,7 @@ void CodeGenFunction::<u></u>StartFunction(Glob<br>
>            Fn->addFnAttr(llvm::Attribute:<u></u>:InlineHint);<br>
>            break;<br>
>          }<br>
> -    } else if (!FD->hasAttr<<u></u>AlwaysInlineAttr>() &&<br>
> -               !FD->hasAttr<ForceInlineAttr>(<u></u>))<br>
> +    } else if (!FD->hasAttr<<u></u>AlwaysInlineAttr>())<br>
>        Fn->addFnAttr(llvm::Attribute:<u></u>:NoInline);<br>
>    }<br>
><br>
><br>
> Modified: cfe/trunk/lib/CodeGen/<u></u>CodeGenModule.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=202131&r1=202130&r2=202131&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/CodeGen/<u></u>CodeGenModule.cpp?rev=202131&<u></u>r1=202130&r2=202131&view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- cfe/trunk/lib/CodeGen/<u></u>CodeGenModule.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/<u></u>CodeGenModule.cpp Tue Feb 25 03:53:29 2014<br>
> @@ -635,8 +635,7 @@ void CodeGenModule::<u></u>SetLLVMFunctionAttri<br>
>      B.addAttribute(llvm::<u></u>Attribute::NoDuplicate);<br>
>    } else if (D->hasAttr<NoInlineAttr>()) {<br>
>      B.addAttribute(llvm::<u></u>Attribute::NoInline);<br>
> -  } else if ((D->hasAttr<AlwaysInlineAttr><u></u>() ||<br>
> -              D->hasAttr<ForceInlineAttr>()) &&<br>
> +  } else if (D->hasAttr<AlwaysInlineAttr>(<u></u>) &&<br>
>               !F->getAttributes().<u></u>hasAttribute(llvm::<u></u>AttributeSet::FunctionIndex,<br>
>                                                llvm::Attribute::NoInline)) {<br>
>      // (noinline wins over always_inline, and we can't specify both in IR)<br>
> @@ -1245,8 +1244,7 @@ CodeGenModule::<u></u>shouldEmitFunction(Global<br>
>    if (getFunctionLinkage(GD) != llvm::Function::<u></u>AvailableExternallyLinkage)<br>
>      return true;<br>
>    const FunctionDecl *F = cast<FunctionDecl>(GD.getDecl(<u></u>));<br>
> -  if (CodeGenOpts.OptimizationLevel == 0 &&<br>
> -      !F->hasAttr<AlwaysInlineAttr>(<u></u>) && !F->hasAttr<ForceInlineAttr>()<u></u>)<br>
> +  if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>(<u></u>))<br>
>      return false;<br>
>    // PR9614. Avoid cases where the source code is lying to us. An available<br>
>    // externally function should have an equivalent function somewhere else,<br>
><br>
> Modified: cfe/trunk/lib/Sema/<u></u>SemaDeclAttr.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=202131&r1=202130&r2=202131&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/cfe/trunk/lib/Sema/<u></u>SemaDeclAttr.cpp?rev=202131&<u></u>r1=202130&r2=202131&view=diff</a><br>

> ==============================<u></u>==============================<u></u>==================<br>
> --- cfe/trunk/lib/Sema/<u></u>SemaDeclAttr.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/<u></u>SemaDeclAttr.cpp Tue Feb 25 03:53:29 2014<br>
> @@ -4269,8 +4269,6 @@ static void ProcessDeclAttribute(Sema &S<br>
>      break;<br>
>    case AttributeList::AT_<u></u>MSInheritance:<br>
>      handleMSInheritanceAttr(S, D, Attr); break;<br>
> -  case AttributeList::AT_ForceInline:<br>
> -    handleSimpleAttribute<<u></u>ForceInlineAttr>(S, D, Attr); break;<br>
>    case AttributeList::AT_SelectAny:<br>
>      handleSimpleAttribute<<u></u>SelectAnyAttr>(S, D, Attr); break;<br>
><br>
><br>
><br>
> ______________________________<u></u>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu" target="_blank">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>