[Sbcl-devel] Improved signed=>unsigned conversion on x86-64

23 views
Skip to first unread message

Douglas Katzman

unread,
Apr 25, 2013, 12:36:45 AM4/25/13
to SBCL Devel-list
Hi developers,

Given this simple definition the compiler emits two RIP-relative constants and one useless AND.

(defun foo (x)
  (declare (fixnum x))
  (zerop (logxor (ldb (byte 64 0) x) #xffffffff80aabbcc)))

; 030DB7A2:       4823155F000000   AND RDX, [RIP+95]          ; #xFFFFFFFFFFFFFFFF
                                                              ; no-arg-parsing entry point
;      7A9:       48331560000000   XOR RDX, [RIP+96]          ; #xFFFFFFFF80AABBCC
;      7B0:       4885D2           TEST RDX, RDX
;      7B3:       BA17001020       MOV EDX, 537919511
;      7B8:       41BB4F001020     MOV R11D, 537919567
;      7BE:       490F44D3         CMOVEQ RDX, R11
;      7C2:       488BE5           MOV RSP, RBP
;      7C5:       F8               CLC
;      7C6:       5D               POP RBP
;      7C7:       C3               RET
... filler ...
;      808:       FF               BYTE #XFF
;      809:       FF               BYTE #XFF
;      80A:       FF               BYTE #XFF
;      80B:       FF               BYTE #XFF
;      80C:       FF               BYTE #XFF
;      80D:       FF               BYTE #XFF
;      80E:       FF               BYTE #XFF
;      80F:       FFCC             DEC ESP
;      811:       BBAA80FFFF       MOV EBX, -32598
;      816:       FF               BYTE #XFF
;      817:       FF00             INC DWORD PTR [RAX]

The AND can be removed, and the other unsigned constant can be treated as signed imm32 because it has 33 leftmost 1 bits. Improved code is below. In both functions, the entry code (not shown) converts RDX fixnum->signed with "SAR RDX,1".

; 02A4CAB2:       4881F2CCBBAA80   XOR RDX, -2136294452       ; no-arg-parsing entry point
;       B9:       4885D2           TEST RDX, RDX
...

Patch is attached for review.
Also an unrelated patch to add a define-instruction for POPCNT.
Look ok?

Doug
constants.patch
popcnt.patch

Paul Khuong

unread,
Apr 25, 2013, 6:09:29 PM4/25/13
to Douglas Katzman, SBCL Devel-list
Douglas Katzman wrote:
> The AND can be removed, and the other unsigned constant can be treated as
> signed imm32 because it has 33 leftmost 1 bits. Improved code is
> below. In
> both functions, the entry code (not shown) converts RDX fixnum->signed
> with
> "SAR RDX,1".
>
> ; 02A4CAB2: 4881F2CCBBAA80 XOR RDX, -2136294452 ;
> no-arg-parsing entry point
> ; B9: 4885D2 TEST RDX, RDX
> ...
>
> Patch is attached for review.

Good stuff; that's been annoying me for a while too.

The constraints on bitwidth date from before unboxed constants. It may
well be worth it to always handle constant operands directly, with
constantize to choose between 32 bit and RIP-relative operands, rather
than leaving some to be loaded via 64 bit moves. I think this is why I
handled truncate/c that way: IDIV with a RIP-relative operand is 7 bytes
(+ 8 for data, which might be reused), versus a 64 bit immediate move
(10 bytes) and a reg-reg IDIV (3 bytes). In the end, it's likely a wash…
Other VOPs can more easily save a register by avoiding 64 bit moves, and
that's a win.

I note that you changed the constraints on fixnum operands. The changes
have no effect: (signed-byte 32)-safe fixnum are exactly (signed-byte (-
32 n-fx-tag-bits)).

> Also an unrelated patch to add a define-instruction for POPCNT.

I hope someone else can take care of that one (:

Paul Khuong

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr
_______________________________________________
Sbcl-devel mailing list
Sbcl-...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-devel

Paul Khuong

unread,
May 20, 2013, 11:21:19 PM5/20/13
to Douglas Katzman, SBCL Devel-list
Douglas Katzman wrote:
> Hi developers,
>
> Given this simple definition the compiler emits two RIP-relative
> constants and one useless AND.
>
> (defun foo (x)
> (declare (fixnum x))
> (zerop (logxor (ldb (byte 64 0) x) #xffffffff80aabbcc)))
[...]
> The AND can be removed, and the other unsigned constant can be treated
> as signed imm32 because it has 33 leftmost 1 bits. Improved code is
> below. In both functions, the entry code (not shown) converts RDX
> fixnum->signed with "SAR RDX,1".
>
> ; 02A4CAB2: 4881F2CCBBAA80 XOR RDX, -2136294452 ;
> no-arg-parsing entry point
> ; B9: 4885D2 TEST RDX, RDX
> ...
>
> Patch is attached for review.
> Also an unrelated patch to add a define-instruction for POPCNT.

Both patches were committed tonight: aae8dd3 (POPCNT instruction on
x86-64) and 39117fb (Cleverer handling of medium (32 < bit width <= 64)
constants on x86-64). For the latter, I also yanked out all the load-if
logic: we always want to the remaining operand and the result in
registers, as the constant operand is either an immediate or RIP-rel.

Thank you,

Paul Khuong

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
Reply all
Reply to author
Forward
0 new messages