This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug inline-asm/24751] New: ARM : poor register allocation around inline assembler


The following example comes from ARM linux kernel 2.6.14

------------------------------------------------------------

#define local_irq_enable()                                      \
        ({                                                      \
                unsigned long temp;                             \
        __asm__ __volatile__(                                   \
        "mrs    %0, cpsr                @ local_irq_enable\n"   \
"       bic     %0, %0, #128\n"                                 \
"       msr     cpsr_c, %0"                                     \
        : "=r" (temp)                                           \
        :                                                       \
        : "memory", "cc");                                      \
        })

------------------------------------------------------------

static int
__do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
{
        unsigned int status;
        int ret, retval = 0;

        spin_unlock(&irq_controller_lock);

        if (!(action->flags & SA_INTERRUPT))
                local_irq_enable();

        status = 0;
        do {
                ret = action->handler(irq, action->dev_id, regs);
                if (ret == IRQ_HANDLED)
                        status |= action->flags;
                retval |= ret;
                action = action->next;
        } while (action);

        if (status & SA_SAMPLE_RANDOM)
                add_interrupt_randomness(irq);

        spin_lock_irq(&irq_controller_lock);

        return retval;
}

------------------------------------------------------------

With arm-linux-gcc 4.0.2, this compiles to:

<__do_irq>:
    mov     ip, sp
    stmdb   sp!, {r4, r5, r6, r7, r8, fp, ip, lr, pc}
    sub     fp, ip, #4      ; 0x4
    ldr     r3, [r1, #4]
    mov     r4, r1                              <-- Unnecessary
    tst     r3, #536870912  ; 0x20000000
    mov     r7, r0                              <-- Unnecessary
    mov     r8, r2                              <-- Unnecessary
    bne     1f

    mrs     r3, CPSR                            ; local_irq_enable
    bic     r3, r3, #128    ; 0x80
    msr     CPSR_c, r3

1:  mov     r6, #0  ; 0x0
    mov     r5, r6
    ldr     r1, [r4, #16]
    mov     r0, r7                              <-- Unnecessary
    mov     r2, r8                              <-- Unnecessary
    mov     lr, pc
    ....
    ....

ie r0, r1 and r2 are copied to callee-saved registers before the inline
assembler (and back again afterwards) as if the inline assember were a function
call.

Inline assembler such as this gets used a lot in the linux kernel...


-- 
           Summary: ARM : poor register allocation around inline assembler
           Product: gcc
           Version: 4.0.2
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: inline-asm
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: armcc2000 at yahoo dot com
  GCC host triplet: i686-host_pc-linux-gnu
GCC target triplet: arm-9tdmi-linux-gnu


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24751


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]