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 ?