Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#10750 closed bug (fixed)

silly assembly for comparing Doubles

Reported by: rwbarton Owned by:
Priority: normal Milestone: 8.0.1
Component: Compiler (CodeGen) Version: 7.11
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Runtime performance bug Test Case:
Blocked By: Blocking:
Related Tickets: #10137, #10677 Differential Rev(s):
Wiki Page:

Description

A function like f x = if x > 0.0 then ... else ... compiles to the assembly

        movsd 7(%rbx),%xmm0
        xorpd %xmm1,%xmm1
        ucomisd %xmm1,%xmm0
        seta %al
        movzbl %al,%eax
        cmpq $1,%rax
        jb _c1tb

This seta/movzbl/cmpq/jb is bad, we can just generate ja (and 7.10 did).

The cause is that the code generator produces Cmm like

           switch [0 .. 1] %MO_F_Gt_W64(_s1sv::F64, 0.0 :: W64)::I64 {
               case 0 : goto c1tb;
               case 1 : goto c1tc;
           }

which turns into

      if (%MO_F_Gt_W64(_s1sv::F64,
                       0.0 :: W64) < 1) goto c1tb; else goto c1tc;

and then GHC is stuck. It knows how to turn condition >= 1 into condition, and it knows how to turn condition < 1 into a negated version of condition when possible, but there is no negated version of MO_F_Gt_W64 (it's not MO_F_Le_W64 because of NaNs and signed zeros). It doesn't know how to turn a negated conditional into a conditional with the branches swapped because it doesn't look at that much at once.

Presumably more fallout from #10137, and maybe can be fixed simultaneously with #10677.

Change History (7)

comment:1 Changed 4 years ago by nomeata

Can you provide me with a working example? For some reason, if I try to reproduce it, I get code that actually calls GHC.Classes.>_info.

comment:2 Changed 4 years ago by nomeata

Anyways, with #10677 resp. D1137, the conditions should be condition != 0, which will hopefully be turned into condition.

comment:3 in reply to:  2 Changed 4 years ago by rwbarton

Replying to nomeata:

Anyways, with #10677 resp. D1137, the conditions should be condition != 0, which will hopefully be turned into condition.

Yes, I believe that case is handled already.

Here is an example (build with -O):

f :: Double -> Double
f x = if x > 0 then 1 else 2

comment:4 Changed 4 years ago by nomeata

Weird. With your example, compiled with ./inplace/bin/ghc-stage2 -fforce-recomp -O -ddump-asm T10677.hs, I get assembly like this:

==================== Asm code ====================
.text
	.align 8
	.long	S1vB_srt-(Zero.f_info)+0
	.long	0
	.quad	4294967301
	.quad	0
	.quad	12884901903
.globl Zero.f_info
.type Zero.f_info, @object
Zero.f_info:
_c1vs:
	leaq -32(%rbp),%rax
	cmpq %r15,%rax
	jb _c1vt
_c1vu:
	movq $block_c1vm_info,-8(%rbp)
	movq %r14,%rax
	movl $GHC.Classes.$fOrdDouble_closure,%r14d
	movq $stg_ap_pp_info,-32(%rbp)
	movq %rax,-24(%rbp)
	movq $Zero.f3_closure+1,-16(%rbp)
	addq $-32,%rbp
	jmp GHC.Classes.>_info
.text
	.align 8
	.quad	0
	.quad	32
block_c1vm_info:
_c1vm:
	andl $7,%ebx
	cmpq $1,%rbx
	jne _c1vq
_c1vp:
	movl $Zero.f2_closure+1,%ebx
	addq $8,%rbp
	jmp *(%rbp)
_c1vq:
	movl $Zero.f1_closure+1,%ebx
	addq $8,%rbp
	jmp *(%rbp)
_c1vt:
	movl $Zero.f_closure,%ebx
	jmp *-8(%r13)
	.size Zero.f_info, .-Zero.f_info

so unless I am reading this wrong, it did not inline specialize or >.

comment:5 Changed 4 years ago by rwbarton

Maybe you built GHC's libraries at too low an optimization level?

comment:6 Changed 4 years ago by nomeata

Resolution: fixed
Status: newclosed

Maybe you built GHC's libraries at too low an optimization level?

Heh, that’s it. I switched to quickest earlier to do a bisect, and did not switch back :-)

Anyways, this produces a ja command now:

_c36F:
	movsd 7(%rbx),%xmm0
	xorpd %xmm1,%xmm1
	ucomisd %xmm1,%xmm0
	ja _c36U

comment:7 Changed 4 years ago by thomie

Milestone: 8.0.1
Note: See TracTickets for help on using tickets.