Cmm missing optimization
Motivation
I am making some changes to the way switch statements are compiled and for a simple function like the following:
foo :: Int -> Int
foo 1 = 23
foo 2 = 5
I generate the assembly below. The code is non-optimal (but correct), but that's not the point of this issue (see below). For reference this is the plan from which the assembly is generated in my patched ghc.
Plan:
IfLT 1 (Unconditionally DEFAULT_EXCEPTION_LABEL)
(IfLE 1 (Unconditionally LABEL_FOR_23)
(IfLE 2 (Unconditionally LABEL_FOR_5)
(Unconditionally DEFAULT_EXCEPTION_LABEL)))
Assembly:
.LcMV_info:
.LcMV:
movq 7(%rbx),%rax
cmpq $1,%rax (**1**)
jl .LcN6
.LuN9:
cmpq $1,%rax (**2**)
jle .LcN7
.LuNa:
cmpq $2,%rax
jg .LcN6
.LcN8:
movl $stg_INTLIKE_closure+337,%ebx
addq $8,%rbp
jmp *(%rbp)
.LcN6:
movl $A_foo3_closure,%ebx
addq $8,%rbp
jmp *(%rbx)
.LcMZ:
movl $A_foo_closure,%ebx
jmp *-8(%r13)
.LcN7:
movl $stg_INTLIKE_closure+625,%ebx
addq $8,%rbp
jmp *(%rbp)
If you check point (**1**)
and (**2**)
above we see the compq $1, %rax
is done twice (which is as we specified).
But since label .LuN9
is NOT the target of any statement it would be nice if there was a Cmm optimization to detect such cases and clean up by deleting the second cmpq
so that we would end up with:
.LcN1:
movq 7(%rbx),%rax
cmpq $1,%rax (**1**)
jl .LcN6
.LuN9:
jle .LcN7