[LLVMbugs] [Bug 13363] New: Missed optimization when arguments are passed in callee-saved registers

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Sat Jul 14 17:10:19 PDT 2012


http://llvm.org/bugs/show_bug.cgi?id=13363

             Bug #: 13363
           Summary: Missed optimization when arguments are passed in
                    callee-saved registers
           Product: libraries
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Common Code Generator Code
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: borja.ferav at gmail.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified


The following missed optimization is from an out of tree target and happens
when some of the input arguments of a function are being passed in callee saved
registers.

Consider the following piece of code:
(reg pairs and ints are 16bits wide)
extern void foo(int);
int bar(int a, int b, char c, float d, int e, char f)
{
  foo(e);
  return e;
}

Generates:
push    r14
push    r15
push    r28
push    r29
movw    r29:r28, r15:r14 ; make a copy of e
movw    r25:r24, r29:r28 ; move e to call foo
call    foo
movw    r25:r24, r29:r28 ; move copy of e to return
pop    r29
pop    r28
pop    r15
pop    r14
ret

Argument "e" comes in r15:r14 (a callee saved reg) and it's moved to r25:r24 to
pass it to foo. But notice it is also being copied to another CS reg (r29:r28)
to be restored after the function call so it can be returned by bar.
Since r15:r14 is a CS reg, it's guaranteed that the call won't modify its
contents, making the copy unncessary, with the result of needing to save and
restore a new CS reg.

Final code should look like this:
push    r14
push    r15
movw    r25:r24, r15:r14 ; move e to make the call
call    foo
movw    r25:r24, r15:r14 ; move e to return reg
pop    r15
pop    r14
ret

If I don't pass "e" to foo then it gets optimized, but when the argument is
passed to a function this happens. Of course things get worse when more
arguments come to play, but this is simplified test case.

SSA code before regalloc is:

Function Live Ins: %R15R14 in %vreg5
Function Live Outs: %R25R24

BB#0: derived from LLVM BB %entry
    Live Ins: %R15R14
    %vreg5<def> = COPY %R15R14<kill>; DREGS:%vreg5
    ADJCALLSTACKDOWN 0, %SP<imp-def>, %SREG<imp-def,dead>, %SP<imp-use>
    %R25R24<def> = COPY %vreg5; DREGS:%vreg5
    CALLk <ga:@foo>, %R25R24<kill>, <regmask>, %SP<imp-use>, %SP<imp-def>
    ADJCALLSTACKUP 0, 0, %SP<imp-def>, %SREG<imp-def,dead>, %SP<imp-use>
    %R25R24<def> = COPY %vreg5<kill>; DREGS:%vreg5
    RET %R25R24<imp-use,kill>
notice how vreg5 is copied to R25:R24 before the ret.
However after regalloc:
%R29R28<def> = MOVWRdRr %R15R14<kill>
see that R15:R14 is marked as killed.

One more place of improvement is that although r15:r14 is a callee saved reg,
in this function it's not being written at all so the push+pop pairs are not
needed. If foo changed its value, it's responsible for saving and restoring its
contents, but the caller bar is safe to make this optimization.

So at the end it should be:
movw    r25:r24, r15:r14 ; move e to make the call
call    foo
movw    r25:r24, r15:r14 ; move e to return reg
ret

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list