What can _not_ be marked pure?

H. S. Teoh via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Mar 9 11:06:03 PST 2016


On Wed, Mar 09, 2016 at 05:12:18AM -0800, Jonathan M Davis via Digitalmars-d-learn wrote:
[...]
> So, in general, you can slap pure on most anything, though it will
> rarely buy you anything in terms of performance.

IMO, this is an area where the compiler could be improved to take better
advantage of pure annotations. The currently-implemented optimizations
based on pure, while nice, are also relatively rare, and don't seem to
outweigh the cost of having to annotate large numbers of functions by
hand.

I think one area where pure could potentially have a large gain is in
loop optimization, where pure annotations may help in increasing the
amount of code that can be hoisted out of the loop. Contrived example:

	long veryExpensiveFunction(T)(T arg) pure { ... }
	long func(long x) {
		long accum;
		foreach (i; 0 .. 1_000_000) {
			accum += i*veryExpensiveFunction(x);
		}
		return accum;
	}

If veryExpensiveFunction() is not pure, we cannot hoist it out of the
loop, since it may change the program's semantics. However, if it's
pure, we can potentially have a large performance gain by hoisting it
outside the loop.

(One may argue that a good programmer would already do this manually, of
course, but the thing about these kinds of loop optimizations is that
they often exhibit domino-effects, where the above code snippet isn't
what the programmer actually wrote, but the result of a previous
optimization on the original code, say an inlining, or some such. Having
the compiler detect this case may then lead to more optimization
opportunities downstream. While dmd is, IME, rather poor at following
these optimization domino chains, gdc's optimizer has a lot of
aggressive loop optimizations, and may be able to do much better than it
can now if the frontend can feed this kind of information about purity
to it.)


[...]
> The reason to avoid pure with templated functions is that whether a
> templated function can really be pure or not usually depends on its
> arguments.

I think a useful pattern that has emerged in Phobos code is that all
template functions, in general, should have no attributes -- it should
be left to the compiler to infer them. To ensure that the code itself
doesn't break purity (etc.), use a pure (etc.) unittest:

	auto func(T)(T args)
		// N.B.: no attributes
	{
		...
	}

	pure unittest
	{
		// We know that int will not introduce impurity to
		// func(), so this unittest will break if func itself
		// contains impure code aside from its template
		// arguments.
		func(1);
	}

This way, we ensure that the compiler will infer func as pure whenever
it can, yet we don't restrict T to be also pure (in the case where T is
impure, the compiler will correctly infer func!T as impure).

Attribute inference is the way of the future.


T

-- 
Let's eat some disquits while we format the biskettes.


More information about the Digitalmars-d-learn mailing list