CTFE and Static If Question
jmh530
john.michael.hall at gmail.com
Thu May 7 19:32:20 UTC 2020
On Thursday, 7 May 2020 at 17:59:30 UTC, Paul Backus wrote:
> On Thursday, 7 May 2020 at 15:00:18 UTC, jmh530 wrote:
>> Does foo!y0(rt) generate the same code as foo(rt, y0)?
>>
>> How is the code generated by foo(rt, x0) different from
>> foo(rt,y0)?
>
> You can look at the generated code using the Compiler Explorer
> at d.godbolt.org. Here's a link to your example, compiled with
> ldc, with optimizations enabled:
>
> https://d.godbolt.org/z/x5K7P6
>
> As you can see, the non-static-if version has a runtime
> comparison and a conditional jump, and the static-if version
> does not. However, it doesn't make a difference in the end,
> because the calls have been optimized out, leaving an empty
> main function.
Thanks for that. I forgot how much nicer godbolt is for looking
assembly than run.dlang.org. Or maybe it's just that the
optimized assembly for ldc looks a lot simpler than dmd?
I eventually played around with it for a bit and ended up with
what's below. When compiled with ldc -O -release, some of the
functions have code that are generated a little differently than
the one above (the assembly looks a little prettier when using
ints than doubles). It looks like there is a little bit of
template bloat too, in that it generates something like four
different versions of the run-time function that all basically do
the same thing (some slight differences I don't really
understand). Anyway, I think that's the first time I've ever used
__traits compiles with a static if and I don't think I've ever
used an template alias bool before, but I thought it was kind of
cool.
int foo(alias bool rtct)(int[] x) {
static if (__traits(compiles, {static if (rtct) { enum val =
rtct;}})) {
static if (rtct) {
return bar(x) / cast(int) x.length;
} else {
return bar(x) / cast(int) (x.length - 1);
}
} else {
if (rtct)
return bar(x) / cast(int) x.length;
else
return bar(x) / cast(int) (x.length - 1);
}
}
int foo(int[] x, bool rtct) {
if (rtct)
return foo!true(x);
else
return foo!false(x);
}
int bar(int[] x) {
return x[0] + x[1];
}
void main() {
import std.stdio: writeln;
int[] a = [1, 2, 3, 4, 5];
bool x0 = true;
bool x1 = false;
int result0 = foo(a, x0);
int result1 = foo(a, x1);
int result2 = foo!x0(a);
int result3 = foo!x1(a);
enum y0 = true;
enum y1 = false;
int result0_ = foo(a, y0);
int result1_ = foo(a, y1);
int result2_ = foo!y0(a);
int result3_ = foo!y1(a);
}
More information about the Digitalmars-d-learn
mailing list