[LLVMdev] Arithmetic right shift emulation folding

me22 me22.ca at gmail.com
Wed Nov 18 07:55:59 PST 2009


Since C doesn't specify whether >> is arithmetic or logical on signed
numbers, portable code would have to emulate it.  Is there a way that
LLVM will fold down to ashr in the IR?

I first tried this:

    int ashr(unsigned a, unsigned b) {
        return (signed)a < 0 ? ~((~a) >> b) : a >> b;
    }

But that generates 4 BBs.  Slightly better is this one:

    int qaz(unsigned a, unsigned b) {
        unsigned c = (signed)a < 0 ? ~0u : 0u;
        return ((a^c) >> b)^c;
    }

Which gives this branch-less IR:

    define i32 @qaz(i32 %a, i32 %b) nounwind readnone {
    entry:
        %ones = ashr i32 %a, 31		; <i32> [#uses=2]
        %0 = xor i32 %ones, %a		; <i32> [#uses=1]
        %1 = lshr i32 %0, %b		; <i32> [#uses=1]
        %2 = xor i32 %1, %ones		; <i32> [#uses=1]
        ret i32 %2
    }

Is there any way to do better?

Thanks,
~ Scott



More information about the llvm-dev mailing list