Skip to content

Optimization: (x != C) comparison can utilize (x ^ C) result #130510

@Explorer09

Description

@Explorer09

This is an optimization opportunity that can benefit RISC-V, MIPS and other processors that don't use condition codes for their compare-and-branch instructions.

#include <stdlib.h>
unsigned int func1_a(unsigned int x) {
    if (x != 0x555)
        return (x ^ 0x555);
    abort();
}

unsigned int func1_c(unsigned int x) {
    unsigned int tmp = x ^ 0x555;
    __asm__ ("" : "+r" (tmp));
    if (tmp == 0)
        abort();
    return tmp;
}

unsigned int func2_a(unsigned int x) {
    if (x != 0x555)
        return (x - 0x555);
    abort();
}

unsigned int func2_c(unsigned int x) {
    unsigned int tmp = x - 0x555;
    __asm__ ("" : "+r" (tmp));
    if (tmp == 0)
        abort();
    return tmp;
}

The example code above can be tested in Compiler Explorer (godbolt.org). (The target architecture I mostly concern here is riscv32.)

func1_c() and func2_c() are the results I expected for func1_a() and func2_a() to optimize to when using the -Os option. Clang 19 is already able to recognize the func2 case (x != 0x555 and x - 0x555 != 0) but misses on the func1 case ((x ^ 0x555) != 0).

(Note: I also reported this in GCC.)

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