Jump to page: 1 2
Thread overview
Is it possible to force CTFE?
Jun 10, 2012
Tommi
Jun 10, 2012
jerro
Sep 27, 2012
Tommi
Jun 10, 2012
Timon Gehr
Jun 10, 2012
Tommi
Sep 27, 2012
bearophile
Sep 27, 2012
Jacob Carlborg
Sep 27, 2012
bearophile
Sep 28, 2012
Tommi
Sep 28, 2012
Tommi
Oct 01, 2012
Don Clugston
June 10, 2012
Three related questions:

1) Is there a way to force a function to be always executed at compile time (when it's possible to do so) no matter what context it's called in?

2) Is it possible to specialize a function based on whether or not the parameter that was passed in is a compile time constant?

3) Does any D compiler currently optimize out a conditional branch which _can_ be evaluated at compile time (but which isn't forced into CTFE)? Like:

int getValue(bool b)
{
    return b ? 123 : 456;
}

//...
   auto value = getValue(true);
June 10, 2012
> 1) Is there a way to force a function to be always executed at compile time (when it's possible to do so) no matter what context it's called in?

No, but you could wrap it in a template to force it to always
execute at compile time. Of course it could then only be called
at compile time.

> 2) Is it possible to specialize a function based on whether or not the parameter that was passed in is a compile time constant?

No.

> 3) Does any D compiler currently optimize out a conditional branch which _can_ be evaluated at compile time (but which isn't forced into CTFE)? Like:
>
> int getValue(bool b)
> {
>     return b ? 123 : 456;
> }
>
> //...
>    auto value = getValue(true);

DMD, LDC and GDC all do this when compiling with optimizations
turned on. They all compile these functions to exactly the
same code:

auto foo()
{
    return getValue(true);
}

auto bar()
{
    return 123;
}




June 10, 2012
On 06/10/2012 09:04 AM, Tommi wrote:
> Three related questions:
>
> 1) Is there a way to force a function to be always executed at compile
> time (when it's possible to do so) no matter what context it's called in?
>

No there is not. You could use a template that calls a private function at compile time instead. What is your use case?

> 2) Is it possible to specialize a function based on whether or not the
> parameter that was passed in is a compile time constant?
>

This has been discussed before, but there is not.


1-2) could be introduced later when D gets AST macros.

> 3) Does any D compiler currently optimize out a conditional branch which
> _can_ be evaluated at compile time (but which isn't forced into CTFE)?
> Like:
>
> int getValue(bool b)
> {
>      return b ? 123 : 456;
> }
>
> //...
>     auto value = getValue(true);

Yes, DMD/GDC/LDC should be able to do this to different extents.
June 10, 2012
On Sunday, 10 June 2012 at 10:23:09 UTC, Timon Gehr wrote:
> No there is not. You could use a template that calls a private function at compile time instead. What is your use case?

I was just thinking about a situation where a property accessor/mutator methods are not as simple as read/assign value, such as in this silly example:

struct Flipping123
{
    private int m_number = 123;

    @property bool isPositive()
    {
        return m_number >= 0;
    }

    @property void isPositive(bool b)
    {
        m_number = b ? 123 : -123;
    }
}

//...
    Flipping123 fl;
    fl.isPositive = false; // I'd rather not have cond. branching in release mode
September 27, 2012
On Sunday, 10 June 2012 at 10:16:23 UTC, jerro wrote:
>
> No, but you could wrap it in a template to force it to always
> execute at compile time.

So, I just realized, I could have just this one convenience template that I can use whenever I want to force an expression to be evaluated at compile-time. Like so:

template ct(alias expr)
{
     enum ct = expr;
}

int fun(int a, int b)
{
     return a + b;
}

//... and use it like:

ct!(fun(1, 2))

That's not *too* inconvenient. Although, best would be a function attribute that would force the compiler to apply ctfe aggressively whenever it can with calls to that function.
September 27, 2012
Tommi:

> 2) Is it possible to specialize a function based on whether or not the parameter that was passed in is a compile time constant?

I am interested in this since some years. I think it's useful, but I don't know if it can be implemented. I don't remember people discussing about this much.

Bye,
bearophile
September 27, 2012
On 2012-09-27 15:01, bearophile wrote:
> Tommi:
>
>> 2) Is it possible to specialize a function based on whether or not the
>> parameter that was passed in is a compile time constant?
>
> I am interested in this since some years. I think it's useful, but I
> don't know if it can be implemented. I don't remember people discussing
> about this much.

There's the if (__ctfe) hack. Also using only template parameters will force the function to be CTFE.

-- 
/Jacob Carlborg
September 27, 2012
Jacob Carlborg:

>> I am interested in this since some years. I think it's useful, but I don't know if it can be implemented. I don't remember
>> people discussing about this much.
>
> There's the if (__ctfe) hack. Also using only template parameters will force the function to be CTFE.

This is quite far from what I was discussing about here...

Bye,
bearophile
September 28, 2012
One use case I can think of for specializing functions based on whether or not its arguments are compile-time evaluable:

// Big container that can't be accessed in constant time:
immutable cachedResults = init();

double getResult(<args>)
    if (areCompileTimeConstants!(<args>) == false)
{
    return cachedResults.at(<args>);
}

double getResult(<args>)
    if (areCompileTimeConstants!(<args>) == true)
{
    // Computing the result takes long time
    ...
    return computedResult;
}

Point being that A) cachedResults takes so much memory we don't want to evaluate it at compile-time and bloat the executable, and B) accessing cachedResults takes some non-trivial time, so we don't want to do that at runtime if it can be done at compile-time. Don't know how common this kind of thing would be though.


But, that made me think...
In a perfect world, I think, the compiler would always evaluate all possible functions at compile-time, given that doing so would produce a smaller (or equal size) executable than what not-evaluating-at-compile-time would produce. For example (assuming the following initialization functions are compile-time evaluable):

// The following wouldn't be evaluated at compile time,
// because that function call (probably) wouldn't take
// as much space in the executable as million ints:

int[1_000_000] bigArray = initBigArray();

// The following would be always evaluated at compile time,
// because a single int value would take less space in the
// executable than the function call:

int myValue = initMyValue();

Although, to speed up test compilations, we'd need a compiler flag to disable this "aggressive" CTFE behaviour.
September 28, 2012
On Friday, 28 September 2012 at 17:52:55 UTC, Tommi wrote:
> In a perfect world, I think, the compiler would always evaluate all possible functions at compile-time, given that doing so would produce a smaller (or equal size) executable than what not-evaluating-at-compile-time would produce.


Or, a simpler rule (for both the compiler and the coder):
Have a compiler flag where you set a value (in bytes), and if a function returns a type that's size is not larger than the set value, the compiler would execute all calls to that function at compile-time (if possible).
« First   ‹ Prev
1 2