On Friday, 8 February 2013 at 09:33:19 UTC, Jonathan M Davis
wrote:
On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:
On 02/08/13 01:33, Jonathan M Davis wrote:
> Hmmm. I wouldn't have thought that you could get the
> function pointer at
> compiler time. Regardless, you lose any possibility of
> inlining the
> function call, which is the main problem AFAIK, though I
> don't know if
> they would have been an option in the case of dup anyway.
It doesn't affect inlining. (Obviously, that's compiler
dependent, but
there's no reason why it should and indeed does not w/ gdc)
How could it not affect inlining? You're using a pointer to a
function instead
of the function itself, so it can't be inlined. Do you mean
that dup in
particular doens't get inlined even when called directly?
That's quite
possible, but in the general case, using a function pointer
rather than
calling a function directly risks taking a small efficiency hit
due to the fact
that the function can no longer be inlined.
- Jonathan M Davis
Well, aren't you saying that because usually, function pointers
aren't obtained at compile time?
In any case, I also tested it, and the disassemble seems to give
the exact same code (inlined, as far as I can tell) for calling
via function or function pointer:
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29\n{\n%20%20%2F%2Fenum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20%2F%2Ffun%28%29%3B\n%20%20foo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}
And a third version, after adding the "nothrow" keyword. Slight
changes, but I can't tell if they are "true" changes:
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29%20nothrow\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}
That said, when everything is said and done, the try catch
version also generates the same inline code
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29%20nothrow\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}
But in this case, the compiler has access to the call, so it can
*tell* exceptions won't get thrown.
Finally, in this last version, which calls dup, we can see the
"cast" version takes less intructions that the try/catch version.
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nchar[]%20s%3B\n\nvoid%20foo%28%29\n{\n%20%20s%20%3D%20\%22hello\%22.dup%3B\n}\n\nversion%28all%29\n{\n%20%20void%20bar%28%29%20nothrow\n%20%20{\n%20%20%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20%20%20fun%28%29%3B\n%20%20}\n}\nelse\n{\n%20%20void%20bar%28%29%20nothrow\n%20%20{\n%20%20%20%20try{\n%20%20%20%20%20%20foo%28%29%3B\n%20%20%20%20}catch{}\n%20%20}\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28s%20%3D%3D%20\%22hello\%22%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}
But at the end of the day, it is a dangerous semantic for not
that much gain.