assemblyarm64neonbigintextended-precision

AArch64: compare 256-bit unsigned integers


While learning Arm NEON instruction set, I tried to implement 256-bit numbers comparison (A <= B). Below is the implementation I ended up with, but I doubt my approach is good. Maybe there's some wiser and more optimized way to compare large numbers? Any advice and comments will be appreciated.

// v1:v0 = number A
// v11:v10 = number B
// out: x0 = 0 if A <= B

        // Check A >= B (element by element) - Result1
        cmhs v13.4s, v1.4s, v11.4s
        cmhs v12.4s, v0.4s, v10.4s

        // Check A > B (element by element) - Result2
        cmhi v11.4s, v1.4s, v11.4s
        cmhi v10.4s, v0.4s, v10.4s

        // Narrow down Result2 vector to 64 bits
        xtn v10.4h, v10.4s
        xtn2 v10.8h, v11.4s
        xtn v10.8b, v10.8h
        
        // Narrow down Result1 vector to 64 bits
        xtn v11.4h, v12.4s
        xtn2 v11.8h, v13.4s
        xtn v11.8b, v11.8h
        not v11.8b, v11.8b

        // Compare elements in Result1 and Result2 as scalars
        // if Result2 has all bits set in higher elements than Result1,
        // then A > B
        cmhi d9, d10, d11
        mov x0, v9.d[0]

Solution

  • I reversed the boolean, replaced xtn/xtn2 pairs with uzp1, and re-scheduled the insructions.

    cmhi v12.4s, v10.4s, v0.4s
    cmhi v13.4s, v11.4s, v1.4s
    
    cmhi v10.4s, v0.4s, v10.4s
    cmhi v11.4s, v1.4s, v11.4s
    
    uzp1    v12.8h, v12.8h, v13.8h
    uzp1    v10.8h, v10.8h, v11.8h
    
    xtn     v12.8b, v12.8h
    xtn     v10.8b, v10.8h
    
    cmhi    d10, d10, d12
    mov     x0, v10.d[0]