Bug 17083 – final switch(bool) should be lowered at least to a simple if else

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-01-10T23:37:00Z
Last change time
2017-01-12T17:48:40Z
Keywords
performance
Assigned to
nobody
Creator
b2.temp

Comments

Comment #0 by b2.temp — 2017-01-10T23:37:39Z
This function bool foo(bool b) { final switch(b) { case true: return b; case false: return b; } } generates, with -O -release, this incredible bloat: ;------- SUB 000000000045E360h ------- 000000000045E360h push rbp 000000000045E361h mov rbp, rsp 000000000045E364h sub rsp, 10h 000000000045E368h mov dword ptr [rbp-08h], edi 000000000045E36Bh movzx eax, byte ptr [rbp-08h] 000000000045E36Fh test eax, eax 000000000045E371h je 0045E37Ah 000000000045E373h cmp eax, 01h 000000000045E376h je 0045E37Ah 000000000045E378h jmp 0045E383h 000000000045E37Ah movsx eax, byte ptr [rbp-08h] 000000000045E37Eh mov rsp, rbp 000000000045E381h pop rbp 000000000045E382h ret 000000000045E383h hlt 000000000045E384h nop dword ptr [rax+00h] 000000000045E388h push rbp 000000000045E389h mov rbp, rsp 000000000045E38Ch lea rsi, qword ptr [000000000045E360h] 000000000045E393h mov edi, 00000001h 000000000045E398h call 000000000045EB80h 000000000045E39Dh mov rdi, rax 000000000045E3A0h mov rsi, rdx 000000000045E3A3h call 000000000045E3B0h 000000000045E3A8h xor eax, eax 000000000045E3AAh pop rbp 000000000045E3ABh ret ;------------------------------------ while GDC or LDC optimizers seems to handle this more reasonably.
Comment #1 by uplink.coder — 2017-01-11T05:47:43Z
This has almost no relevance. code such as this is unlikely to be written in performance critical circumstances. One should not need to complicate codegen for a matter like this.
Comment #2 by b2.temp — 2017-01-12T17:48:40Z
I've seen you closed. However it is almost done in StatementSwitchVisitor.visit(SwitchStatement ss); There would just be the BreakStatement to remove in each case: @@ -1987,10 +1987,11 @@ else ss.condition = ss.condition.semantic(sc); ss.condition = resolveProperties(sc, ss.condition); Type att = null; TypeEnum te = null; + Type tb = ss.condition.type; while (ss.condition.op != TOKerror) { // preserve enum type for final switches if (ss.condition.type.ty == Tenum) te = cast(TypeEnum)ss.condition.type; @@ -2146,12 +2147,82 @@ else { sc.pop(); return setError(); } - sc.pop(); result = ss; + + if (!te && tb && tb.ty == Tbool && ss.isFinal && ss.cases.dim == 2 && + cast(EqualExp) ss.condition) + { + EqualExp eq = cast(EqualExp) ss.condition; + + if (auto e = eq.toBoolean(sc)) + { + CompoundStatement true_; + CompoundStatement false_; + + dinteger_t c; + foreach (cs; *ss.cases) + { + dinteger_t v = cs.exp.toInteger; + if (v != 0) + { + true_ = cast(CompoundStatement) cs.statement; + } + else + { + false_ = cast(CompoundStatement) cs.statement; + } + c++; + } + if (true_ && false_) + { + void removeThisSwitchBreaks(CompoundStatement cs) + { + if (cs.statements is null) + return; + // TODO: remove breaks; + } + removeThisSwitchBreaks(true_); + removeThisSwitchBreaks(false_); + + result = new IfStatement(ss.loc, null, ss.condition, + true_, false_, false_.loc); + } + else ss.error("final switch(bool) cannot be converted to a IfStatement"); + } + } + + sc.pop(); } override void visit(CaseStatement cs) { SwitchStatement sw = sc.sw; Isn't this reasonable ?