[LLVMbugs] [Bug 7221] New: [ARM JIT] emitVFPLoadStoreMultipleInstructio() does not handle s* registers

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon May 24 23:52:31 PDT 2010


           Summary: [ARM JIT] emitVFPLoadStoreMultipleInstructio() does
                    not handle s* registers
           Product: new-bugs
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: sliao at google.com
                CC: llvmbugs at cs.uiuc.edu

In JITting clouds.c on ARM, I found that the VFP instruction "vstmia" is not
generated correctly. The problem code is:

$ cat clouds.c
float xshift[5];
float rotation[5];

void init() {
    int i;
    for (i=0;i<5;i++) {
        xshift[i] = 0.f;
        rotation[i] = 360.f * i / 5.f;

The generated code is:
JIT: Disassembled code: init
    0xf7c68000:    mov    r0, #0
    0xf7c68004:    movw    r1, #4064
    0xf7c68008:    movt    r1, #63432
    0xf7c6800c:    movw    r2, #4032
    0xf7c68010:    movt    r2, #63432
    0xf7c68014:    vldr.32    s0, [pc, #44]
    0xf7c68018:    vmov.f32    s1, #20
    0xf7c6801c:    mov    r3, #0
    0xf7c68020:    vmov    s2, r3
    0xf7c68024:    add    r3, r3, #1
    0xf7c68028:    str    r0, [r2], #4
    0xf7c6802c:    cmp    r3, #5
    0xf7c68030:    vcvt.f32.s32    s2, s2
    0xf7c68034:    vmul.f32    s2, s2, s0
    0xf7c68038:    vdiv.f32    s2, s2, s1
    0xf7c6803c:    vstmia    r1!, {s2, s3}
    0xf7c68040:    bne    #-32
    0xf7c68044:    bx    lr
    0xf7c68048:    movmis    r0, #0

MagicSmoke/clouds.c caused error due to the instruction above: vstmia    r1!,
{s2, s3}.

The right instruction should be vstmia r1!, {r2}. According to ARM Instruction
Manual, if an instruction operates on 64-bit registers as load/store extension
register, Bit 8 will be 1 and NumReg = (last 8 bit in the instruction) / 2. If
an instruction operates on 32-bit registers as load/store extension register,
Bit 8 will be 0 and NumReg should be (last 8 bit in the instruction). So, the
current implementation only considers the former case: 
   Binary |= NumRegs * 2;
The correct code should first determine if it's the former case or the latter
and compute the Binary accordingly.

After applying the following fix, then all the test cases pass.

--- lib/Target/ARM/ARMCodeEmitter.cpp
+++ lib/Target/ARM/ARMCodeEmitter.cpp
-  Binary |= NumRegs * 2;
+  // bit 8 will be set if <list> is consecutive 64-bit registers (e.g., d0)
+  if(Binary & 0x100)
+    Binary |= NumRegs * 2;
+  else
+    Binary |= NumRegs;


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