Skip to content

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
Edited by Neo
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information