[LLVMdev] Unnecessary moves after sign-extension in 2-address target

Greg McGary greg at mcgary.org
Sun Apr 19 18:15:17 PDT 2009

My two-address target machine has sign-extension instructions to extend
i8->i32 and i16->i32.  When I compile this simple program:

    sext (unsigned a, unsigned b, int c)
      return (signed char) a + (signed short) b + c;

I get this IR:

    define i32 @sext(i32 %a, i32 %b, i32 %c) nounwind readnone {
        %conv = trunc i32 %a to i8        ; <i8> [#uses=1]
        %conv1 = sext i8 %conv to i32        ; <i32> [#uses=1]
        %conv3 = trunc i32 %b to i16        ; <i16> [#uses=1]
        %conv4 = sext i16 %conv3 to i32        ; <i32> [#uses=1]
        %add = add i32 %conv1, %c        ; <i32> [#uses=1]
        %add6 = add i32 %add, %conv4        ; <i32> [#uses=1]
        ret i32 %add6

And this not-so-great assembler code:

    sextb r1
    mov r4,r1    ### unnecessary move
    add r4,r3
    sextw r2
    mov r1,r2    ### unnecessary move
    add r1,r4
    jmp [r30]

Which should  be this:

    sextb r1
    add r1,r3
    sextw r2
    add r1,r2
    jmp [r30]

The debug output from LLVM shows this:

********** REWRITING TWO-ADDR INSTRS **********
********** Function: sext
    %reg1028<def> = sextb_r %reg1025<kill>
        prepend:    %reg1028<def> = mov_rr %reg1025<kill>
        rewrite to:    %reg1028<def> = sextb_r %reg1028
    %reg1030<def> = sextw_r %reg1026<kill>
        prepend:    %reg1030<def> = mov_rr %reg1026<kill>
        rewrite to:    %reg1030<def> = sextw_r %reg1030

Because sextb_r and sextw_r have destination tied to source operands,
TwoAddressInstructionPass thinks it needs a copy.  However, since the
sext kills its source, the copy is unnecessary.  Why does this happen?
Is TwoAddressInstructionPass relying on a later pass to notice this and
transform it again?


More information about the llvm-dev mailing list