December 09, 2013
On Sun, Dec 08, 2013 at 10:56:09AM +0100, John Colvin wrote:
> On Sunday, 8 December 2013 at 05:27:12 UTC, H. S. Teoh wrote:
> >Once I hacked up a script  (well, a little D program :P) that disassembles D executables and builds a reference graph of its symbols.
> 
> Do you still have that somewhere? I've never attempted such a thing and would like to see what it entailed.

Well, all it does is to run objdump to disassemble the executable, then
parse the output to extract (1) symbols (usually functions) and (2)
references to other symbols (within the function body), and construct a
graph out of that.

It's not 100% accurate, though, because objdump doesn't know anything about vtables or jump tables, so any references through those would not be found. Also, it will obviously produce useless results if your executable has been stripped of symbols.

I'll put the code up on github if you're interested. And, looking at the code again, it appears that I was in the middle of a rewrite (doesn't even compile yet), which is in a separate git branch; but master seems usable enough so I'll just push that.


T

-- 
Skill without imagination is craftsmanship and gives us many useful objects such as wickerwork picnic baskets.  Imagination without skill gives us modern art. -- Tom Stoppard
December 09, 2013
On Sun, Dec 08, 2013 at 10:56:09AM +0100, John Colvin wrote:
> On Sunday, 8 December 2013 at 05:27:12 UTC, H. S. Teoh wrote:
> >Once I hacked up a script  (well, a little D program :P) that disassembles D executables and builds a reference graph of its symbols.
> 
> Do you still have that somewhere? I've never attempted such a thing and would like to see what it entailed.

Heh, apparently I already have the code up on github:

	https://github.com/quickfur/symdep


T

-- 
It won't be covered in the book. The source code has to be useful for something, after all. -- Larry Wall
December 09, 2013
On Mon, Dec 09, 2013 at 12:45:37AM -0800, Walter Bright wrote: [...]
> Try this:
> 
>   pure int foo (int a, int b) nothrow {
>     return a + b;
>   }
> 
>   int test() {
>     return foo(1, 2) + foo(1, 2);
>   }
> 
> Compile with:
> 
>   dmd foo -O -release -c
> 
> And dump the assembly:
> 
>             push    EAX
>             mov     EAX,2
>             push    1
>             call    near ptr _D3foo3fooFNaNbiiZi
>             add     EAX,EAX
>             pop     ECX
>             ret
> 
> Granted, more cases can be done, but it *does* take advantage of purity here and there.
[...]

Does this currently only happen inside a single expression? Any plans to have the optimizer recognize pure calls in separate (but identical) expressions? Jacob's example seems like it *should* be easily detected:

	int a = pureFunc(a,b,c);
	int b = pureFunc(a,b,c); // should elide this second call


T

-- 
The only difference between male factor and malefactor is just a little emptiness inside.
December 09, 2013
On 12/9/2013 10:50 AM, H. S. Teoh wrote:
> Does this currently only happen inside a single expression? Any plans to
> have the optimizer recognize pure calls in separate (but identical)
> expressions? Jacob's example seems like it *should* be easily detected:
>
> 	int a = pureFunc(a,b,c);
> 	int b = pureFunc(a,b,c); // should elide this second call

Certainly more can be done, as with many other optimizations, but I haven't been able to spend much time on it.

December 09, 2013
On 12/9/2013 8:03 AM, Jacob Carlborg wrote:
> Sure, but then this comparison might not be so interesting. I'm trying to say
> that it might be more interesting in what D can do now and what developers are
> actually using, including vendor extension.

As pointed out, there are several outstanding examples where D outperforms C.

December 09, 2013
On 12/9/2013 6:24 AM, Araq wrote:
> ("When in doubt, assume it modifies this location.")

And it's usually in doubt, often enough to make that optimization a pipe dream.


>> (2) is impractical because there's no way for the programmer to detect if his
>> call stack is pure or not, so he can't reasonably fix it to make it pure.
>
> Well look at the subject: "inherent" vs "practical".

When you're dealing with real code, it might as well be inherent. Your argument boils down to "a sufficiently smart compiler" which will never exist and "programmers going to superhuman lengths" which never happens to try and justify that C is the fastest.

You might as well claim that a cyclist could bicycle from Seattle to Portland and average 30 mph, because he can hit 30 in a sprint.


>> (3) does require whole program analysis, which is done (as I said) by the
>> linker, and is not normally done. Will gcc/ld do it? Nope. (It's not so trivial.)
> Both GCC and LLVM can perform link time optimizations.

Inlining across source files?


>> (4) just try retrofitting an existing C program to do this. I have. You'll
>> give it up soon :-)
> Again -- the subject is "inherent code performance advantages".

It's inherent, as C does not support this, everything about C works against you if you try it, and those who try are punished. You can't even use much of the standard library if you try this.

December 09, 2013
On Monday, 9 December 2013 at 19:19:46 UTC, Walter Bright wrote:
> On 12/9/2013 6:24 AM, Araq wrote:
>> ("When in doubt, assume it modifies this location.")
>
> And it's usually in doubt, often enough to make that optimization a pipe dream.
>

I disagree.

>
>>> (2) is impractical because there's no way for the programmer to detect if his
>>> call stack is pure or not, so he can't reasonably fix it to make it pure.
>>
>> Well look at the subject: "inherent" vs "practical".
>
> When you're dealing with real code, it might as well be inherent.

*shrug* so go ahead and redefine the meaning of words as you please.

That language X is faster than C in "practice" because X is much more developer friendly and thus you can tweak your code much easier etc. is an argument of every language out there.
December 09, 2013
On Monday, 9 December 2013 at 19:45:34 UTC, Araq wrote:
> That language X is faster than C in "practice" because X is much more developer friendly and thus you can tweak your code much easier etc. is an argument of every language out there.

Not really. It's very hard to beat sensibly written C* in most languages. D is one of the few where you have a chance on anything other than very specific benchmarks. Others include fortran and c++.


*Note: not the impossible, perfect C that no one can actually write for more than ~1000 lines. Just good, straightforward, normal C code.
December 09, 2013
On 12/9/2013 11:45 AM, Araq wrote:
> On Monday, 9 December 2013 at 19:19:46 UTC, Walter Bright wrote:
>> On 12/9/2013 6:24 AM, Araq wrote:
>>> ("When in doubt, assume it modifies this location.")
> > And it's usually in doubt, often enough to make that optimization a pipe dream.
> I disagree.

I'm not without some experience with this - I have written a data flow analysis optimizer (it's in dmd) and I know how they work.

December 09, 2013
On 12/09/2013 02:05 AM, Walter Bright wrote:
> On 12/8/2013 4:47 PM, Timon Gehr wrote:
>> Static analysis will tell you where a pointer might point to (more
>> importantly,
>> it may exclude aliasing) and what values the variable 'i' might have
>> in it. How
>> precise this information is hinges on the details of the analysis and the
>> program it is applied on. I'm just saying that this may be more
>> precise than
>> what 'immutable' qualifiers give you (since those are quite easy to
>> infer, given
>> the program, and alias analysis may be non-trivial.)
>
> There has been a lot of work trying to eliminate array bounds checking
> by figuring out the limits of i. This has met with only limited success.
>
> I know of no C compiler that even attempts such things, and it certainly
> would be done if it was trivial.
>
> "Proper" D code makes routine use of const and immutable, and so that
> information is effortlessly available to even simple optimizers.

Sorry, I'm lost. What point are you arguing? None of this disputes in any way anything I wrote.