mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-12 03:32:10 +00:00
We were previously codegen'ing these as regular load/store operations and hoping that the register allocator would allocate registers in ascending order so that we could apply an LDM/STM combine after register allocation. According to the commit that first introduced this code (r37179), we planned to teach the register allocator to allocate the registers in ascending order. This never got implemented, and up to now we've been stuck with very poor codegen. A much simpler approach for achiveing better codegen is to create LDM/STM instructions with identical sets of virtual registers, let the register allocator pick arbitrary registers and order register lists when printing an MCInst. This approach also avoids the need to repeatedly calculate offsets which ultimately ought to be eliminated pre-RA in order to decrease register pressure. This is implemented by lowering the memcpy intrinsic to a series of SD-only MCOPY pseudo-instructions which performs a memory copy using a given number of registers. During SD->MI lowering, we lower MCOPY to LDM/STM. This is a little unusual, but it avoids the need to encode register lists in the SD, and we can take advantage of SD use lists to decide whether to use the _UPD variant of the instructions. Fixes PR9199. Differential Revision: http://reviews.llvm.org/D9508 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238473 91177308-0d34-0410-b5e6-96231b3b80d8
37 lines
1.2 KiB
LLVM
37 lines
1.2 KiB
LLVM
; RUN: llc -mtriple=thumbv6m-eabi -verify-machineinstrs %s -o - | FileCheck %s
|
|
@d = external global [64 x i32]
|
|
@s = external global [64 x i32]
|
|
|
|
; Function Attrs: nounwind
|
|
define void @t1() #0 {
|
|
entry:
|
|
; CHECK-LABEL: t1:
|
|
; CHECK: ldr r[[LB:[0-9]]],
|
|
; CHECK-NEXT: ldr r[[SB:[0-9]]],
|
|
; CHECK-NEXT: ldm r[[LB]]!,
|
|
; CHECK-NEXT: stm r[[SB]]!,
|
|
; CHECK-NEXT: ldrb {{.*}}, [r[[LB]]]
|
|
; CHECK-NEXT: strb {{.*}}, [r[[SB]]]
|
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast ([64 x i32]* @s to i8*), i8* bitcast ([64 x i32]* @d to i8*), i32 17, i32 4, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
define void @t2() #0 {
|
|
entry:
|
|
; CHECK-LABEL: t2:
|
|
; CHECK: ldr r[[LB:[0-9]]],
|
|
; CHECK-NEXT: ldr r[[SB:[0-9]]],
|
|
; CHECK-NEXT: ldm r[[LB]]!,
|
|
; CHECK-NEXT: stm r[[SB]]!,
|
|
; CHECK-NEXT: ldrh {{.*}}, [r[[LB]]]
|
|
; CHECK-NEXT: ldrb {{.*}}, [r[[LB]], #2]
|
|
; CHECK-NEXT: strb {{.*}}, [r[[SB]], #2]
|
|
; CHECK-NEXT: strh {{.*}}, [r[[SB]]]
|
|
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast ([64 x i32]* @s to i8*), i8* bitcast ([64 x i32]* @d to i8*), i32 15, i32 4, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; Function Attrs: nounwind
|
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) #1
|