Skip to content

Manual application of De Morgan's laws results in better emit #71390

Closed
@Validark

Description

@Validark

I had some code and wanted to wrap the return statement in parenthesis and do a bitwise negation to see if the emit is better. Here is the code after the aforementioned modification:

export fn swarControlCharMask1(v: u64) u64 {
    const ones: u64 = 0x0101010101010101;
    const mask = ones * 0x7F;
    const low_7_bits = v & mask;
    const del = low_7_bits + ones;
    const non_control_or_space = low_7_bits + ones * (0x80 - 0x21);
    return ~(~v & (del | ~non_control_or_space));
}

What I got was:

swarControlCharMask1:
        movabs  rcx, 9187201950435737471
        movabs  rdx, 72340172838076673
        movabs  rax, -6872316419617283936
        and     rcx, rdi
        add     rdx, rcx
        sub     rax, rcx
        or      rax, rdx
        not     rax
        or      rax, rdi
        ret

I had a hunch this was not the best the compiler could do, so I manually applied De Morgan's laws by inverting the bits of each operand and changing the bitwise OR's to AND's and the AND's to OR's:

export fn swarControlCharMask2(v: u64) u64 {
    const ones: u64 = 0x0101010101010101;
    const mask = ones * 0x7F;
    const low_7_bits = v & mask;
    const del = low_7_bits + ones;
    const non_control_or_space = low_7_bits + ones * (0x80 - 0x21);
    return (v | (~del & non_control_or_space));
}

And, sure enough, we save an instruction:

swarControlCharMask2:
        movabs  rcx, 9187201950435737471
        movabs  rdx, 6872316419617283935
        movabs  rax, -72340172838076674
        and     rcx, rdi
        add     rdx, rcx
        sub     rax, rcx
        and     rax, rdx
        or      rax, rdi
        ret

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions