[LLVMdev] [fwd] Re: LLVM Compiler Infrastructure

Chris Lattner sabre at nondot.org
Tue Nov 1 14:47:58 PST 2005


>   Now we got a small but annoying problem. When we get the following C 
> code to llvm-gcc,
>
> short test(int x) {
>        return (short) (x >> 10);
> }
>
>   It will generate the following LLVM code:
> short %test(int %x) {
>        %x = cast int %x to uint                ; <uint> [#uses=1]
>        %tmp.2 = shr uint %x, ubyte 10          ; <uint> [#uses=1]
>        %tmp.3 = cast uint %tmp.2 to short              ; <short> [#uses=1]
>        ret short %tmp.3
> }

ok.

> Basically, LLVM frontend will first convert an integer to unsigned 
> integer, and then do shifting. It seems that this conversion often 
> occurs for SHIFTING operations.

The cast from 'int' to 'uint' changes the semantics of the shift from 
being an arithmetic shift to a logical shift.

> So our question is that do you know there is any option in LLVM to 
> disable this kind of cast-to-unsigned code generation?

No.

I'm not sure exactly why you don't like the code above, but here's the 
basic idea that we're following:

1. All code generators have to support all operations, no exceptions.  The
    above code should *work* for you, no matter what.
2. Performance, on the other hand, is different.  It is quite possible
    that some code will result in really lousy machine code or even a call
    to a library support routine if it doesn't map to the hardware well.
    Because of this, the optimizers are occasionally aware of things that
    are bad for targets.

In the case above, the cast from "int to uint" results in no code.  The 
optimization being done is probably performed by the 'instcombine' pass, 
as it is strength reducing an arithmetic shift right into a logical shift 
right.  It currently assumes that a logical shift is always at least as 
cheap as an arithmetic shift: this is true for all targets that I am aware 
of, and certainly true for all that LLVM supports currently.

An important part of this discussion is that the sign flag in this 
function does not matter, thus it is safe to convert one shift into the 
other.

> Although it is correct for 32-bit general purpose processor, it does not 
> fit well for hardware synthesis, since we need to use wider components 
> (up to 32-bit) to implement these operations, otherwise we may lose sign 
> flag. Our favorite LLVM code is that without (or with very few) CAST, 
> and doing the SHR directly for the signed integers.

I'm not sure I understand what you are saying here.  Can you please 
clarify whether:

1. signed shift is cheaper than logical/unsigned shift, or
2. the cast is causing the problem?

For example, is this code:

short %test(uint %x) {
        %tmp.2 = shr uint %x, ubyte 10          ; <uint> [#uses=1]
        %tmp.3 = cast uint %tmp.2 to short              ; <short> [#uses=1]
        ret short %tmp.3
}

okay for you?  It has no cast, but does the same operations as the above 
code.

If so, I would argue strongly that this is a bug/missing-feature from your 
code generator.  The two pieces of code should generate *exactly* the same 
machine code (or circuits :) ).

-Chris

-- 
http://nondot.org/sabre/
http://llvm.org/




More information about the llvm-dev mailing list