mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-05 12:31:33 +00:00
04c559569f
The AMDGPUIndirectAddressing pass was previously responsible for lowering private loads and stores to indirect addressing instructions. However, this pass was buggy and way too complicated. The only advantage it had over the new simplified code was that it saved one instruction per direct write to private memory. This optimization likely has a minimal impact on performance, and we may be able to duplicate it using some other transformation. For the private address space, we now: 1. Lower private loads/store to Register(Load|Store) instructions 2. Reserve part of the register file as 'private memory' 3. After regalloc lower the Register(Load|Store) instructions to MOV instructions that use indirect addressing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193179 91177308-0d34-0410-b5e6-96231b3b80d8
105 lines
3.6 KiB
LLVM
105 lines
3.6 KiB
LLVM
; RUN: llc < %s -march=r600 -mcpu=redwood | FileCheck %s
|
|
|
|
; This test checks that uses and defs of the AR register happen in the same
|
|
; instruction clause.
|
|
|
|
; CHECK: @mova_same_clause
|
|
; CHECK: MOVA_INT
|
|
; CHECK-NOT: ALU clause
|
|
; CHECK: 0 + AR.x
|
|
; CHECK: MOVA_INT
|
|
; CHECK-NOT: ALU clause
|
|
; CHECK: 0 + AR.x
|
|
|
|
define void @mova_same_clause(i32 addrspace(1)* nocapture %out, i32 addrspace(1)* nocapture %in) {
|
|
entry:
|
|
%stack = alloca [5 x i32], align 4
|
|
%0 = load i32 addrspace(1)* %in, align 4
|
|
%arrayidx1 = getelementptr inbounds [5 x i32]* %stack, i32 0, i32 %0
|
|
store i32 4, i32* %arrayidx1, align 4
|
|
%arrayidx2 = getelementptr inbounds i32 addrspace(1)* %in, i32 1
|
|
%1 = load i32 addrspace(1)* %arrayidx2, align 4
|
|
%arrayidx3 = getelementptr inbounds [5 x i32]* %stack, i32 0, i32 %1
|
|
store i32 5, i32* %arrayidx3, align 4
|
|
%arrayidx10 = getelementptr inbounds [5 x i32]* %stack, i32 0, i32 0
|
|
%2 = load i32* %arrayidx10, align 4
|
|
store i32 %2, i32 addrspace(1)* %out, align 4
|
|
%arrayidx12 = getelementptr inbounds [5 x i32]* %stack, i32 0, i32 1
|
|
%3 = load i32* %arrayidx12
|
|
%arrayidx13 = getelementptr inbounds i32 addrspace(1)* %out, i32 1
|
|
store i32 %3, i32 addrspace(1)* %arrayidx13
|
|
ret void
|
|
}
|
|
|
|
; This test checks that the stack offset is calculated correctly for structs.
|
|
; All register loads/stores should be optimized away, so there shouldn't be
|
|
; any MOVA instructions.
|
|
;
|
|
; XXX: This generated code has unnecessary MOVs, we should be able to optimize
|
|
; this.
|
|
|
|
; CHECK: @multiple_structs
|
|
; CHECK-NOT: MOVA_INT
|
|
|
|
%struct.point = type { i32, i32 }
|
|
|
|
define void @multiple_structs(i32 addrspace(1)* %out) {
|
|
entry:
|
|
%a = alloca %struct.point
|
|
%b = alloca %struct.point
|
|
%a.x.ptr = getelementptr %struct.point* %a, i32 0, i32 0
|
|
%a.y.ptr = getelementptr %struct.point* %a, i32 0, i32 1
|
|
%b.x.ptr = getelementptr %struct.point* %b, i32 0, i32 0
|
|
%b.y.ptr = getelementptr %struct.point* %b, i32 0, i32 1
|
|
store i32 0, i32* %a.x.ptr
|
|
store i32 1, i32* %a.y.ptr
|
|
store i32 2, i32* %b.x.ptr
|
|
store i32 3, i32* %b.y.ptr
|
|
%a.indirect.ptr = getelementptr %struct.point* %a, i32 0, i32 0
|
|
%b.indirect.ptr = getelementptr %struct.point* %b, i32 0, i32 0
|
|
%a.indirect = load i32* %a.indirect.ptr
|
|
%b.indirect = load i32* %b.indirect.ptr
|
|
%0 = add i32 %a.indirect, %b.indirect
|
|
store i32 %0, i32 addrspace(1)* %out
|
|
ret void
|
|
}
|
|
|
|
; Test direct access of a private array inside a loop. The private array
|
|
; loads and stores should be lowered to copies, so there shouldn't be any
|
|
; MOVA instructions.
|
|
|
|
; CHECK: @direct_loop
|
|
; CHECK-NOT: MOVA_INT
|
|
|
|
define void @direct_loop(i32 addrspace(1)* %out, i32 addrspace(1)* %in) {
|
|
entry:
|
|
%prv_array_const = alloca [2 x i32]
|
|
%prv_array = alloca [2 x i32]
|
|
%a = load i32 addrspace(1)* %in
|
|
%b_src_ptr = getelementptr i32 addrspace(1)* %in, i32 1
|
|
%b = load i32 addrspace(1)* %b_src_ptr
|
|
%a_dst_ptr = getelementptr [2 x i32]* %prv_array_const, i32 0, i32 0
|
|
store i32 %a, i32* %a_dst_ptr
|
|
%b_dst_ptr = getelementptr [2 x i32]* %prv_array_const, i32 0, i32 1
|
|
store i32 %b, i32* %b_dst_ptr
|
|
br label %for.body
|
|
|
|
for.body:
|
|
%inc = phi i32 [0, %entry], [%count, %for.body]
|
|
%x_ptr = getelementptr [2 x i32]* %prv_array_const, i32 0, i32 0
|
|
%x = load i32* %x_ptr
|
|
%y_ptr = getelementptr [2 x i32]* %prv_array, i32 0, i32 0
|
|
%y = load i32* %y_ptr
|
|
%xy = add i32 %x, %y
|
|
store i32 %xy, i32* %y_ptr
|
|
%count = add i32 %inc, 1
|
|
%done = icmp eq i32 %count, 4095
|
|
br i1 %done, label %for.end, label %for.body
|
|
|
|
for.end:
|
|
%value_ptr = getelementptr [2 x i32]* %prv_array, i32 0, i32 0
|
|
%value = load i32* %value_ptr
|
|
store i32 %value, i32 addrspace(1)* %out
|
|
ret void
|
|
}
|