Skip to content

Improve cmm/assembly for pattern matches with two constants.

For a pattern like:

f_test :: Int#->Int#
f_test a = case a of
    1# -> 33#
    7# -> 34#
     _ -> -1#

GHC currently generates code that works best if the default branch is taken most often.

Pseudo-Code

if (a >= 8)
    return -1;
else {
    if (a < 7) {
        if(a != 1)
            return -1;
        else
            return 33;
    } 
    else
        return 34;
}

CMM:

       c1cr: // global
           if (%MO_S_Ge_W64(R2, 8)) goto c1co; else goto u1cu;
       u1cu: // global
           if (%MO_S_Lt_W64(R2, 7)) goto u1cv; else goto c1cq;
       u1cv: // global
           if (R2 != 1) goto c1co; else goto c1cp;
       c1co: // global
           R1 = (-1);
           call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
       c1cp: // global
           R1 = 33;
           call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
       c1cq: // global
           R1 = 34;
           call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
     }

Wouldn't the following be better?

if(a == 1)
    return 33
else if(a == 7)
    return 34
else
    return -1

I would expect that to

  • Improve the cases:

    * a = 1

    * a < 7

  • Be the same for:

    * a = 7

  • Be worse for

    * a > 8

This would be especially nice for the cases where the default branch is raising a pattern match exception. Which is a code path I wouldn't expect to be taken often nor be very performance sensitive.

Even if we keep the current logic there is room for improvement. GHC currently creates the following assembly:

_c1cr:
	cmpq $8,%r14
	jge _c1co
_u1cu:
	cmpq $7,%r14
	jl _u1cv
_c1cq:
	movl $34,%ebx
	jmp *(%rbp)
_u1cv:
	cmpq $1,%r14
	jne _c1co
_c1cp:
	movl $33,%ebx
	jmp *(%rbp)
_c1co:
	movq $-1,%rbx
	jmp *(%rbp)

It would be nice if we could remove one comparison at least.

_c1cr:
	cmpq $7,%r14
	jg _c1co
_u1cu:
	;No longer neccesary cmpq $7,%r14
	jl _u1cv
_c1cq:
	movl $34,%ebx
	jmp *(%rbp)
_u1cv:
	cmpq $1,%r14
	jne _c1co
_c1cp:
	movl $33,%ebx
	jmp *(%rbp)
_c1co:
	movq $-1,%rbx
	jmp *(%rbp)
Trac metadata
Trac field Value
Version 8.2.2
Type Task
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler (CodeGen)
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information