digitalmars.D - Schrodinger's CTFE
- Steven Schveighoffer (50/50) Jul 15 2020 I found a weird workaround to the "Unreachable code" problem.
- Andrei Alexandrescu (4/14) Jul 15 2020 Would a function work?
- Steven Schveighoffer (39/56) Jul 15 2020 I actually tried that, and it does prevent the "Unreachable statement"
- Steven Schveighoffer (4/5) Jul 15 2020 I should clarify, I meant it results as the same thing as the
- Andrei Alexandrescu (2/68) Jul 15 2020 I got good news for you then: https://github.com/dlang/dmd/pull/11236
- Steven Schveighoffer (9/10) Jul 16 2020 That is good news, and will help here!
- Andrei Alexandrescu (3/16) Jul 16 2020 Perhaps in std.benchmark. This function is loosely related to
- Steven Schveighoffer (7/24) Jul 16 2020 Possibly. But this is not exactly for benchmarking, it's for making
- Paul Backus (8/19) Jul 16 2020 [...]
- Steven Schveighoffer (5/27) Jul 16 2020 I would be fine if the compiler just didn't generate unreachable code,
- Paul Backus (9/20) Jul 16 2020 [...]
- Ben Jones (14/18) Jul 17 2020 I'm taking a look into trying to get rid of "false positive"
I found a weird workaround to the "Unreachable code" problem. In a nutshell, code that is sometimes reachable given the correct template parameters can be flagged as unreachable when instantiated with different ones. An example (compile with -w): int foo(bool x)() { if(x) return 1; return 2; } void main() { auto x = foo!false(); // ok auto y = foo!true(); // Warning: "return 2;" is unreachable } A weird solution is to declare a boolean value somewhere as always true, and use it to "break" free from the constant folding: int foo(bool x)() { auto b = true; if(x && b) return 1; return 2; } The boolean will likely be removed by the optimizer, but it's kind of a clunky solution. However, we also have a special boolean __ctfe that is treated as a runtime variable for things like checking reachability, but treated as a compile-time constant for code generation (so truly unreachable code is simply removed instead of being flagged for unreachability). This also works, but is only good for compile time or runtime (depending on your intentions for foo): int foo(bool x)() { if(x && __ctfe) return 1; // or !__ctfe for runtime return 2; } I was going to ask if we could have another special variable that is like __ctfe in these respects, but is *always* true for both runtime and compile time, but I actually found out a weird trick. This works, and does the same thing at both runtime and compile time, plus will only generate one branch for the runtime (without even the optimizer turned on): int foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable? -Steve
Jul 15 2020
On 7/15/20 4:33 PM, Steven Schveighoffer wrote:int foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable?Would a function work? property bool __schro() pure nothrow nogc { return __ctfe || !__ctfe; }
Jul 15 2020
On 7/15/20 6:44 PM, Andrei Alexandrescu wrote:On 7/15/20 4:33 PM, Steven Schveighoffer wrote:I actually tried that, and it does prevent the "Unreachable statement" problem, but the runtime code contains a call to that function where it is used, which means that it's not as effective in all cases. With a straight usage of the expression, you get (without -inline or -O): pure nothrow nogc safe int onlineapp.foo!(false).foo(): push RBP mov RBP,RSP mov EAX,2 pop RBP ret add [RAX],AL pure nothrow nogc safe int onlineapp.foo!(true).foo(): push RBP mov RBP,RSP mov EAX,1 pop RBP ret add [RAX],AL With the schro function, you get the same result for foo!false (as the short circuiting of the if statement prunes out the check of __ctfe), but you get this for foo!true: pure nothrow nogc int onlineapp.foo!(true).foo(): push RBP mov RBP,RSP call pure nothrow property nogc bool onlineapp.schro() PLT32 test AL,AL je L14 mov EAX,1 pop RBP ret L14: mov EAX,2 pop RBP ret add [RAX],AL With -inline, it results as the same thing. Note that if you put it in a function, you can just return true, you don't need the __ctfe || !__ctfe. -Steveint foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable?Would a function work? property bool __schro() pure nothrow nogc { return __ctfe || !__ctfe; }
Jul 15 2020
On 7/15/20 6:58 PM, Steven Schveighoffer wrote:With -inline, it results as the same thing.I should clarify, I meant it results as the same thing as the hand-written check. -Steve
Jul 15 2020
On 7/15/20 6:58 PM, Steven Schveighoffer wrote:On 7/15/20 6:44 PM, Andrei Alexandrescu wrote:I got good news for you then: https://github.com/dlang/dmd/pull/11236On 7/15/20 4:33 PM, Steven Schveighoffer wrote:I actually tried that, and it does prevent the "Unreachable statement" problem, but the runtime code contains a call to that function where it is used, which means that it's not as effective in all cases. With a straight usage of the expression, you get (without -inline or -O): pure nothrow nogc safe int onlineapp.foo!(false).foo(): push RBP mov RBP,RSP mov EAX,2 pop RBP ret add [RAX],AL pure nothrow nogc safe int onlineapp.foo!(true).foo(): push RBP mov RBP,RSP mov EAX,1 pop RBP ret add [RAX],AL With the schro function, you get the same result for foo!false (as the short circuiting of the if statement prunes out the check of __ctfe), but you get this for foo!true: pure nothrow nogc int onlineapp.foo!(true).foo(): push RBP mov RBP,RSP call pure nothrow property nogc bool onlineapp.schro() PLT32 test AL,AL je L14 mov EAX,1 pop RBP ret L14: mov EAX,2 pop RBP ret add [RAX],AL With -inline, it results as the same thing. Note that if you put it in a function, you can just return true, you don't need the __ctfe || !__ctfe. -Steveint foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable?Would a function work? property bool __schro() pure nothrow nogc { return __ctfe || !__ctfe; }
Jul 15 2020
On 7/16/20 2:32 AM, Andrei Alexandrescu wrote:I got good news for you then: https://github.com/dlang/dmd/pull/11236That is good news, and will help here! This should suffice: property pure safe nothrow bool reachable() { pragma(inline, true); return true; } Though I don't know if this is something we should include in Phobos? -Steve
Jul 16 2020
On 7/16/20 12:04 PM, Steven Schveighoffer wrote:On 7/16/20 2:32 AM, Andrei Alexandrescu wrote:Perhaps in std.benchmark. This function is loosely related to DoNotOptimize in https://github.com/google/benchmark.I got good news for you then: https://github.com/dlang/dmd/pull/11236That is good news, and will help here! This should suffice: property pure safe nothrow bool reachable() { pragma(inline, true); return true; } Though I don't know if this is something we should include in Phobos?
Jul 16 2020
On 7/16/20 4:51 PM, Andrei Alexandrescu wrote:On 7/16/20 12:04 PM, Steven Schveighoffer wrote:Possibly. But this is not exactly for benchmarking, it's for making something compile when it normally doesn't. I don't know if it's related to DoNotOptimize. In fact, we want it to be optimized away completely, and be replaced with `true`. I was thinking std.meta, since it's a tool for compile-time branches/loops. -SteveOn 7/16/20 2:32 AM, Andrei Alexandrescu wrote:Perhaps in std.benchmark. This function is loosely related to DoNotOptimize in https://github.com/google/benchmark.I got good news for you then: https://github.com/dlang/dmd/pull/11236That is good news, and will help here! This should suffice: property pure safe nothrow bool reachable() { pragma(inline, true); return true; } Though I don't know if this is something we should include in Phobos?
Jul 16 2020
On Wednesday, 15 July 2020 at 20:33:23 UTC, Steven Schveighoffer wrote:I found a weird workaround to the "Unreachable code" problem.[...]int foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable? -SteveAm I the only one who thinks that this is completely insane? Maybe if the unreachable code warning is causing us this much trouble, we should just get rid of it. Personally, the number of times it's done anything helpful for me are far outweighed by the number of times it's gotten in my way.
Jul 16 2020
On 7/16/20 6:12 PM, Paul Backus wrote:On Wednesday, 15 July 2020 at 20:33:23 UTC, Steven Schveighoffer wrote:It's not just you.I found a weird workaround to the "Unreachable code" problem.[...]int foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable?Am I the only one who thinks that this is completely insane?Maybe if the unreachable code warning is causing us this much trouble, we should just get rid of it. Personally, the number of times it's done anything helpful for me are far outweighed by the number of times it's gotten in my way.I would be fine if the compiler just didn't generate unreachable code, and didn't tell me about it. -Steve
Jul 16 2020
On Wednesday, 15 July 2020 at 20:33:23 UTC, Steven Schveighoffer wrote:I found a weird workaround to the "Unreachable code" problem.[...]int foo(bool x)() { if(x && (__ctfe || !__ctfe)) return 1; return 2; } I think this is a way to fix some of those static foreach loops with returns which can have these reachability problems. Only, it's really verbose and ugly. Maybe we still should have that other variable? -SteveIs it just me, or does anyone else think that this is completely insane? Maybe if the unreachable code warning is causing us this much trouble, we should just get rid of it. Personally, the number of times it's done anything helpful for me are far outweighed by the number of times it's gotten in my way.
Jul 16 2020
On Thursday, 16 July 2020 at 22:15:05 UTC, Paul Backus wrote:Maybe if the unreachable code warning is causing us this much trouble, we should just get rid of it. Personally, the number of times it's done anything helpful for me are far outweighed by the number of times it's gotten in my way.I'm taking a look into trying to get rid of "false positive" warnings. I think considering whether a return statement comes from a static if when doing stuff in blockexit.d. Would love to hear suggestions for this/other approaches. My test case is basically: static foreach(whatever){ static if(something){ return false; } } return true; which currently warns whenever one of the early returns is triggered.
Jul 17 2020